mirror of https://github.com/coder/coder.git
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:
parent
f4393d0c3f
commit
93cf5dcd47
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue