-
Notifications
You must be signed in to change notification settings - Fork 881
feat: Add support for shutdown_script #5171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
153ac9e
0144b77
855a640
eee2914
f28ca32
887a2b0
6831ab3
29b6127
297dcfe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -370,14 +370,22 @@ func (a *agent) runCoordinator(ctx context.Context, network *tailnet.Conn) error | |
} | ||
|
||
func (a *agent) runStartupScript(ctx context.Context, script string) error { | ||
return a.runScript(ctx, "startup", script) | ||
} | ||
|
||
func (a *agent) runShutdownScript(ctx context.Context, script string) error { | ||
return a.runScript(ctx, "shutdown", script) | ||
} | ||
|
||
func (a *agent) runScript(ctx context.Context, lifecycle, script string) error { | ||
if script == "" { | ||
return nil | ||
} | ||
|
||
a.logger.Info(ctx, "running startup script", slog.F("script", script)) | ||
writer, err := a.filesystem.OpenFile(filepath.Join(a.tempDir, "coder-startup-script.log"), os.O_CREATE|os.O_RDWR, 0o600) | ||
a.logger.Info(ctx, "running script", slog.F("lifecycle", lifecycle), slog.F("script", script)) | ||
writer, err := a.filesystem.OpenFile(filepath.Join(a.tempDir, fmt.Sprintf("coder-%s-script.log", lifecycle)), os.O_CREATE|os.O_RDWR, 0o600) | ||
if err != nil { | ||
return xerrors.Errorf("open startup script log file: %w", err) | ||
return xerrors.Errorf("open %s script log file: %w", lifecycle, err) | ||
} | ||
defer func() { | ||
_ = writer.Close() | ||
|
@@ -569,7 +577,7 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri | |
|
||
rawMetadata := a.metadata.Load() | ||
if rawMetadata == nil { | ||
return nil, xerrors.Errorf("no metadata was provided: %w", err) | ||
return nil, xerrors.Errorf("no metadata was provided") | ||
} | ||
metadata, valid := rawMetadata.(codersdk.WorkspaceAgentMetadata) | ||
if !valid { | ||
|
@@ -943,6 +951,22 @@ func (a *agent) Close() error { | |
} | ||
close(a.closed) | ||
a.closeCancel() | ||
|
||
rawMetadata := a.metadata.Load() | ||
if rawMetadata == nil { | ||
return xerrors.Errorf("no metadata was provided") | ||
} | ||
metadata, valid := rawMetadata.(codersdk.WorkspaceAgentMetadata) | ||
if !valid { | ||
return xerrors.Errorf("metadata is the wrong type: %T", metadata) | ||
} | ||
|
||
ctx := context.Background() | ||
err := a.runShutdownScript(ctx, metadata.ShutdownScript) | ||
if err != nil { | ||
a.logger.Error(ctx, "shutdown script failed", slog.Error(err)) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want to do this earlier. And also, we might not want to continue on error. Critical workspace tasks could be performed at this step, like syncing filesystem to cold storage or something similar. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I assumed the opposite condition. I wouldn't like to end up with 100 workspaces I can't kill. I suppose that it depends on which option is less evil. I'm fine to change the approach to be aligned with your suggestion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It’s a valid thought. Another way to look at it is that if it’s allowed to fail. Why have it at all? Both are of course valid. In the PR review comment I mentioned a force stop would allow shutting down such workspaces. That’s one option, alternatively it could be a provider option but we should be careful with adding those until there are real use-cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I might have missed this comment, but do you mean to have the option to configure the forced-stop somewhere in metadata which can be changed using UI or a different place? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was hinting that |
||
|
||
if a.network != nil { | ||
_ = a.network.Close() | ||
} | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TABLE workspace_agents DROP COLUMN shutdown_script; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
ALTER TABLE workspace_agents ADD COLUMN shutdown_script varchar(65534); | ||
|
||
COMMENT ON COLUMN workspace_agents.shutdown_script IS 'Script that is executed before the agent is stopped.'; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -336,6 +336,7 @@ practices: | |
- Manually connect to the resource and check the agent logs (e.g., `docker exec` or AWS console) | ||
- The Coder agent logs are typically stored in `/var/log/coder-agent.log` | ||
- The Coder agent startup script logs are typically stored in `/var/log/coder-startup-script.log` | ||
- The Coder agent shutdown script logs are typically stored in `/var/log/coder-shutdown-script.log` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This (and previous) documentation seems wrong. We currently always store in |
||
|
||
## Template permissions (enterprise) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably shouldn't do an early exit here and leave closure half-way after it's already started.