Skip to content

Commit 93cf5dc

Browse files
authored
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
1 parent f4393d0 commit 93cf5dc

File tree

8 files changed

+412
-83
lines changed

8 files changed

+412
-83
lines changed

coderd/apidoc/docs.go

Lines changed: 16 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 16 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/healthcheck/provisioner.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package healthcheck
22

33
import (
44
"context"
5+
"sort"
56
"time"
67

78
"golang.org/x/mod/semver"
@@ -26,7 +27,13 @@ type ProvisionerDaemonsReport struct {
2627
Dismissed bool `json:"dismissed"`
2728
Error *string `json:"error"`
2829

29-
ProvisionerDaemons []codersdk.ProvisionerDaemon `json:"provisioner_daemons"`
30+
Items []ProvisionerDaemonsReportItem `json:"items"`
31+
}
32+
33+
// @typescript-generate ProvisionerDaemonsReportItem
34+
type ProvisionerDaemonsReportItem struct {
35+
codersdk.ProvisionerDaemon `json:"provisioner_daemon"`
36+
Warnings []health.Message `json:"warnings"`
3037
}
3138

3239
type ProvisionerDaemonsReportDeps struct {
@@ -47,7 +54,7 @@ type ProvisionerDaemonsStore interface {
4754
}
4855

4956
func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDaemonsReportDeps) {
50-
r.ProvisionerDaemons = make([]codersdk.ProvisionerDaemon, 0)
57+
r.Items = make([]ProvisionerDaemonsReportItem, 0)
5158
r.Severity = health.SeverityOK
5259
r.Warnings = make([]health.Message, 0)
5360
r.Dismissed = opts.Dismissed
@@ -86,6 +93,12 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae
8693
r.Error = ptr.Ref("error fetching provisioner daemons: " + err.Error())
8794
return
8895
}
96+
97+
// Ensure stable order for display and for tests
98+
sort.Slice(daemons, func(i, j int) bool {
99+
return daemons[i].Name < daemons[j].Name
100+
})
101+
89102
for _, daemon := range daemons {
90103
// Daemon never connected, skip.
91104
if !daemon.LastSeenAt.Valid {
@@ -96,19 +109,24 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae
96109
continue
97110
}
98111

99-
r.ProvisionerDaemons = append(r.ProvisionerDaemons, db2sdk.ProvisionerDaemon(daemon))
112+
it := ProvisionerDaemonsReportItem{
113+
ProvisionerDaemon: db2sdk.ProvisionerDaemon(daemon),
114+
Warnings: make([]health.Message, 0),
115+
}
100116

101117
// For release versions, just check MAJOR.MINOR and ignore patch.
102118
if !semver.IsValid(daemon.Version) {
103119
if r.Severity.Value() < health.SeverityError.Value() {
104120
r.Severity = health.SeverityError
105121
}
106-
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Provisioner daemon %q reports invalid version %q", opts.CurrentVersion, daemon.Version))
122+
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Some provisioner daemons report invalid version information."))
123+
it.Warnings = append(it.Warnings, health.Messagef(health.CodeUnknown, "Invalid version %q", daemon.Version))
107124
} else if !buildinfo.VersionsMatch(opts.CurrentVersion, daemon.Version) {
108125
if r.Severity.Value() < health.SeverityWarning.Value() {
109126
r.Severity = health.SeverityWarning
110127
}
111-
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Provisioner daemon %q has outdated version %q", daemon.Name, daemon.Version))
128+
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Some provisioner daemons report mismatched versions."))
129+
it.Warnings = append(it.Warnings, health.Messagef(health.CodeProvisionerDaemonVersionMismatch, "Mismatched version %q", daemon.Version))
112130
}
113131

114132
// 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
119137
if r.Severity.Value() < health.SeverityError.Value() {
120138
r.Severity = health.SeverityError
121139
}
122-
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Provisioner daemon %q reports invalid API version: %s", daemon.Name, err.Error()))
140+
r.Warnings = append(r.Warnings, health.Messagef(health.CodeUnknown, "Some provisioner daemons report invalid API version information."))
141+
it.Warnings = append(it.Warnings, health.Messagef(health.CodeUnknown, "Invalid API version: %s", err.Error())) // contains version string
123142
} else if maj != opts.CurrentAPIMajorVersion {
124143
if r.Severity.Value() < health.SeverityWarning.Value() {
125144
r.Severity = health.SeverityWarning
126145
}
127-
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Provisioner daemon %q reports deprecated major API version %d. Consider upgrading!", daemon.Name, provisionersdk.CurrentMajor))
146+
r.Warnings = append(r.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Some provisioner daemons report deprecated major API versions. Consider upgrading!"))
147+
it.Warnings = append(it.Warnings, health.Messagef(health.CodeProvisionerDaemonAPIMajorVersionDeprecated, "Deprecated major API version %d.", provisionersdk.CurrentMajor))
128148
}
149+
150+
r.Items = append(r.Items, it)
129151
}
130152

131-
if len(r.ProvisionerDaemons) == 0 {
153+
if len(r.Items) == 0 {
132154
r.Severity = health.SeverityError
133155
r.Error = ptr.Ref("No active provisioner daemons found!")
134156
return

0 commit comments

Comments
 (0)