From 3fa77cea3e9317ab40794a6891db8c552277c567 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 15 Apr 2024 14:44:57 +0100 Subject: [PATCH 01/10] refactor(codersdk): extract common fields from HealthReport and friends --- coderd/debug_test.go | 2 +- coderd/healthcheck/derphealth/derp.go | 6 +- coderd/healthcheck/healthcheck_test.go | 380 +++++++++++++++++-------- coderd/healthcheck/websocket.go | 2 +- codersdk/healthsdk/healthsdk.go | 98 +++---- 5 files changed, 299 insertions(+), 189 deletions(-) diff --git a/coderd/debug_test.go b/coderd/debug_test.go index 0d5dfd1885f12..ac87583218676 100644 --- a/coderd/debug_test.go +++ b/coderd/debug_test.go @@ -213,7 +213,7 @@ func TestDebugHealth(t *testing.T) { return &healthsdk.HealthcheckReport{ Time: time.Now(), Healthy: true, - DERP: healthsdk.DERPHealthReport{Healthy: true}, + DERP: healthsdk.DERPHealthReport{BaseReport: healthsdk.BaseReport{Healthy: true}}, } }, }) diff --git a/coderd/healthcheck/derphealth/derp.go b/coderd/healthcheck/derphealth/derp.go index e72c527d700c4..b114531350895 100644 --- a/coderd/healthcheck/derphealth/derp.go +++ b/coderd/healthcheck/derphealth/derp.go @@ -133,8 +133,10 @@ func (r *RegionReport) Run(ctx context.Context) { node = node nodeReport = NodeReport{ DERPNodeReport: healthsdk.DERPNodeReport{ - Node: node, - Healthy: true, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + }, + Node: node, }, } ) diff --git a/coderd/healthcheck/healthcheck_test.go b/coderd/healthcheck/healthcheck_test.go index bb5cd581dbf9c..47abaf45e45f8 100644 --- a/coderd/healthcheck/healthcheck_test.go +++ b/coderd/healthcheck/healthcheck_test.go @@ -58,27 +58,39 @@ func TestHealthcheck(t *testing.T) { name: "OK", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: true, @@ -88,27 +100,39 @@ func TestHealthcheck(t *testing.T) { name: "DERPFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: false, @@ -118,28 +142,40 @@ func TestHealthcheck(t *testing.T) { name: "DERPWarning", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, - Severity: health.SeverityWarning, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, + Severity: health.SeverityWarning, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: true, @@ -149,27 +185,39 @@ func TestHealthcheck(t *testing.T) { name: "AccessURLFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: false, - Severity: health.SeverityWarning, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityWarning, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: false, @@ -179,27 +227,39 @@ func TestHealthcheck(t *testing.T) { name: "WebsocketFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: false, @@ -209,27 +269,39 @@ func TestHealthcheck(t *testing.T) { name: "DatabaseFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, healthy: false, @@ -239,27 +311,39 @@ func TestHealthcheck(t *testing.T) { name: "ProxyFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, severity: health.SeverityError, @@ -269,28 +353,40 @@ func TestHealthcheck(t *testing.T) { name: "ProxyWarn", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, - Severity: health.SeverityWarning, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, + Severity: health.SeverityWarning, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityOK, + }, }, }, severity: health.SeverityWarning, @@ -300,27 +396,39 @@ func TestHealthcheck(t *testing.T) { name: "ProvisionerDaemonsFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityError, + }, }, }, severity: health.SeverityError, @@ -330,28 +438,40 @@ func TestHealthcheck(t *testing.T) { name: "ProvisionerDaemonsWarn", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: true, - Severity: health.SeverityOK, + BaseReport: healthsdk.BaseReport{ + Healthy: true, + Severity: health.SeverityOK, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityWarning, - Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityWarning, + Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, + }, }, }, severity: health.SeverityWarning, @@ -362,27 +482,39 @@ func TestHealthcheck(t *testing.T) { healthy: false, checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, AccessURLReport: healthsdk.AccessURLReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, WebsocketReport: healthsdk.WebsocketReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, DatabaseReport: healthsdk.DatabaseReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ - Healthy: false, - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Healthy: false, + Severity: health.SeverityError, + }, }, ProvisionerDaemonsReport: healthsdk.ProvisionerDaemonsReport{ - Severity: health.SeverityError, + BaseReport: healthsdk.BaseReport{ + Severity: health.SeverityError, + }, }, }, severity: health.SeverityError, diff --git a/coderd/healthcheck/websocket.go b/coderd/healthcheck/websocket.go index 75ee3cdf05c58..f195b01f0f569 100644 --- a/coderd/healthcheck/websocket.go +++ b/coderd/healthcheck/websocket.go @@ -31,7 +31,7 @@ func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions) defer cancel() r.Severity = health.SeverityOK - r.Warnings = []string{} + r.Warnings = []health.Message{} r.Dismissed = opts.Dismissed u, err := opts.AccessURL.Parse("/api/v2/debug/ws") diff --git a/codersdk/healthsdk/healthsdk.go b/codersdk/healthsdk/healthsdk.go index 26e72e4e5f5d8..212a9b555b2fe 100644 --- a/codersdk/healthsdk/healthsdk.go +++ b/codersdk/healthsdk/healthsdk.go @@ -95,6 +95,7 @@ func (c *HealthClient) PutHealthSettings(ctx context.Context, settings HealthSet return nil } +// HealthcheckReport contains information about the health status of a Coder deployment. type HealthcheckReport struct { // Time is the time the report was generated at. Time time.Time `json:"time" format:"date-time"` @@ -117,52 +118,44 @@ type HealthcheckReport struct { CoderVersion string `json:"coder_version"` } -type AccessURLReport struct { +// BaseReport holds fields common to various health reports. +type BaseReport struct { // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. Healthy bool `json:"healthy"` + Error *string `json:"error"` Severity health.Severity `json:"severity" enums:"ok,warning,error"` Warnings []health.Message `json:"warnings"` Dismissed bool `json:"dismissed"` +} - AccessURL string `json:"access_url"` - Reachable bool `json:"reachable"` - StatusCode int `json:"status_code"` - HealthzResponse string `json:"healthz_response"` - Error *string `json:"error"` +// AccessURLReport shows the results of performing a HTTP_GET to the /healthz endpoint through the configured access URL. +type AccessURLReport struct { + BaseReport + AccessURL string `json:"access_url"` + Reachable bool `json:"reachable"` + StatusCode int `json:"status_code"` + HealthzResponse string `json:"healthz_response"` } +// DERPHealthReport includes health details of each configured DERP/STUN region. type DERPHealthReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - Warnings []health.Message `json:"warnings"` - Dismissed bool `json:"dismissed"` - - Regions map[int]*DERPRegionReport `json:"regions"` - - Netcheck *netcheck.Report `json:"netcheck"` - NetcheckErr *string `json:"netcheck_err"` - NetcheckLogs []string `json:"netcheck_logs"` - - Error *string `json:"error"` + BaseReport + Regions map[int]*DERPRegionReport `json:"regions"` + Netcheck *netcheck.Report `json:"netcheck"` + NetcheckErr *string `json:"netcheck_err"` + NetcheckLogs []string `json:"netcheck_logs"` } +// DERPHealthReport includes health details of each node in a single region. type DERPRegionReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - Warnings []health.Message `json:"warnings"` - + BaseReport Region *tailcfg.DERPRegion `json:"region"` NodeReports []*DERPNodeReport `json:"node_reports"` - Error *string `json:"error"` } +// DERPHealthReport includes health details of a single node in a single region. type DERPNodeReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - Warnings []health.Message `json:"warnings"` + BaseReport Node *tailcfg.DERPNode `json:"node"` @@ -173,37 +166,29 @@ type DERPNodeReport struct { UsesWebsocket bool `json:"uses_websocket"` ClientLogs [][]string `json:"client_logs"` ClientErrs [][]string `json:"client_errs"` - Error *string `json:"error"` STUN STUNReport `json:"stun"` } +// STUNReport contains information about a given node's STUN capabilities. type STUNReport struct { Enabled bool CanSTUN bool Error *string } +// DatabaseReport shows the results of pinging the configured database.Conn. type DatabaseReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - Warnings []health.Message `json:"warnings"` - Dismissed bool `json:"dismissed"` - - Reachable bool `json:"reachable"` - Latency string `json:"latency"` - LatencyMS int64 `json:"latency_ms"` - ThresholdMS int64 `json:"threshold_ms"` - Error *string `json:"error"` + BaseReport + Reachable bool `json:"reachable"` + Latency string `json:"latency"` + LatencyMS int64 `json:"latency_ms"` + ThresholdMS int64 `json:"threshold_ms"` } +// ProvisionerDaemonsReport includes health details of each connected provisioner daemon. type ProvisionerDaemonsReport struct { - Severity health.Severity `json:"severity"` - Warnings []health.Message `json:"warnings"` - Dismissed bool `json:"dismissed"` - Error *string `json:"error"` - + BaseReport Items []ProvisionerDaemonsReportItem `json:"items"` } @@ -212,24 +197,15 @@ type ProvisionerDaemonsReportItem struct { Warnings []health.Message `json:"warnings"` } +// WebsocketReport shows if the configured access URL allows establishing WebSocket connections. type WebsocketReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - Warnings []string `json:"warnings"` - Dismissed bool `json:"dismissed"` - - Body string `json:"body"` - Code int `json:"code"` - Error *string `json:"error"` + BaseReport + Body string `json:"body"` + Code int `json:"code"` } +// WorkspaceProxyReport includes health details of each connected workspace proxy. type WorkspaceProxyReport struct { - Healthy bool `json:"healthy"` - Severity health.Severity `json:"severity"` - Warnings []health.Message `json:"warnings"` - Dismissed bool `json:"dismissed"` - Error *string `json:"error"` - + BaseReport WorkspaceProxies codersdk.RegionsResponse[codersdk.WorkspaceProxy] `json:"workspace_proxies"` } From 185a915e6ea35f42a562456c8434f70cb365ce38 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 15 Apr 2024 15:36:57 +0100 Subject: [PATCH 02/10] feat(codersdk/healthsdk): add Summarize() method --- codersdk/healthsdk/healthsdk.go | 43 +++++++++ codersdk/healthsdk/healthsdk_test.go | 127 +++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 codersdk/healthsdk/healthsdk_test.go diff --git a/codersdk/healthsdk/healthsdk.go b/codersdk/healthsdk/healthsdk.go index 212a9b555b2fe..47478023f0500 100644 --- a/codersdk/healthsdk/healthsdk.go +++ b/codersdk/healthsdk/healthsdk.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "strings" "time" "golang.org/x/xerrors" @@ -118,6 +119,18 @@ type HealthcheckReport struct { CoderVersion string `json:"coder_version"` } +// Summarize returns a summary of all errors and warnings of components of HealthcheckReport. +func (r *HealthcheckReport) Summarize() []string { + var msgs []string + msgs = append(msgs, r.AccessURL.Summarize("Access URL:")...) + msgs = append(msgs, r.Database.Summarize("Database:")...) + msgs = append(msgs, r.DERP.Summarize("DERP:")...) + msgs = append(msgs, r.ProvisionerDaemons.Summarize("Provisioner Daemons:")...) + msgs = append(msgs, r.Websocket.Summarize("Websocket:")...) + msgs = append(msgs, r.WorkspaceProxy.Summarize("Workspace Proxies:")...) + return msgs +} + // BaseReport holds fields common to various health reports. type BaseReport struct { // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. @@ -128,6 +141,36 @@ type BaseReport struct { Dismissed bool `json:"dismissed"` } +// Summarize returns a list of strings containing the errors and warnings of BaseReport, if present. +// All strings are prefixed with prefix. +func (b *BaseReport) Summarize(prefix string) []string { + if b == nil { + return []string{} + } + var msgs []string + if b.Error != nil { + var sb strings.Builder + if prefix != "" { + _, _ = sb.WriteString(prefix) + _, _ = sb.WriteString(" ") + } + _, _ = sb.WriteString("Error: ") + _, _ = sb.WriteString(*b.Error) + msgs = append(msgs, sb.String()) + } + for _, warn := range b.Warnings { + var sb strings.Builder + if prefix != "" { + _, _ = sb.WriteString(prefix) + _, _ = sb.WriteString(" ") + } + _, _ = sb.WriteString("Warn: ") + _, _ = sb.WriteString(warn.String()) + msgs = append(msgs, sb.String()) + } + return msgs +} + // AccessURLReport shows the results of performing a HTTP_GET to the /healthz endpoint through the configured access URL. type AccessURLReport struct { BaseReport diff --git a/codersdk/healthsdk/healthsdk_test.go b/codersdk/healthsdk/healthsdk_test.go new file mode 100644 index 0000000000000..d89c9991259ba --- /dev/null +++ b/codersdk/healthsdk/healthsdk_test.go @@ -0,0 +1,127 @@ +package healthsdk_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/coder/coder/v2/coderd/healthcheck/health" + "github.com/coder/coder/v2/coderd/util/ptr" + "github.com/coder/coder/v2/codersdk/healthsdk" +) + +func TestSummarize(t *testing.T) { + t.Parallel() + + t.Run("HealthcheckReport", func(t *testing.T) { + unhealthy := healthsdk.BaseReport{ + Error: ptr.Ref("test error"), + Warnings: []health.Message{{Code: "TEST", Message: "testing"}}, + } + hr := healthsdk.HealthcheckReport{ + AccessURL: healthsdk.AccessURLReport{ + BaseReport: unhealthy, + }, + Database: healthsdk.DatabaseReport{ + BaseReport: unhealthy, + }, + DERP: healthsdk.DERPHealthReport{ + BaseReport: unhealthy, + }, + ProvisionerDaemons: healthsdk.ProvisionerDaemonsReport{ + BaseReport: unhealthy, + }, + Websocket: healthsdk.WebsocketReport{ + BaseReport: unhealthy, + }, + WorkspaceProxy: healthsdk.WorkspaceProxyReport{ + BaseReport: unhealthy, + }, + } + expected := []string{ + "Access URL: Error: test error", + "Access URL: Warn: TEST: testing", + "Database: Error: test error", + "Database: Warn: TEST: testing", + "DERP: Error: test error", + "DERP: Warn: TEST: testing", + "Provisioner Daemons: Error: test error", + "Provisioner Daemons: Warn: TEST: testing", + "Websocket: Error: test error", + "Websocket: Warn: TEST: testing", + "Workspace Proxies: Error: test error", + "Workspace Proxies: Warn: TEST: testing", + } + actual := hr.Summarize() + assert.Equal(t, expected, actual) + }) + + for _, tt := range []struct { + name string + br healthsdk.BaseReport + pfx string + expected []string + }{ + { + name: "empty", + br: healthsdk.BaseReport{}, + pfx: "", + expected: []string{}, + }, + { + name: "no prefix", + br: healthsdk.BaseReport{ + Error: ptr.Ref("testing"), + Warnings: []health.Message{ + { + Code: "TEST01", + Message: "testing one", + }, + { + Code: "TEST02", + Message: "testing two", + }, + }, + }, + pfx: "", + expected: []string{ + "Error: testing", + "Warn: TEST01: testing one", + "Warn: TEST02: testing two", + }, + }, + { + name: "prefix", + br: healthsdk.BaseReport{ + Error: ptr.Ref("testing"), + Warnings: []health.Message{ + { + Code: "TEST01", + Message: "testing one", + }, + { + Code: "TEST02", + Message: "testing two", + }, + }, + }, + pfx: "TEST:", + expected: []string{ + "TEST: Error: testing", + "TEST: Warn: TEST01: testing one", + "TEST: Warn: TEST02: testing two", + }, + }, + } { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + actual := tt.br.Summarize(tt.pfx) + if len(tt.expected) == 0 { + assert.Empty(t, actual) + return + } + assert.Equal(t, tt.expected, actual) + }) + } +} From 2b205eccf82dcd95ace8b89df1d9084999a2add8 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 15 Apr 2024 15:37:24 +0100 Subject: [PATCH 03/10] feat(cli): support bundle: dump healthcheck summary --- cli/support.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cli/support.go b/cli/support.go index f2f962a358f1a..d2b94440773ca 100644 --- a/cli/support.go +++ b/cli/support.go @@ -184,6 +184,15 @@ func (r *RootCmd) supportBundle() *serpent.Command { _ = os.Remove(outputPath) // best effort return xerrors.Errorf("create support bundle: %w", err) } + deployHealthSummary := bun.Deployment.HealthReport.Summarize() + if len(deployHealthSummary) > 0 { + cliui.Warn(inv.Stdout, "Deployment health issues detected:", deployHealthSummary...) + } + clientNetcheckSummary := bun.Network.Netcheck.Summarize("Client netcheck:") + if len(clientNetcheckSummary) > 0 { + cliui.Warn(inv.Stdout, "Networking issues detected:", deployHealthSummary...) + } + bun.CLILogs = cliLogBuf.Bytes() if err := writeBundle(bun, zwr); err != nil { From e1cb6c591c784f836897a9b8398abcb5b032ed22 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 15 Apr 2024 15:59:17 +0100 Subject: [PATCH 04/10] make gen --- coderd/apidoc/docs.go | 35 +++++++++++-- coderd/apidoc/swagger.json | 27 ++++++++-- docs/api/debug.md | 12 ++++- docs/api/schemas.md | 94 ++++++++++++++++++++++++---------- site/src/api/typesGenerated.ts | 48 +++++------------ 5 files changed, 149 insertions(+), 67 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index bcd2b3b15ccd6..8a6b9f8c35d5b 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13603,6 +13603,9 @@ const docTemplate = `{ } } }, + "dismissed": { + "type": "boolean" + }, "error": { "type": "string" }, @@ -13651,6 +13654,9 @@ const docTemplate = `{ "healthsdk.DERPRegionReport": { "type": "object", "properties": { + "dismissed": { + "type": "boolean" + }, "error": { "type": "string" }, @@ -13827,6 +13833,10 @@ const docTemplate = `{ "error": { "type": "string" }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", + "type": "boolean" + }, "items": { "type": "array", "items": { @@ -13834,7 +13844,16 @@ const docTemplate = `{ } }, "severity": { - "$ref": "#/definitions/health.Severity" + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] }, "warnings": { "type": "array", @@ -13917,7 +13936,7 @@ const docTemplate = `{ "warnings": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/health.Message" } } } @@ -13932,10 +13951,20 @@ const docTemplate = `{ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", "type": "boolean" }, "severity": { - "$ref": "#/definitions/health.Severity" + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] }, "warnings": { "type": "array", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 47bac4fc4ecab..4746c1bd27a7a 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12359,6 +12359,9 @@ } } }, + "dismissed": { + "type": "boolean" + }, "error": { "type": "string" }, @@ -12403,6 +12406,9 @@ "healthsdk.DERPRegionReport": { "type": "object", "properties": { + "dismissed": { + "type": "boolean" + }, "error": { "type": "string" }, @@ -12567,6 +12573,10 @@ "error": { "type": "string" }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", + "type": "boolean" + }, "items": { "type": "array", "items": { @@ -12574,7 +12584,12 @@ } }, "severity": { - "$ref": "#/definitions/health.Severity" + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] }, "warnings": { "type": "array", @@ -12653,7 +12668,7 @@ "warnings": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/health.Message" } } } @@ -12668,10 +12683,16 @@ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", "type": "boolean" }, "severity": { - "$ref": "#/definitions/health.Severity" + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] }, "warnings": { "type": "array", diff --git a/docs/api/debug.md b/docs/api/debug.md index 917088de576ba..68b7c9bf01eea 100644 --- a/docs/api/debug.md +++ b/docs/api/debug.md @@ -116,6 +116,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "netcheck_logs": ["string"], "regions": { "property1": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -123,6 +124,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -194,6 +196,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ ] }, "property2": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -201,6 +204,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -285,6 +289,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "provisioner_daemons": { "dismissed": true, "error": "string", + "healthy": true, "items": [ { "provisioner_daemon": { @@ -325,7 +330,12 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "error": "string", "healthy": true, "severity": "ok", - "warnings": ["string"] + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] }, "workspace_proxy": { "dismissed": true, diff --git a/docs/api/schemas.md b/docs/api/schemas.md index efc3a38f01219..0ed3fe3e62c0f 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -7411,6 +7411,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "netcheck_logs": ["string"], "regions": { "property1": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7418,6 +7419,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7489,6 +7491,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| ] }, "property2": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7496,6 +7499,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7607,6 +7611,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7653,6 +7658,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `can_exchange_messages` | boolean | false | | | | `client_errs` | array of array | false | | | | `client_logs` | array of array | false | | | +| `dismissed` | boolean | false | | | | `error` | string | false | | | | `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | | `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | @@ -7676,6 +7682,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| ```json { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7683,6 +7690,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7759,6 +7767,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| | Name | Type | Required | Restrictions | Description | | -------------- | ------------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `dismissed` | boolean | false | | | | `error` | string | false | | | | `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | | `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false | | | @@ -7925,6 +7934,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "netcheck_logs": ["string"], "regions": { "property1": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7932,6 +7942,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -8003,6 +8014,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| ] }, "property2": { + "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -8010,6 +8022,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], + "dismissed": true, "error": "string", "healthy": true, "node": { @@ -8094,6 +8107,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "provisioner_daemons": { "dismissed": true, "error": "string", + "healthy": true, "items": [ { "provisioner_daemon": { @@ -8134,7 +8148,12 @@ If the schedule is empty, the user will be updated to use the default schedule.| "error": "string", "healthy": true, "severity": "ok", - "warnings": ["string"] + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] }, "workspace_proxy": { "dismissed": true, @@ -8208,6 +8227,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| { "dismissed": true, "error": "string", + "healthy": true, "items": [ { "provisioner_daemon": { @@ -8243,13 +8263,22 @@ 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 | | | -| `items` | array of [healthsdk.ProvisionerDaemonsReportItem](#healthsdkprovisionerdaemonsreportitem) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | +| Name | Type | Required | Restrictions | Description | +| ----------- | ----------------------------------------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `dismissed` | boolean | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `items` | array of [healthsdk.ProvisionerDaemonsReportItem](#healthsdkprovisionerdaemonsreportitem) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | ## healthsdk.ProvisionerDaemonsReportItem @@ -8326,21 +8355,26 @@ If the schedule is empty, the user will be updated to use the default schedule.| "error": "string", "healthy": true, "severity": "ok", - "warnings": ["string"] + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -| ----------- | ---------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | -| `body` | string | false | | | -| `code` | integer | false | | | -| `dismissed` | boolean | false | | | -| `error` | string | false | | | -| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of string | false | | | +| Name | Type | Required | Restrictions | Description | +| ----------- | ----------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `body` | string | false | | | +| `code` | integer | false | | | +| `dismissed` | boolean | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values @@ -8396,14 +8430,22 @@ 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 | | | -| `healthy` | boolean | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | -| `workspace_proxies` | [codersdk.RegionsResponse-codersdk_WorkspaceProxy](#codersdkregionsresponse-codersdk_workspaceproxy) | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------- | ---------------------------------------------------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `dismissed` | boolean | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | +| `workspace_proxies` | [codersdk.RegionsResponse-codersdk_WorkspaceProxy](#codersdkregionsresponse-codersdk_workspaceproxy) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | ## key.NodePublic diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index be751559f21d9..5c83d34f550de 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -2283,37 +2283,36 @@ export type RegionTypes = Region | WorkspaceProxy; // From healthsdk/healthsdk.go export interface AccessURLReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; + readonly BaseReport: BaseReport; readonly access_url: string; readonly reachable: boolean; readonly status_code: number; readonly healthz_response: string; - readonly error?: string; } // From healthsdk/healthsdk.go -export interface DERPHealthReport { +export interface BaseReport { readonly healthy: boolean; + readonly error?: string; readonly severity: HealthSeverity; readonly warnings: HealthMessage[]; readonly dismissed: boolean; +} + +// From healthsdk/healthsdk.go +export interface DERPHealthReport { + readonly BaseReport: BaseReport; readonly regions: Record; // Named type "tailscale.com/net/netcheck.Report" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly netcheck?: any; readonly netcheck_err?: string; readonly netcheck_logs: string[]; - readonly error?: string; } // From healthsdk/healthsdk.go export interface DERPNodeReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; + readonly BaseReport: BaseReport; // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly node?: any; @@ -2326,33 +2325,25 @@ export interface DERPNodeReport { readonly uses_websocket: boolean; readonly client_logs: string[][]; readonly client_errs: string[][]; - readonly error?: string; readonly stun: STUNReport; } // From healthsdk/healthsdk.go export interface DERPRegionReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; + readonly BaseReport: BaseReport; // Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly region?: any; readonly node_reports: DERPNodeReport[]; - readonly error?: string; } // From healthsdk/healthsdk.go export interface DatabaseReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; + readonly BaseReport: BaseReport; readonly reachable: boolean; readonly latency: string; readonly latency_ms: number; readonly threshold_ms: number; - readonly error?: string; } // From healthsdk/healthsdk.go @@ -2377,10 +2368,7 @@ export interface HealthcheckReport { // From healthsdk/healthsdk.go export interface ProvisionerDaemonsReport { - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; + readonly BaseReport: BaseReport; readonly items: ProvisionerDaemonsReportItem[]; } @@ -2404,22 +2392,14 @@ export interface UpdateHealthSettings { // From healthsdk/healthsdk.go export interface WebsocketReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: string[]; - readonly dismissed: boolean; + readonly BaseReport: BaseReport; readonly body: string; readonly code: number; - readonly error?: string; } // From healthsdk/healthsdk.go export interface WorkspaceProxyReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; + readonly BaseReport: BaseReport; readonly workspace_proxies: RegionsResponse; } From 2c412388021d54d485d23b71c2b28cb4097b461f Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 10:42:35 +0100 Subject: [PATCH 05/10] reduce diff size --- coderd/apidoc/docs.go | 12 --- coderd/apidoc/swagger.json | 12 --- coderd/healthcheck/derphealth/derp.go | 6 +- coderd/healthcheck/healthcheck_test.go | 110 ++++++++++++------------- codersdk/healthsdk/healthsdk.go | 22 ++++- docs/api/debug.md | 5 -- docs/api/schemas.md | 76 +++++++---------- scripts/apitypings/main.go | 3 +- site/src/api/typesGenerated.ts | 34 ++++---- 9 files changed, 126 insertions(+), 154 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8a6b9f8c35d5b..9e99cc7315146 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13603,14 +13603,10 @@ const docTemplate = `{ } } }, - "dismissed": { - "type": "boolean" - }, "error": { "type": "string" }, "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", "type": "boolean" }, "node": { @@ -13654,14 +13650,10 @@ const docTemplate = `{ "healthsdk.DERPRegionReport": { "type": "object", "properties": { - "dismissed": { - "type": "boolean" - }, "error": { "type": "string" }, "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", "type": "boolean" }, "node_reports": { @@ -13833,10 +13825,6 @@ const docTemplate = `{ "error": { "type": "string" }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", - "type": "boolean" - }, "items": { "type": "array", "items": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 4746c1bd27a7a..71d7f75e21c12 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12359,14 +12359,10 @@ } } }, - "dismissed": { - "type": "boolean" - }, "error": { "type": "string" }, "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", "type": "boolean" }, "node": { @@ -12406,14 +12402,10 @@ "healthsdk.DERPRegionReport": { "type": "object", "properties": { - "dismissed": { - "type": "boolean" - }, "error": { "type": "string" }, "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", "type": "boolean" }, "node_reports": { @@ -12573,10 +12565,6 @@ "error": { "type": "string" }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", - "type": "boolean" - }, "items": { "type": "array", "items": { diff --git a/coderd/healthcheck/derphealth/derp.go b/coderd/healthcheck/derphealth/derp.go index b114531350895..ac46582afcf09 100644 --- a/coderd/healthcheck/derphealth/derp.go +++ b/coderd/healthcheck/derphealth/derp.go @@ -133,10 +133,8 @@ func (r *RegionReport) Run(ctx context.Context) { node = node nodeReport = NodeReport{ DERPNodeReport: healthsdk.DERPNodeReport{ - BaseReport: healthsdk.BaseReport{ - Healthy: true, - }, - Node: node, + Healthy: true, + Node: node, }, } ) diff --git a/coderd/healthcheck/healthcheck_test.go b/coderd/healthcheck/healthcheck_test.go index 47abaf45e45f8..58fbe7305380d 100644 --- a/coderd/healthcheck/healthcheck_test.go +++ b/coderd/healthcheck/healthcheck_test.go @@ -58,32 +58,32 @@ func TestHealthcheck(t *testing.T) { name: "OK", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -100,32 +100,32 @@ func TestHealthcheck(t *testing.T) { name: "DERPFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -142,33 +142,33 @@ func TestHealthcheck(t *testing.T) { name: "DERPWarning", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, Severity: health.SeverityWarning, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -185,32 +185,32 @@ func TestHealthcheck(t *testing.T) { name: "AccessURLFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityWarning, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -227,32 +227,32 @@ func TestHealthcheck(t *testing.T) { name: "WebsocketFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -269,32 +269,32 @@ func TestHealthcheck(t *testing.T) { name: "DatabaseFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -311,32 +311,32 @@ func TestHealthcheck(t *testing.T) { name: "ProxyFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, @@ -353,32 +353,32 @@ func TestHealthcheck(t *testing.T) { name: "ProxyWarn", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, Severity: health.SeverityWarning, }, @@ -396,32 +396,32 @@ func TestHealthcheck(t *testing.T) { name: "ProvisionerDaemonsFail", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -438,32 +438,32 @@ func TestHealthcheck(t *testing.T) { name: "ProvisionerDaemonsWarn", checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: true, BaseReport: healthsdk.BaseReport{ - Healthy: true, Severity: health.SeverityOK, }, }, @@ -482,32 +482,32 @@ func TestHealthcheck(t *testing.T) { healthy: false, checker: &testChecker{ DERPReport: healthsdk.DERPHealthReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, AccessURLReport: healthsdk.AccessURLReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, WebsocketReport: healthsdk.WebsocketReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, DatabaseReport: healthsdk.DatabaseReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, WorkspaceProxyReport: healthsdk.WorkspaceProxyReport{ + Healthy: false, BaseReport: healthsdk.BaseReport{ - Healthy: false, Severity: health.SeverityError, }, }, diff --git a/codersdk/healthsdk/healthsdk.go b/codersdk/healthsdk/healthsdk.go index 47478023f0500..dec4a3555e2c7 100644 --- a/codersdk/healthsdk/healthsdk.go +++ b/codersdk/healthsdk/healthsdk.go @@ -133,8 +133,6 @@ func (r *HealthcheckReport) Summarize() []string { // BaseReport holds fields common to various health reports. type BaseReport struct { - // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. - Healthy bool `json:"healthy"` Error *string `json:"error"` Severity health.Severity `json:"severity" enums:"ok,warning,error"` Warnings []health.Message `json:"warnings"` @@ -174,6 +172,8 @@ func (b *BaseReport) Summarize(prefix string) []string { // AccessURLReport shows the results of performing a HTTP_GET to the /healthz endpoint through the configured access URL. type AccessURLReport struct { BaseReport + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. + Healthy bool `json:"healthy"` AccessURL string `json:"access_url"` Reachable bool `json:"reachable"` StatusCode int `json:"status_code"` @@ -183,6 +183,8 @@ type AccessURLReport struct { // DERPHealthReport includes health details of each configured DERP/STUN region. type DERPHealthReport struct { BaseReport + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. + Healthy bool `json:"healthy"` Regions map[int]*DERPRegionReport `json:"regions"` Netcheck *netcheck.Report `json:"netcheck"` NetcheckErr *string `json:"netcheck_err"` @@ -191,14 +193,20 @@ type DERPHealthReport struct { // DERPHealthReport includes health details of each node in a single region. type DERPRegionReport struct { - BaseReport + Healthy bool `json:"healthy"` + Severity health.Severity `json:"severity" enums:"ok,warning,error"` + Warnings []health.Message `json:"warnings"` + Error *string `json:"error"` Region *tailcfg.DERPRegion `json:"region"` NodeReports []*DERPNodeReport `json:"node_reports"` } // DERPHealthReport includes health details of a single node in a single region. type DERPNodeReport struct { - BaseReport + Healthy bool `json:"healthy"` + Severity health.Severity `json:"severity" enums:"ok,warning,error"` + Warnings []health.Message `json:"warnings"` + Error *string `json:"error"` Node *tailcfg.DERPNode `json:"node"` @@ -223,6 +231,8 @@ type STUNReport struct { // DatabaseReport shows the results of pinging the configured database.Conn. type DatabaseReport struct { BaseReport + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. + Healthy bool `json:"healthy"` Reachable bool `json:"reachable"` Latency string `json:"latency"` LatencyMS int64 `json:"latency_ms"` @@ -242,6 +252,8 @@ type ProvisionerDaemonsReportItem struct { // WebsocketReport shows if the configured access URL allows establishing WebSocket connections. type WebsocketReport struct { + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. + Healthy bool `json:"healthy"` BaseReport Body string `json:"body"` Code int `json:"code"` @@ -249,6 +261,8 @@ type WebsocketReport struct { // WorkspaceProxyReport includes health details of each connected workspace proxy. type WorkspaceProxyReport struct { + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. + Healthy bool `json:"healthy"` BaseReport WorkspaceProxies codersdk.RegionsResponse[codersdk.WorkspaceProxy] `json:"workspace_proxies"` } diff --git a/docs/api/debug.md b/docs/api/debug.md index 68b7c9bf01eea..0ae74b501210a 100644 --- a/docs/api/debug.md +++ b/docs/api/debug.md @@ -116,7 +116,6 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "netcheck_logs": ["string"], "regions": { "property1": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -124,7 +123,6 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -196,7 +194,6 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ ] }, "property2": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -204,7 +201,6 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -289,7 +285,6 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "provisioner_daemons": { "dismissed": true, "error": "string", - "healthy": true, "items": [ { "provisioner_daemon": { diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 0ed3fe3e62c0f..54e97deb3a7c8 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -7411,7 +7411,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "netcheck_logs": ["string"], "regions": { "property1": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7419,7 +7418,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7491,7 +7489,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| ] }, "property2": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7499,7 +7496,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7611,7 +7607,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7653,22 +7648,21 @@ If the schedule is empty, the user will be updated to use the default schedule.| ### Properties -| Name | Type | Required | Restrictions | Description | -| ----------------------- | ------------------------------------------------ | -------- | ------------ | ------------------------------------------------------------------------------------------- | -| `can_exchange_messages` | boolean | false | | | -| `client_errs` | array of array | false | | | -| `client_logs` | array of array | false | | | -| `dismissed` | boolean | false | | | -| `error` | string | false | | | -| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | -| `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | -| `node_info` | [derp.ServerInfoMessage](#derpserverinfomessage) | false | | | -| `round_trip_ping` | string | false | | | -| `round_trip_ping_ms` | integer | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `stun` | [healthsdk.STUNReport](#healthsdkstunreport) | false | | | -| `uses_websocket` | boolean | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | +| Name | Type | Required | Restrictions | Description | +| ----------------------- | ------------------------------------------------ | -------- | ------------ | ----------- | +| `can_exchange_messages` | boolean | false | | | +| `client_errs` | array of array | false | | | +| `client_logs` | array of array | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | | +| `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | +| `node_info` | [derp.ServerInfoMessage](#derpserverinfomessage) | false | | | +| `round_trip_ping` | string | false | | | +| `round_trip_ping_ms` | integer | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `stun` | [healthsdk.STUNReport](#healthsdkstunreport) | false | | | +| `uses_websocket` | boolean | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values @@ -7682,7 +7676,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| ```json { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7690,7 +7683,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -7765,15 +7757,14 @@ 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 | | | -| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | -| `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false | | | -| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | +| Name | Type | Required | Restrictions | Description | +| -------------- | ------------------------------------------------------------- | -------- | ------------ | ----------- | +| `error` | string | false | | | +| `healthy` | boolean | false | | | +| `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false | | | +| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values @@ -7934,7 +7925,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "netcheck_logs": ["string"], "regions": { "property1": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -7942,7 +7932,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -8014,7 +8003,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| ] }, "property2": { - "dismissed": true, "error": "string", "healthy": true, "node_reports": [ @@ -8022,7 +8010,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "can_exchange_messages": true, "client_errs": [["string"]], "client_logs": [["string"]], - "dismissed": true, "error": "string", "healthy": true, "node": { @@ -8107,7 +8094,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| "provisioner_daemons": { "dismissed": true, "error": "string", - "healthy": true, "items": [ { "provisioner_daemon": { @@ -8227,7 +8213,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| { "dismissed": true, "error": "string", - "healthy": true, "items": [ { "provisioner_daemon": { @@ -8263,14 +8248,13 @@ 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 | | | -| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | -| `items` | array of [healthsdk.ProvisionerDaemonsReportItem](#healthsdkprovisionerdaemonsreportitem) | 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 [healthsdk.ProvisionerDaemonsReportItem](#healthsdkprovisionerdaemonsreportitem) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 6107396eaa8e3..a672d388e0444 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -544,7 +544,8 @@ func (g *Generator) buildStruct(obj types.Object, st *types.Struct) (string, err tag := reflect.StructTag(st.Tag(i)) // Adding a json struct tag causes the json package to consider // the field unembedded. - if field.Embedded() && tag.Get("json") == "" && field.Pkg().Name() == "codersdk" { + // if field.Embedded() && tag.Get("json") == "" && field.Pkg().Name() == "codersdk" { + if field.Embedded() && tag.Get("json") == "" { extendedFields[i] = true extends = append(extends, field.Name()) } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 5c83d34f550de..374762fbce990 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -2282,8 +2282,8 @@ export type RegionTypes = Region | WorkspaceProxy; // The code below is generated from codersdk/healthsdk. // From healthsdk/healthsdk.go -export interface AccessURLReport { - readonly BaseReport: BaseReport; +export interface AccessURLReport extends BaseReport { + readonly healthy: boolean; readonly access_url: string; readonly reachable: boolean; readonly status_code: number; @@ -2292,7 +2292,6 @@ export interface AccessURLReport { // From healthsdk/healthsdk.go export interface BaseReport { - readonly healthy: boolean; readonly error?: string; readonly severity: HealthSeverity; readonly warnings: HealthMessage[]; @@ -2300,8 +2299,8 @@ export interface BaseReport { } // From healthsdk/healthsdk.go -export interface DERPHealthReport { - readonly BaseReport: BaseReport; +export interface DERPHealthReport extends BaseReport { + readonly healthy: boolean; readonly regions: Record; // Named type "tailscale.com/net/netcheck.Report" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type @@ -2312,7 +2311,10 @@ export interface DERPHealthReport { // From healthsdk/healthsdk.go export interface DERPNodeReport { - readonly BaseReport: BaseReport; + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly error?: string; // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly node?: any; @@ -2330,7 +2332,10 @@ export interface DERPNodeReport { // From healthsdk/healthsdk.go export interface DERPRegionReport { - readonly BaseReport: BaseReport; + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly error?: string; // Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly region?: any; @@ -2338,8 +2343,8 @@ export interface DERPRegionReport { } // From healthsdk/healthsdk.go -export interface DatabaseReport { - readonly BaseReport: BaseReport; +export interface DatabaseReport extends BaseReport { + readonly healthy: boolean; readonly reachable: boolean; readonly latency: string; readonly latency_ms: number; @@ -2367,8 +2372,7 @@ export interface HealthcheckReport { } // From healthsdk/healthsdk.go -export interface ProvisionerDaemonsReport { - readonly BaseReport: BaseReport; +export interface ProvisionerDaemonsReport extends BaseReport { readonly items: ProvisionerDaemonsReportItem[]; } @@ -2391,15 +2395,15 @@ export interface UpdateHealthSettings { } // From healthsdk/healthsdk.go -export interface WebsocketReport { - readonly BaseReport: BaseReport; +export interface WebsocketReport extends BaseReport { + readonly healthy: boolean; readonly body: string; readonly code: number; } // From healthsdk/healthsdk.go -export interface WorkspaceProxyReport { - readonly BaseReport: BaseReport; +export interface WorkspaceProxyReport extends BaseReport { + readonly healthy: boolean; readonly workspace_proxies: RegionsResponse; } From 16af4a61c71f24befb9cbfa19977dd79e3ff0c85 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 10:44:52 +0100 Subject: [PATCH 06/10] UI fixup --- site/src/pages/HealthPage/WebsocketPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/pages/HealthPage/WebsocketPage.tsx b/site/src/pages/HealthPage/WebsocketPage.tsx index 97fac9e867ad9..ddc37bc971330 100644 --- a/site/src/pages/HealthPage/WebsocketPage.tsx +++ b/site/src/pages/HealthPage/WebsocketPage.tsx @@ -41,8 +41,8 @@ export const WebsocketPage = () => { {websocket.warnings.map((warning) => { return ( - - {warning} + + {warning.message} ); })} From 60295adec17fcad2748b781713dcc211562f8e53 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 11:42:43 +0100 Subject: [PATCH 07/10] fixup! Merge remote-tracking branch 'origin/main' into cj/healthreport-summarize --- site/src/api/typesGenerated.ts | 62 ++-------------------------------- 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 8451c4c189261..13971a03457fb 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -2284,12 +2284,6 @@ export type RegionTypes = Region | WorkspaceProxy; // From healthsdk/healthsdk.go export interface AccessURLReport extends BaseReport { readonly healthy: boolean; -<<<<<<< HEAD -======= - readonly severity: HealthSeverity; - readonly warnings: readonly HealthMessage[]; - readonly dismissed: boolean; ->>>>>>> origin/main readonly access_url: string; readonly reachable: boolean; readonly status_code: number; @@ -2312,24 +2306,15 @@ export interface DERPHealthReport extends BaseReport { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly netcheck?: any; readonly netcheck_err?: string; -<<<<<<< HEAD - readonly netcheck_logs: string[]; -======= readonly netcheck_logs: readonly string[]; - readonly error?: string; ->>>>>>> origin/main } // From healthsdk/healthsdk.go export interface DERPNodeReport { readonly healthy: boolean; readonly severity: HealthSeverity; -<<<<<<< HEAD - readonly warnings: HealthMessage[]; - readonly error?: string; -======= readonly warnings: readonly HealthMessage[]; ->>>>>>> origin/main + readonly error?: string; // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly node?: any; @@ -2340,14 +2325,8 @@ export interface DERPNodeReport { readonly round_trip_ping: string; readonly round_trip_ping_ms: number; readonly uses_websocket: boolean; -<<<<<<< HEAD - readonly client_logs: string[][]; - readonly client_errs: string[][]; -======= readonly client_logs: readonly (readonly string[])[]; readonly client_errs: readonly (readonly string[])[]; - readonly error?: string; ->>>>>>> origin/main readonly stun: STUNReport; } @@ -2355,32 +2334,17 @@ export interface DERPNodeReport { export interface DERPRegionReport { readonly healthy: boolean; readonly severity: HealthSeverity; -<<<<<<< HEAD - readonly warnings: HealthMessage[]; - readonly error?: string; - // Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any" - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type - readonly region?: any; - readonly node_reports: DERPNodeReport[]; -======= readonly warnings: readonly HealthMessage[]; + readonly error?: string; // Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any" // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly region?: any; readonly node_reports: readonly DERPNodeReport[]; - readonly error?: string; ->>>>>>> origin/main } // From healthsdk/healthsdk.go export interface DatabaseReport extends BaseReport { readonly healthy: boolean; -<<<<<<< HEAD -======= - readonly severity: HealthSeverity; - readonly warnings: readonly HealthMessage[]; - readonly dismissed: boolean; ->>>>>>> origin/main readonly reachable: boolean; readonly latency: string; readonly latency_ms: number; @@ -2408,17 +2372,8 @@ export interface HealthcheckReport { } // From healthsdk/healthsdk.go -<<<<<<< HEAD export interface ProvisionerDaemonsReport extends BaseReport { - readonly items: ProvisionerDaemonsReportItem[]; -======= -export interface ProvisionerDaemonsReport { - readonly severity: HealthSeverity; - readonly warnings: readonly HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; readonly items: readonly ProvisionerDaemonsReportItem[]; ->>>>>>> origin/main } // From healthsdk/healthsdk.go @@ -2442,12 +2397,6 @@ export interface UpdateHealthSettings { // From healthsdk/healthsdk.go export interface WebsocketReport extends BaseReport { readonly healthy: boolean; -<<<<<<< HEAD -======= - readonly severity: HealthSeverity; - readonly warnings: readonly string[]; - readonly dismissed: boolean; ->>>>>>> origin/main readonly body: string; readonly code: number; } @@ -2455,13 +2404,6 @@ export interface WebsocketReport extends BaseReport { // From healthsdk/healthsdk.go export interface WorkspaceProxyReport extends BaseReport { readonly healthy: boolean; -<<<<<<< HEAD -======= - readonly severity: HealthSeverity; - readonly warnings: readonly HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; ->>>>>>> origin/main readonly workspace_proxies: RegionsResponse; } From cfce2e02bde606ebbb07a3d6b6ac61366e473131 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 11:44:25 +0100 Subject: [PATCH 08/10] rm commented code --- scripts/apitypings/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 454c85ae45d90..0b4571a6af0a5 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -544,7 +544,6 @@ func (g *Generator) buildStruct(obj types.Object, st *types.Struct) (string, err tag := reflect.StructTag(st.Tag(i)) // Adding a json struct tag causes the json package to consider // the field unembedded. - // if field.Embedded() && tag.Get("json") == "" && field.Pkg().Name() == "codersdk" { if field.Embedded() && tag.Get("json") == "" { extendedFields[i] = true extends = append(extends, field.Name()) From 70c6a094f47fd00dd3f79eb549d447137e1b7db4 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 11:52:03 +0100 Subject: [PATCH 09/10] re-add deprecation notice on Healthy --- coderd/apidoc/docs.go | 2 ++ coderd/apidoc/swagger.json | 2 ++ codersdk/healthsdk/healthsdk.go | 2 ++ docs/api/schemas.md | 46 ++++++++++++++++----------------- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 9e99cc7315146..60ed16632c574 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13607,6 +13607,7 @@ const docTemplate = `{ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", "type": "boolean" }, "node": { @@ -13654,6 +13655,7 @@ const docTemplate = `{ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", "type": "boolean" }, "node_reports": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 71d7f75e21c12..785450be71cdb 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12363,6 +12363,7 @@ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", "type": "boolean" }, "node": { @@ -12406,6 +12407,7 @@ "type": "string" }, "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", "type": "boolean" }, "node_reports": { diff --git a/codersdk/healthsdk/healthsdk.go b/codersdk/healthsdk/healthsdk.go index dec4a3555e2c7..51cf4b6957c4d 100644 --- a/codersdk/healthsdk/healthsdk.go +++ b/codersdk/healthsdk/healthsdk.go @@ -193,6 +193,7 @@ type DERPHealthReport struct { // DERPHealthReport includes health details of each node in a single region. type DERPRegionReport struct { + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. Healthy bool `json:"healthy"` Severity health.Severity `json:"severity" enums:"ok,warning,error"` Warnings []health.Message `json:"warnings"` @@ -203,6 +204,7 @@ type DERPRegionReport struct { // DERPHealthReport includes health details of a single node in a single region. type DERPNodeReport struct { + // Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. Healthy bool `json:"healthy"` Severity health.Severity `json:"severity" enums:"ok,warning,error"` Warnings []health.Message `json:"warnings"` diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 54e97deb3a7c8..1d00ac18c3586 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -7648,21 +7648,21 @@ If the schedule is empty, the user will be updated to use the default schedule.| ### Properties -| Name | Type | Required | Restrictions | Description | -| ----------------------- | ------------------------------------------------ | -------- | ------------ | ----------- | -| `can_exchange_messages` | boolean | false | | | -| `client_errs` | array of array | false | | | -| `client_logs` | array of array | false | | | -| `error` | string | false | | | -| `healthy` | boolean | false | | | -| `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | -| `node_info` | [derp.ServerInfoMessage](#derpserverinfomessage) | false | | | -| `round_trip_ping` | string | false | | | -| `round_trip_ping_ms` | integer | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `stun` | [healthsdk.STUNReport](#healthsdkstunreport) | false | | | -| `uses_websocket` | boolean | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | +| Name | Type | Required | Restrictions | Description | +| ----------------------- | ------------------------------------------------ | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `can_exchange_messages` | boolean | false | | | +| `client_errs` | array of array | false | | | +| `client_logs` | array of array | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | +| `node_info` | [derp.ServerInfoMessage](#derpserverinfomessage) | false | | | +| `round_trip_ping` | string | false | | | +| `round_trip_ping_ms` | integer | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `stun` | [healthsdk.STUNReport](#healthsdkstunreport) | false | | | +| `uses_websocket` | boolean | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values @@ -7757,14 +7757,14 @@ If the schedule is empty, the user will be updated to use the default schedule.| ### Properties -| Name | Type | Required | Restrictions | Description | -| -------------- | ------------------------------------------------------------- | -------- | ------------ | ----------- | -| `error` | string | false | | | -| `healthy` | boolean | false | | | -| `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false | | | -| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | +| Name | Type | Required | Restrictions | Description | +| -------------- | ------------------------------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false | | | +| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | #### Enumerated Values From 993cb8480b88a56f3b6cad577d586ca9acca21f0 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 16 Apr 2024 12:21:15 +0100 Subject: [PATCH 10/10] fixup! reduce diff size --- coderd/debug_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/debug_test.go b/coderd/debug_test.go index ac87583218676..0d5dfd1885f12 100644 --- a/coderd/debug_test.go +++ b/coderd/debug_test.go @@ -213,7 +213,7 @@ func TestDebugHealth(t *testing.T) { return &healthsdk.HealthcheckReport{ Time: time.Now(), Healthy: true, - DERP: healthsdk.DERPHealthReport{BaseReport: healthsdk.BaseReport{Healthy: true}}, + DERP: healthsdk.DERPHealthReport{Healthy: true}, } }, })