Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita17ec4c

Browse files
committed
feat(coderd/healthcheck): add health check for proxy
1 parent78df683 commita17ec4c

File tree

4 files changed

+316
-16
lines changed

4 files changed

+316
-16
lines changed

‎coderd/healthcheck/healthcheck.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,19 @@ import (
1313
)
1414

1515
const (
16-
SectionDERPstring="DERP"
17-
SectionAccessURLstring="AccessURL"
18-
SectionWebsocketstring="Websocket"
19-
SectionDatabasestring="Database"
16+
SectionDERPstring="DERP"
17+
SectionAccessURLstring="AccessURL"
18+
SectionWebsocketstring="Websocket"
19+
SectionDatabasestring="Database"
20+
SectionWorkspaceProxystring="WorkspaceProxy"
2021
)
2122

2223
typeCheckerinterface {
2324
DERP(ctx context.Context,opts*derphealth.ReportOptions) derphealth.Report
2425
AccessURL(ctx context.Context,opts*AccessURLReportOptions)AccessURLReport
2526
Websocket(ctx context.Context,opts*WebsocketReportOptions)WebsocketReport
2627
Database(ctx context.Context,opts*DatabaseReportOptions)DatabaseReport
28+
WorkspaceProxy(ctx context.Context,opts*WorkspaceProxyReportOptions)WorkspaceProxyReport
2729
}
2830

2931
// @typescript-generate Report
@@ -38,20 +40,22 @@ type Report struct {
3840
// FailingSections is a list of sections that have failed their healthcheck.
3941
FailingSections []string`json:"failing_sections"`
4042

41-
DERP derphealth.Report`json:"derp"`
42-
AccessURLAccessURLReport`json:"access_url"`
43-
WebsocketWebsocketReport`json:"websocket"`
44-
DatabaseDatabaseReport`json:"database"`
43+
DERP derphealth.Report`json:"derp"`
44+
AccessURLAccessURLReport`json:"access_url"`
45+
WebsocketWebsocketReport`json:"websocket"`
46+
DatabaseDatabaseReport`json:"database"`
47+
WorkspaceProxyWorkspaceProxyReport`json:"workspace_proxy"`
4548

4649
// The Coder version of the server that the report was generated on.
4750
CoderVersionstring`json:"coder_version"`
4851
}
4952

5053
typeReportOptionsstruct {
51-
AccessURLAccessURLReportOptions
52-
DatabaseDatabaseReportOptions
53-
DerpHealth derphealth.ReportOptions
54-
WebsocketWebsocketReportOptions
54+
AccessURLAccessURLReportOptions
55+
DatabaseDatabaseReportOptions
56+
DerpHealth derphealth.ReportOptions
57+
WebsocketWebsocketReportOptions
58+
WorkspaceProxyWorkspaceProxyReportOptions
5559

5660
CheckerChecker
5761
}
@@ -78,6 +82,11 @@ func (defaultChecker) Database(ctx context.Context, opts *DatabaseReportOptions)
7882
returnreport
7983
}
8084

85+
func (defaultChecker)WorkspaceProxy(ctx context.Context,opts*WorkspaceProxyReportOptions) (reportWorkspaceProxyReport) {
86+
report.Run(ctx,opts)
87+
returnreport
88+
}
89+
8190
funcRun(ctx context.Context,opts*ReportOptions)*Report {
8291
var (
8392
wg sync.WaitGroup
@@ -136,6 +145,18 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
136145
report.Database=opts.Checker.Database(ctx,&opts.Database)
137146
}()
138147

148+
wg.Add(1)
149+
gofunc() {
150+
deferwg.Done()
151+
deferfunc() {
152+
iferr:=recover();err!=nil {
153+
report.WorkspaceProxy.Error=ptr.Ref(fmt.Sprint(err))
154+
}
155+
}()
156+
157+
report.WorkspaceProxy=opts.Checker.WorkspaceProxy(ctx,&opts.WorkspaceProxy)
158+
}()
159+
139160
report.CoderVersion=buildinfo.Version()
140161
wg.Wait()
141162

@@ -153,6 +174,9 @@ func Run(ctx context.Context, opts *ReportOptions) *Report {
153174
if!report.Database.Healthy {
154175
report.FailingSections=append(report.FailingSections,SectionDatabase)
155176
}
177+
if!report.WorkspaceProxy.Healthy {
178+
report.FailingSections=append(report.FailingSections,SectionWorkspaceProxy)
179+
}
156180

157181
report.Healthy=len(report.FailingSections)==0
158182

‎coderd/healthcheck/healthcheck_test.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import (
1111
)
1212

1313
typetestCheckerstruct {
14-
DERPReport derphealth.Report
15-
AccessURLReport healthcheck.AccessURLReport
16-
WebsocketReport healthcheck.WebsocketReport
17-
DatabaseReport healthcheck.DatabaseReport
14+
DERPReport derphealth.Report
15+
AccessURLReport healthcheck.AccessURLReport
16+
WebsocketReport healthcheck.WebsocketReport
17+
DatabaseReport healthcheck.DatabaseReport
18+
WorkspaceProxyReport healthcheck.WorkspaceProxyReport
1819
}
1920

2021
func (c*testChecker)DERP(context.Context,*derphealth.ReportOptions) derphealth.Report {
@@ -33,6 +34,10 @@ func (c *testChecker) Database(context.Context, *healthcheck.DatabaseReportOptio
3334
returnc.DatabaseReport
3435
}
3536

37+
func (c*testChecker)WorkspaceProxy(context.Context,*healthcheck.WorkspaceProxyReportOptions) healthcheck.WorkspaceProxyReport {
38+
returnc.WorkspaceProxyReport
39+
}
40+
3641
funcTestHealthcheck(t*testing.T) {
3742
t.Parallel()
3843

@@ -56,6 +61,9 @@ func TestHealthcheck(t *testing.T) {
5661
DatabaseReport: healthcheck.DatabaseReport{
5762
Healthy:true,
5863
},
64+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
65+
Healthy:true,
66+
},
5967
},
6068
healthy:true,
6169
failingSections: []string{},
@@ -74,6 +82,9 @@ func TestHealthcheck(t *testing.T) {
7482
DatabaseReport: healthcheck.DatabaseReport{
7583
Healthy:true,
7684
},
85+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
86+
Healthy:true,
87+
},
7788
},
7889
healthy:false,
7990
failingSections: []string{healthcheck.SectionDERP},
@@ -93,6 +104,9 @@ func TestHealthcheck(t *testing.T) {
93104
DatabaseReport: healthcheck.DatabaseReport{
94105
Healthy:true,
95106
},
107+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
108+
Healthy:true,
109+
},
96110
},
97111
healthy:true,
98112
failingSections: []string{},
@@ -111,6 +125,9 @@ func TestHealthcheck(t *testing.T) {
111125
DatabaseReport: healthcheck.DatabaseReport{
112126
Healthy:true,
113127
},
128+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
129+
Healthy:true,
130+
},
114131
},
115132
healthy:false,
116133
failingSections: []string{healthcheck.SectionAccessURL},
@@ -129,6 +146,9 @@ func TestHealthcheck(t *testing.T) {
129146
DatabaseReport: healthcheck.DatabaseReport{
130147
Healthy:true,
131148
},
149+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
150+
Healthy:true,
151+
},
132152
},
133153
healthy:false,
134154
failingSections: []string{healthcheck.SectionWebsocket},
@@ -147,9 +167,33 @@ func TestHealthcheck(t *testing.T) {
147167
DatabaseReport: healthcheck.DatabaseReport{
148168
Healthy:false,
149169
},
170+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
171+
Healthy:true,
172+
},
150173
},
151174
healthy:false,
152175
failingSections: []string{healthcheck.SectionDatabase},
176+
}, {
177+
name:"ProxyFail",
178+
checker:&testChecker{
179+
DERPReport: derphealth.Report{
180+
Healthy:true,
181+
},
182+
AccessURLReport: healthcheck.AccessURLReport{
183+
Healthy:true,
184+
},
185+
WebsocketReport: healthcheck.WebsocketReport{
186+
Healthy:true,
187+
},
188+
DatabaseReport: healthcheck.DatabaseReport{
189+
Healthy:true,
190+
},
191+
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
192+
Healthy:false,
193+
},
194+
},
195+
healthy:false,
196+
failingSections: []string{healthcheck.SectionWorkspaceProxy},
153197
}, {
154198
name:"AllFail",
155199
checker:&testChecker{},
@@ -159,6 +203,7 @@ func TestHealthcheck(t *testing.T) {
159203
healthcheck.SectionAccessURL,
160204
healthcheck.SectionWebsocket,
161205
healthcheck.SectionDatabase,
206+
healthcheck.SectionWorkspaceProxy,
162207
},
163208
}} {
164209
c:=c
@@ -175,6 +220,8 @@ func TestHealthcheck(t *testing.T) {
175220
assert.Equal(t,c.checker.DERPReport.Warnings,report.DERP.Warnings)
176221
assert.Equal(t,c.checker.AccessURLReport.Healthy,report.AccessURL.Healthy)
177222
assert.Equal(t,c.checker.WebsocketReport.Healthy,report.Websocket.Healthy)
223+
assert.Equal(t,c.checker.WorkspaceProxyReport.Healthy,report.WorkspaceProxy.Healthy)
224+
assert.Equal(t,c.checker.WorkspaceProxyReport.Warnings,report.WorkspaceProxy.Warnings)
178225
assert.NotZero(t,report.Time)
179226
assert.NotZero(t,report.CoderVersion)
180227
})

‎coderd/healthcheck/workspaceproxy.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package healthcheck
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"cdr.dev/slog"
8+
"github.com/coder/coder/v2/buildinfo"
9+
"github.com/coder/coder/v2/coderd/util/ptr"
10+
"github.com/coder/coder/v2/codersdk"
11+
)
12+
13+
typeWorkspaceProxyReportOptionsstruct {
14+
// UpdateProxyHealth is a function called when healthcheck is run.
15+
// This would normally be ProxyHealth.ForceUpdate().
16+
// We do this because if someone mashes the healthcheck refresh button
17+
// they would expect up-to-date data.
18+
UpdateProxyHealthfunc(context.Context)error
19+
// FetchWorkspaceProxies is a function that returns the available workspace proxies.
20+
FetchWorkspaceProxiesfunc(context.Context) (codersdk.RegionsResponse[codersdk.WorkspaceProxy],error)
21+
// CurrentVersion is the current server version.
22+
// We pass this in to make it easier to test.
23+
CurrentVersionstring
24+
Logger slog.Logger
25+
}
26+
27+
// @typescript-generate Report
28+
typeWorkspaceProxyReportstruct {
29+
Healthybool`json:"healthy"`
30+
Warnings []string`json:"warnings"`
31+
Error*string`json:"error"`
32+
33+
WorkspaceProxies codersdk.RegionsResponse[codersdk.WorkspaceProxy]
34+
}
35+
36+
func (r*WorkspaceProxyReport)Run(ctx context.Context,opts*WorkspaceProxyReportOptions) {
37+
r.Healthy=true
38+
r.Warnings= []string{}
39+
40+
ifopts.FetchWorkspaceProxies==nil {
41+
opts.Logger.Debug(ctx,"no workspace proxies configured")
42+
return
43+
}
44+
45+
ifopts.UpdateProxyHealth==nil {
46+
err:="opts.UpdateProxyHealth must not be nil if opts.FetchWorkspaceProxies is not nil"
47+
opts.Logger.Error(ctx,"developer error: "+err)
48+
r.Error=ptr.Ref(err)
49+
return
50+
}
51+
52+
iferr:=opts.UpdateProxyHealth(ctx);err!=nil {
53+
opts.Logger.Error(ctx,"failed to update proxy health: %w",err)
54+
r.Error=ptr.Ref(err.Error())
55+
return
56+
}
57+
58+
proxies,err:=opts.FetchWorkspaceProxies(ctx)
59+
iferr!=nil {
60+
opts.Logger.Error(ctx,"failed to fetch workspace proxies",slog.Error(err))
61+
r.Healthy=false
62+
r.Error=ptr.Ref(err.Error())
63+
return
64+
}
65+
66+
r.WorkspaceProxies=proxies
67+
68+
varnumProxiesint
69+
varhealthyProxiesint
70+
for_,proxy:=ranger.WorkspaceProxies.Regions {
71+
numProxies++
72+
ifproxy.Healthy {
73+
healthyProxies++
74+
}
75+
76+
// check versions
77+
if!buildinfo.VersionsMatch(proxy.Version,opts.CurrentVersion) {
78+
opts.Logger.Warn(ctx,"proxy version mismatch",
79+
slog.F("version",opts.CurrentVersion),
80+
slog.F("proxy_version",proxy.Version),
81+
slog.F("proxy_name",proxy.Name),
82+
)
83+
r.Healthy=false
84+
r.Warnings=append(r.Warnings,fmt.Sprintf("Proxy %q version %q does not match primary server version %q",proxy.Name,proxy.Version,opts.CurrentVersion))
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp