refactor(coderd): move healthcheck report structs to codersdk (#12279)

Moves healthcheck report-related structs from coderd/healthcheck to codersdk
This prevents an import cycle when adding a codersdk.Client method to hit /api/v2/debug/health.
This commit is contained in:
Cian Johnston 2024-02-23 13:13:28 +00:00 committed by GitHub
parent aa7a9f5cc4
commit 2cb9bfd517
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 2314 additions and 2298 deletions

View File

@ -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)

849
coderd/apidoc/docs.go generated
View File

@ -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"
},

View File

@ -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"
},

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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] = &regionReport
r.Regions[region.RegionID] = &regionReport.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)
})
}

View File

@ -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 {

View File

@ -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,
},
},

View File

@ -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),
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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"`
}

8
docs/api/debug.md generated
View File

@ -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).

2062
docs/api/schemas.md generated

File diff suppressed because it is too large Load Diff

View File

@ -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 = " "
)

View File

@ -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<number, DERPRegionReport>;
// 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<string, string>;
}
// 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<string, string>;
}
// 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<WorkspaceProxy>;
}
// 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<WorkspaceProxy>;
}
// 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<number, DerphealthRegionReport>;
// 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;
}