diff --git a/cli/netcheck_test.go b/cli/netcheck_test.go index 79abf77556..a2004a2224 100644 --- a/cli/netcheck_test.go +++ b/cli/netcheck_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/coder/coder/v2/cli/clitest" - "github.com/coder/coder/v2/coderd/healthcheck/derphealth" + "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/pty/ptytest" ) @@ -27,7 +27,7 @@ func TestNetcheck(t *testing.T) { b := out.Bytes() t.Log(string(b)) - var report derphealth.Report + var report codersdk.DERPHealthReport require.NoError(t, json.Unmarshal(b, &report)) assert.True(t, report.Healthy) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index b733846963..bf44240fd0 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -485,7 +485,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/healthcheck.Report" + "$ref": "#/definitions/codersdk.HealthcheckReport" } } } @@ -8394,6 +8394,51 @@ const docTemplate = `{ "APIKeyScopeApplicationConnect" ] }, + "codersdk.AccessURLReport": { + "type": "object", + "properties": { + "access_url": { + "type": "string" + }, + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", + "type": "boolean" + }, + "healthz_response": { + "type": "string" + }, + "reachable": { + "type": "boolean" + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "status_code": { + "type": "integer" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.AddLicenseRequest": { "type": "object", "required": [ @@ -9305,6 +9350,126 @@ const docTemplate = `{ } } }, + "codersdk.DERPHealthReport": { + "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" + }, + "netcheck": { + "$ref": "#/definitions/netcheck.Report" + }, + "netcheck_err": { + "type": "string" + }, + "netcheck_logs": { + "type": "array", + "items": { + "type": "string" + } + }, + "regions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/codersdk.DERPRegionReport" + } + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, + "codersdk.DERPNodeReport": { + "type": "object", + "properties": { + "can_exchange_messages": { + "type": "boolean" + }, + "client_errs": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "client_logs": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", + "type": "boolean" + }, + "node": { + "$ref": "#/definitions/tailcfg.DERPNode" + }, + "node_info": { + "$ref": "#/definitions/derp.ServerInfoMessage" + }, + "round_trip_ping": { + "type": "string" + }, + "round_trip_ping_ms": { + "type": "integer" + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "stun": { + "$ref": "#/definitions/codersdk.STUNReport" + }, + "uses_websocket": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DERPRegion": { "type": "object", "properties": { @@ -9316,6 +9481,45 @@ const docTemplate = `{ } } }, + "codersdk.DERPRegionReport": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", + "type": "boolean" + }, + "node_reports": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.DERPNodeReport" + } + }, + "region": { + "$ref": "#/definitions/tailcfg.DERPRegion" + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DERPServerConfig": { "type": "object", "properties": { @@ -9356,6 +9560,51 @@ const docTemplate = `{ } } }, + "codersdk.DatabaseReport": { + "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" + }, + "latency": { + "type": "string" + }, + "latency_ms": { + "type": "integer" + }, + "reachable": { + "type": "boolean" + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "threshold_ms": { + "type": "integer" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DeleteWorkspaceAgentPortShareRequest": { "type": "object", "properties": { @@ -10033,6 +10282,62 @@ const docTemplate = `{ } } }, + "codersdk.HealthcheckReport": { + "type": "object", + "properties": { + "access_url": { + "$ref": "#/definitions/codersdk.AccessURLReport" + }, + "coder_version": { + "description": "The Coder version of the server that the report was generated on.", + "type": "string" + }, + "database": { + "$ref": "#/definitions/codersdk.DatabaseReport" + }, + "derp": { + "$ref": "#/definitions/codersdk.DERPHealthReport" + }, + "failing_sections": { + "description": "FailingSections is a list of sections that have failed their healthcheck.", + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.HealthSection" + } + }, + "healthy": { + "description": "Healthy is true if the report returns no errors.\nDeprecated: use ` + "`" + `Severity` + "`" + ` instead", + "type": "boolean" + }, + "provisioner_daemons": { + "$ref": "#/definitions/codersdk.ProvisionerDaemonsReport" + }, + "severity": { + "description": "Severity indicates the status of Coder health.", + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "time": { + "description": "Time is the time the report was generated at.", + "type": "string", + "format": "date-time" + }, + "websocket": { + "$ref": "#/definitions/codersdk.WebsocketReport" + }, + "workspace_proxy": { + "$ref": "#/definitions/codersdk.WorkspaceProxyReport" + } + } + }, "codersdk.InsightsReportInterval": { "type": "string", "enum": [ @@ -10719,6 +11024,46 @@ const docTemplate = `{ } } }, + "codersdk.ProvisionerDaemonsReport": { + "type": "object", + "properties": { + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ProvisionerDaemonsReportItem" + } + }, + "severity": { + "$ref": "#/definitions/health.Severity" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, + "codersdk.ProvisionerDaemonsReportItem": { + "type": "object", + "properties": { + "provisioner_daemon": { + "$ref": "#/definitions/codersdk.ProvisionerDaemon" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.ProvisionerJob": { "type": "object", "properties": { @@ -11238,6 +11583,20 @@ const docTemplate = `{ } } }, + "codersdk.STUNReport": { + "type": "object", + "properties": { + "canSTUN": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "error": { + "type": "string" + } + } + }, "codersdk.ServiceBannerConfig": { "type": "object", "properties": { @@ -12558,6 +12917,45 @@ const docTemplate = `{ } } }, + "codersdk.WebsocketReport": { + "type": "object", + "properties": { + "body": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", + "type": "boolean" + }, + "severity": { + "enum": [ + "ok", + "warning", + "error" + ], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "codersdk.Workspace": { "type": "object", "properties": { @@ -13384,6 +13782,32 @@ const docTemplate = `{ } } }, + "codersdk.WorkspaceProxyReport": { + "type": "object", + "properties": { + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "type": "boolean" + }, + "severity": { + "$ref": "#/definitions/health.Severity" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + }, + "workspace_proxies": { + "$ref": "#/definitions/codersdk.RegionsResponse-codersdk_WorkspaceProxy" + } + } + }, "codersdk.WorkspaceProxyStatus": { "type": "object", "properties": { @@ -13571,179 +13995,6 @@ const docTemplate = `{ } } }, - "derphealth.NodeReport": { - "type": "object", - "properties": { - "can_exchange_messages": { - "type": "boolean" - }, - "client_errs": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "client_logs": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", - "type": "boolean" - }, - "node": { - "$ref": "#/definitions/tailcfg.DERPNode" - }, - "node_info": { - "$ref": "#/definitions/derp.ServerInfoMessage" - }, - "round_trip_ping": { - "type": "string" - }, - "round_trip_ping_ms": { - "type": "integer" - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "stun": { - "$ref": "#/definitions/derphealth.StunReport" - }, - "uses_websocket": { - "type": "boolean" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.RegionReport": { - "type": "object", - "properties": { - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", - "type": "boolean" - }, - "node_reports": { - "type": "array", - "items": { - "$ref": "#/definitions/derphealth.NodeReport" - } - }, - "region": { - "$ref": "#/definitions/tailcfg.DERPRegion" - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.Report": { - "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" - }, - "netcheck": { - "$ref": "#/definitions/netcheck.Report" - }, - "netcheck_err": { - "type": "string" - }, - "netcheck_logs": { - "type": "array", - "items": { - "type": "string" - } - }, - "regions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/derphealth.RegionReport" - } - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.StunReport": { - "type": "object", - "properties": { - "canSTUN": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "error": { - "type": "string" - } - } - }, "health.Code": { "type": "string", "enum": [ @@ -13813,256 +14064,6 @@ const docTemplate = `{ "SeverityError" ] }, - "healthcheck.AccessURLReport": { - "type": "object", - "properties": { - "access_url": { - "type": "string" - }, - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", - "type": "boolean" - }, - "healthz_response": { - "type": "string" - }, - "reachable": { - "type": "boolean" - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "status_code": { - "type": "integer" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.DatabaseReport": { - "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" - }, - "latency": { - "type": "string" - }, - "latency_ms": { - "type": "integer" - }, - "reachable": { - "type": "boolean" - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "threshold_ms": { - "type": "integer" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.ProvisionerDaemonsReport": { - "type": "object", - "properties": { - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/healthcheck.ProvisionerDaemonsReportItem" - } - }, - "severity": { - "$ref": "#/definitions/health.Severity" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.ProvisionerDaemonsReportItem": { - "type": "object", - "properties": { - "provisioner_daemon": { - "$ref": "#/definitions/codersdk.ProvisionerDaemon" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.Report": { - "type": "object", - "properties": { - "access_url": { - "$ref": "#/definitions/healthcheck.AccessURLReport" - }, - "coder_version": { - "description": "The Coder version of the server that the report was generated on.", - "type": "string" - }, - "database": { - "$ref": "#/definitions/healthcheck.DatabaseReport" - }, - "derp": { - "$ref": "#/definitions/derphealth.Report" - }, - "failing_sections": { - "description": "FailingSections is a list of sections that have failed their healthcheck.", - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.HealthSection" - } - }, - "healthy": { - "description": "Healthy is true if the report returns no errors.\nDeprecated: use ` + "`" + `Severity` + "`" + ` instead", - "type": "boolean" - }, - "provisioner_daemons": { - "$ref": "#/definitions/healthcheck.ProvisionerDaemonsReport" - }, - "severity": { - "description": "Severity indicates the status of Coder health.", - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "time": { - "description": "Time is the time the report was generated at.", - "type": "string" - }, - "websocket": { - "$ref": "#/definitions/healthcheck.WebsocketReport" - }, - "workspace_proxy": { - "$ref": "#/definitions/healthcheck.WorkspaceProxyReport" - } - } - }, - "healthcheck.WebsocketReport": { - "type": "object", - "properties": { - "body": { - "type": "string" - }, - "code": { - "type": "integer" - }, - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use ` + "`" + `Severity` + "`" + ` instead.", - "type": "boolean" - }, - "severity": { - "enum": [ - "ok", - "warning", - "error" - ], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "healthcheck.WorkspaceProxyReport": { - "type": "object", - "properties": { - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "severity": { - "$ref": "#/definitions/health.Severity" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - }, - "workspace_proxies": { - "$ref": "#/definitions/codersdk.RegionsResponse-codersdk_WorkspaceProxy" - } - } - }, "key.NodePublic": { "type": "object" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index a3f00910e7..edae5dee2f 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -413,7 +413,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/healthcheck.Report" + "$ref": "#/definitions/codersdk.HealthcheckReport" } } } @@ -7465,6 +7465,47 @@ "enum": ["all", "application_connect"], "x-enum-varnames": ["APIKeyScopeAll", "APIKeyScopeApplicationConnect"] }, + "codersdk.AccessURLReport": { + "type": "object", + "properties": { + "access_url": { + "type": "string" + }, + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", + "type": "boolean" + }, + "healthz_response": { + "type": "string" + }, + "reachable": { + "type": "boolean" + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "status_code": { + "type": "integer" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.AddLicenseRequest": { "type": "object", "required": ["license"], @@ -8306,6 +8347,118 @@ } } }, + "codersdk.DERPHealthReport": { + "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" + }, + "netcheck": { + "$ref": "#/definitions/netcheck.Report" + }, + "netcheck_err": { + "type": "string" + }, + "netcheck_logs": { + "type": "array", + "items": { + "type": "string" + } + }, + "regions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/codersdk.DERPRegionReport" + } + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, + "codersdk.DERPNodeReport": { + "type": "object", + "properties": { + "can_exchange_messages": { + "type": "boolean" + }, + "client_errs": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "client_logs": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", + "type": "boolean" + }, + "node": { + "$ref": "#/definitions/tailcfg.DERPNode" + }, + "node_info": { + "$ref": "#/definitions/derp.ServerInfoMessage" + }, + "round_trip_ping": { + "type": "string" + }, + "round_trip_ping_ms": { + "type": "integer" + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "stun": { + "$ref": "#/definitions/codersdk.STUNReport" + }, + "uses_websocket": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DERPRegion": { "type": "object", "properties": { @@ -8317,6 +8470,41 @@ } } }, + "codersdk.DERPRegionReport": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", + "type": "boolean" + }, + "node_reports": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.DERPNodeReport" + } + }, + "region": { + "$ref": "#/definitions/tailcfg.DERPRegion" + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DERPServerConfig": { "type": "object", "properties": { @@ -8357,6 +8545,47 @@ } } }, + "codersdk.DatabaseReport": { + "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" + }, + "latency": { + "type": "string" + }, + "latency_ms": { + "type": "integer" + }, + "reachable": { + "type": "boolean" + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "threshold_ms": { + "type": "integer" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.DeleteWorkspaceAgentPortShareRequest": { "type": "object", "properties": { @@ -9020,6 +9249,58 @@ } } }, + "codersdk.HealthcheckReport": { + "type": "object", + "properties": { + "access_url": { + "$ref": "#/definitions/codersdk.AccessURLReport" + }, + "coder_version": { + "description": "The Coder version of the server that the report was generated on.", + "type": "string" + }, + "database": { + "$ref": "#/definitions/codersdk.DatabaseReport" + }, + "derp": { + "$ref": "#/definitions/codersdk.DERPHealthReport" + }, + "failing_sections": { + "description": "FailingSections is a list of sections that have failed their healthcheck.", + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.HealthSection" + } + }, + "healthy": { + "description": "Healthy is true if the report returns no errors.\nDeprecated: use `Severity` instead", + "type": "boolean" + }, + "provisioner_daemons": { + "$ref": "#/definitions/codersdk.ProvisionerDaemonsReport" + }, + "severity": { + "description": "Severity indicates the status of Coder health.", + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "time": { + "description": "Time is the time the report was generated at.", + "type": "string", + "format": "date-time" + }, + "websocket": { + "$ref": "#/definitions/codersdk.WebsocketReport" + }, + "workspace_proxy": { + "$ref": "#/definitions/codersdk.WorkspaceProxyReport" + } + } + }, "codersdk.InsightsReportInterval": { "type": "string", "enum": ["day", "week"], @@ -9651,6 +9932,46 @@ } } }, + "codersdk.ProvisionerDaemonsReport": { + "type": "object", + "properties": { + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ProvisionerDaemonsReportItem" + } + }, + "severity": { + "$ref": "#/definitions/health.Severity" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, + "codersdk.ProvisionerDaemonsReportItem": { + "type": "object", + "properties": { + "provisioner_daemon": { + "$ref": "#/definitions/codersdk.ProvisionerDaemon" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + } + } + }, "codersdk.ProvisionerJob": { "type": "object", "properties": { @@ -10136,6 +10457,20 @@ } } }, + "codersdk.STUNReport": { + "type": "object", + "properties": { + "canSTUN": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "error": { + "type": "string" + } + } + }, "codersdk.ServiceBannerConfig": { "type": "object", "properties": { @@ -11387,6 +11722,41 @@ } } }, + "codersdk.WebsocketReport": { + "type": "object", + "properties": { + "body": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", + "type": "boolean" + }, + "severity": { + "enum": ["ok", "warning", "error"], + "allOf": [ + { + "$ref": "#/definitions/health.Severity" + } + ] + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "codersdk.Workspace": { "type": "object", "properties": { @@ -12177,6 +12547,32 @@ } } }, + "codersdk.WorkspaceProxyReport": { + "type": "object", + "properties": { + "dismissed": { + "type": "boolean" + }, + "error": { + "type": "string" + }, + "healthy": { + "type": "boolean" + }, + "severity": { + "$ref": "#/definitions/health.Severity" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/health.Message" + } + }, + "workspace_proxies": { + "$ref": "#/definitions/codersdk.RegionsResponse-codersdk_WorkspaceProxy" + } + } + }, "codersdk.WorkspaceProxyStatus": { "type": "object", "properties": { @@ -12356,167 +12752,6 @@ } } }, - "derphealth.NodeReport": { - "type": "object", - "properties": { - "can_exchange_messages": { - "type": "boolean" - }, - "client_errs": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "client_logs": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", - "type": "boolean" - }, - "node": { - "$ref": "#/definitions/tailcfg.DERPNode" - }, - "node_info": { - "$ref": "#/definitions/derp.ServerInfoMessage" - }, - "round_trip_ping": { - "type": "string" - }, - "round_trip_ping_ms": { - "type": "integer" - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "stun": { - "$ref": "#/definitions/derphealth.StunReport" - }, - "uses_websocket": { - "type": "boolean" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.RegionReport": { - "type": "object", - "properties": { - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", - "type": "boolean" - }, - "node_reports": { - "type": "array", - "items": { - "$ref": "#/definitions/derphealth.NodeReport" - } - }, - "region": { - "$ref": "#/definitions/tailcfg.DERPRegion" - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.Report": { - "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" - }, - "netcheck": { - "$ref": "#/definitions/netcheck.Report" - }, - "netcheck_err": { - "type": "string" - }, - "netcheck_logs": { - "type": "array", - "items": { - "type": "string" - } - }, - "regions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/derphealth.RegionReport" - } - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "derphealth.StunReport": { - "type": "object", - "properties": { - "canSTUN": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "error": { - "type": "string" - } - } - }, "health.Code": { "type": "string", "enum": [ @@ -12578,240 +12813,6 @@ "enum": ["ok", "warning", "error"], "x-enum-varnames": ["SeverityOK", "SeverityWarning", "SeverityError"] }, - "healthcheck.AccessURLReport": { - "type": "object", - "properties": { - "access_url": { - "type": "string" - }, - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", - "type": "boolean" - }, - "healthz_response": { - "type": "string" - }, - "reachable": { - "type": "boolean" - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "status_code": { - "type": "integer" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.DatabaseReport": { - "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" - }, - "latency": { - "type": "string" - }, - "latency_ms": { - "type": "integer" - }, - "reachable": { - "type": "boolean" - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "threshold_ms": { - "type": "integer" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.ProvisionerDaemonsReport": { - "type": "object", - "properties": { - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/healthcheck.ProvisionerDaemonsReportItem" - } - }, - "severity": { - "$ref": "#/definitions/health.Severity" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.ProvisionerDaemonsReportItem": { - "type": "object", - "properties": { - "provisioner_daemon": { - "$ref": "#/definitions/codersdk.ProvisionerDaemon" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - } - } - }, - "healthcheck.Report": { - "type": "object", - "properties": { - "access_url": { - "$ref": "#/definitions/healthcheck.AccessURLReport" - }, - "coder_version": { - "description": "The Coder version of the server that the report was generated on.", - "type": "string" - }, - "database": { - "$ref": "#/definitions/healthcheck.DatabaseReport" - }, - "derp": { - "$ref": "#/definitions/derphealth.Report" - }, - "failing_sections": { - "description": "FailingSections is a list of sections that have failed their healthcheck.", - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.HealthSection" - } - }, - "healthy": { - "description": "Healthy is true if the report returns no errors.\nDeprecated: use `Severity` instead", - "type": "boolean" - }, - "provisioner_daemons": { - "$ref": "#/definitions/healthcheck.ProvisionerDaemonsReport" - }, - "severity": { - "description": "Severity indicates the status of Coder health.", - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "time": { - "description": "Time is the time the report was generated at.", - "type": "string" - }, - "websocket": { - "$ref": "#/definitions/healthcheck.WebsocketReport" - }, - "workspace_proxy": { - "$ref": "#/definitions/healthcheck.WorkspaceProxyReport" - } - } - }, - "healthcheck.WebsocketReport": { - "type": "object", - "properties": { - "body": { - "type": "string" - }, - "code": { - "type": "integer" - }, - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "description": "Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead.", - "type": "boolean" - }, - "severity": { - "enum": ["ok", "warning", "error"], - "allOf": [ - { - "$ref": "#/definitions/health.Severity" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "healthcheck.WorkspaceProxyReport": { - "type": "object", - "properties": { - "dismissed": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "severity": { - "$ref": "#/definitions/health.Severity" - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/definitions/health.Message" - } - }, - "workspace_proxies": { - "$ref": "#/definitions/codersdk.RegionsResponse-codersdk_WorkspaceProxy" - } - } - }, "key.NodePublic": { "type": "object" }, diff --git a/coderd/coderd.go b/coderd/coderd.go index a4bf3b52a3..119953dfaa 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -143,7 +143,7 @@ type Options struct { // workspace applications. It consists of both a signing and encryption key. AppSecurityKey workspaceapps.SecurityKey - HealthcheckFunc func(ctx context.Context, apiKey string) *healthcheck.Report + HealthcheckFunc func(ctx context.Context, apiKey string) *codersdk.HealthcheckReport HealthcheckTimeout time.Duration HealthcheckRefresh time.Duration WorkspaceProxiesFetchUpdater *atomic.Pointer[healthcheck.WorkspaceProxiesFetchUpdater] @@ -397,7 +397,7 @@ func New(options *Options) *API { UserQuietHoursScheduleStore: options.UserQuietHoursScheduleStore, AccessControlStore: options.AccessControlStore, Experiments: experiments, - healthCheckGroup: &singleflight.Group[string, *healthcheck.Report]{}, + healthCheckGroup: &singleflight.Group[string, *codersdk.HealthcheckReport]{}, Acquirer: provisionerdserver.NewAcquirer( ctx, options.Logger.Named("acquirer"), @@ -433,7 +433,7 @@ func New(options *Options) *API { } if options.HealthcheckFunc == nil { - options.HealthcheckFunc = func(ctx context.Context, apiKey string) *healthcheck.Report { + options.HealthcheckFunc = func(ctx context.Context, apiKey string) *codersdk.HealthcheckReport { // NOTE: dismissed healthchecks are marked in formatHealthcheck. // Not here, as this result gets cached. return healthcheck.Run(ctx, &healthcheck.ReportOptions{ @@ -1170,8 +1170,8 @@ type API struct { // This is used to gate features that are not yet ready for production. Experiments codersdk.Experiments - healthCheckGroup *singleflight.Group[string, *healthcheck.Report] - healthCheckCache atomic.Pointer[healthcheck.Report] + healthCheckGroup *singleflight.Group[string, *codersdk.HealthcheckReport] + healthCheckCache atomic.Pointer[codersdk.HealthcheckReport] statsBatcher *batchstats.Batcher diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index e75c32f9b0..f1a53815bb 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -61,7 +61,6 @@ import ( "github.com/coder/coder/v2/coderd/database/pubsub" "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/gitsshkey" - "github.com/coder/coder/v2/coderd/healthcheck" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/coderd/schedule" @@ -111,7 +110,7 @@ type Options struct { TemplateScheduleStore schedule.TemplateScheduleStore Coordinator tailnet.Coordinator - HealthcheckFunc func(ctx context.Context, apiKey string) *healthcheck.Report + HealthcheckFunc func(ctx context.Context, apiKey string) *codersdk.HealthcheckReport HealthcheckTimeout time.Duration HealthcheckRefresh time.Duration diff --git a/coderd/debug.go b/coderd/debug.go index 40e3b10b82..da40167c9c 100644 --- a/coderd/debug.go +++ b/coderd/debug.go @@ -17,7 +17,6 @@ import ( "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/database" - "github.com/coder/coder/v2/coderd/healthcheck" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" @@ -51,7 +50,7 @@ func (api *API) debugTailnet(rw http.ResponseWriter, r *http.Request) { // @Security CoderSessionToken // @Produce json // @Tags Debug -// @Success 200 {object} healthcheck.Report +// @Success 200 {object} codersdk.HealthcheckReport // @Router /debug/health [get] // @Param force query boolean false "Force a healthcheck to run" func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { @@ -77,7 +76,7 @@ func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { } } - resChan := api.healthCheckGroup.DoChan("", func() (*healthcheck.Report, error) { + resChan := api.healthCheckGroup.DoChan("", func() (*codersdk.HealthcheckReport, error) { // Create a new context not tied to the request. ctx, cancel := context.WithTimeout(context.Background(), api.Options.HealthcheckTimeout) defer cancel() @@ -107,7 +106,7 @@ func (api *API) debugDeploymentHealth(rw http.ResponseWriter, r *http.Request) { } } -func formatHealthcheck(ctx context.Context, rw http.ResponseWriter, r *http.Request, hc healthcheck.Report, dismissed ...codersdk.HealthSection) { +func formatHealthcheck(ctx context.Context, rw http.ResponseWriter, r *http.Request, hc codersdk.HealthcheckReport, dismissed ...codersdk.HealthSection) { // Mark any sections previously marked as dismissed. for _, d := range dismissed { switch d { diff --git a/coderd/debug_test.go b/coderd/debug_test.go index faa8efe747..b3ba003755 100644 --- a/coderd/debug_test.go +++ b/coderd/debug_test.go @@ -15,8 +15,6 @@ import ( "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/coderd/coderdtest" - "github.com/coder/coder/v2/coderd/healthcheck" - "github.com/coder/coder/v2/coderd/healthcheck/derphealth" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/testutil" ) @@ -31,10 +29,10 @@ func TestDebugHealth(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), testutil.WaitShort) sessionToken string client = coderdtest.New(t, &coderdtest.Options{ - HealthcheckFunc: func(_ context.Context, apiKey string) *healthcheck.Report { + HealthcheckFunc: func(_ context.Context, apiKey string) *codersdk.HealthcheckReport { calls.Add(1) assert.Equal(t, sessionToken, apiKey) - return &healthcheck.Report{ + return &codersdk.HealthcheckReport{ Time: time.Now(), } }, @@ -64,10 +62,10 @@ func TestDebugHealth(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), testutil.WaitShort) sessionToken string client = coderdtest.New(t, &coderdtest.Options{ - HealthcheckFunc: func(_ context.Context, apiKey string) *healthcheck.Report { + HealthcheckFunc: func(_ context.Context, apiKey string) *codersdk.HealthcheckReport { calls.Add(1) assert.Equal(t, sessionToken, apiKey) - return &healthcheck.Report{ + return &codersdk.HealthcheckReport{ Time: time.Now(), } }, @@ -99,15 +97,15 @@ func TestDebugHealth(t *testing.T) { client = coderdtest.New(t, &coderdtest.Options{ Logger: &logger, HealthcheckTimeout: time.Microsecond, - HealthcheckFunc: func(context.Context, string) *healthcheck.Report { + HealthcheckFunc: func(context.Context, string) *codersdk.HealthcheckReport { t := time.NewTimer(time.Second) defer t.Stop() select { case <-ctx.Done(): - return &healthcheck.Report{} + return &codersdk.HealthcheckReport{} case <-t.C: - return &healthcheck.Report{} + return &codersdk.HealthcheckReport{} } }, }) @@ -131,9 +129,9 @@ func TestDebugHealth(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), testutil.WaitShort) client = coderdtest.New(t, &coderdtest.Options{ HealthcheckRefresh: time.Microsecond, - HealthcheckFunc: func(context.Context, string) *healthcheck.Report { + HealthcheckFunc: func(context.Context, string) *codersdk.HealthcheckReport { calls <- struct{}{} - return &healthcheck.Report{} + return &codersdk.HealthcheckReport{} }, }) _ = coderdtest.CreateFirstUser(t, client) @@ -176,9 +174,9 @@ func TestDebugHealth(t *testing.T) { client = coderdtest.New(t, &coderdtest.Options{ HealthcheckRefresh: time.Hour, HealthcheckTimeout: time.Hour, - HealthcheckFunc: func(context.Context, string) *healthcheck.Report { + HealthcheckFunc: func(context.Context, string) *codersdk.HealthcheckReport { calls++ - return &healthcheck.Report{ + return &codersdk.HealthcheckReport{ Time: time.Now(), } }, @@ -210,12 +208,12 @@ func TestDebugHealth(t *testing.T) { ctx, cancel = context.WithTimeout(context.Background(), testutil.WaitShort) sessionToken string client = coderdtest.New(t, &coderdtest.Options{ - HealthcheckFunc: func(_ context.Context, apiKey string) *healthcheck.Report { + HealthcheckFunc: func(_ context.Context, apiKey string) *codersdk.HealthcheckReport { assert.Equal(t, sessionToken, apiKey) - return &healthcheck.Report{ + return &codersdk.HealthcheckReport{ Time: time.Now(), Healthy: true, - DERP: derphealth.Report{Healthy: true}, + DERP: codersdk.DERPHealthReport{Healthy: true}, } }, }) @@ -289,7 +287,7 @@ func TestHealthSettings(t *testing.T) { bs, err := io.ReadAll(res.Body) require.NoError(t, err) defer res.Body.Close() - var hc healthcheck.Report + var hc codersdk.HealthcheckReport require.NoError(t, json.Unmarshal(bs, &hc)) require.True(t, hc.DERP.Dismissed) require.True(t, hc.Websocket.Dismissed) @@ -331,7 +329,7 @@ func TestHealthSettings(t *testing.T) { bs, err := io.ReadAll(res.Body) require.NoError(t, err) defer res.Body.Close() - var hc healthcheck.Report + var hc codersdk.HealthcheckReport require.NoError(t, json.Unmarshal(bs, &hc)) require.True(t, hc.DERP.Dismissed) require.False(t, hc.Websocket.Dismissed) diff --git a/coderd/healthcheck/accessurl.go b/coderd/healthcheck/accessurl.go index 2c1d27f164..53ca693a9b 100644 --- a/coderd/healthcheck/accessurl.go +++ b/coderd/healthcheck/accessurl.go @@ -8,22 +8,10 @@ import ( "time" "github.com/coder/coder/v2/coderd/healthcheck/health" + "github.com/coder/coder/v2/codersdk" ) -// @typescript-generate AccessURLReport -type AccessURLReport 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"` - - AccessURL string `json:"access_url"` - Reachable bool `json:"reachable"` - StatusCode int `json:"status_code"` - HealthzResponse string `json:"healthz_response"` - Error *string `json:"error"` -} +type AccessURLReport codersdk.AccessURLReport type AccessURLReportOptions struct { AccessURL *url.URL diff --git a/coderd/healthcheck/database.go b/coderd/healthcheck/database.go index ac36ec0d53..5d8455da87 100644 --- a/coderd/healthcheck/database.go +++ b/coderd/healthcheck/database.go @@ -8,26 +8,14 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/healthcheck/health" + "github.com/coder/coder/v2/codersdk" ) const ( DatabaseDefaultThreshold = 15 * time.Millisecond ) -// @typescript-generate DatabaseReport -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"` -} +type DatabaseReport codersdk.DatabaseReport type DatabaseReportOptions struct { DB database.Store diff --git a/coderd/healthcheck/derphealth/derp.go b/coderd/healthcheck/derphealth/derp.go index de8899fcf1..d3f99fbed0 100644 --- a/coderd/healthcheck/derphealth/derp.go +++ b/coderd/healthcheck/derphealth/derp.go @@ -25,6 +25,7 @@ import ( "github.com/coder/coder/v2/coderd/healthcheck/health" "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/coderd/util/slice" + "github.com/coder/coder/v2/codersdk" ) const ( @@ -33,81 +34,32 @@ const ( missingNodeReport = "Missing node health report, probably a developer error." ) -// @typescript-generate Report -type Report 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]*RegionReport `json:"regions"` - - Netcheck *netcheck.Report `json:"netcheck"` - NetcheckErr *string `json:"netcheck_err"` - NetcheckLogs []string `json:"netcheck_logs"` - - Error *string `json:"error"` -} - -// @typescript-generate RegionReport -type RegionReport struct { - mu sync.Mutex - - // 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"` - - Region *tailcfg.DERPRegion `json:"region"` - NodeReports []*NodeReport `json:"node_reports"` - Error *string `json:"error"` -} - -// @typescript-generate NodeReport -type NodeReport struct { - mu sync.Mutex - clientCounter int - - // 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"` - - Node *tailcfg.DERPNode `json:"node"` - - ServerInfo derp.ServerInfoMessage `json:"node_info"` - CanExchangeMessages bool `json:"can_exchange_messages"` - RoundTripPing string `json:"round_trip_ping"` - RoundTripPingMs int `json:"round_trip_ping_ms"` - UsesWebsocket bool `json:"uses_websocket"` - ClientLogs [][]string `json:"client_logs"` - ClientErrs [][]string `json:"client_errs"` - Error *string `json:"error"` - - STUN StunReport `json:"stun"` -} - -// @typescript-generate StunReport -type StunReport struct { - Enabled bool - CanSTUN bool - Error *string -} - type ReportOptions struct { Dismissed bool DERPMap *tailcfg.DERPMap } +type Report codersdk.DERPHealthReport + +type RegionReport struct { + codersdk.DERPRegionReport + mu sync.Mutex +} + +type NodeReport struct { + codersdk.DERPNodeReport + mu sync.Mutex + clientCounter int +} + func (r *Report) Run(ctx context.Context, opts *ReportOptions) { r.Healthy = true r.Severity = health.SeverityOK r.Warnings = []health.Message{} r.Dismissed = opts.Dismissed - r.Regions = map[int]*RegionReport{} + r.Regions = map[int]*codersdk.DERPRegionReport{} wg := &sync.WaitGroup{} mu := sync.Mutex{} @@ -117,7 +69,9 @@ func (r *Report) Run(ctx context.Context, opts *ReportOptions) { var ( region = region regionReport = RegionReport{ - Region: region, + DERPRegionReport: codersdk.DERPRegionReport{ + Region: region, + }, } ) go func() { @@ -131,7 +85,7 @@ func (r *Report) Run(ctx context.Context, opts *ReportOptions) { regionReport.Run(ctx) mu.Lock() - r.Regions[region.RegionID] = ®ionReport + r.Regions[region.RegionID] = ®ionReport.DERPRegionReport if !regionReport.Healthy { r.Healthy = false } @@ -167,7 +121,7 @@ func (r *Report) Run(ctx context.Context, opts *ReportOptions) { func (r *RegionReport) Run(ctx context.Context) { r.Healthy = true r.Severity = health.SeverityOK - r.NodeReports = []*NodeReport{} + r.NodeReports = []*codersdk.DERPNodeReport{} r.Warnings = []health.Message{} wg := &sync.WaitGroup{} @@ -178,8 +132,10 @@ func (r *RegionReport) Run(ctx context.Context) { var ( node = node nodeReport = NodeReport{ - Node: node, - Healthy: true, + DERPNodeReport: codersdk.DERPNodeReport{ + Node: node, + Healthy: true, + }, } ) @@ -195,7 +151,7 @@ func (r *RegionReport) Run(ctx context.Context) { nodeReport.Run(ctx) r.mu.Lock() - r.NodeReports = append(r.NodeReports, &nodeReport) + r.NodeReports = append(r.NodeReports, &nodeReport.DERPNodeReport) if nodeReport.Severity != health.SeverityOK { unhealthyNodes++ } @@ -347,8 +303,8 @@ func (r *NodeReport) doExchangeMessage(ctx context.Context) { } defer send.Close() - key := send.SelfPublicKey() - peerKey.Store(&key) + pk := send.SelfPublicKey() + peerKey.Store(&pk) ticker := time.NewTicker(time.Second) defer ticker.Stop() @@ -543,8 +499,8 @@ func convertError(err error) *string { return nil } -func sortNodeReports(reports []*NodeReport) { - slices.SortFunc(reports, func(a, b *NodeReport) int { +func sortNodeReports(reports []*codersdk.DERPNodeReport) { + slices.SortFunc(reports, func(a, b *codersdk.DERPNodeReport) int { return slice.Ascending(a.Node.Name, b.Node.Name) }) } diff --git a/coderd/healthcheck/healthcheck.go b/coderd/healthcheck/healthcheck.go index 1d1890ba23..0b058dea35 100644 --- a/coderd/healthcheck/healthcheck.go +++ b/coderd/healthcheck/healthcheck.go @@ -13,35 +13,12 @@ import ( ) type Checker interface { - DERP(ctx context.Context, opts *derphealth.ReportOptions) derphealth.Report - AccessURL(ctx context.Context, opts *AccessURLReportOptions) AccessURLReport - Websocket(ctx context.Context, opts *WebsocketReportOptions) WebsocketReport - Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport - WorkspaceProxy(ctx context.Context, opts *WorkspaceProxyReportOptions) WorkspaceProxyReport - ProvisionerDaemons(ctx context.Context, opts *ProvisionerDaemonsReportDeps) ProvisionerDaemonsReport -} - -// @typescript-generate Report -type Report struct { - // Time is the time the report was generated at. - Time time.Time `json:"time"` - // Healthy is true if the report returns no errors. - // Deprecated: use `Severity` instead - Healthy bool `json:"healthy"` - // Severity indicates the status of Coder health. - Severity health.Severity `json:"severity" enums:"ok,warning,error"` - // FailingSections is a list of sections that have failed their healthcheck. - FailingSections []codersdk.HealthSection `json:"failing_sections"` - - DERP derphealth.Report `json:"derp"` - AccessURL AccessURLReport `json:"access_url"` - Websocket WebsocketReport `json:"websocket"` - Database DatabaseReport `json:"database"` - WorkspaceProxy WorkspaceProxyReport `json:"workspace_proxy"` - ProvisionerDaemons ProvisionerDaemonsReport `json:"provisioner_daemons"` - - // The Coder version of the server that the report was generated on. - CoderVersion string `json:"coder_version"` + DERP(ctx context.Context, opts *derphealth.ReportOptions) codersdk.DERPHealthReport + AccessURL(ctx context.Context, opts *AccessURLReportOptions) codersdk.AccessURLReport + Websocket(ctx context.Context, opts *WebsocketReportOptions) codersdk.WebsocketReport + Database(ctx context.Context, opts *DatabaseReportOptions) codersdk.DatabaseReport + WorkspaceProxy(ctx context.Context, opts *WorkspaceProxyReportOptions) codersdk.WorkspaceProxyReport + ProvisionerDaemons(ctx context.Context, opts *ProvisionerDaemonsReportDeps) codersdk.ProvisionerDaemonsReport } type ReportOptions struct { @@ -57,46 +34,46 @@ type ReportOptions struct { type defaultChecker struct{} -func (defaultChecker) DERP(ctx context.Context, opts *derphealth.ReportOptions) derphealth.Report { +func (defaultChecker) DERP(ctx context.Context, opts *derphealth.ReportOptions) codersdk.DERPHealthReport { var report derphealth.Report report.Run(ctx, opts) - return report + return codersdk.DERPHealthReport(report) } -func (defaultChecker) AccessURL(ctx context.Context, opts *AccessURLReportOptions) AccessURLReport { +func (defaultChecker) AccessURL(ctx context.Context, opts *AccessURLReportOptions) codersdk.AccessURLReport { var report AccessURLReport report.Run(ctx, opts) - return report + return codersdk.AccessURLReport(report) } -func (defaultChecker) Websocket(ctx context.Context, opts *WebsocketReportOptions) WebsocketReport { +func (defaultChecker) Websocket(ctx context.Context, opts *WebsocketReportOptions) codersdk.WebsocketReport { var report WebsocketReport report.Run(ctx, opts) - return report + return codersdk.WebsocketReport(report) } -func (defaultChecker) Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport { +func (defaultChecker) Database(ctx context.Context, opts *DatabaseReportOptions) codersdk.DatabaseReport { var report DatabaseReport report.Run(ctx, opts) - return report + return codersdk.DatabaseReport(report) } -func (defaultChecker) WorkspaceProxy(ctx context.Context, opts *WorkspaceProxyReportOptions) WorkspaceProxyReport { +func (defaultChecker) WorkspaceProxy(ctx context.Context, opts *WorkspaceProxyReportOptions) codersdk.WorkspaceProxyReport { var report WorkspaceProxyReport report.Run(ctx, opts) - return report + return codersdk.WorkspaceProxyReport(report) } -func (defaultChecker) ProvisionerDaemons(ctx context.Context, opts *ProvisionerDaemonsReportDeps) ProvisionerDaemonsReport { +func (defaultChecker) ProvisionerDaemons(ctx context.Context, opts *ProvisionerDaemonsReportDeps) codersdk.ProvisionerDaemonsReport { var report ProvisionerDaemonsReport report.Run(ctx, opts) - return report + return codersdk.ProvisionerDaemonsReport(report) } -func Run(ctx context.Context, opts *ReportOptions) *Report { +func Run(ctx context.Context, opts *ReportOptions) *codersdk.HealthcheckReport { var ( wg sync.WaitGroup - report Report + report codersdk.HealthcheckReport ) if opts.Checker == nil { diff --git a/coderd/healthcheck/healthcheck_test.go b/coderd/healthcheck/healthcheck_test.go index 1dc155623a..01cd08fb7a 100644 --- a/coderd/healthcheck/healthcheck_test.go +++ b/coderd/healthcheck/healthcheck_test.go @@ -13,35 +13,35 @@ import ( ) type testChecker struct { - DERPReport derphealth.Report - AccessURLReport healthcheck.AccessURLReport - WebsocketReport healthcheck.WebsocketReport - DatabaseReport healthcheck.DatabaseReport - WorkspaceProxyReport healthcheck.WorkspaceProxyReport - ProvisionerDaemonsReport healthcheck.ProvisionerDaemonsReport + DERPReport codersdk.DERPHealthReport + AccessURLReport codersdk.AccessURLReport + WebsocketReport codersdk.WebsocketReport + DatabaseReport codersdk.DatabaseReport + WorkspaceProxyReport codersdk.WorkspaceProxyReport + ProvisionerDaemonsReport codersdk.ProvisionerDaemonsReport } -func (c *testChecker) DERP(context.Context, *derphealth.ReportOptions) derphealth.Report { +func (c *testChecker) DERP(context.Context, *derphealth.ReportOptions) codersdk.DERPHealthReport { return c.DERPReport } -func (c *testChecker) AccessURL(context.Context, *healthcheck.AccessURLReportOptions) healthcheck.AccessURLReport { +func (c *testChecker) AccessURL(context.Context, *healthcheck.AccessURLReportOptions) codersdk.AccessURLReport { return c.AccessURLReport } -func (c *testChecker) Websocket(context.Context, *healthcheck.WebsocketReportOptions) healthcheck.WebsocketReport { +func (c *testChecker) Websocket(context.Context, *healthcheck.WebsocketReportOptions) codersdk.WebsocketReport { return c.WebsocketReport } -func (c *testChecker) Database(context.Context, *healthcheck.DatabaseReportOptions) healthcheck.DatabaseReport { +func (c *testChecker) Database(context.Context, *healthcheck.DatabaseReportOptions) codersdk.DatabaseReport { return c.DatabaseReport } -func (c *testChecker) WorkspaceProxy(context.Context, *healthcheck.WorkspaceProxyReportOptions) healthcheck.WorkspaceProxyReport { +func (c *testChecker) WorkspaceProxy(context.Context, *healthcheck.WorkspaceProxyReportOptions) codersdk.WorkspaceProxyReport { return c.WorkspaceProxyReport } -func (c *testChecker) ProvisionerDaemons(context.Context, *healthcheck.ProvisionerDaemonsReportDeps) healthcheck.ProvisionerDaemonsReport { +func (c *testChecker) ProvisionerDaemons(context.Context, *healthcheck.ProvisionerDaemonsReportDeps) codersdk.ProvisionerDaemonsReport { return c.ProvisionerDaemonsReport } @@ -57,27 +57,27 @@ func TestHealthcheck(t *testing.T) { }{{ name: "OK", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -87,27 +87,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "DERPFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: false, Severity: health.SeverityError, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -117,28 +117,28 @@ func TestHealthcheck(t *testing.T) { }, { name: "DERPWarning", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, Severity: health.SeverityWarning, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -148,27 +148,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "AccessURLFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: false, Severity: health.SeverityWarning, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -178,27 +178,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "WebsocketFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: false, Severity: health.SeverityError, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -208,27 +208,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "DatabaseFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: false, Severity: health.SeverityError, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -238,27 +238,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "ProxyFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: false, Severity: health.SeverityError, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -268,28 +268,28 @@ func TestHealthcheck(t *testing.T) { }, { name: "ProxyWarn", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, Severity: health.SeverityWarning, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityOK, }, }, @@ -299,27 +299,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "ProvisionerDaemonsFail", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityError, }, }, @@ -329,27 +329,27 @@ func TestHealthcheck(t *testing.T) { }, { name: "ProvisionerDaemonsWarn", checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: true, Severity: health.SeverityOK, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: true, Severity: health.SeverityOK, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: true, Severity: health.SeverityOK, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: true, Severity: health.SeverityOK, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: true, Severity: health.SeverityOK, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityWarning, Warnings: []health.Message{{Message: "foobar", Code: "EFOOBAR"}}, }, @@ -361,27 +361,27 @@ func TestHealthcheck(t *testing.T) { name: "AllFail", healthy: false, checker: &testChecker{ - DERPReport: derphealth.Report{ + DERPReport: codersdk.DERPHealthReport{ Healthy: false, Severity: health.SeverityError, }, - AccessURLReport: healthcheck.AccessURLReport{ + AccessURLReport: codersdk.AccessURLReport{ Healthy: false, Severity: health.SeverityError, }, - WebsocketReport: healthcheck.WebsocketReport{ + WebsocketReport: codersdk.WebsocketReport{ Healthy: false, Severity: health.SeverityError, }, - DatabaseReport: healthcheck.DatabaseReport{ + DatabaseReport: codersdk.DatabaseReport{ Healthy: false, Severity: health.SeverityError, }, - WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{ + WorkspaceProxyReport: codersdk.WorkspaceProxyReport{ Healthy: false, Severity: health.SeverityError, }, - ProvisionerDaemonsReport: healthcheck.ProvisionerDaemonsReport{ + ProvisionerDaemonsReport: codersdk.ProvisionerDaemonsReport{ Severity: health.SeverityError, }, }, diff --git a/coderd/healthcheck/provisioner.go b/coderd/healthcheck/provisioner.go index 36ef4d3b3a..f30f067fb5 100644 --- a/coderd/healthcheck/provisioner.go +++ b/coderd/healthcheck/provisioner.go @@ -20,21 +20,7 @@ import ( "github.com/coder/coder/v2/provisionerd/proto" ) -// @typescript-generate ProvisionerDaemonsReport -type ProvisionerDaemonsReport struct { - Severity health.Severity `json:"severity"` - Warnings []health.Message `json:"warnings"` - Dismissed bool `json:"dismissed"` - Error *string `json:"error"` - - Items []ProvisionerDaemonsReportItem `json:"items"` -} - -// @typescript-generate ProvisionerDaemonsReportItem -type ProvisionerDaemonsReportItem struct { - codersdk.ProvisionerDaemon `json:"provisioner_daemon"` - Warnings []health.Message `json:"warnings"` -} +type ProvisionerDaemonsReport codersdk.ProvisionerDaemonsReport type ProvisionerDaemonsReportDeps struct { // Required @@ -54,7 +40,7 @@ type ProvisionerDaemonsStore interface { } func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDaemonsReportDeps) { - r.Items = make([]ProvisionerDaemonsReportItem, 0) + r.Items = make([]codersdk.ProvisionerDaemonsReportItem, 0) r.Severity = health.SeverityOK r.Warnings = make([]health.Message, 0) r.Dismissed = opts.Dismissed @@ -109,7 +95,7 @@ func (r *ProvisionerDaemonsReport) Run(ctx context.Context, opts *ProvisionerDae continue } - it := ProvisionerDaemonsReportItem{ + it := codersdk.ProvisionerDaemonsReportItem{ ProvisionerDaemon: db2sdk.ProvisionerDaemon(daemon), Warnings: make([]health.Message, 0), } diff --git a/coderd/healthcheck/provisioner_test.go b/coderd/healthcheck/provisioner_test.go index d627e2f573..7942f5a7dd 100644 --- a/coderd/healthcheck/provisioner_test.go +++ b/coderd/healthcheck/provisioner_test.go @@ -34,21 +34,21 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity health.Severity expectedWarningCode health.Code expectedError string - expectedItems []healthcheck.ProvisionerDaemonsReportItem + expectedItems []codersdk.ProvisionerDaemonsReportItem }{ { name: "current version empty", currentVersion: "", expectedSeverity: health.SeverityError, expectedError: "Developer error: CurrentVersion is empty", - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{}, + expectedItems: []codersdk.ProvisionerDaemonsReportItem{}, }, { name: "no daemons", currentVersion: "v1.2.3", currentAPIMajorVersion: proto.CurrentMajor, expectedSeverity: health.SeverityError, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{}, + expectedItems: []codersdk.ProvisionerDaemonsReportItem{}, expectedWarningCode: health.CodeProvisionerDaemonsNoProvisionerDaemons, }, { @@ -58,7 +58,7 @@ func TestProvisionerDaemonReport(t *testing.T) { provisionerDaemonsErr: assert.AnError, expectedSeverity: health.SeverityError, expectedError: assert.AnError.Error(), - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{}, + expectedItems: []codersdk.ProvisionerDaemonsReportItem{}, }, { name: "one daemon up to date", @@ -66,7 +66,7 @@ func TestProvisionerDaemonReport(t *testing.T) { currentAPIMajorVersion: proto.CurrentMajor, expectedSeverity: health.SeverityOK, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -89,7 +89,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityWarning, expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -117,7 +117,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityError, expectedWarningCode: health.CodeUnknown, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-invalid-version", "invalid", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -145,7 +145,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityError, expectedWarningCode: health.CodeUnknown, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-invalid-api", "v1.2.3", "invalid", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -173,7 +173,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityWarning, expectedWarningCode: health.CodeProvisionerDaemonAPIMajorVersionDeprecated, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-old-api", "v2.3.4", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -201,7 +201,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityWarning, expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now), fakeProvisionerDaemon(t, "pd-old", "v1.1.2", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -242,7 +242,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityWarning, expectedWarningCode: health.CodeProvisionerDaemonVersionMismatch, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemon(t, "pd-ok", "v1.2.3", "1.0", now), fakeProvisionerDaemon(t, "pd-new", "v2.3.4", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -282,7 +282,7 @@ func TestProvisionerDaemonReport(t *testing.T) { currentAPIMajorVersion: proto.CurrentMajor, expectedSeverity: health.SeverityOK, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-stale", "v1.2.3", "0.9", now.Add(-5*time.Minute), now), fakeProvisionerDaemon(t, "pd-ok", "v2.3.4", "1.0", now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{ + expectedItems: []codersdk.ProvisionerDaemonsReportItem{ { ProvisionerDaemon: codersdk.ProvisionerDaemon{ ID: uuid.Nil, @@ -305,7 +305,7 @@ func TestProvisionerDaemonReport(t *testing.T) { expectedSeverity: health.SeverityError, expectedWarningCode: health.CodeProvisionerDaemonsNoProvisionerDaemons, provisionerDaemons: []database.ProvisionerDaemon{fakeProvisionerDaemonStale(t, "pd-ok", "v1.2.3", "0.9", now.Add(-5*time.Minute), now)}, - expectedItems: []healthcheck.ProvisionerDaemonsReportItem{}, + expectedItems: []codersdk.ProvisionerDaemonsReportItem{}, }, } { tt := tt diff --git a/coderd/healthcheck/websocket.go b/coderd/healthcheck/websocket.go index 215465fe5c..582a5023ef 100644 --- a/coderd/healthcheck/websocket.go +++ b/coderd/healthcheck/websocket.go @@ -13,20 +13,10 @@ import ( "nhooyr.io/websocket" "github.com/coder/coder/v2/coderd/healthcheck/health" + "github.com/coder/coder/v2/codersdk" ) -// @typescript-generate WebsocketReport -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"` -} +type WebsocketReport codersdk.WebsocketReport type WebsocketReportOptions struct { APIKey string diff --git a/coderd/healthcheck/workspaceproxy.go b/coderd/healthcheck/workspaceproxy.go index 509ac3318b..c5ff1c7082 100644 --- a/coderd/healthcheck/workspaceproxy.go +++ b/coderd/healthcheck/workspaceproxy.go @@ -14,16 +14,7 @@ import ( "golang.org/x/xerrors" ) -// @typescript-generate WorkspaceProxyReport -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"` - - WorkspaceProxies codersdk.RegionsResponse[codersdk.WorkspaceProxy] `json:"workspace_proxies"` -} +type WorkspaceProxyReport codersdk.WorkspaceProxyReport type WorkspaceProxyReportOptions struct { // CurrentVersion is the current server version. diff --git a/codersdk/health.go b/codersdk/health.go index a54b65762e..266d05c2e2 100644 --- a/codersdk/health.go +++ b/codersdk/health.go @@ -4,6 +4,13 @@ import ( "context" "encoding/json" "net/http" + "time" + + "tailscale.com/derp" + "tailscale.com/net/netcheck" + "tailscale.com/tailcfg" + + "github.com/coder/coder/v2/coderd/healthcheck/health" "golang.org/x/xerrors" ) @@ -65,3 +72,142 @@ func (c *Client) PutHealthSettings(ctx context.Context, settings HealthSettings) } return nil } + +type HealthcheckReport struct { + // Time is the time the report was generated at. + Time time.Time `json:"time" format:"date-time"` + // Healthy is true if the report returns no errors. + // Deprecated: use `Severity` instead + Healthy bool `json:"healthy"` + // Severity indicates the status of Coder health. + Severity health.Severity `json:"severity" enums:"ok,warning,error"` + // FailingSections is a list of sections that have failed their healthcheck. + FailingSections []HealthSection `json:"failing_sections"` + + DERP DERPHealthReport `json:"derp"` + AccessURL AccessURLReport `json:"access_url"` + Websocket WebsocketReport `json:"websocket"` + Database DatabaseReport `json:"database"` + WorkspaceProxy WorkspaceProxyReport `json:"workspace_proxy"` + ProvisionerDaemons ProvisionerDaemonsReport `json:"provisioner_daemons"` + + // The Coder version of the server that the report was generated on. + CoderVersion string `json:"coder_version"` +} + +type AccessURLReport 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"` + + AccessURL string `json:"access_url"` + Reachable bool `json:"reachable"` + StatusCode int `json:"status_code"` + HealthzResponse string `json:"healthz_response"` + Error *string `json:"error"` +} + +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"` +} + +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"` + + Region *tailcfg.DERPRegion `json:"region"` + NodeReports []*DERPNodeReport `json:"node_reports"` + Error *string `json:"error"` +} + +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"` + + Node *tailcfg.DERPNode `json:"node"` + + ServerInfo derp.ServerInfoMessage `json:"node_info"` + CanExchangeMessages bool `json:"can_exchange_messages"` + RoundTripPing string `json:"round_trip_ping"` + RoundTripPingMs int `json:"round_trip_ping_ms"` + UsesWebsocket bool `json:"uses_websocket"` + ClientLogs [][]string `json:"client_logs"` + ClientErrs [][]string `json:"client_errs"` + Error *string `json:"error"` + + STUN STUNReport `json:"stun"` +} + +type STUNReport struct { + Enabled bool + CanSTUN bool + Error *string +} + +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"` +} + +type ProvisionerDaemonsReport struct { + Severity health.Severity `json:"severity"` + Warnings []health.Message `json:"warnings"` + Dismissed bool `json:"dismissed"` + Error *string `json:"error"` + + Items []ProvisionerDaemonsReportItem `json:"items"` +} + +type ProvisionerDaemonsReportItem struct { + ProvisionerDaemon `json:"provisioner_daemon"` + Warnings []health.Message `json:"warnings"` +} + +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"` +} + +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"` + + WorkspaceProxies RegionsResponse[WorkspaceProxy] `json:"workspace_proxies"` +} diff --git a/docs/api/debug.md b/docs/api/debug.md index 7b84457ad2..6f9bee2f55 100644 --- a/docs/api/debug.md +++ b/docs/api/debug.md @@ -317,7 +317,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ ] }, "severity": "ok", - "time": "string", + "time": "2019-08-24T14:15:22Z", "websocket": { "body": "string", "code": 0, @@ -371,9 +371,9 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ ### Responses -| Status | Meaning | Description | Schema | -| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------------- | -| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [healthcheck.Report](schemas.md#healthcheckreport) | +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.HealthcheckReport](schemas.md#codersdkhealthcheckreport) | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/schemas.md b/docs/api/schemas.md index c4ab8128fa..b383a707c6 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -955,6 +955,49 @@ _None_ | `all` | | `application_connect` | +## codersdk.AccessURLReport + +```json +{ + "access_url": "string", + "dismissed": true, + "error": "string", + "healthy": true, + "healthz_response": "string", + "reachable": true, + "severity": "ok", + "status_code": 0, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------------ | ----------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | +| `access_url` | string | false | | | +| `dismissed` | boolean | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | +| `healthz_response` | string | false | | | +| `reachable` | boolean | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `status_code` | integer | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.AddLicenseRequest ```json @@ -2011,6 +2054,308 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `path` | string | false | | | | `url` | string | false | | | +## codersdk.DERPHealthReport + +```json +{ + "dismissed": true, + "error": "string", + "healthy": true, + "netcheck": { + "captivePortal": "string", + "globalV4": "string", + "globalV6": "string", + "hairPinning": "string", + "icmpv4": true, + "ipv4": true, + "ipv4CanSend": true, + "ipv6": true, + "ipv6CanSend": true, + "mappingVariesByDestIP": "string", + "oshasIPv6": true, + "pcp": "string", + "pmp": "string", + "preferredDERP": 0, + "regionLatency": { + "property1": 0, + "property2": 0 + }, + "regionV4Latency": { + "property1": 0, + "property2": 0 + }, + "regionV6Latency": { + "property1": 0, + "property2": 0 + }, + "udp": true, + "upnP": "string" + }, + "netcheck_err": "string", + "netcheck_logs": ["string"], + "regions": { + "property1": { + "error": "string", + "healthy": true, + "node_reports": [ + { + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "region": { + "avoid": true, + "embeddedRelay": true, + "nodes": [ + { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + } + ], + "regionCode": "string", + "regionID": 0, + "regionName": "string" + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "property2": { + "error": "string", + "healthy": true, + "node_reports": [ + { + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "region": { + "avoid": true, + "embeddedRelay": true, + "nodes": [ + { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + } + ], + "regionCode": "string", + "regionID": 0, + "regionName": "string" + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### 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. | +| `netcheck` | [netcheck.Report](#netcheckreport) | false | | | +| `netcheck_err` | string | false | | | +| `netcheck_logs` | array of string | false | | | +| `regions` | object | false | | | +| » `[any property]` | [codersdk.DERPRegionReport](#codersdkderpregionreport) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + +## codersdk.DERPNodeReport + +```json +{ + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### 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 | | 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` | [codersdk.STUNReport](#codersdkstunreport) | false | | | +| `uses_websocket` | boolean | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.DERPRegion ```json @@ -2027,6 +2372,108 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `latency_ms` | number | false | | | | `preferred` | boolean | false | | | +## codersdk.DERPRegionReport + +```json +{ + "error": "string", + "healthy": true, + "node_reports": [ + { + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "region": { + "avoid": true, + "embeddedRelay": true, + "nodes": [ + { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + } + ], + "regionCode": "string", + "regionID": 0, + "regionName": "string" + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### Properties + +| 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 [codersdk.DERPNodeReport](#codersdkderpnodereport) | false | | | +| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.DERPServerConfig ```json @@ -2081,6 +2528,49 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `allow_path_app_sharing` | boolean | false | | | | `allow_path_app_site_owner_access` | boolean | false | | | +## codersdk.DatabaseReport + +```json +{ + "dismissed": true, + "error": "string", + "healthy": true, + "latency": "string", + "latency_ms": 0, + "reachable": true, + "severity": "ok", + "threshold_ms": 0, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### 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. | +| `latency` | string | false | | | +| `latency_ms` | integer | false | | | +| `reachable` | boolean | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `threshold_ms` | integer | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.DeleteWorkspaceAgentPortShareRequest ```json @@ -3300,6 +3790,358 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `refresh` | integer | false | | | | `threshold_database` | integer | false | | | +## codersdk.HealthcheckReport + +```json +{ + "access_url": { + "access_url": "string", + "dismissed": true, + "error": "string", + "healthy": true, + "healthz_response": "string", + "reachable": true, + "severity": "ok", + "status_code": 0, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "coder_version": "string", + "database": { + "dismissed": true, + "error": "string", + "healthy": true, + "latency": "string", + "latency_ms": 0, + "reachable": true, + "severity": "ok", + "threshold_ms": 0, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "derp": { + "dismissed": true, + "error": "string", + "healthy": true, + "netcheck": { + "captivePortal": "string", + "globalV4": "string", + "globalV6": "string", + "hairPinning": "string", + "icmpv4": true, + "ipv4": true, + "ipv4CanSend": true, + "ipv6": true, + "ipv6CanSend": true, + "mappingVariesByDestIP": "string", + "oshasIPv6": true, + "pcp": "string", + "pmp": "string", + "preferredDERP": 0, + "regionLatency": { + "property1": 0, + "property2": 0 + }, + "regionV4Latency": { + "property1": 0, + "property2": 0 + }, + "regionV6Latency": { + "property1": 0, + "property2": 0 + }, + "udp": true, + "upnP": "string" + }, + "netcheck_err": "string", + "netcheck_logs": ["string"], + "regions": { + "property1": { + "error": "string", + "healthy": true, + "node_reports": [ + { + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "region": { + "avoid": true, + "embeddedRelay": true, + "nodes": [ + { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + } + ], + "regionCode": "string", + "regionID": 0, + "regionName": "string" + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "property2": { + "error": "string", + "healthy": true, + "node_reports": [ + { + "can_exchange_messages": true, + "client_errs": [["string"]], + "client_logs": [["string"]], + "error": "string", + "healthy": true, + "node": { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + }, + "node_info": { + "tokenBucketBytesBurst": 0, + "tokenBucketBytesPerSecond": 0 + }, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, + "severity": "ok", + "stun": { + "canSTUN": true, + "enabled": true, + "error": "string" + }, + "uses_websocket": true, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "region": { + "avoid": true, + "embeddedRelay": true, + "nodes": [ + { + "canPort80": true, + "certName": "string", + "derpport": 0, + "forceHTTP": true, + "hostName": "string", + "insecureForTests": true, + "ipv4": "string", + "ipv6": "string", + "name": "string", + "regionID": 0, + "stunonly": true, + "stunport": 0, + "stuntestIP": "string" + } + ], + "regionCode": "string", + "regionID": 0, + "regionName": "string" + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + }, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "failing_sections": ["DERP"], + "healthy": true, + "provisioner_daemons": { + "dismissed": true, + "error": "string", + "items": [ + { + "provisioner_daemon": { + "api_version": "string", + "created_at": "2019-08-24T14:15:22Z", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "name": "string", + "provisioners": ["string"], + "tags": { + "property1": "string", + "property2": "string" + }, + "version": "string" + }, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + }, + "severity": "ok", + "time": "2019-08-24T14:15:22Z", + "websocket": { + "body": "string", + "code": 0, + "dismissed": true, + "error": "string", + "healthy": true, + "severity": "ok", + "warnings": ["string"] + }, + "workspace_proxy": { + "dismissed": true, + "error": "string", + "healthy": true, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ], + "workspace_proxies": { + "regions": [ + { + "created_at": "2019-08-24T14:15:22Z", + "deleted": true, + "derp_enabled": true, + "derp_only": true, + "display_name": "string", + "healthy": true, + "icon_url": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "path_app_url": "string", + "status": { + "checked_at": "2019-08-24T14:15:22Z", + "report": { + "errors": ["string"], + "warnings": ["string"] + }, + "status": "ok" + }, + "updated_at": "2019-08-24T14:15:22Z", + "version": "string", + "wildcard_hostname": "string" + } + ] + } + } +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| --------------------- | ---------------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------------------- | +| `access_url` | [codersdk.AccessURLReport](#codersdkaccessurlreport) | false | | | +| `coder_version` | string | false | | The Coder version of the server that the report was generated on. | +| `database` | [codersdk.DatabaseReport](#codersdkdatabasereport) | false | | | +| `derp` | [codersdk.DERPHealthReport](#codersdkderphealthreport) | false | | | +| `failing_sections` | array of [codersdk.HealthSection](#codersdkhealthsection) | false | | Failing sections is a list of sections that have failed their healthcheck. | +| `healthy` | boolean | false | | Healthy is true if the report returns no errors. Deprecated: use `Severity` instead | +| `provisioner_daemons` | [codersdk.ProvisionerDaemonsReport](#codersdkprovisionerdaemonsreport) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | Severity indicates the status of Coder health. | +| `time` | string | false | | Time is the time the report was generated at. | +| `websocket` | [codersdk.WebsocketReport](#codersdkwebsocketreport) | false | | | +| `workspace_proxy` | [codersdk.WorkspaceProxyReport](#codersdkworkspaceproxyreport) | false | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.InsightsReportInterval ```json @@ -4012,6 +4854,88 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | » `[any property]` | string | false | | | | `version` | string | false | | | +## codersdk.ProvisionerDaemonsReport + +```json +{ + "dismissed": true, + "error": "string", + "items": [ + { + "provisioner_daemon": { + "api_version": "string", + "created_at": "2019-08-24T14:15:22Z", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "name": "string", + "provisioners": ["string"], + "tags": { + "property1": "string", + "property2": "string" + }, + "version": "string" + }, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] + } + ], + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ----------- | --------------------------------------------------------------------------------------- | -------- | ------------ | ----------- | +| `dismissed` | boolean | false | | | +| `error` | string | false | | | +| `items` | array of [codersdk.ProvisionerDaemonsReportItem](#codersdkprovisionerdaemonsreportitem) | false | | | +| `severity` | [health.Severity](#healthseverity) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + +## codersdk.ProvisionerDaemonsReportItem + +```json +{ + "provisioner_daemon": { + "api_version": "string", + "created_at": "2019-08-24T14:15:22Z", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "name": "string", + "provisioners": ["string"], + "tags": { + "property1": "string", + "property2": "string" + }, + "version": "string" + }, + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| -------------------- | -------------------------------------------------------- | -------- | ------------ | ----------- | +| `provisioner_daemon` | [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false | | | +| `warnings` | array of [health.Message](#healthmessage) | false | | | + ## codersdk.ProvisionerJob ```json @@ -4534,6 +5458,24 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `ssh_config_options` | object | false | | | | » `[any property]` | string | false | | | +## codersdk.STUNReport + +```json +{ + "canSTUN": true, + "enabled": true, + "error": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| --------- | ------- | -------- | ------------ | ----------- | +| `canSTUN` | boolean | false | | | +| `enabled` | boolean | false | | | +| `error` | string | false | | | + ## codersdk.ServiceBannerConfig ```json @@ -6025,6 +6967,40 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `name` | string | false | | | | `value` | string | false | | | +## codersdk.WebsocketReport + +```json +{ + "body": "string", + "code": 0, + "dismissed": true, + "error": "string", + "healthy": true, + "severity": "ok", + "warnings": ["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 | | | + +#### Enumerated Values + +| Property | Value | +| ---------- | --------- | +| `severity` | `ok` | +| `severity` | `warning` | +| `severity` | `error` | + ## codersdk.Workspace ```json @@ -7119,6 +8095,61 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `version` | string | false | | | | `wildcard_hostname` | string | false | | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. _.us.example.com E.g. _--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. | +## codersdk.WorkspaceProxyReport + +```json +{ + "dismissed": true, + "error": "string", + "healthy": true, + "severity": "ok", + "warnings": [ + { + "code": "EUNKNOWN", + "message": "string" + } + ], + "workspace_proxies": { + "regions": [ + { + "created_at": "2019-08-24T14:15:22Z", + "deleted": true, + "derp_enabled": true, + "derp_only": true, + "display_name": "string", + "healthy": true, + "icon_url": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "path_app_url": "string", + "status": { + "checked_at": "2019-08-24T14:15:22Z", + "report": { + "errors": ["string"], + "warnings": ["string"] + }, + "status": "ok" + }, + "updated_at": "2019-08-24T14:15:22Z", + "version": "string", + "wildcard_hostname": "string" + } + ] + } +} +``` + +### 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 | | | + ## codersdk.WorkspaceProxyStatus ```json @@ -7576,428 +8607,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `tokenBucketBytesPerSecond` | integer | false | | Tokenbucketbytespersecond is how many bytes per second the server says it will accept, including all framing bytes. | | Zero means unspecified. There might be a limit, but the client need not try to respect it. | -## derphealth.NodeReport - -```json -{ - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### 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 | | 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` | [derphealth.StunReport](#derphealthstunreport) | false | | | -| `uses_websocket` | boolean | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## derphealth.RegionReport - -```json -{ - "error": "string", - "healthy": true, - "node_reports": [ - { - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "region": { - "avoid": true, - "embeddedRelay": true, - "nodes": [ - { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - } - ], - "regionCode": "string", - "regionID": 0, - "regionName": "string" - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### Properties - -| 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 [derphealth.NodeReport](#derphealthnodereport) | false | | | -| `region` | [tailcfg.DERPRegion](#tailcfgderpregion) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## derphealth.Report - -```json -{ - "dismissed": true, - "error": "string", - "healthy": true, - "netcheck": { - "captivePortal": "string", - "globalV4": "string", - "globalV6": "string", - "hairPinning": "string", - "icmpv4": true, - "ipv4": true, - "ipv4CanSend": true, - "ipv6": true, - "ipv6CanSend": true, - "mappingVariesByDestIP": "string", - "oshasIPv6": true, - "pcp": "string", - "pmp": "string", - "preferredDERP": 0, - "regionLatency": { - "property1": 0, - "property2": 0 - }, - "regionV4Latency": { - "property1": 0, - "property2": 0 - }, - "regionV6Latency": { - "property1": 0, - "property2": 0 - }, - "udp": true, - "upnP": "string" - }, - "netcheck_err": "string", - "netcheck_logs": ["string"], - "regions": { - "property1": { - "error": "string", - "healthy": true, - "node_reports": [ - { - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "region": { - "avoid": true, - "embeddedRelay": true, - "nodes": [ - { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - } - ], - "regionCode": "string", - "regionID": 0, - "regionName": "string" - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "property2": { - "error": "string", - "healthy": true, - "node_reports": [ - { - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "region": { - "avoid": true, - "embeddedRelay": true, - "nodes": [ - { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - } - ], - "regionCode": "string", - "regionID": 0, - "regionName": "string" - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### 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. | -| `netcheck` | [netcheck.Report](#netcheckreport) | false | | | -| `netcheck_err` | string | false | | | -| `netcheck_logs` | array of string | false | | | -| `regions` | object | false | | | -| » `[any property]` | [derphealth.RegionReport](#derphealthregionreport) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## derphealth.StunReport - -```json -{ - "canSTUN": true, - "enabled": true, - "error": "string" -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| --------- | ------- | -------- | ------------ | ----------- | -| `canSTUN` | boolean | false | | | -| `enabled` | boolean | false | | | -| `error` | string | false | | | - ## health.Code ```json @@ -8062,615 +8671,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `warning` | | `error` | -## healthcheck.AccessURLReport - -```json -{ - "access_url": "string", - "dismissed": true, - "error": "string", - "healthy": true, - "healthz_response": "string", - "reachable": true, - "severity": "ok", - "status_code": 0, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ------------------ | ----------------------------------------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | -| `access_url` | string | false | | | -| `dismissed` | boolean | false | | | -| `error` | string | false | | | -| `healthy` | boolean | false | | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. | -| `healthz_response` | string | false | | | -| `reachable` | boolean | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `status_code` | integer | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## healthcheck.DatabaseReport - -```json -{ - "dismissed": true, - "error": "string", - "healthy": true, - "latency": "string", - "latency_ms": 0, - "reachable": true, - "severity": "ok", - "threshold_ms": 0, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### 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. | -| `latency` | string | false | | | -| `latency_ms` | integer | false | | | -| `reachable` | boolean | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `threshold_ms` | integer | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## healthcheck.ProvisionerDaemonsReport - -```json -{ - "dismissed": true, - "error": "string", - "items": [ - { - "provisioner_daemon": { - "api_version": "string", - "created_at": "2019-08-24T14:15:22Z", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "last_seen_at": "2019-08-24T14:15:22Z", - "name": "string", - "provisioners": ["string"], - "tags": { - "property1": "string", - "property2": "string" - }, - "version": "string" - }, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ----------- | --------------------------------------------------------------------------------------------- | -------- | ------------ | ----------- | -| `dismissed` | boolean | false | | | -| `error` | string | false | | | -| `items` | array of [healthcheck.ProvisionerDaemonsReportItem](#healthcheckprovisionerdaemonsreportitem) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -## healthcheck.ProvisionerDaemonsReportItem - -```json -{ - "provisioner_daemon": { - "api_version": "string", - "created_at": "2019-08-24T14:15:22Z", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "last_seen_at": "2019-08-24T14:15:22Z", - "name": "string", - "provisioners": ["string"], - "tags": { - "property1": "string", - "property2": "string" - }, - "version": "string" - }, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| -------------------- | -------------------------------------------------------- | -------- | ------------ | ----------- | -| `provisioner_daemon` | [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false | | | -| `warnings` | array of [health.Message](#healthmessage) | false | | | - -## healthcheck.Report - -```json -{ - "access_url": { - "access_url": "string", - "dismissed": true, - "error": "string", - "healthy": true, - "healthz_response": "string", - "reachable": true, - "severity": "ok", - "status_code": 0, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "coder_version": "string", - "database": { - "dismissed": true, - "error": "string", - "healthy": true, - "latency": "string", - "latency_ms": 0, - "reachable": true, - "severity": "ok", - "threshold_ms": 0, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "derp": { - "dismissed": true, - "error": "string", - "healthy": true, - "netcheck": { - "captivePortal": "string", - "globalV4": "string", - "globalV6": "string", - "hairPinning": "string", - "icmpv4": true, - "ipv4": true, - "ipv4CanSend": true, - "ipv6": true, - "ipv6CanSend": true, - "mappingVariesByDestIP": "string", - "oshasIPv6": true, - "pcp": "string", - "pmp": "string", - "preferredDERP": 0, - "regionLatency": { - "property1": 0, - "property2": 0 - }, - "regionV4Latency": { - "property1": 0, - "property2": 0 - }, - "regionV6Latency": { - "property1": 0, - "property2": 0 - }, - "udp": true, - "upnP": "string" - }, - "netcheck_err": "string", - "netcheck_logs": ["string"], - "regions": { - "property1": { - "error": "string", - "healthy": true, - "node_reports": [ - { - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "region": { - "avoid": true, - "embeddedRelay": true, - "nodes": [ - { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - } - ], - "regionCode": "string", - "regionID": 0, - "regionName": "string" - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "property2": { - "error": "string", - "healthy": true, - "node_reports": [ - { - "can_exchange_messages": true, - "client_errs": [["string"]], - "client_logs": [["string"]], - "error": "string", - "healthy": true, - "node": { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - }, - "node_info": { - "tokenBucketBytesBurst": 0, - "tokenBucketBytesPerSecond": 0 - }, - "round_trip_ping": "string", - "round_trip_ping_ms": 0, - "severity": "ok", - "stun": { - "canSTUN": true, - "enabled": true, - "error": "string" - }, - "uses_websocket": true, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "region": { - "avoid": true, - "embeddedRelay": true, - "nodes": [ - { - "canPort80": true, - "certName": "string", - "derpport": 0, - "forceHTTP": true, - "hostName": "string", - "insecureForTests": true, - "ipv4": "string", - "ipv6": "string", - "name": "string", - "regionID": 0, - "stunonly": true, - "stunport": 0, - "stuntestIP": "string" - } - ], - "regionCode": "string", - "regionID": 0, - "regionName": "string" - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - }, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "failing_sections": ["DERP"], - "healthy": true, - "provisioner_daemons": { - "dismissed": true, - "error": "string", - "items": [ - { - "provisioner_daemon": { - "api_version": "string", - "created_at": "2019-08-24T14:15:22Z", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "last_seen_at": "2019-08-24T14:15:22Z", - "name": "string", - "provisioners": ["string"], - "tags": { - "property1": "string", - "property2": "string" - }, - "version": "string" - }, - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - } - ], - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ] - }, - "severity": "ok", - "time": "string", - "websocket": { - "body": "string", - "code": 0, - "dismissed": true, - "error": "string", - "healthy": true, - "severity": "ok", - "warnings": ["string"] - }, - "workspace_proxy": { - "dismissed": true, - "error": "string", - "healthy": true, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ], - "workspace_proxies": { - "regions": [ - { - "created_at": "2019-08-24T14:15:22Z", - "deleted": true, - "derp_enabled": true, - "derp_only": true, - "display_name": "string", - "healthy": true, - "icon_url": "string", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "name": "string", - "path_app_url": "string", - "status": { - "checked_at": "2019-08-24T14:15:22Z", - "report": { - "errors": ["string"], - "warnings": ["string"] - }, - "status": "ok" - }, - "updated_at": "2019-08-24T14:15:22Z", - "version": "string", - "wildcard_hostname": "string" - } - ] - } - } -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| --------------------- | ---------------------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------------------- | -| `access_url` | [healthcheck.AccessURLReport](#healthcheckaccessurlreport) | false | | | -| `coder_version` | string | false | | The Coder version of the server that the report was generated on. | -| `database` | [healthcheck.DatabaseReport](#healthcheckdatabasereport) | false | | | -| `derp` | [derphealth.Report](#derphealthreport) | false | | | -| `failing_sections` | array of [codersdk.HealthSection](#codersdkhealthsection) | false | | Failing sections is a list of sections that have failed their healthcheck. | -| `healthy` | boolean | false | | Healthy is true if the report returns no errors. Deprecated: use `Severity` instead | -| `provisioner_daemons` | [healthcheck.ProvisionerDaemonsReport](#healthcheckprovisionerdaemonsreport) | false | | | -| `severity` | [health.Severity](#healthseverity) | false | | Severity indicates the status of Coder health. | -| `time` | string | false | | Time is the time the report was generated at. | -| `websocket` | [healthcheck.WebsocketReport](#healthcheckwebsocketreport) | false | | | -| `workspace_proxy` | [healthcheck.WorkspaceProxyReport](#healthcheckworkspaceproxyreport) | false | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## healthcheck.WebsocketReport - -```json -{ - "body": "string", - "code": 0, - "dismissed": true, - "error": "string", - "healthy": true, - "severity": "ok", - "warnings": ["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 | | | - -#### Enumerated Values - -| Property | Value | -| ---------- | --------- | -| `severity` | `ok` | -| `severity` | `warning` | -| `severity` | `error` | - -## healthcheck.WorkspaceProxyReport - -```json -{ - "dismissed": true, - "error": "string", - "healthy": true, - "severity": "ok", - "warnings": [ - { - "code": "EUNKNOWN", - "message": "string" - } - ], - "workspace_proxies": { - "regions": [ - { - "created_at": "2019-08-24T14:15:22Z", - "deleted": true, - "derp_enabled": true, - "derp_only": true, - "display_name": "string", - "healthy": true, - "icon_url": "string", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "name": "string", - "path_app_url": "string", - "status": { - "checked_at": "2019-08-24T14:15:22Z", - "report": { - "errors": ["string"], - "warnings": ["string"] - }, - "status": "ok" - }, - "updated_at": "2019-08-24T14:15:22Z", - "version": "string", - "wildcard_hostname": "string" - } - ] - } -} -``` - -### 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 | | | - ## key.NodePublic ```json diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 5840afd3d6..6d2993dcde 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -28,13 +28,13 @@ import ( var ( // baseDirs are the directories to introspect for types to generate. - baseDirs = [...]string{"./codersdk", "./coderd/healthcheck"} + baseDirs = [...]string{"./codersdk"} // externalTypes are types that are not in the baseDirs, but we want to // support. These are usually types that are used in the baseDirs. // Do not include things like "Database", as that would break the idea // of splitting db and api types. // Only include dirs that are client facing packages. - externalTypeDirs = [...]string{"./cli/clibase", "./coderd/healthcheck/health", "./coderd/healthcheck/derphealth"} + externalTypeDirs = [...]string{"./cli/clibase", "./coderd/healthcheck/health"} indent = " " ) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 731b7b3a41..c24005c754 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -27,6 +27,19 @@ export interface APIKeyWithOwner extends APIKey { readonly username: string; } +// From codersdk/health.go +export interface AccessURLReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly dismissed: boolean; + readonly access_url: string; + readonly reachable: boolean; + readonly status_code: number; + readonly healthz_response: string; + readonly error?: string; +} + // From codersdk/licenses.go export interface AddLicenseRequest { readonly license: string; @@ -346,12 +359,60 @@ export interface DERPConfig { readonly path: string; } +// From codersdk/health.go +export interface DERPHealthReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly dismissed: 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 + readonly netcheck?: any; + readonly netcheck_err?: string; + readonly netcheck_logs: string[]; + readonly error?: string; +} + +// From codersdk/health.go +export interface DERPNodeReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly node?: any; + // Named type "tailscale.com/derp.ServerInfoMessage" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly node_info: any; + readonly can_exchange_messages: boolean; + readonly round_trip_ping: string; + readonly round_trip_ping_ms: number; + readonly uses_websocket: boolean; + readonly client_logs: string[][]; + readonly client_errs: string[][]; + readonly error?: string; + readonly stun: STUNReport; +} + // From codersdk/workspaceagents.go export interface DERPRegion { readonly preferred: boolean; readonly latency_ms: number; } +// From codersdk/health.go +export interface DERPRegionReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + // 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 codersdk/deployment.go export interface DERPServerConfig { readonly enable: boolean; @@ -369,6 +430,19 @@ export interface DangerousConfig { readonly allow_all_cors: boolean; } +// From codersdk/health.go +export interface DatabaseReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly dismissed: boolean; + readonly reachable: boolean; + readonly latency: string; + readonly latency_ms: number; + readonly threshold_ms: number; + readonly error?: string; +} + // From codersdk/workspaceagentportshare.go export interface DeleteWorkspaceAgentPortShareRequest { readonly agent_name: string; @@ -605,6 +679,21 @@ export interface HealthcheckConfig { readonly threshold_database: number; } +// From codersdk/health.go +export interface HealthcheckReport { + readonly time: string; + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly failing_sections: HealthSection[]; + readonly derp: DERPHealthReport; + readonly access_url: AccessURLReport; + readonly websocket: WebsocketReport; + readonly database: DatabaseReport; + readonly workspace_proxy: WorkspaceProxyReport; + readonly provisioner_daemons: ProvisionerDaemonsReport; + readonly coder_version: string; +} + // From codersdk/workspaceagents.go export interface IssueReconnectingPTYSignedTokenRequest { readonly url: string; @@ -860,6 +949,21 @@ export interface ProvisionerDaemon { readonly tags: Record; } +// From codersdk/health.go +export interface ProvisionerDaemonsReport { + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly dismissed: boolean; + readonly error?: string; + readonly items: ProvisionerDaemonsReportItem[]; +} + +// From codersdk/health.go +export interface ProvisionerDaemonsReportItem { + readonly provisioner_daemon: ProvisionerDaemon; + readonly warnings: HealthMessage[]; +} + // From codersdk/provisionerdaemons.go export interface ProvisionerJob { readonly id: string; @@ -979,6 +1083,13 @@ export interface SSHConfigResponse { readonly ssh_config_options: Record; } +// From codersdk/health.go +export interface STUNReport { + readonly Enabled: boolean; + readonly CanSTUN: boolean; + readonly Error?: string; +} + // From codersdk/serversentevents.go export interface ServerSentEvent { readonly type: ServerSentEventType; @@ -1509,6 +1620,17 @@ export interface VariableValue { readonly value: string; } +// From codersdk/health.go +export interface WebsocketReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: string[]; + readonly dismissed: boolean; + readonly body: string; + readonly code: number; + readonly error?: string; +} + // From codersdk/workspaces.go export interface Workspace { readonly id: string; @@ -1762,6 +1884,16 @@ export interface WorkspaceProxyBuildInfo { readonly dashboard_url: string; } +// From codersdk/health.go +export interface WorkspaceProxyReport { + readonly healthy: boolean; + readonly severity: HealthSeverity; + readonly warnings: HealthMessage[]; + readonly dismissed: boolean; + readonly error?: string; + readonly workspace_proxies: RegionsResponse; +} + // From codersdk/workspaceproxy.go export interface WorkspaceProxyStatus { readonly status: ProxyHealthStatus; @@ -2286,85 +2418,6 @@ export const WorkspaceTransitions: WorkspaceTransition[] = [ // From codersdk/workspaceproxy.go export type RegionTypes = Region | WorkspaceProxy; -// The code below is generated from coderd/healthcheck. - -// From healthcheck/accessurl.go -export interface HealthcheckAccessURLReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly access_url: string; - readonly reachable: boolean; - readonly status_code: number; - readonly healthz_response: string; - readonly error?: string; -} - -// From healthcheck/database.go -export interface HealthcheckDatabaseReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly reachable: boolean; - readonly latency: string; - readonly latency_ms: number; - readonly threshold_ms: number; - readonly error?: string; -} - -// From healthcheck/provisioner.go -export interface HealthcheckProvisionerDaemonsReport { - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; - readonly items: HealthcheckProvisionerDaemonsReportItem[]; -} - -// From healthcheck/provisioner.go -export interface HealthcheckProvisionerDaemonsReportItem { - readonly provisioner_daemon: ProvisionerDaemon; - readonly warnings: HealthMessage[]; -} - -// From healthcheck/healthcheck.go -export interface HealthcheckReport { - readonly time: string; - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly failing_sections: HealthSection[]; - readonly derp: DerphealthReport; - readonly access_url: HealthcheckAccessURLReport; - readonly websocket: HealthcheckWebsocketReport; - readonly database: HealthcheckDatabaseReport; - readonly workspace_proxy: HealthcheckWorkspaceProxyReport; - readonly provisioner_daemons: HealthcheckProvisionerDaemonsReport; - readonly coder_version: string; -} - -// From healthcheck/websocket.go -export interface HealthcheckWebsocketReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: string[]; - readonly dismissed: boolean; - readonly body: string; - readonly code: number; - readonly error?: string; -} - -// From healthcheck/workspaceproxy.go -export interface HealthcheckWorkspaceProxyReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: boolean; - readonly error?: string; - readonly workspace_proxies: RegionsResponse; -} - // The code below is generated from cli/clibase. // From clibase/clibase.go @@ -2464,60 +2517,3 @@ export const HealthCodes: HealthCode[] = [ // From health/model.go export type HealthSeverity = "error" | "ok" | "warning"; export const HealthSeveritys: HealthSeverity[] = ["error", "ok", "warning"]; - -// The code below is generated from coderd/healthcheck/derphealth. - -// From derphealth/derp.go -export interface DerphealthNodeReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type - readonly node?: any; - // Named type "tailscale.com/derp.ServerInfoMessage" unknown, using "any" - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type - readonly node_info: any; - readonly can_exchange_messages: boolean; - readonly round_trip_ping: string; - readonly round_trip_ping_ms: number; - readonly uses_websocket: boolean; - readonly client_logs: string[][]; - readonly client_errs: string[][]; - readonly error?: string; - readonly stun: DerphealthStunReport; -} - -// From derphealth/derp.go -export interface DerphealthRegionReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - // 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: DerphealthNodeReport[]; - readonly error?: string; -} - -// From derphealth/derp.go -export interface DerphealthReport { - readonly healthy: boolean; - readonly severity: HealthSeverity; - readonly warnings: HealthMessage[]; - readonly dismissed: 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 - readonly netcheck?: any; - readonly netcheck_err?: string; - readonly netcheck_logs: string[]; - readonly error?: string; -} - -// From derphealth/derp.go -export interface DerphealthStunReport { - readonly Enabled: boolean; - readonly CanSTUN: boolean; - readonly Error?: string; -}