@@ -2,6 +2,7 @@ package healthcheck
22
33import (
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
3239type ProvisionerDaemonsReportDeps struct {
@@ -47,7 +54,7 @@ type ProvisionerDaemonsStore interface {
4754}
4855
4956func (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