From 3cf35ebad20f7d2535a9631a23cc23b2a5b009fd Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Mon, 13 Nov 2023 13:32:25 +0100 Subject: [PATCH 1/5] WIP --- coderd/healthcheck/healthcheck.go | 2 +- scripts/apitypings/main_test.go | 6 +++ site/src/api/api.ts | 12 +---- .../DeploymentBanner/DeploymentBannerView.tsx | 5 +- site/src/testHelpers/entities.ts | 49 ++++++++++++------- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/coderd/healthcheck/healthcheck.go b/coderd/healthcheck/healthcheck.go index 61c6e40c1e1be..d90f3529af7e2 100644 --- a/coderd/healthcheck/healthcheck.go +++ b/coderd/healthcheck/healthcheck.go @@ -30,7 +30,7 @@ type Checker interface { Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport } -// @typescript-generate Report +// @typescript-generate DerphealthReport type Report struct { // Time is the time the report was generated at. Time time.Time `json:"time"` diff --git a/scripts/apitypings/main_test.go b/scripts/apitypings/main_test.go index d777f18950f17..e2b35351d505c 100644 --- a/scripts/apitypings/main_test.go +++ b/scripts/apitypings/main_test.go @@ -41,3 +41,9 @@ func TestGeneration(t *testing.T) { }) } } + +func TestFoo(t *testing.T) { + output, err := Generate("/Users/mtojek/code/coder/coderd/healthcheck") + require.NoError(t, err) + require.Equal(t, "a", output) +} diff --git a/site/src/api/api.ts b/site/src/api/api.ts index ae26b8b0cbb80..2a9fe0e68a981 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1555,17 +1555,7 @@ export const getInsightsTemplate = async ( return response.data; }; -export interface Health { - healthy: boolean; - time: string; - coder_version: string; - access_url: { healthy: boolean }; - database: { healthy: boolean }; - derp: { healthy: boolean }; - websocket: { healthy: boolean }; -} - export const getHealth = async () => { - const response = await axios.get("/api/v2/debug/health"); + const response = await axios.get("/api/v2/debug/health"); return response.data; }; diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx index 61f68cc5b0f0b..1f27a9a38975d 100644 --- a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx +++ b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx @@ -1,5 +1,4 @@ -import type { Health } from "api/api"; -import type { DeploymentStats, WorkspaceStatus } from "api/typesGenerated"; +import type { DeploymentStats, HealthcheckReport, WorkspaceStatus } from "api/typesGenerated"; import { type FC, useMemo, @@ -67,7 +66,7 @@ const styles = { } satisfies Record>; export interface DeploymentBannerViewProps { - health?: Health; + health?: HealthcheckReport; stats?: DeploymentStats; fetchStats?: () => void; } diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 0a8cf0e1b3ff2..998ae49e73632 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1,8 +1,7 @@ import { withDefaultFeatures, type GetLicensesResponse, - type DeploymentConfig, - type Health, + type DeploymentConfig } from "api/api"; import { FieldError } from "api/errors"; import * as TypesGen from "api/typesGenerated"; @@ -2385,10 +2384,10 @@ export const MockLicenseResponse: GetLicensesResponse[] = [ }, ]; -export const MockHealth = { +export const MockHealth: TypesGen.HealthcheckReport = { time: "2023-08-01T16:51:03.29792825Z", healthy: true, - failing_sections: null, + failing_sections: [], derp: { healthy: true, regions: { @@ -2785,21 +2784,17 @@ export const MockHealth = { reachable: true, status_code: 200, healthz_response: "OK", - error: null, }, websocket: { healthy: true, - response: { - body: "", - code: 101, - }, - error: null, + body: "", + code: 101 }, database: { healthy: true, reachable: true, - latency: 92570, - error: null, + latency: "92570", + latency_ms: 92570, }, coder_version: "v0.27.1-devel+c575292", }; @@ -2813,12 +2808,32 @@ export const MockListeningPortsResponse: TypesGen.WorkspaceAgentListeningPortsRe ], }; -export const DeploymentHealthUnhealthy: Health = { +export const DeploymentHealthUnhealthy: TypesGen.HealthcheckReport = { healthy: false, + failing_sections: [], // apparently this property is not used at all? time: "2023-10-12T23:15:00.000000000Z", coder_version: "v2.3.0-devel+8cca4915a", - access_url: { healthy: true }, - database: { healthy: false }, - derp: { healthy: false }, - websocket: { healthy: false }, + access_url: { + healthy: true, + access_url: "", + healthz_response: "", + reachable: true, + status_code: 0, + }, + database: { + healthy: false, + latency: "", + latency_ms: 0, + reachable: true, + }, + derp: { + healthy: false, + regions: [], + netcheck_logs: [], + }, + websocket: { + healthy: false, + body: "", + code: 0, + }, }; From a7ec151ff6af5d187d851a57cb398043b972c6ff Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Mon, 13 Nov 2023 13:59:49 +0100 Subject: [PATCH 2/5] Healthcheck fix --- coderd/healthcheck/healthcheck.go | 2 +- scripts/apitypings/main.go | 4 +- site/src/api/typesGenerated.ts | 94 +++++++++++++++---------------- 3 files changed, 49 insertions(+), 51 deletions(-) diff --git a/coderd/healthcheck/healthcheck.go b/coderd/healthcheck/healthcheck.go index d90f3529af7e2..61c6e40c1e1be 100644 --- a/coderd/healthcheck/healthcheck.go +++ b/coderd/healthcheck/healthcheck.go @@ -30,7 +30,7 @@ type Checker interface { Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport } -// @typescript-generate DerphealthReport +// @typescript-generate Report type Report struct { // Time is the time the report was generated at. Time time.Time `json:"time"` diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index cb842d601fbfa..06b5d44e6dd3c 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", "./coderd/healthcheck/derphealth"} + baseDirs = [...]string{"./codersdk", "./coderd/healthcheck"} // 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"} + externalTypeDirs = [...]string{"./cli/clibase", "./coderd/healthcheck/derphealth"} indent = " " ) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 920237160dfd1..876695ec11c3d 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -2096,9 +2096,7 @@ export interface HealthcheckReport { readonly time: string; readonly healthy: boolean; readonly failing_sections: string[]; - // Named type "github.com/coder/coder/v2/coderd/healthcheck/derphealth.Report" unknown, using "any" - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type - readonly derp: any; + readonly derp: DerphealthReport; readonly access_url: HealthcheckAccessURLReport; readonly websocket: HealthcheckWebsocketReport; readonly database: HealthcheckDatabaseReport; @@ -2113,6 +2111,51 @@ export interface HealthcheckWebsocketReport { readonly error?: string; } +// The code below is generated from cli/clibase. + +// From clibase/clibase.go +export type ClibaseAnnotations = Record; + +// From clibase/clibase.go +export interface ClibaseGroup { + readonly parent?: ClibaseGroup; + readonly name?: string; + readonly yaml?: string; + readonly description?: string; +} + +// From clibase/option.go +export interface ClibaseOption { + readonly name?: string; + readonly description?: string; + readonly required?: boolean; + readonly flag?: string; + readonly flag_shorthand?: string; + readonly env?: string; + readonly yaml?: string; + readonly default?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Golang interface, unable to resolve type. + readonly value?: any; + readonly annotations?: ClibaseAnnotations; + readonly group?: ClibaseGroup; + readonly use_instead?: ClibaseOption[]; + readonly hidden?: boolean; + readonly value_source?: ClibaseValueSource; +} + +// From clibase/option.go +export type ClibaseOptionSet = ClibaseOption[]; + +// From clibase/option.go +export type ClibaseValueSource = "" | "default" | "env" | "flag" | "yaml"; +export const ClibaseValueSources: ClibaseValueSource[] = [ + "", + "default", + "env", + "flag", + "yaml", +]; + // The code below is generated from coderd/healthcheck/derphealth. // From derphealth/derp.go @@ -2162,48 +2205,3 @@ export interface DerphealthStunReport { readonly CanSTUN: boolean; readonly Error?: string; } - -// The code below is generated from cli/clibase. - -// From clibase/clibase.go -export type ClibaseAnnotations = Record; - -// From clibase/clibase.go -export interface ClibaseGroup { - readonly parent?: ClibaseGroup; - readonly name?: string; - readonly yaml?: string; - readonly description?: string; -} - -// From clibase/option.go -export interface ClibaseOption { - readonly name?: string; - readonly description?: string; - readonly required?: boolean; - readonly flag?: string; - readonly flag_shorthand?: string; - readonly env?: string; - readonly yaml?: string; - readonly default?: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Golang interface, unable to resolve type. - readonly value?: any; - readonly annotations?: ClibaseAnnotations; - readonly group?: ClibaseGroup; - readonly use_instead?: ClibaseOption[]; - readonly hidden?: boolean; - readonly value_source?: ClibaseValueSource; -} - -// From clibase/option.go -export type ClibaseOptionSet = ClibaseOption[]; - -// From clibase/option.go -export type ClibaseValueSource = "" | "default" | "env" | "flag" | "yaml"; -export const ClibaseValueSources: ClibaseValueSource[] = [ - "", - "default", - "env", - "flag", - "yaml", -]; From 220091e0bdbc9fc83c4ea2660eed8371c3192498 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Mon, 13 Nov 2023 14:03:04 +0100 Subject: [PATCH 3/5] fix --- scripts/apitypings/main_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/apitypings/main_test.go b/scripts/apitypings/main_test.go index e2b35351d505c..d777f18950f17 100644 --- a/scripts/apitypings/main_test.go +++ b/scripts/apitypings/main_test.go @@ -41,9 +41,3 @@ func TestGeneration(t *testing.T) { }) } } - -func TestFoo(t *testing.T) { - output, err := Generate("/Users/mtojek/code/coder/coderd/healthcheck") - require.NoError(t, err) - require.Equal(t, "a", output) -} From c613e176404ac68edb1b6829a9bdf769f6d33f96 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Mon, 13 Nov 2023 14:08:21 +0100 Subject: [PATCH 4/5] fmt --- site/src/api/api.ts | 4 +++- .../Dashboard/DeploymentBanner/DeploymentBannerView.tsx | 6 +++++- site/src/testHelpers/entities.ts | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 2a9fe0e68a981..0f1d75b0bb9b9 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1556,6 +1556,8 @@ export const getInsightsTemplate = async ( }; export const getHealth = async () => { - const response = await axios.get("/api/v2/debug/health"); + const response = await axios.get( + "/api/v2/debug/health", + ); return response.data; }; diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx index 1f27a9a38975d..3fea96bc4cc4f 100644 --- a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx +++ b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx @@ -1,4 +1,8 @@ -import type { DeploymentStats, HealthcheckReport, WorkspaceStatus } from "api/typesGenerated"; +import type { + DeploymentStats, + HealthcheckReport, + WorkspaceStatus, +} from "api/typesGenerated"; import { type FC, useMemo, diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 998ae49e73632..67fc9d2cb308e 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1,7 +1,7 @@ import { withDefaultFeatures, type GetLicensesResponse, - type DeploymentConfig + type DeploymentConfig, } from "api/api"; import { FieldError } from "api/errors"; import * as TypesGen from "api/typesGenerated"; @@ -2788,7 +2788,7 @@ export const MockHealth: TypesGen.HealthcheckReport = { websocket: { healthy: true, body: "", - code: 101 + code: 101, }, database: { healthy: true, From f23c827a13fcf3acc79b24a3693fae41be50292f Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Mon, 13 Nov 2023 14:16:36 +0100 Subject: [PATCH 5/5] entities --- site/src/testHelpers/entities.ts | 46 +++++++++++--------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 67fc9d2cb308e..151a11c7fe0f3 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -2430,15 +2430,14 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: false, - round_trip_ping: 0, + round_trip_ping: "0", + round_trip_ping_ms: 0, uses_websocket: false, client_logs: [], client_errs: [], - error: null, stun: { Enabled: true, CanSTUN: true, - Error: null, }, }, { @@ -2455,7 +2454,8 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: true, - round_trip_ping: 7674330, + round_trip_ping: "7674330", + round_trip_ping_ms: 7674330, uses_websocket: false, client_logs: [ [ @@ -2466,15 +2466,12 @@ export const MockHealth: TypesGen.HealthcheckReport = { ], ], client_errs: [[], []], - error: null, stun: { Enabled: false, CanSTUN: false, - Error: null, }, }, ], - error: null, }, "10007": { healthy: true, @@ -2515,15 +2512,14 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: false, - round_trip_ping: 0, + round_trip_ping: "0", + round_trip_ping_ms: 0, uses_websocket: false, client_logs: [], client_errs: [], - error: null, stun: { Enabled: true, CanSTUN: true, - Error: null, }, }, { @@ -2540,7 +2536,8 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: true, - round_trip_ping: 170527034, + round_trip_ping: "170527034", + round_trip_ping_ms: 170527034, uses_websocket: false, client_logs: [ [ @@ -2551,15 +2548,12 @@ export const MockHealth: TypesGen.HealthcheckReport = { ], ], client_errs: [[], []], - error: null, stun: { Enabled: false, CanSTUN: false, - Error: null, }, }, ], - error: null, }, "10008": { healthy: true, @@ -2600,15 +2594,14 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: false, - round_trip_ping: 0, + round_trip_ping: "0", + round_trip_ping_ms: 0, uses_websocket: false, client_logs: [], client_errs: [], - error: null, stun: { Enabled: true, CanSTUN: true, - Error: null, }, }, { @@ -2625,7 +2618,8 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: true, - round_trip_ping: 111329690, + round_trip_ping: "111329690", + round_trip_ping_ms: 111329690, uses_websocket: false, client_logs: [ [ @@ -2636,15 +2630,12 @@ export const MockHealth: TypesGen.HealthcheckReport = { ], ], client_errs: [[], []], - error: null, stun: { Enabled: false, CanSTUN: false, - Error: null, }, }, ], - error: null, }, "10009": { healthy: true, @@ -2685,15 +2676,14 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: false, - round_trip_ping: 0, + round_trip_ping: "0", + round_trip_ping_ms: 0, uses_websocket: false, client_logs: [], client_errs: [], - error: null, stun: { Enabled: true, CanSTUN: true, - Error: null, }, }, { @@ -2710,7 +2700,8 @@ export const MockHealth: TypesGen.HealthcheckReport = { TokenBucketBytesBurst: 0, }, can_exchange_messages: true, - round_trip_ping: 138185506, + round_trip_ping: "138185506", + round_trip_ping_ms: 138185506, uses_websocket: false, client_logs: [ [ @@ -2721,15 +2712,12 @@ export const MockHealth: TypesGen.HealthcheckReport = { ], ], client_errs: [[], []], - error: null, stun: { Enabled: false, CanSTUN: false, - Error: null, }, }, ], - error: null, }, }, netcheck: { @@ -2763,7 +2751,6 @@ export const MockHealth: TypesGen.HealthcheckReport = { GlobalV6: "", CaptivePortal: null, }, - netcheck_err: null, netcheck_logs: [ "netcheck: netcheck.runProbe: got STUN response for 10007stun0 from 34.71.26.24:55368 (9b07930007da49dd7df79bc7) in 1.791799ms", "netcheck: netcheck.runProbe: got STUN response for 999stun0 from 34.71.26.24:55368 (7397fec097f1d5b01364566b) in 1.791529ms", @@ -2776,7 +2763,6 @@ export const MockHealth: TypesGen.HealthcheckReport = { "netcheck: [v1] measureAllICMPLatency: listen ip4:icmp 0.0.0.0: socket: operation not permitted", "netcheck: [v1] report: udp=true v6=false v6os=true mapvarydest=false hair= portmap= v4a=34.71.26.24:55368 derp=999 derpdist=999v4:2ms,10007v4:175ms,10008v4:112ms,10009v4:139ms", ], - error: null, }, access_url: { access_url: "https://dev.coder.com",