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

Commit1924f58

Browse files
committed
Merge branch 'main' into exportstats
2 parents506740b +09f87d1 commit1924f58

File tree

123 files changed

+3560
-1242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+3560
-1242
lines changed

‎.github/workflows/contrib.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,28 @@ concurrency: pr-${{ github.ref }}
1919

2020
jobs:
2121
# Dependabot is annoying, but this makes it a bit less so.
22-
auto-approve:
22+
auto-approve-dependabot:
2323
runs-on:ubuntu-latest
2424
if:github.event_name == 'pull_request_target'
2525
permissions:
2626
pull-requests:write
2727
steps:
2828
-uses:hmarr/auto-approve-action@v3
2929
if:github.actor == 'dependabot[bot]'
30+
auto-approve-docs:
31+
runs-on:ubuntu-latest
32+
if:github.event_name == 'pull_request_target'
33+
permissions:
34+
pull-requests:write
35+
steps:
36+
-uses:actions/checkout@v3
37+
-name:Get changed files in the docs folder
38+
id:changed-files
39+
uses:tj-actions/changed-files@v35
40+
with:
41+
files:docs/*
42+
-uses:hmarr/auto-approve-action@v3
43+
if:github.actor == 'bpmct' && steps.changed-files.outputs.only_changed == 'true'
3044

3145
cla:
3246
runs-on:ubuntu-latest

‎agent/agent.go

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ func New(options Options) io.Closer {
122122
logDir:options.LogDir,
123123
tempDir:options.TempDir,
124124
lifecycleUpdate:make(chanstruct{},1),
125+
lifecycleReported:make(chan codersdk.WorkspaceAgentLifecycle,1),
125126
connStatsChan:make(chan*agentsdk.Stats,1),
126127
}
127128
a.init(ctx)
@@ -150,9 +151,10 @@ type agent struct {
150151
sessionToken atomic.Pointer[string]
151152
sshServer*ssh.Server
152153

153-
lifecycleUpdatechanstruct{}
154-
lifecycleMu sync.Mutex// Protects following.
155-
lifecycleState codersdk.WorkspaceAgentLifecycle
154+
lifecycleUpdatechanstruct{}
155+
lifecycleReportedchan codersdk.WorkspaceAgentLifecycle
156+
lifecycleMu sync.RWMutex// Protects following.
157+
lifecycleState codersdk.WorkspaceAgentLifecycle
156158

157159
network*tailnet.Conn
158160
connStatsChanchan*agentsdk.Stats
@@ -205,9 +207,9 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
205207
}
206208

207209
forr:=retry.New(time.Second,15*time.Second);r.Wait(ctx); {
208-
a.lifecycleMu.Lock()
210+
a.lifecycleMu.RLock()
209211
state:=a.lifecycleState
210-
a.lifecycleMu.Unlock()
212+
a.lifecycleMu.RUnlock()
211213

212214
ifstate==lastReported {
213215
break
@@ -220,6 +222,11 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
220222
})
221223
iferr==nil {
222224
lastReported=state
225+
select {
226+
casea.lifecycleReported<-state:
227+
case<-a.lifecycleReported:
228+
a.lifecycleReported<-state
229+
}
223230
break
224231
}
225232
ifxerrors.Is(err,context.Canceled)||xerrors.Is(err,context.DeadlineExceeded) {
@@ -231,13 +238,20 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
231238
}
232239
}
233240

241+
// setLifecycle sets the lifecycle state and notifies the lifecycle loop.
242+
// The state is only updated if it's a valid state transition.
234243
func (a*agent)setLifecycle(ctx context.Context,state codersdk.WorkspaceAgentLifecycle) {
235244
a.lifecycleMu.Lock()
236-
defera.lifecycleMu.Unlock()
237-
238-
a.logger.Debug(ctx,"set lifecycle state",slog.F("state",state),slog.F("previous",a.lifecycleState))
239-
245+
lastState:=a.lifecycleState
246+
ifslices.Index(codersdk.WorkspaceAgentLifecycleOrder,lastState)>slices.Index(codersdk.WorkspaceAgentLifecycleOrder,state) {
247+
a.logger.Warn(ctx,"attempted to set lifecycle state to a previous state",slog.F("last",lastState),slog.F("state",state))
248+
a.lifecycleMu.Unlock()
249+
return
250+
}
240251
a.lifecycleState=state
252+
a.logger.Debug(ctx,"set lifecycle state",slog.F("state",state),slog.F("last",lastState))
253+
a.lifecycleMu.Unlock()
254+
241255
select {
242256
casea.lifecycleUpdate<-struct{}{}:
243257
default:
@@ -297,9 +311,10 @@ func (a *agent) run(ctx context.Context) error {
297311
}
298312
}
299313

314+
lifecycleState:=codersdk.WorkspaceAgentLifecycleReady
300315
scriptDone:=make(chanerror,1)
301316
scriptStart:=time.Now()
302-
err:=a.trackConnGoroutine(func() {
317+
err=a.trackConnGoroutine(func() {
303318
deferclose(scriptDone)
304319
scriptDone<-a.runStartupScript(ctx,metadata.StartupScript)
305320
})
@@ -327,16 +342,17 @@ func (a *agent) run(ctx context.Context) error {
327342
iferrors.Is(err,context.Canceled) {
328343
return
329344
}
330-
execTime:=time.Since(scriptStart)
331-
lifecycleStatus:=codersdk.WorkspaceAgentLifecycleReady
332-
iferr!=nil {
333-
a.logger.Warn(ctx,"startup script failed",slog.F("execution_time",execTime),slog.Error(err))
334-
lifecycleStatus=codersdk.WorkspaceAgentLifecycleStartError
335-
}else {
336-
a.logger.Info(ctx,"startup script completed",slog.F("execution_time",execTime))
345+
// Only log if there was a startup script.
346+
ifmetadata.StartupScript!="" {
347+
execTime:=time.Since(scriptStart)
348+
iferr!=nil {
349+
a.logger.Warn(ctx,"startup script failed",slog.F("execution_time",execTime),slog.Error(err))
350+
lifecycleState=codersdk.WorkspaceAgentLifecycleStartError
351+
}else {
352+
a.logger.Info(ctx,"startup script completed",slog.F("execution_time",execTime))
353+
}
337354
}
338-
339-
a.setLifecycle(ctx,lifecycleStatus)
355+
a.setLifecycle(ctx,lifecycleState)
340356
}()
341357
}
342358

@@ -604,14 +620,22 @@ func (a *agent) runCoordinator(ctx context.Context, network *tailnet.Conn) error
604620
}
605621

606622
func (a*agent)runStartupScript(ctx context.Context,scriptstring)error {
623+
returna.runScript(ctx,"startup",script)
624+
}
625+
626+
func (a*agent)runShutdownScript(ctx context.Context,scriptstring)error {
627+
returna.runScript(ctx,"shutdown",script)
628+
}
629+
630+
func (a*agent)runScript(ctx context.Context,lifecycle,scriptstring)error {
607631
ifscript=="" {
608632
returnnil
609633
}
610634

611-
a.logger.Info(ctx,"runningstartupscript",slog.F("script",script))
612-
writer,err:=a.filesystem.OpenFile(filepath.Join(a.logDir,"coder-startup-script.log"),os.O_CREATE|os.O_RDWR,0o600)
635+
a.logger.Info(ctx,"running script",slog.F("lifecycle",lifecycle),slog.F("script",script))
636+
writer,err:=a.filesystem.OpenFile(filepath.Join(a.logDir,fmt.Sprintf("coder-%s-script.log",lifecycle)),os.O_CREATE|os.O_RDWR,0o600)
613637
iferr!=nil {
614-
returnxerrors.Errorf("openstartup script log file: %w",err)
638+
returnxerrors.Errorf("open%s script log file: %w",lifecycle,err)
615639
}
616640
deferfunc() {
617641
_=writer.Close()
@@ -772,7 +796,7 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
772796

773797
rawMetadata:=a.metadata.Load()
774798
ifrawMetadata==nil {
775-
returnnil,xerrors.Errorf("no metadata was provided: %w",err)
799+
returnnil,xerrors.Errorf("no metadata was provided")
776800
}
777801
metadata,valid:=rawMetadata.(agentsdk.Metadata)
778802
if!valid {
@@ -1296,13 +1320,73 @@ func (a *agent) Close() error {
12961320
ifa.isClosed() {
12971321
returnnil
12981322
}
1323+
1324+
ctx:=context.Background()
1325+
a.setLifecycle(ctx,codersdk.WorkspaceAgentLifecycleShuttingDown)
1326+
1327+
lifecycleState:=codersdk.WorkspaceAgentLifecycleOff
1328+
ifmetadata,ok:=a.metadata.Load().(agentsdk.Metadata);ok&&metadata.ShutdownScript!="" {
1329+
scriptDone:=make(chanerror,1)
1330+
scriptStart:=time.Now()
1331+
gofunc() {
1332+
deferclose(scriptDone)
1333+
scriptDone<-a.runShutdownScript(ctx,metadata.ShutdownScript)
1334+
}()
1335+
1336+
vartimeout<-chan time.Time
1337+
// If timeout is zero, an older version of the coder
1338+
// provider was used. Otherwise a timeout is always > 0.
1339+
ifmetadata.ShutdownScriptTimeout>0 {
1340+
t:=time.NewTimer(metadata.ShutdownScriptTimeout)
1341+
defert.Stop()
1342+
timeout=t.C
1343+
}
1344+
1345+
varerrerror
1346+
select {
1347+
caseerr=<-scriptDone:
1348+
case<-timeout:
1349+
a.logger.Warn(ctx,"shutdown script timed out")
1350+
a.setLifecycle(ctx,codersdk.WorkspaceAgentLifecycleShutdownTimeout)
1351+
err=<-scriptDone// The script can still complete after a timeout.
1352+
}
1353+
execTime:=time.Since(scriptStart)
1354+
iferr!=nil {
1355+
a.logger.Warn(ctx,"shutdown script failed",slog.F("execution_time",execTime),slog.Error(err))
1356+
lifecycleState=codersdk.WorkspaceAgentLifecycleShutdownError
1357+
}else {
1358+
a.logger.Info(ctx,"shutdown script completed",slog.F("execution_time",execTime))
1359+
}
1360+
}
1361+
1362+
// Set final state and wait for it to be reported because context
1363+
// cancellation will stop the report loop.
1364+
a.setLifecycle(ctx,lifecycleState)
1365+
1366+
// Wait for the lifecycle to be reported, but don't wait forever so
1367+
// that we don't break user expectations.
1368+
ctx,cancel:=context.WithTimeout(ctx,5*time.Second)
1369+
defercancel()
1370+
lifecycleWaitLoop:
1371+
for {
1372+
select {
1373+
case<-ctx.Done():
1374+
break lifecycleWaitLoop
1375+
cases:=<-a.lifecycleReported:
1376+
ifs==lifecycleState {
1377+
break lifecycleWaitLoop
1378+
}
1379+
}
1380+
}
1381+
12991382
close(a.closed)
13001383
a.closeCancel()
1384+
_=a.sshServer.Close()
13011385
ifa.network!=nil {
13021386
_=a.network.Close()
13031387
}
1304-
_=a.sshServer.Close()
13051388
a.connCloseWait.Wait()
1389+
13061390
returnnil
13071391
}
13081392

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp