fix(coderd/healthcheck): add daemon-specific warnings to healthcheck output (#11490)

- Sorts provisioner daemons by name ascending in output
- Adds daemon-specific warnings to healthcheck output
- Reword some messages
This commit is contained in:
Cian Johnston 2024-01-08 13:55:00 +00:00 committed by GitHub
parent f4393d0c3f
commit 93cf5dcd47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 412 additions and 83 deletions

18
coderd/apidoc/docs.go generated
View File

@ -13109,10 +13109,10 @@ const docTemplate = `{
"error": {
"type": "string"
},
"provisioner_daemons": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.ProvisionerDaemon"
"$ref": "#/definitions/healthcheck.ProvisionerDaemonsReportItem"
}
},
"severity": {
@ -13126,6 +13126,20 @@ const docTemplate = `{
}
}
},
"healthcheck.ProvisionerDaemonsReportItem": {
"type": "object",
"properties": {
"provisioner_daemon": {
"$ref": "#/definitions/codersdk.ProvisionerDaemon"
},
"warnings": {
"type": "array",
"items": {
"$ref": "#/definitions/health.Message"
}
}
}
},
"healthcheck.Report": {
"type": "object",
"properties": {

View File

@ -11933,10 +11933,10 @@
"error": {
"type": "string"
},
"provisioner_daemons": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.ProvisionerDaemon"
"$ref": "#/definitions/healthcheck.ProvisionerDaemonsReportItem"
}
},
"severity": {
@ -11950,6 +11950,20 @@
}
}
},
"healthcheck.ProvisionerDaemonsReportItem": {
"type": "object",
"properties": {
"provisioner_daemon": {
"$ref": "#/definitions/codersdk.ProvisionerDaemon"
},
"warnings": {
"type": "array",
"items": {
"$ref": "#/definitions/health.Message"
}
}
}
},
"healthcheck.Report": {
"type": "object",
"properties": {

View File

@ -2,6 +2,7 @@ package healthcheck
import (
"context"
"sort"
"time"
"golang.org/x/mod/semver"
@ -26,7 +27,13 @@ type ProvisionerDaemonsReport struct {
Dismissed bool `json:"dismissed"`
Error *string `json:"error"`
ProvisionerDaemons []codersdk.ProvisionerDaemon `json:"provisioner_daemons"`
Items []ProvisionerDaemonsReportItem `json:"items"`
}
// @typescript-generate ProvisionerDaemonsReportItem
type ProvisionerDaemonsReportItem struct {
codersdk.ProvisionerDaemon `json:"provisioner_daemon"`
Warnings []health.Message `json:"warnings"`
}
type ProvisionerDaemonsReportDeps struct {
@ -47,7 +54,7 @@ type ProvisionerDaemonsStore interface {
}
func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDaemonsReportDeps) {
r.ProvisionerDaemons = make([]codersdk.ProvisionerDaemon, 0)
r.Items = make([]ProvisionerDaemonsReportItem, 0)
r.Severity = health.SeverityOK
r.Warnings = make([]health.Message, 0)
r.Dismissed = opts.Dismissed
@ -86,6 +93,12 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae
r.Error = ptr.Ref("error fetching provisioner daemons: " + err.Error())
return
}
// Ensure stable order for display and for tests
sort.Slice(daemons, func(i, j int) bool {
return daemons[i].Name < daemons[j].Name
})
for _, daemon := range daemons {
// Daemon never connected, skip.
if !daemon.LastSeenAt.Valid {
@ -96,19 +109,24 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae
continue
}
r.ProvisionerDaemons = append(r.ProvisionerDaemons, db2sdk.ProvisionerDaemon(daemon))
it := ProvisionerDaemonsReportItem{
ProvisionerDaemon: db2sdk.ProvisionerDaemon(daemon),
Warnings: make([]health.Message, 0),
}
// For release versions, just check MAJOR.MINOR and ignore patch.
if !semver.IsValid(daemon.Version) {
if r.Severity.Value() < health.SeverityError.Value() {
r.Severity = health.SeverityError
}
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Provisioner daemon %q reports invalid version %q", opts.CurrentVersion, daemon.Version))
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Some provisioner daemons report invalid version information."))
it.Warnings = append(it.Warnings, health.Messagef(health.CodeUnknown, "Invalid version %q", daemon.Version))
} else if !buildinfo.VersionsMatch(opts.CurrentVersion, daemon.Version) {
if r.Severity.Value() < health.SeverityWarning.Value() {
r.Severity = health.SeverityWarning
}
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Provisioner daemon %q has outdated version %q", daemon.Name, daemon.Version))
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Some provisioner daemons report mismatched versions."))
it.Warnings = append(it.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Mismatched version %q", daemon.Version))
}
// Provisioner daemon API version follows different rules; we just want to check the major API version and
@ -119,16 +137,20 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae
if r.Severity.Value() < health.SeverityError.Value() {
r.Severity = health.SeverityError
}
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Provisioner daemon %q reports invalid API version: %s", daemon.Name, err.Error()))
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Some provisioner daemons report invalid API version information."))
it.Warnings = append(it.Warnings, health.Messagef(health.CodeUnknown, "Invalid API version: %s", err.Error())) // contains version string
} else if maj != opts.CurrentAPIMajorVersion {
if r.Severity.Value() < health.SeverityWarning.Value() {
r.Severity = health.SeverityWarning
}
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Provisioner daemon %q reports deprecated major API version %d. Consider upgrading!", daemon.Name, provisionersdk.CurrentMajor))
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Some provisioner daemons report deprecated major API versions. Consider upgrading!"))
it.Warnings = append(it.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Deprecated major API version %d.", provisionersdk.CurrentMajor))
}
r.Items = append(r.Items, it)
}
if len(r.ProvisionerDaemons) == 0 {
if len(r.Items) == 0 {
r.Severity = health.SeverityError
r.Error = ptr.Ref("No active provisioner daemons found!")
return

View File

@ -14,6 +14,7 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/healthcheck"
"github.com/coder/coder/v2/coderd/healthcheck/health"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisionersdk"
gomock "go.uber.org/mock/gomock"
@ -22,6 +23,8 @@ import (
func TestProvisionerDaemonReport(t *testing.T) {
t.Parallel()
now := dbtime.Now()
for _, tt := range []struct {
name string
currentVersion string
@ -31,12 +34,14 @@ func TestProvisionerDaemonReport(t *testing.T) {
expectedSeverity health.Severity
expectedWarningCode health.Code
expectedError string
expectedItems []healthcheck.ProvisionerDaemonsReportItem
}{
{
name: "current version empty",
currentVersion: "",
expectedSeverity: health.SeverityError,
expectedError: "Developer error: CurrentVersion is empty",
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{},
},
{
name: "no daemons",
@ -44,6 +49,7 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityError,
expectedError: "No active provisioner daemons found!",
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{},
},
{
name: "error fetching daemons",
@ -52,13 +58,29 @@ func TestProvisionerDaemonReport(t *testing.T) {
provisionerDaemonsErr: assert.AnError,
expectedSeverity: health.SeverityError,
expectedError: assert.AnError.Error(),
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{},
},
{
name: "one daemon up to date",
currentVersion: "v1.2.3",
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityOK,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-ok",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.2.3",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{},
},
},
},
{
name: "one daemon out of date",
@ -66,7 +88,27 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityWarning,
expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-old",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.1.2",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeProvisionerDaemonVersionMismatch,
Message: `Mismatched version "v1.1.2"`,
},
},
},
},
},
{
name: "invalid daemon version",
@ -74,7 +116,27 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityError,
expectedWarningCode: health.CodeUnknown,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-invalid-version", "invalid", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-invalid-version", "invalid", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-invalid-version",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "invalid",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeUnknown,
Message: `Invalid version "invalid"`,
},
},
},
},
},
{
name: "invalid daemon api version",
@ -82,7 +144,27 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityError,
expectedWarningCode: health.CodeUnknown,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-new-minor", "v1.2.3", "invalid")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-invalid-api", "v1.2.3", "invalid", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-invalid-api",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.2.3",
APIVersion: "invalid",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeUnknown,
Message: `Invalid API version: invalid version string: invalid`,
},
},
},
},
},
{
name: "api version backward compat",
@ -90,7 +172,27 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: 2,
expectedSeverity: health.SeverityWarning,
expectedWarningCode: health.CodeProvisionerDaemonAPIMajorVersionDeprecated,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old-api", "v2.3.4", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old-api", "v2.3.4", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-old-api",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v2.3.4",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeProvisionerDaemonAPIMajorVersionDeprecated,
Message: "Deprecated major API version 1.",
},
},
},
},
},
{
name: "one up to date, one out of date",
@ -98,7 +200,40 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityWarning,
expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0"), fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now), fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-ok",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.2.3",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{},
},
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-old",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.1.2",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeProvisionerDaemonVersionMismatch,
Message: `Mismatched version "v1.1.2"`,
},
},
},
},
},
{
name: "one up to date, one newer",
@ -106,14 +241,62 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityWarning,
expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0"), fakeProvisionerDaemon(t, "pd-new", "v2.3.4", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now), fakeProvisionerDaemon(t, "pd-new", "v2.3.4", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-new",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v2.3.4",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{
{
Code: health.CodeProvisionerDaemonVersionMismatch,
Message: `Mismatched version "v2.3.4"`,
},
},
},
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-ok",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v1.2.3",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{},
},
},
},
{
name: "one up to date, one stale older",
currentVersion: "v2.3.4",
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityOK,
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-ok", "v1.2.3", "0.9", dbtime.Now().Add(-5*time.Minute)), fakeProvisionerDaemon(t, "pd-new", "v2.3.4", "1.0")},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-stale", "v1.2.3", "0.9", now.Add(-5*time.Minute), now), fakeProvisionerDaemon(t, "pd-ok", "v2.3.4", "1.0", now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{
{
ProvisionerDaemon: codersdk.ProvisionerDaemon{
ID: uuid.Nil,
Name: "pd-ok",
CreatedAt: now,
LastSeenAt: codersdk.NewNullTime(now, true),
Version: "v2.3.4",
APIVersion: "1.0",
Provisioners: []codersdk.ProvisionerType{codersdk.ProvisionerTypeEcho, codersdk.ProvisionerTypeTerraform},
Tags: map[string]string{},
},
Warnings: []health.Message{},
},
},
},
{
name: "one stale",
@ -121,7 +304,8 @@ func TestProvisionerDaemonReport(t *testing.T) {
currentAPIMajorVersion: provisionersdk.CurrentMajor,
expectedSeverity: health.SeverityError,
expectedError: "No active provisioner daemons found!",
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-ok", "v1.2.3", "0.9", dbtime.Now().Add(-5*time.Minute))},
provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-ok", "v1.2.3", "0.9", now.Add(-5*time.Minute), now)},
expectedItems: []healthcheck.ProvisionerDaemonsReportItem{},
},
} {
tt := tt
@ -135,7 +319,6 @@ func TestProvisionerDaemonReport(t *testing.T) {
if tt.currentAPIMajorVersion == 0 {
deps.CurrentAPIMajorVersion = provisionersdk.CurrentMajor
}
now := dbtime.Now()
deps.TimeNow = func() time.Time {
return now
}
@ -163,17 +346,20 @@ func TestProvisionerDaemonReport(t *testing.T) {
if tt.expectedError != "" && assert.NotNil(t, rpt.Error) {
assert.Contains(t, *rpt.Error, tt.expectedError)
}
if tt.expectedItems != nil {
assert.Equal(t, tt.expectedItems, rpt.Items)
}
})
}
}
func fakeProvisionerDaemon(t *testing.T, name, version, apiVersion string) database.ProvisionerDaemon {
func fakeProvisionerDaemon(t *testing.T, name, version, apiVersion string, now time.Time) database.ProvisionerDaemon {
t.Helper()
return database.ProvisionerDaemon{
ID: uuid.New(),
ID: uuid.Nil,
Name: name,
CreatedAt: dbtime.Now(),
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
CreatedAt: now,
LastSeenAt: sql.NullTime{Time: now, Valid: true},
Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho, database.ProvisionerTypeTerraform},
ReplicaID: uuid.NullUUID{},
Tags: map[string]string{},
@ -182,9 +368,9 @@ func fakeProvisionerDaemon(t *testing.T, name, version, apiVersion string) datab
}
}
func fakeProvisionerDaemonStale(t *testing.T, name, version, apiVersion string, lastSeenAt time.Time) database.ProvisionerDaemon {
func fakeProvisionerDaemonStale(t *testing.T, name, version, apiVersion string, lastSeenAt, now time.Time) database.ProvisionerDaemon {
t.Helper()
d := fakeProvisionerDaemon(t, name, version, apiVersion)
d := fakeProvisionerDaemon(t, name, version, apiVersion, now)
d.LastSeenAt.Valid = true
d.LastSeenAt.Time = lastSeenAt
return d

30
docs/api/debug.md generated
View File

@ -285,19 +285,27 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \
"provisioner_daemons": {
"dismissed": true,
"error": "string",
"provisioner_daemons": [
"items": [
{
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
"provisioner_daemon": {
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
},
"version": "string"
},
"version": "string"
"warnings": [
{
"code": "EUNKNOWN",
"message": "string"
}
]
}
],
"severity": "ok",

107
docs/api/schemas.md generated
View File

@ -7900,19 +7900,27 @@ If the schedule is empty, the user will be updated to use the default schedule.|
{
"dismissed": true,
"error": "string",
"provisioner_daemons": [
"items": [
{
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
"provisioner_daemon": {
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
},
"version": "string"
},
"version": "string"
"warnings": [
{
"code": "EUNKNOWN",
"message": "string"
}
]
}
],
"severity": "ok",
@ -7927,13 +7935,46 @@ If the schedule is empty, the user will be updated to use the default schedule.|
### Properties
| Name | Type | Required | Restrictions | Description |
| --------------------- | ----------------------------------------------------------------- | -------- | ------------ | ----------- |
| `dismissed` | boolean | false | | |
| `error` | string | false | | |
| `provisioner_daemons` | array of [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false | | |
| `severity` | [health.Severity](#healthseverity) | false | | |
| `warnings` | array of [health.Message](#healthmessage) | false | | |
| Name | Type | Required | Restrictions | Description |
| ----------- | --------------------------------------------------------------------------------------------- | -------- | ------------ | ----------- |
| `dismissed` | boolean | false | | |
| `error` | string | false | | |
| `items` | array of [healthcheck.ProvisionerDaemonsReportItem](#healthcheckprovisionerdaemonsreportitem) | false | | |
| `severity` | [health.Severity](#healthseverity) | false | | |
| `warnings` | array of [health.Message](#healthmessage) | false | | |
## healthcheck.ProvisionerDaemonsReportItem
```json
{
"provisioner_daemon": {
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
},
"version": "string"
},
"warnings": [
{
"code": "EUNKNOWN",
"message": "string"
}
]
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
| -------------------- | -------------------------------------------------------- | -------- | ------------ | ----------- |
| `provisioner_daemon` | [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false | | |
| `warnings` | array of [health.Message](#healthmessage) | false | | |
## healthcheck.Report
@ -8179,19 +8220,27 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"provisioner_daemons": {
"dismissed": true,
"error": "string",
"provisioner_daemons": [
"items": [
{
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
"provisioner_daemon": {
"api_version": "string",
"created_at": "2019-08-24T14:15:22Z",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"name": "string",
"provisioners": ["string"],
"tags": {
"property1": "string",
"property2": "string"
},
"version": "string"
},
"version": "string"
"warnings": [
{
"code": "EUNKNOWN",
"message": "string"
}
]
}
],
"severity": "ok",

View File

@ -2211,7 +2211,13 @@ export interface HealthcheckProvisionerDaemonsReport {
readonly warnings: HealthMessage[];
readonly dismissed: boolean;
readonly error?: string;
readonly provisioner_daemons: ProvisionerDaemon[];
readonly items: HealthcheckProvisionerDaemonsReportItem[];
}
// From healthcheck/provisioner.go
export interface HealthcheckProvisionerDaemonsReportItem {
readonly provisioner_daemon: ProvisionerDaemon;
readonly warnings: HealthMessage[];
}
// From healthcheck/healthcheck.go

View File

@ -3105,19 +3105,22 @@ export const MockHealth: TypesGen.HealthcheckReport = {
severity: "ok",
warnings: [],
dismissed: false,
provisioner_daemons: [
items: [
{
id: "e455b582-ac04-4323-9ad6-ab71301fa006",
created_at: "2024-01-04T15:53:03.21563Z",
last_seen_at: "2024-01-04T16:05:03.967551Z",
name: "vvuurrkk-2",
version: "v2.6.0-devel+965ad5e96",
api_version: "1.0",
provisioners: ["echo", "terraform"],
tags: {
owner: "",
scope: "organization",
provisioner_daemon: {
id: "e455b582-ac04-4323-9ad6-ab71301fa006",
created_at: "2024-01-04T15:53:03.21563Z",
last_seen_at: "2024-01-04T16:05:03.967551Z",
name: "vvuurrkk-2",
version: "v2.6.0-devel+965ad5e96",
api_version: "1.0",
provisioners: ["echo", "terraform"],
tags: {
owner: "",
scope: "organization",
},
},
warnings: [],
},
],
},
@ -3211,10 +3214,37 @@ export const DeploymentHealthUnhealthy: TypesGen.HealthcheckReport = {
},
provisioner_daemons: {
severity: "error",
error: "something went wrong lol",
warnings: [],
error: "something went wrong",
warnings: [
{
message: "this is a message",
code: "EUNKNOWN",
},
],
dismissed: false,
provisioner_daemons: [],
items: [
{
provisioner_daemon: {
id: "e455b582-ac04-4323-9ad6-ab71301fa006",
created_at: "2024-01-04T15:53:03.21563Z",
last_seen_at: "2024-01-04T16:05:03.967551Z",
name: "vvuurrkk-2",
version: "v2.6.0-devel+965ad5e96",
api_version: "1.0",
provisioners: ["echo", "terraform"],
tags: {
owner: "",
scope: "organization",
},
},
warnings: [
{
message: "this is a specific message for this thing",
code: "EUNKNOWN",
},
],
},
],
},
};