mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat(agent): Add shutdown lifecycle states and shutdown_script support (#6139)
* feat(api): Add agent shutdown lifecycle states * feat(agent): Add shutdown_script support * feat(agent): Add shutdown_script timeout * feat(site): Support new agent lifecycle states --- Co-authored-by: Marcin Tojek <marcin@coder.com>
This commit is contained in:
committed by
GitHub
parent
02100c64b5
commit
22e3ff96be
24
coderd/apidoc/docs.go
generated
24
coderd/apidoc/docs.go
generated
@ -5198,6 +5198,12 @@ const docTemplate = `{
|
||||
"motd_file": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -8425,6 +8431,12 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout_seconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -8462,14 +8474,22 @@ const docTemplate = `{
|
||||
"starting",
|
||||
"start_timeout",
|
||||
"start_error",
|
||||
"ready"
|
||||
"ready",
|
||||
"shutting_down",
|
||||
"shutdown_timeout",
|
||||
"shutdown_error",
|
||||
"off"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"WorkspaceAgentLifecycleCreated",
|
||||
"WorkspaceAgentLifecycleStarting",
|
||||
"WorkspaceAgentLifecycleStartTimeout",
|
||||
"WorkspaceAgentLifecycleStartError",
|
||||
"WorkspaceAgentLifecycleReady"
|
||||
"WorkspaceAgentLifecycleReady",
|
||||
"WorkspaceAgentLifecycleShuttingDown",
|
||||
"WorkspaceAgentLifecycleShutdownTimeout",
|
||||
"WorkspaceAgentLifecycleShutdownError",
|
||||
"WorkspaceAgentLifecycleOff"
|
||||
]
|
||||
},
|
||||
"codersdk.WorkspaceAgentListeningPort": {
|
||||
|
30
coderd/apidoc/swagger.json
generated
30
coderd/apidoc/swagger.json
generated
@ -4587,6 +4587,12 @@
|
||||
"motd_file": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -7592,6 +7598,12 @@
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout_seconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -7624,13 +7636,27 @@
|
||||
},
|
||||
"codersdk.WorkspaceAgentLifecycle": {
|
||||
"type": "string",
|
||||
"enum": ["created", "starting", "start_timeout", "start_error", "ready"],
|
||||
"enum": [
|
||||
"created",
|
||||
"starting",
|
||||
"start_timeout",
|
||||
"start_error",
|
||||
"ready",
|
||||
"shutting_down",
|
||||
"shutdown_timeout",
|
||||
"shutdown_error",
|
||||
"off"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"WorkspaceAgentLifecycleCreated",
|
||||
"WorkspaceAgentLifecycleStarting",
|
||||
"WorkspaceAgentLifecycleStartTimeout",
|
||||
"WorkspaceAgentLifecycleStartError",
|
||||
"WorkspaceAgentLifecycleReady"
|
||||
"WorkspaceAgentLifecycleReady",
|
||||
"WorkspaceAgentLifecycleShuttingDown",
|
||||
"WorkspaceAgentLifecycleShutdownTimeout",
|
||||
"WorkspaceAgentLifecycleShutdownError",
|
||||
"WorkspaceAgentLifecycleOff"
|
||||
]
|
||||
},
|
||||
"codersdk.WorkspaceAgentListeningPort": {
|
||||
|
@ -2856,6 +2856,7 @@ func (q *fakeQuerier) InsertWorkspaceAgent(_ context.Context, arg database.Inser
|
||||
TroubleshootingURL: arg.TroubleshootingURL,
|
||||
MOTDFile: arg.MOTDFile,
|
||||
LifecycleState: database.WorkspaceAgentLifecycleStateCreated,
|
||||
ShutdownScript: arg.ShutdownScript,
|
||||
}
|
||||
|
||||
q.workspaceAgents = append(q.workspaceAgents, agent)
|
||||
|
14
coderd/database/dump.sql
generated
14
coderd/database/dump.sql
generated
@ -107,7 +107,11 @@ CREATE TYPE workspace_agent_lifecycle_state AS ENUM (
|
||||
'starting',
|
||||
'start_timeout',
|
||||
'start_error',
|
||||
'ready'
|
||||
'ready',
|
||||
'shutting_down',
|
||||
'shutdown_timeout',
|
||||
'shutdown_error',
|
||||
'off'
|
||||
);
|
||||
|
||||
CREATE TYPE workspace_app_health AS ENUM (
|
||||
@ -509,7 +513,9 @@ CREATE TABLE workspace_agents (
|
||||
lifecycle_state workspace_agent_lifecycle_state DEFAULT 'created'::workspace_agent_lifecycle_state NOT NULL,
|
||||
login_before_ready boolean DEFAULT true NOT NULL,
|
||||
startup_script_timeout_seconds integer DEFAULT 0 NOT NULL,
|
||||
expanded_directory character varying(4096) DEFAULT ''::character varying NOT NULL
|
||||
expanded_directory character varying(4096) DEFAULT ''::character varying NOT NULL,
|
||||
shutdown_script character varying(65534),
|
||||
shutdown_script_timeout_seconds integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.version IS 'Version tracks the version of the currently running workspace agent. Workspace agents register their version upon start.';
|
||||
@ -528,6 +534,10 @@ COMMENT ON COLUMN workspace_agents.startup_script_timeout_seconds IS 'The number
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.expanded_directory IS 'The resolved path of a user-specified directory. e.g. ~/coder -> /home/coder/coder';
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script IS 'Script that is executed before the agent is stopped.';
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script_timeout_seconds IS 'The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.';
|
||||
|
||||
CREATE TABLE workspace_apps (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
|
@ -0,0 +1,12 @@
|
||||
ALTER TABLE workspace_agents DROP COLUMN shutdown_script;
|
||||
|
||||
ALTER TABLE workspace_agents DROP COLUMN shutdown_script_timeout_seconds;
|
||||
|
||||
-- We can't drop values from enums, so we have to create a new one and convert the data.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'ready' WHERE lifecycle_state IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off');
|
||||
ALTER TYPE workspace_agent_lifecycle_state RENAME TO workspace_agent_lifecycle_state_old;
|
||||
CREATE TYPE workspace_agent_lifecycle_state AS ENUM ('created', 'starting', 'start_timeout', 'start_error', 'ready');
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state DROP DEFAULT;
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state TYPE workspace_agent_lifecycle_state USING lifecycle_state::text::workspace_agent_lifecycle_state;
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state SET DEFAULT 'created';
|
||||
DROP TYPE workspace_agent_lifecycle_state_old;
|
@ -0,0 +1,14 @@
|
||||
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.';
|
||||
|
||||
-- Disable shutdown script timeouts by default.
|
||||
ALTER TABLE workspace_agents ADD COLUMN shutdown_script_timeout_seconds int4 NOT NULL DEFAULT 0;
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script_timeout_seconds IS 'The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.';
|
||||
|
||||
-- Add enum fields
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutting_down';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutdown_timeout';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutdown_error';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'off';
|
2
coderd/database/migrations/testdata/fixtures/000091_lifecycle.up.sql
vendored
Normal file
2
coderd/database/migrations/testdata/fixtures/000091_lifecycle.up.sql
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
-- Set a non-default lifecycle_state.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'ready' WHERE id = '7a1ce5f8-8d00-431c-ad1b-97a846512804';
|
2
coderd/database/migrations/testdata/fixtures/000104_lifecycle.up.sql
vendored
Normal file
2
coderd/database/migrations/testdata/fixtures/000104_lifecycle.up.sql
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
-- Set lifecycle_state to enum value not available in previous migration.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'off' WHERE id = '7a1ce5f8-8d00-431c-ad1b-97a846512804';
|
@ -1014,11 +1014,15 @@ func AllUserStatusValues() []UserStatus {
|
||||
type WorkspaceAgentLifecycleState string
|
||||
|
||||
const (
|
||||
WorkspaceAgentLifecycleStateCreated WorkspaceAgentLifecycleState = "created"
|
||||
WorkspaceAgentLifecycleStateStarting WorkspaceAgentLifecycleState = "starting"
|
||||
WorkspaceAgentLifecycleStateStartTimeout WorkspaceAgentLifecycleState = "start_timeout"
|
||||
WorkspaceAgentLifecycleStateStartError WorkspaceAgentLifecycleState = "start_error"
|
||||
WorkspaceAgentLifecycleStateReady WorkspaceAgentLifecycleState = "ready"
|
||||
WorkspaceAgentLifecycleStateCreated WorkspaceAgentLifecycleState = "created"
|
||||
WorkspaceAgentLifecycleStateStarting WorkspaceAgentLifecycleState = "starting"
|
||||
WorkspaceAgentLifecycleStateStartTimeout WorkspaceAgentLifecycleState = "start_timeout"
|
||||
WorkspaceAgentLifecycleStateStartError WorkspaceAgentLifecycleState = "start_error"
|
||||
WorkspaceAgentLifecycleStateReady WorkspaceAgentLifecycleState = "ready"
|
||||
WorkspaceAgentLifecycleStateShuttingDown WorkspaceAgentLifecycleState = "shutting_down"
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout WorkspaceAgentLifecycleState = "shutdown_timeout"
|
||||
WorkspaceAgentLifecycleStateShutdownError WorkspaceAgentLifecycleState = "shutdown_error"
|
||||
WorkspaceAgentLifecycleStateOff WorkspaceAgentLifecycleState = "off"
|
||||
)
|
||||
|
||||
func (e *WorkspaceAgentLifecycleState) Scan(src interface{}) error {
|
||||
@ -1062,7 +1066,11 @@ func (e WorkspaceAgentLifecycleState) Valid() bool {
|
||||
WorkspaceAgentLifecycleStateStarting,
|
||||
WorkspaceAgentLifecycleStateStartTimeout,
|
||||
WorkspaceAgentLifecycleStateStartError,
|
||||
WorkspaceAgentLifecycleStateReady:
|
||||
WorkspaceAgentLifecycleStateReady,
|
||||
WorkspaceAgentLifecycleStateShuttingDown,
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout,
|
||||
WorkspaceAgentLifecycleStateShutdownError,
|
||||
WorkspaceAgentLifecycleStateOff:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -1075,6 +1083,10 @@ func AllWorkspaceAgentLifecycleStateValues() []WorkspaceAgentLifecycleState {
|
||||
WorkspaceAgentLifecycleStateStartTimeout,
|
||||
WorkspaceAgentLifecycleStateStartError,
|
||||
WorkspaceAgentLifecycleStateReady,
|
||||
WorkspaceAgentLifecycleStateShuttingDown,
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout,
|
||||
WorkspaceAgentLifecycleStateShutdownError,
|
||||
WorkspaceAgentLifecycleStateOff,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1547,6 +1559,10 @@ type WorkspaceAgent struct {
|
||||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
// The resolved path of a user-specified directory. e.g. ~/coder -> /home/coder/coder
|
||||
ExpandedDirectory string `db:"expanded_directory" json:"expanded_directory"`
|
||||
// Script that is executed before the agent is stopped.
|
||||
ShutdownScript sql.NullString `db:"shutdown_script" json:"shutdown_script"`
|
||||
// The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.
|
||||
ShutdownScriptTimeoutSeconds int32 `db:"shutdown_script_timeout_seconds" json:"shutdown_script_timeout_seconds"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentStat struct {
|
||||
|
@ -4937,7 +4937,7 @@ func (q *sqlQuerier) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusP
|
||||
|
||||
const getWorkspaceAgentByAuthToken = `-- name: GetWorkspaceAgentByAuthToken :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -4976,13 +4976,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByID = `-- name: GetWorkspaceAgentByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5019,13 +5021,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (W
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByInstanceID = `-- name: GetWorkspaceAgentByInstanceID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5064,13 +5068,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentsByResourceIDs = `-- name: GetWorkspaceAgentsByResourceIDs :many
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
@ -5113,6 +5119,8 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -5128,7 +5136,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
||||
}
|
||||
|
||||
const getWorkspaceAgentsCreatedAfter = `-- name: GetWorkspaceAgentsCreatedAfter :many
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory FROM workspace_agents WHERE created_at > $1
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds FROM workspace_agents WHERE created_at > $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceAgent, error) {
|
||||
@ -5167,6 +5175,8 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -5202,32 +5212,36 @@ INSERT INTO
|
||||
troubleshooting_url,
|
||||
motd_file,
|
||||
login_before_ready,
|
||||
startup_script_timeout_seconds
|
||||
startup_script_timeout_seconds,
|
||||
shutdown_script,
|
||||
shutdown_script_timeout_seconds
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
`
|
||||
|
||||
type InsertWorkspaceAgentParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
ResourceID uuid.UUID `db:"resource_id" json:"resource_id"`
|
||||
AuthToken uuid.UUID `db:"auth_token" json:"auth_token"`
|
||||
AuthInstanceID sql.NullString `db:"auth_instance_id" json:"auth_instance_id"`
|
||||
Architecture string `db:"architecture" json:"architecture"`
|
||||
EnvironmentVariables pqtype.NullRawMessage `db:"environment_variables" json:"environment_variables"`
|
||||
OperatingSystem string `db:"operating_system" json:"operating_system"`
|
||||
StartupScript sql.NullString `db:"startup_script" json:"startup_script"`
|
||||
Directory string `db:"directory" json:"directory"`
|
||||
InstanceMetadata pqtype.NullRawMessage `db:"instance_metadata" json:"instance_metadata"`
|
||||
ResourceMetadata pqtype.NullRawMessage `db:"resource_metadata" json:"resource_metadata"`
|
||||
ConnectionTimeoutSeconds int32 `db:"connection_timeout_seconds" json:"connection_timeout_seconds"`
|
||||
TroubleshootingURL string `db:"troubleshooting_url" json:"troubleshooting_url"`
|
||||
MOTDFile string `db:"motd_file" json:"motd_file"`
|
||||
LoginBeforeReady bool `db:"login_before_ready" json:"login_before_ready"`
|
||||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
ResourceID uuid.UUID `db:"resource_id" json:"resource_id"`
|
||||
AuthToken uuid.UUID `db:"auth_token" json:"auth_token"`
|
||||
AuthInstanceID sql.NullString `db:"auth_instance_id" json:"auth_instance_id"`
|
||||
Architecture string `db:"architecture" json:"architecture"`
|
||||
EnvironmentVariables pqtype.NullRawMessage `db:"environment_variables" json:"environment_variables"`
|
||||
OperatingSystem string `db:"operating_system" json:"operating_system"`
|
||||
StartupScript sql.NullString `db:"startup_script" json:"startup_script"`
|
||||
Directory string `db:"directory" json:"directory"`
|
||||
InstanceMetadata pqtype.NullRawMessage `db:"instance_metadata" json:"instance_metadata"`
|
||||
ResourceMetadata pqtype.NullRawMessage `db:"resource_metadata" json:"resource_metadata"`
|
||||
ConnectionTimeoutSeconds int32 `db:"connection_timeout_seconds" json:"connection_timeout_seconds"`
|
||||
TroubleshootingURL string `db:"troubleshooting_url" json:"troubleshooting_url"`
|
||||
MOTDFile string `db:"motd_file" json:"motd_file"`
|
||||
LoginBeforeReady bool `db:"login_before_ready" json:"login_before_ready"`
|
||||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
ShutdownScript sql.NullString `db:"shutdown_script" json:"shutdown_script"`
|
||||
ShutdownScriptTimeoutSeconds int32 `db:"shutdown_script_timeout_seconds" json:"shutdown_script_timeout_seconds"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error) {
|
||||
@ -5251,6 +5265,8 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
|
||||
arg.MOTDFile,
|
||||
arg.LoginBeforeReady,
|
||||
arg.StartupScriptTimeoutSeconds,
|
||||
arg.ShutdownScript,
|
||||
arg.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
var i WorkspaceAgent
|
||||
err := row.Scan(
|
||||
@ -5280,6 +5296,8 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
|
||||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
@ -58,10 +58,12 @@ INSERT INTO
|
||||
troubleshooting_url,
|
||||
motd_file,
|
||||
login_before_ready,
|
||||
startup_script_timeout_seconds
|
||||
startup_script_timeout_seconds,
|
||||
shutdown_script,
|
||||
shutdown_script_timeout_seconds
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING *;
|
||||
|
||||
-- name: UpdateWorkspaceAgentConnectionByID :exec
|
||||
UPDATE
|
||||
|
@ -1144,6 +1144,11 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
|
||||
MOTDFile: prAgent.GetMotdFile(),
|
||||
LoginBeforeReady: prAgent.GetLoginBeforeReady(),
|
||||
StartupScriptTimeoutSeconds: prAgent.GetStartupScriptTimeoutSeconds(),
|
||||
ShutdownScript: sql.NullString{
|
||||
String: prAgent.ShutdownScript,
|
||||
Valid: prAgent.ShutdownScript != "",
|
||||
},
|
||||
ShutdownScriptTimeoutSeconds: prAgent.GetShutdownScriptTimeoutSeconds(),
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert agent: %w", err)
|
||||
|
@ -957,6 +957,7 @@ func TestInsertWorkspaceResource(t *testing.T) {
|
||||
Apps: []*sdkproto.App{{
|
||||
Slug: "a",
|
||||
}},
|
||||
ShutdownScript: "shutdown",
|
||||
}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@ -971,6 +972,7 @@ func TestInsertWorkspaceResource(t *testing.T) {
|
||||
require.Equal(t, "amd64", agent.Architecture)
|
||||
require.Equal(t, "linux", agent.OperatingSystem)
|
||||
require.Equal(t, "value", agent.StartupScript.String)
|
||||
require.Equal(t, "shutdown", agent.ShutdownScript.String)
|
||||
want, err := json.Marshal(map[string]string{
|
||||
"something": "test",
|
||||
})
|
||||
|
@ -550,6 +550,7 @@ func ConvertWorkspaceAgent(agent database.WorkspaceAgent) WorkspaceAgent {
|
||||
StartupScript: agent.StartupScript.Valid,
|
||||
Directory: agent.Directory != "",
|
||||
ConnectionTimeoutSeconds: agent.ConnectionTimeoutSeconds,
|
||||
ShutdownScript: agent.ShutdownScript.Valid,
|
||||
}
|
||||
if agent.FirstConnectedAt.Valid {
|
||||
snapAgent.FirstConnectedAt = &agent.FirstConnectedAt.Time
|
||||
@ -750,6 +751,7 @@ type WorkspaceAgent struct {
|
||||
LastConnectedAt *time.Time `json:"last_connected_at"`
|
||||
DisconnectedAt *time.Time `json:"disconnected_at"`
|
||||
ConnectionTimeoutSeconds int32 `json:"connection_timeout_seconds"`
|
||||
ShutdownScript bool `json:"shutdown_script"`
|
||||
}
|
||||
|
||||
type WorkspaceApp struct {
|
||||
|
@ -144,15 +144,17 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, agentsdk.Metadata{
|
||||
Apps: convertApps(dbApps),
|
||||
DERPMap: api.DERPMap,
|
||||
GitAuthConfigs: len(api.GitAuthConfigs),
|
||||
EnvironmentVariables: apiAgent.EnvironmentVariables,
|
||||
StartupScript: apiAgent.StartupScript,
|
||||
Directory: apiAgent.Directory,
|
||||
VSCodePortProxyURI: vscodeProxyURI,
|
||||
MOTDFile: workspaceAgent.MOTDFile,
|
||||
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
|
||||
Apps: convertApps(dbApps),
|
||||
DERPMap: api.DERPMap,
|
||||
GitAuthConfigs: len(api.GitAuthConfigs),
|
||||
EnvironmentVariables: apiAgent.EnvironmentVariables,
|
||||
StartupScript: apiAgent.StartupScript,
|
||||
Directory: apiAgent.Directory,
|
||||
VSCodePortProxyURI: vscodeProxyURI,
|
||||
MOTDFile: workspaceAgent.MOTDFile,
|
||||
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
|
||||
ShutdownScript: apiAgent.ShutdownScript,
|
||||
ShutdownScriptTimeout: time.Duration(apiAgent.ShutdownScriptTimeoutSeconds) * time.Second,
|
||||
})
|
||||
}
|
||||
|
||||
@ -803,25 +805,27 @@ func convertWorkspaceAgent(derpMap *tailcfg.DERPMap, coordinator tailnet.Coordin
|
||||
troubleshootingURL = dbAgent.TroubleshootingURL
|
||||
}
|
||||
workspaceAgent := codersdk.WorkspaceAgent{
|
||||
ID: dbAgent.ID,
|
||||
CreatedAt: dbAgent.CreatedAt,
|
||||
UpdatedAt: dbAgent.UpdatedAt,
|
||||
ResourceID: dbAgent.ResourceID,
|
||||
InstanceID: dbAgent.AuthInstanceID.String,
|
||||
Name: dbAgent.Name,
|
||||
Architecture: dbAgent.Architecture,
|
||||
OperatingSystem: dbAgent.OperatingSystem,
|
||||
StartupScript: dbAgent.StartupScript.String,
|
||||
Version: dbAgent.Version,
|
||||
EnvironmentVariables: envs,
|
||||
Directory: dbAgent.Directory,
|
||||
ExpandedDirectory: dbAgent.ExpandedDirectory,
|
||||
Apps: apps,
|
||||
ConnectionTimeoutSeconds: dbAgent.ConnectionTimeoutSeconds,
|
||||
TroubleshootingURL: troubleshootingURL,
|
||||
LifecycleState: codersdk.WorkspaceAgentLifecycle(dbAgent.LifecycleState),
|
||||
LoginBeforeReady: dbAgent.LoginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds,
|
||||
ID: dbAgent.ID,
|
||||
CreatedAt: dbAgent.CreatedAt,
|
||||
UpdatedAt: dbAgent.UpdatedAt,
|
||||
ResourceID: dbAgent.ResourceID,
|
||||
InstanceID: dbAgent.AuthInstanceID.String,
|
||||
Name: dbAgent.Name,
|
||||
Architecture: dbAgent.Architecture,
|
||||
OperatingSystem: dbAgent.OperatingSystem,
|
||||
StartupScript: dbAgent.StartupScript.String,
|
||||
Version: dbAgent.Version,
|
||||
EnvironmentVariables: envs,
|
||||
Directory: dbAgent.Directory,
|
||||
ExpandedDirectory: dbAgent.ExpandedDirectory,
|
||||
Apps: apps,
|
||||
ConnectionTimeoutSeconds: dbAgent.ConnectionTimeoutSeconds,
|
||||
TroubleshootingURL: troubleshootingURL,
|
||||
LifecycleState: codersdk.WorkspaceAgentLifecycle(dbAgent.LifecycleState),
|
||||
LoginBeforeReady: dbAgent.LoginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds,
|
||||
ShutdownScript: dbAgent.ShutdownScript.String,
|
||||
ShutdownScriptTimeoutSeconds: dbAgent.ShutdownScriptTimeoutSeconds,
|
||||
}
|
||||
node := coordinator.Node(dbAgent.ID)
|
||||
if node != nil {
|
||||
|
@ -1256,6 +1256,10 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
|
||||
{codersdk.WorkspaceAgentLifecycleStartTimeout, false},
|
||||
{codersdk.WorkspaceAgentLifecycleStartError, false},
|
||||
{codersdk.WorkspaceAgentLifecycleReady, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShuttingDown, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShutdownTimeout, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShutdownError, false},
|
||||
{codersdk.WorkspaceAgentLifecycleOff, false},
|
||||
{codersdk.WorkspaceAgentLifecycle("nonexistent_state"), true},
|
||||
{codersdk.WorkspaceAgentLifecycle(""), true},
|
||||
}
|
||||
|
Reference in New Issue
Block a user