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

Commit220e95d

Browse files
authored
feat(site): add healthcheck page for provisioner daemons (#11494)
Part of#10676- Adds a health section for provisioner daemons (mostly cannibalized from the Workspace Proxy section)- Adds a corresponding storybook entry for provisioner daemons health section- Fixed an issue where dismissing the provisioner daemons warnings would result in a 500 error- Adds provisioner daemon error codes to docs
1 parent6096af7 commit220e95d

File tree

8 files changed

+277
-3
lines changed

8 files changed

+277
-3
lines changed

‎codersdk/health.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var HealthSections = []HealthSection{
2626
HealthSectionWebsocket,
2727
HealthSectionDatabase,
2828
HealthSectionWorkspaceProxy,
29+
HealthSectionProvisionerDaemons,
2930
}
3031

3132
typeHealthSettingsstruct {

‎docs/admin/healthcheck.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,54 @@ _One or more Workspace Proxies Unhealthy_
267267
**Solution:** Ensure that Coder can establish a connection to the configured
268268
workspace proxies.
269269

270+
###EPD01
271+
272+
_No Provisioner Daemons Available_
273+
274+
**Problem:** No provisioner daemons are registered with Coder. No workspaces can
275+
be built until there is at least one provisioner daemon running.
276+
277+
**Solution:**
278+
279+
If you are using
280+
[External Provisioner Daemons](./provisioners.md#external-provisioners), ensure
281+
that they are able to successfully connect to Coder. Otherwise, ensure
282+
[`--provisioner-daemons`](../cli/server.md#provisioner-daemons) is set to a
283+
value greater than 0.
284+
285+
>Note: This may be a transient issue if you are currently in the process of
286+
>updating your deployment.
287+
288+
###EPD02
289+
290+
_Provisioner Daemon Version Mismatch_
291+
292+
**Problem:** One or more provisioner daemons are more than one major or minor
293+
version out of date with the main deployment. It is important that provisioner
294+
daemons are updated at the same time as the main deployment to minimize the risk
295+
of API incompatibility.
296+
297+
**Solution:** Update the provisioner daemon to match the currently running
298+
version of Coder.
299+
300+
>Note: This may be a transient issue if you are currently in the process of
301+
>updating your deployment.
302+
303+
###EPD03
304+
305+
_Provisioner Daemon API Version Mismatch_
306+
307+
**Problem:** One or more provisioner daemons are using APIs that are marked as
308+
deprecated. These deprecated APIs may be removed in a future release of Coder,
309+
at which point the affected provisioner daemons will no longer be able to
310+
connect to Coder.
311+
312+
**Solution:** Update the provisioner daemon to match the currently running
313+
version of Coder.
314+
315+
>Note: This may be a transient issue if you are currently in the process of
316+
>updating your deployment.
317+
270318
##EUNKNOWN
271319

272320
_Unknown Error_

‎site/src/AppRouter.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ const WebsocketPage = lazy(() => import("./pages/HealthPage/WebsocketPage"));
234234
constWorkspaceProxyHealthPage=lazy(
235235
()=>import("./pages/HealthPage/WorkspaceProxyPage"),
236236
);
237+
constProvisionerDaemonsHealthPage=lazy(
238+
()=>import("./pages/HealthPage/ProvisionerDaemonsPage"),
239+
);
237240

238241
exportconstAppRouter:FC=()=>{
239242
return(
@@ -400,6 +403,10 @@ export const AppRouter: FC = () => {
400403
path="workspace-proxy"
401404
element={<WorkspaceProxyHealthPage/>}
402405
/>
406+
<Route
407+
path="provisioner-daemons"
408+
element={<ProvisionerDaemonsHealthPage/>}
409+
/>
403410
</Route>
404411
{/* Using path="*"" means "match anything", so this route
405412
acts like a catch-all for URLs that we don't have explicit

‎site/src/pages/HealthPage/HealthLayout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function HealthLayout() {
3434
websocket:"Websocket",
3535
database:"Database",
3636
workspace_proxy:"Workspace Proxy",
37+
provisioner_daemons:"Provisioner Daemons",
3738
}asconst;
3839
constvisibleSections=filterVisibleSections(sections);
3940

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import{StoryObj,Meta}from"@storybook/react";
2+
import{ProvisionerDaemonsPage}from"./ProvisionerDaemonsPage";
3+
import{generateMeta}from"./storybook";
4+
5+
constmeta:Meta={
6+
title:"pages/Health/ProvisionerDaemons",
7+
...generateMeta({
8+
path:"/health/provisioner-daemons",
9+
element:<ProvisionerDaemonsPage/>,
10+
}),
11+
};
12+
13+
exportdefaultmeta;
14+
typeStory=StoryObj;
15+
16+
exportconstDefault:Story={};
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import{Header,HeaderTitle,HealthyDot,Main,Pill}from"./Content";
2+
import{Helmet}from"react-helmet-async";
3+
import{pageTitle}from"utils/page";
4+
import{useTheme}from"@mui/material/styles";
5+
import{DismissWarningButton}from"./DismissWarningButton";
6+
import{Alert}from"components/Alert/Alert";
7+
import{HealthcheckReport}from"api/typesGenerated";
8+
import{createDayString}from"utils/createDayString";
9+
10+
import{useOutletContext}from"react-router-dom";
11+
importBusinessfrom"@mui/icons-material/Business";
12+
importPersonfrom"@mui/icons-material/Person";
13+
importSwapHorizfrom"@mui/icons-material/SwapHoriz";
14+
importTooltipfrom"@mui/material/Tooltip";
15+
importSellfrom"@mui/icons-material/Sell";
16+
17+
exportconstProvisionerDaemonsPage=()=>{
18+
consthealthStatus=useOutletContext<HealthcheckReport>();
19+
const{provisioner_daemons:daemons}=healthStatus;
20+
consttheme=useTheme();
21+
return(
22+
<>
23+
<Helmet>
24+
<title>{pageTitle("Provisioner Daemons - Health")}</title>
25+
</Helmet>
26+
27+
<Header>
28+
<HeaderTitle>
29+
<HealthyDotseverity={daemons.severity}/>
30+
Provisioner Daemons
31+
</HeaderTitle>
32+
<DismissWarningButtonhealthcheck="ProvisionerDaemons"/>
33+
</Header>
34+
35+
<Main>
36+
{daemons.warnings.map((warning)=>{
37+
return(
38+
<Alertkey={warning.code}severity="warning">
39+
{warning.message}
40+
</Alert>
41+
);
42+
})}
43+
44+
{daemons.items.map(({provisioner_daemon:daemon, warnings})=>{
45+
constdaemonScope=daemon.tags["scope"]||"organization";
46+
consticonScope=
47+
daemonScope==="organization" ?<Business/> :<Person/>;
48+
constextraTags=Object.keys(daemon.tags)
49+
.filter((key)=>key!=="scope"&&key!=="owner")
50+
.reduce(
51+
(acc,key)=>{
52+
acc[key]=daemon.tags[key];
53+
returnacc;
54+
},
55+
{}asRecord<string,string>,
56+
);
57+
constisWarning=warnings.length>0;
58+
return(
59+
<div
60+
key={daemon.name}
61+
css={{
62+
borderRadius:8,
63+
border:`1px solid${
64+
isWarning
65+
?theme.palette.warning.light
66+
:theme.palette.divider
67+
}`,
68+
fontSize:14,
69+
}}
70+
>
71+
<header
72+
css={{
73+
padding:24,
74+
display:"flex",
75+
alignItems:"center",
76+
justifyContenxt:"space-between",
77+
gap:24,
78+
}}
79+
>
80+
<div
81+
css={{
82+
display:"flex",
83+
alignItems:"center",
84+
gap:24,
85+
objectFit:"fill",
86+
}}
87+
>
88+
<divcss={{lineHeight:"160%"}}>
89+
<h4css={{fontWeight:500,margin:0}}>{daemon.name}</h4>
90+
<spancss={{color:theme.palette.text.secondary}}>
91+
<code>{daemon.version}</code>
92+
</span>
93+
</div>
94+
</div>
95+
<div
96+
css={{
97+
marginLeft:"auto",
98+
display:"flex",
99+
flexWrap:"wrap",
100+
gap:12,
101+
}}
102+
>
103+
<Tooltiptitle="API Version">
104+
<Pillicon={<SwapHoriz/>}>
105+
<code>{daemon.api_version}</code>
106+
</Pill>
107+
</Tooltip>
108+
<Tooltiptitle="Scope">
109+
<Pillicon={iconScope}>
110+
<span
111+
css={{
112+
":first-letter":{textTransform:"uppercase"},
113+
}}
114+
>
115+
{daemonScope}
116+
</span>
117+
</Pill>
118+
</Tooltip>
119+
{Object.keys(extraTags).map((k)=>(
120+
<Tooltipkey={k}title={k}>
121+
<Pillkey={k}icon={<Sell/>}>
122+
{extraTags[k]}
123+
</Pill>
124+
</Tooltip>
125+
))}
126+
</div>
127+
</header>
128+
129+
<div
130+
css={{
131+
borderTop:`1px solid${theme.palette.divider}`,
132+
display:"flex",
133+
alignItems:"center",
134+
justifyContent:"space-between",
135+
padding:"8px 24px",
136+
fontSize:12,
137+
color:theme.palette.text.secondary,
138+
}}
139+
>
140+
{warnings.length>0 ?(
141+
<divcss={{display:"flex",flexDirection:"column"}}>
142+
{warnings.map((warning,i)=>(
143+
<spankey={i}>{warning.message}</span>
144+
))}
145+
</div>
146+
) :(
147+
<span>No warnings</span>
148+
)}
149+
{daemon.last_seen_at&&(
150+
<span
151+
css={{color:theme.palette.text.secondary}}
152+
data-chromatic="ignore"
153+
>
154+
Last seen{createDayString(daemon.last_seen_at)}
155+
</span>
156+
)}
157+
</div>
158+
</div>
159+
);
160+
})}
161+
</Main>
162+
</>
163+
);
164+
};
165+
166+
exportdefaultProvisionerDaemonsPage;

‎site/src/testHelpers/entities.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,25 +3103,60 @@ export const MockHealth: TypesGen.HealthcheckReport = {
31033103
},
31043104
provisioner_daemons:{
31053105
severity:"ok",
3106-
warnings:[],
3106+
warnings:[
3107+
{
3108+
message:"Something is wrong!",
3109+
code:"EUNKNOWN",
3110+
},
3111+
{
3112+
message:"This is also bad.",
3113+
code:"EPD01",
3114+
},
3115+
],
31073116
dismissed:false,
31083117
items:[
31093118
{
31103119
provisioner_daemon:{
31113120
id:"e455b582-ac04-4323-9ad6-ab71301fa006",
31123121
created_at:"2024-01-04T15:53:03.21563Z",
31133122
last_seen_at:"2024-01-04T16:05:03.967551Z",
3114-
name:"vvuurrkk-2",
3115-
version:"v2.6.0-devel+965ad5e96",
3123+
name:"ok",
3124+
version:"v2.3.4-devel+abcd1234",
31163125
api_version:"1.0",
31173126
provisioners:["echo","terraform"],
31183127
tags:{
31193128
owner:"",
31203129
scope:"organization",
3130+
custom_tag_name:"custom_tag_value",
31213131
},
31223132
},
31233133
warnings:[],
31243134
},
3135+
{
3136+
provisioner_daemon:{
3137+
id:"e455b582-ac04-4323-9ad6-ab71301fa006",
3138+
created_at:"2024-01-04T15:53:03.21563Z",
3139+
last_seen_at:"2024-01-04T16:05:03.967551Z",
3140+
name:"unhappy",
3141+
version:"v0.0.1",
3142+
api_version:"0.1",
3143+
provisioners:["echo","terraform"],
3144+
tags:{
3145+
owner:"",
3146+
scope:"organization",
3147+
},
3148+
},
3149+
warnings:[
3150+
{
3151+
message:"Something specific is wrong with this daemon.",
3152+
code:"EUNKNOWN",
3153+
},
3154+
{
3155+
message:"And now for something completely different.",
3156+
code:"EUNKNOWN",
3157+
},
3158+
],
3159+
},
31253160
],
31263161
},
31273162
coder_version:"v2.5.0-devel+5fad61102",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp