From 660bbb8d3884b4b29f3afeb2426d96aeda7eff52 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 6 Jun 2023 11:58:07 +0300 Subject: [PATCH] refactor: deprecate `login_before_ready` in favor of `startup_script_behavior` (#7837) Fixes #7758 --- cli/cliui/agent.go | 6 +- cli/cliui/agent_test.go | 44 +- cli/ssh.go | 2 +- cli/testdata/coder_ssh_--help.golden | 6 +- coderd/apidoc/docs.go | 16 +- coderd/apidoc/swagger.json | 13 +- coderd/database/dbauthz/system_test.go | 3 +- coderd/database/dbgen/generator.go | 2 +- coderd/database/dump.sql | 11 +- ..._ready_to_startup_script_behavior.down.sql | 12 + ...re_ready_to_startup_script_behavior.up.sql | 12 + coderd/database/models.go | 62 ++- coderd/database/queries.sql.go | 34 +- coderd/database/queries/workspaceagents.sql | 2 +- .../provisionerdserver/provisionerdserver.go | 7 +- coderd/workspaceagents.go | 3 +- codersdk/workspaceagents.go | 19 +- docs/api/agents.md | 1 + docs/api/builds.md | 484 +++++++++--------- docs/api/schemas.md | 87 ++-- docs/api/templates.md | 368 ++++++------- docs/api/workspaces.md | 4 + docs/cli/ssh.md | 2 +- dogfood/main.tf | 4 +- examples/templates/azure-windows/main.tf | 7 +- provisioner/terraform/resources.go | 53 +- provisioner/terraform/resources_test.go | 37 +- .../multiple-agents/multiple-agents.tf | 22 +- .../multiple-agents.tfplan.dot | 4 + .../multiple-agents.tfplan.json | 141 ++++- .../multiple-agents.tfstate.dot | 4 + .../multiple-agents.tfstate.json | 68 ++- provisionersdk/proto/provisioner.pb.go | 471 ++++++++--------- provisionersdk/proto/provisioner.proto | 6 +- site/src/api/typesGenerated.ts | 6 + site/src/components/Resources/AgentStatus.tsx | 69 ++- site/src/testHelpers/entities.ts | 3 +- 37 files changed, 1238 insertions(+), 857 deletions(-) create mode 100644 coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.down.sql create mode 100644 coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.up.sql diff --git a/cli/cliui/agent.go b/cli/cliui/agent.go index fda7b84b72..8973606ec7 100644 --- a/cli/cliui/agent.go +++ b/cli/cliui/agent.go @@ -48,7 +48,7 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error { // We don't take the fast path for opts.NoWait yet because we want to // show the message. if agent.Status == codersdk.WorkspaceAgentConnected && - (agent.LoginBeforeReady || agent.LifecycleState == codersdk.WorkspaceAgentLifecycleReady) { + (agent.StartupScriptBehavior == codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking || agent.LifecycleState == codersdk.WorkspaceAgentLifecycleReady) { return nil } @@ -96,7 +96,7 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error { // we do this just before starting the spinner to avoid needless // spinning. if agent.Status == codersdk.WorkspaceAgentConnected && - !agent.LoginBeforeReady && opts.NoWait { + agent.StartupScriptBehavior == codersdk.WorkspaceAgentStartupScriptBehaviorBlocking && opts.NoWait { showMessage() return nil } @@ -140,7 +140,7 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error { // NOTE(mafredri): Once we have access to the workspace agent's // startup script logs, we can show them here. // https://github.com/coder/coder/issues/2957 - if !agent.LoginBeforeReady && !opts.NoWait { + if agent.StartupScriptBehavior == codersdk.WorkspaceAgentStartupScriptBehaviorBlocking && !opts.NoWait { switch agent.LifecycleState { case codersdk.WorkspaceAgentLifecycleReady: return nil diff --git a/cli/cliui/agent_test.go b/cli/cliui/agent_test.go index c6b13b3bbe..efed058e4f 100644 --- a/cli/cliui/agent_test.go +++ b/cli/cliui/agent_test.go @@ -30,8 +30,8 @@ func TestAgent(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentDisconnected, - LoginBeforeReady: true, + Status: codersdk.WorkspaceAgentDisconnected, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking, } if disconnected.Load() { agent.Status = codersdk.WorkspaceAgentConnected @@ -73,9 +73,9 @@ func TestAgent_TimeoutWithTroubleshootingURL(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentConnecting, - TroubleshootingURL: wantURL, - LoginBeforeReady: true, + Status: codersdk.WorkspaceAgentConnecting, + TroubleshootingURL: wantURL, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking, } switch { case !connected.Load() && timeout.Load(): @@ -124,10 +124,10 @@ func TestAgent_StartupTimeout(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentConnecting, - LoginBeforeReady: false, - LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, - TroubleshootingURL: wantURL, + Status: codersdk.WorkspaceAgentConnecting, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorBlocking, + LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, + TroubleshootingURL: wantURL, } if s := status.Load(); s != "" { @@ -183,10 +183,10 @@ func TestAgent_StartErrorExit(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentConnecting, - LoginBeforeReady: false, - LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, - TroubleshootingURL: wantURL, + Status: codersdk.WorkspaceAgentConnecting, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorBlocking, + LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, + TroubleshootingURL: wantURL, } if s := status.Load(); s != "" { @@ -239,10 +239,10 @@ func TestAgent_NoWait(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentConnecting, - LoginBeforeReady: false, - LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, - TroubleshootingURL: wantURL, + Status: codersdk.WorkspaceAgentConnecting, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorBlocking, + LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, + TroubleshootingURL: wantURL, } if s := status.Load(); s != "" { @@ -292,7 +292,7 @@ func TestAgent_NoWait(t *testing.T) { require.NoError(t, <-done, "ready - should exit early") } -func TestAgent_LoginBeforeReadyEnabled(t *testing.T) { +func TestAgent_StartupScriptBehaviorNonBlocking(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) @@ -309,10 +309,10 @@ func TestAgent_LoginBeforeReadyEnabled(t *testing.T) { WorkspaceName: "example", Fetch: func(_ context.Context) (codersdk.WorkspaceAgent, error) { agent := codersdk.WorkspaceAgent{ - Status: codersdk.WorkspaceAgentConnecting, - LoginBeforeReady: true, - LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, - TroubleshootingURL: wantURL, + Status: codersdk.WorkspaceAgentConnecting, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking, + LifecycleState: codersdk.WorkspaceAgentLifecycleCreated, + TroubleshootingURL: wantURL, } if s := status.Load(); s != "" { diff --git a/cli/ssh.go b/cli/ssh.go index fa3611a055..3a22ab1172 100644 --- a/cli/ssh.go +++ b/cli/ssh.go @@ -350,7 +350,7 @@ func (r *RootCmd) ssh() *clibase.Cmd { { Flag: "no-wait", Env: "CODER_SSH_NO_WAIT", - Description: "Specifies whether to wait for a workspace to become ready before logging in (only applicable when the login before ready option has not been enabled). Note that the workspace agent may still be in the process of executing the startup script and the workspace may be in an incomplete state.", + Description: "Specifies whether to wait for a workspace to become ready before logging in (only applicable when the startup script behavior is blocking). Note that the workspace agent may still be in the process of executing the startup script and the workspace may be in an incomplete state.", Value: clibase.BoolOf(&noWait), }, { diff --git a/cli/testdata/coder_ssh_--help.golden b/cli/testdata/coder_ssh_--help.golden index 632003ffdb..036a1a357e 100644 --- a/cli/testdata/coder_ssh_--help.golden +++ b/cli/testdata/coder_ssh_--help.golden @@ -26,9 +26,9 @@ Start a shell into a workspace --no-wait bool, $CODER_SSH_NO_WAIT Specifies whether to wait for a workspace to become ready before - logging in (only applicable when the login before ready option has not - been enabled). Note that the workspace agent may still be in the - process of executing the startup script and the workspace may be in an + logging in (only applicable when the startup script behavior is + blocking). Note that the workspace agent may still be in the process + of executing the startup script and the workspace may be in an incomplete state. --stdio bool, $CODER_SSH_STDIO diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8d6ae565d5..62b95d1f7b 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -9216,7 +9216,7 @@ const docTemplate = `{ "$ref": "#/definitions/codersdk.WorkspaceAgentLifecycle" }, "login_before_ready": { - "description": "LoginBeforeReady if true, the agent will delay logins until it is ready (e.g. executing startup script has ended).", + "description": "Deprecated: Use StartupScriptBehavior instead.", "type": "boolean" }, "name": { @@ -9244,6 +9244,9 @@ const docTemplate = `{ "startup_script": { "type": "string" }, + "startup_script_behavior": { + "$ref": "#/definitions/codersdk.WorkspaceAgentStartupScriptBehavior" + }, "startup_script_timeout_seconds": { "description": "StartupScriptTimeoutSeconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout.", "type": "integer" @@ -9365,6 +9368,17 @@ const docTemplate = `{ } } }, + "codersdk.WorkspaceAgentStartupScriptBehavior": { + "type": "string", + "enum": [ + "blocking", + "non-blocking" + ], + "x-enum-varnames": [ + "WorkspaceAgentStartupScriptBehaviorBlocking", + "WorkspaceAgentStartupScriptBehaviorNonBlocking" + ] + }, "codersdk.WorkspaceAgentStatus": { "type": "string", "enum": [ diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 90ccbaad1b..5aa2e8e099 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -8312,7 +8312,7 @@ "$ref": "#/definitions/codersdk.WorkspaceAgentLifecycle" }, "login_before_ready": { - "description": "LoginBeforeReady if true, the agent will delay logins until it is ready (e.g. executing startup script has ended).", + "description": "Deprecated: Use StartupScriptBehavior instead.", "type": "boolean" }, "name": { @@ -8340,6 +8340,9 @@ "startup_script": { "type": "string" }, + "startup_script_behavior": { + "$ref": "#/definitions/codersdk.WorkspaceAgentStartupScriptBehavior" + }, "startup_script_timeout_seconds": { "description": "StartupScriptTimeoutSeconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout.", "type": "integer" @@ -8461,6 +8464,14 @@ } } }, + "codersdk.WorkspaceAgentStartupScriptBehavior": { + "type": "string", + "enum": ["blocking", "non-blocking"], + "x-enum-varnames": [ + "WorkspaceAgentStartupScriptBehaviorBlocking", + "WorkspaceAgentStartupScriptBehaviorNonBlocking" + ] + }, "codersdk.WorkspaceAgentStatus": { "type": "string", "enum": ["connecting", "connected", "disconnected", "timeout"], diff --git a/coderd/database/dbauthz/system_test.go b/coderd/database/dbauthz/system_test.go index 76661c00fb..4154398d2a 100644 --- a/coderd/database/dbauthz/system_test.go +++ b/coderd/database/dbauthz/system_test.go @@ -212,7 +212,8 @@ func (s *MethodTestSuite) TestSystemFunctions() { })) s.Run("InsertWorkspaceAgent", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceAgentParams{ - ID: uuid.New(), + ID: uuid.New(), + StartupScriptBehavior: database.StartupScriptBehaviorNonBlocking, }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) })) s.Run("InsertWorkspaceApp", s.Subtest(func(db database.Store, check *expects) { diff --git a/coderd/database/dbgen/generator.go b/coderd/database/dbgen/generator.go index 282058e9ac..c21a795290 100644 --- a/coderd/database/dbgen/generator.go +++ b/coderd/database/dbgen/generator.go @@ -152,7 +152,7 @@ func WorkspaceAgent(t testing.TB, db database.Store, orig database.WorkspaceAgen ConnectionTimeoutSeconds: takeFirst(orig.ConnectionTimeoutSeconds, 3600), TroubleshootingURL: takeFirst(orig.TroubleshootingURL, "https://example.com"), MOTDFile: takeFirst(orig.TroubleshootingURL, ""), - LoginBeforeReady: takeFirst(orig.LoginBeforeReady, false), + StartupScriptBehavior: takeFirst(orig.StartupScriptBehavior, "non-blocking"), StartupScriptTimeoutSeconds: takeFirst(orig.StartupScriptTimeoutSeconds, 3600), }) require.NoError(t, err, "insert workspace agent") diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 0c5846749a..174e6d42aa 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -99,6 +99,11 @@ CREATE TYPE resource_type AS ENUM ( 'workspace_proxy' ); +CREATE TYPE startup_script_behavior AS ENUM ( + 'blocking', + 'non-blocking' +); + CREATE TYPE user_status AS ENUM ( 'active', 'suspended' @@ -596,7 +601,6 @@ CREATE TABLE workspace_agents ( troubleshooting_url text DEFAULT ''::text NOT NULL, motd_file text DEFAULT ''::text NOT NULL, 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, shutdown_script character varying(65534), @@ -604,6 +608,7 @@ CREATE TABLE workspace_agents ( startup_logs_length integer DEFAULT 0 NOT NULL, startup_logs_overflowed boolean DEFAULT false NOT NULL, subsystem workspace_agent_subsystem DEFAULT 'none'::workspace_agent_subsystem NOT NULL, + startup_script_behavior startup_script_behavior DEFAULT 'non-blocking'::startup_script_behavior NOT NULL, CONSTRAINT max_startup_logs_length CHECK ((startup_logs_length <= 1048576)) ); @@ -617,8 +622,6 @@ COMMENT ON COLUMN workspace_agents.motd_file IS 'Path to file inside workspace c COMMENT ON COLUMN workspace_agents.lifecycle_state IS 'The current lifecycle state reported by the workspace agent.'; -COMMENT ON COLUMN workspace_agents.login_before_ready IS 'If true, the agent will not prevent login before it is ready (e.g. startup script is still executing).'; - COMMENT ON COLUMN workspace_agents.startup_script_timeout_seconds IS 'The number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout.'; COMMENT ON COLUMN workspace_agents.expanded_directory IS 'The resolved path of a user-specified directory. e.g. ~/coder -> /home/coder/coder'; @@ -631,6 +634,8 @@ COMMENT ON COLUMN workspace_agents.startup_logs_length IS 'Total length of start COMMENT ON COLUMN workspace_agents.startup_logs_overflowed IS 'Whether the startup logs overflowed in length'; +COMMENT ON COLUMN workspace_agents.startup_script_behavior IS 'When startup script behavior is non-blocking, the workspace will be ready and accessible upon agent connection, when it is blocking, workspace will wait for the startup script to complete before becoming ready and accessible.'; + CREATE TABLE workspace_apps ( id uuid NOT NULL, created_at timestamp with time zone NOT NULL, diff --git a/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.down.sql b/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.down.sql new file mode 100644 index 0000000000..3c93e6e92b --- /dev/null +++ b/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.down.sql @@ -0,0 +1,12 @@ +BEGIN; + +ALTER TABLE workspace_agents ADD COLUMN login_before_ready boolean NOT NULL DEFAULT TRUE; + +UPDATE workspace_agents SET login_before_ready = CASE WHEN startup_script_behavior = 'non-blocking' THEN TRUE ELSE FALSE END; + +ALTER TABLE workspace_agents DROP COLUMN startup_script_behavior; +DROP TYPE startup_script_behavior; + +COMMENT ON COLUMN workspace_agents.login_before_ready IS 'If true, the agent will delay logins until it is ready (e.g. executing startup script has ended).'; + +COMMIT; diff --git a/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.up.sql b/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.up.sql new file mode 100644 index 0000000000..408cd854de --- /dev/null +++ b/coderd/database/migrations/000125_rename_login_before_ready_to_startup_script_behavior.up.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TYPE startup_script_behavior AS ENUM ('blocking', 'non-blocking'); +ALTER TABLE workspace_agents ADD COLUMN startup_script_behavior startup_script_behavior NOT NULL DEFAULT 'non-blocking'; + +UPDATE workspace_agents SET startup_script_behavior = (CASE WHEN login_before_ready THEN 'non-blocking' ELSE 'blocking' END)::startup_script_behavior; + +ALTER TABLE workspace_agents DROP COLUMN login_before_ready; + +COMMENT ON COLUMN workspace_agents.startup_script_behavior IS 'When startup script behavior is non-blocking, the workspace will be ready and accessible upon agent connection, when it is blocking, workspace will wait for the startup script to complete before becoming ready and accessible.'; + +COMMIT; diff --git a/coderd/database/models.go b/coderd/database/models.go index 33b5145133..558e1c51a9 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -959,6 +959,64 @@ func AllResourceTypeValues() []ResourceType { } } +type StartupScriptBehavior string + +const ( + StartupScriptBehaviorBlocking StartupScriptBehavior = "blocking" + StartupScriptBehaviorNonBlocking StartupScriptBehavior = "non-blocking" +) + +func (e *StartupScriptBehavior) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = StartupScriptBehavior(s) + case string: + *e = StartupScriptBehavior(s) + default: + return fmt.Errorf("unsupported scan type for StartupScriptBehavior: %T", src) + } + return nil +} + +type NullStartupScriptBehavior struct { + StartupScriptBehavior StartupScriptBehavior + Valid bool // Valid is true if StartupScriptBehavior is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullStartupScriptBehavior) Scan(value interface{}) error { + if value == nil { + ns.StartupScriptBehavior, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.StartupScriptBehavior.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullStartupScriptBehavior) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.StartupScriptBehavior), nil +} + +func (e StartupScriptBehavior) Valid() bool { + switch e { + case StartupScriptBehaviorBlocking, + StartupScriptBehaviorNonBlocking: + return true + } + return false +} + +func AllStartupScriptBehaviorValues() []StartupScriptBehavior { + return []StartupScriptBehavior{ + StartupScriptBehaviorBlocking, + StartupScriptBehaviorNonBlocking, + } +} + type UserStatus string const ( @@ -1635,8 +1693,6 @@ type WorkspaceAgent struct { MOTDFile string `db:"motd_file" json:"motd_file"` // The current lifecycle state reported by the workspace agent. LifecycleState WorkspaceAgentLifecycleState `db:"lifecycle_state" json:"lifecycle_state"` - // If true, the agent will not prevent login before it is ready (e.g. startup script is still executing). - LoginBeforeReady bool `db:"login_before_ready" json:"login_before_ready"` // The number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. 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 @@ -1650,6 +1706,8 @@ type WorkspaceAgent struct { // Whether the startup logs overflowed in length StartupLogsOverflowed bool `db:"startup_logs_overflowed" json:"startup_logs_overflowed"` Subsystem WorkspaceAgentSubsystem `db:"subsystem" json:"subsystem"` + // When startup script behavior is non-blocking, the workspace will be ready and accessible upon agent connection, when it is blocking, workspace will wait for the startup script to complete before becoming ready and accessible. + StartupScriptBehavior StartupScriptBehavior `db:"startup_script_behavior" json:"startup_script_behavior"` } type WorkspaceAgentMetadatum struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 0358cb00b7..64eddee4fc 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -5200,7 +5200,7 @@ func (q *sqlQuerier) DeleteOldWorkspaceAgentStartupLogs(ctx context.Context) err 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, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem + 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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior FROM workspace_agents WHERE @@ -5236,7 +5236,6 @@ func (q *sqlQuerier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5244,13 +5243,14 @@ func (q *sqlQuerier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ) 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, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem + 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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior FROM workspace_agents WHERE @@ -5284,7 +5284,6 @@ func (q *sqlQuerier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (W &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5292,13 +5291,14 @@ func (q *sqlQuerier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (W &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ) 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, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem + 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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior FROM workspace_agents WHERE @@ -5334,7 +5334,6 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5342,6 +5341,7 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ) return i, err } @@ -5436,7 +5436,7 @@ func (q *sqlQuerier) GetWorkspaceAgentStartupLogsAfter(ctx context.Context, arg 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, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem + 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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior FROM workspace_agents WHERE @@ -5476,7 +5476,6 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids [] &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5484,6 +5483,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids [] &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ); err != nil { return nil, err } @@ -5499,7 +5499,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, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem 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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior FROM workspace_agents WHERE created_at > $1 ` func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceAgent, error) { @@ -5535,7 +5535,6 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5543,6 +5542,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ); err != nil { return nil, err } @@ -5559,7 +5559,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created const getWorkspaceAgentsInLatestBuildByWorkspaceID = `-- name: GetWorkspaceAgentsInLatestBuildByWorkspaceID :many SELECT - workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.startup_script, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.login_before_ready, workspace_agents.startup_script_timeout_seconds, workspace_agents.expanded_directory, workspace_agents.shutdown_script, workspace_agents.shutdown_script_timeout_seconds, workspace_agents.startup_logs_length, workspace_agents.startup_logs_overflowed, workspace_agents.subsystem + workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.startup_script, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.startup_script_timeout_seconds, workspace_agents.expanded_directory, workspace_agents.shutdown_script, workspace_agents.shutdown_script_timeout_seconds, workspace_agents.startup_logs_length, workspace_agents.startup_logs_overflowed, workspace_agents.subsystem, workspace_agents.startup_script_behavior FROM workspace_agents JOIN @@ -5611,7 +5611,6 @@ func (q *sqlQuerier) GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx context.Co &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5619,6 +5618,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx context.Co &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ); err != nil { return nil, err } @@ -5653,13 +5653,13 @@ INSERT INTO connection_timeout_seconds, troubleshooting_url, motd_file, - login_before_ready, + startup_script_behavior, 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, $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, startup_logs_length, startup_logs_overflowed, subsystem + ($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, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds, startup_logs_length, startup_logs_overflowed, subsystem, startup_script_behavior ` type InsertWorkspaceAgentParams struct { @@ -5680,7 +5680,7 @@ type InsertWorkspaceAgentParams struct { 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"` + StartupScriptBehavior StartupScriptBehavior `db:"startup_script_behavior" json:"startup_script_behavior"` 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"` @@ -5705,7 +5705,7 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa arg.ConnectionTimeoutSeconds, arg.TroubleshootingURL, arg.MOTDFile, - arg.LoginBeforeReady, + arg.StartupScriptBehavior, arg.StartupScriptTimeoutSeconds, arg.ShutdownScript, arg.ShutdownScriptTimeoutSeconds, @@ -5735,7 +5735,6 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa &i.TroubleshootingURL, &i.MOTDFile, &i.LifecycleState, - &i.LoginBeforeReady, &i.StartupScriptTimeoutSeconds, &i.ExpandedDirectory, &i.ShutdownScript, @@ -5743,6 +5742,7 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa &i.StartupLogsLength, &i.StartupLogsOverflowed, &i.Subsystem, + &i.StartupScriptBehavior, ) return i, err } diff --git a/coderd/database/queries/workspaceagents.sql b/coderd/database/queries/workspaceagents.sql index 3ceb2c70c2..b587e314fe 100644 --- a/coderd/database/queries/workspaceagents.sql +++ b/coderd/database/queries/workspaceagents.sql @@ -57,7 +57,7 @@ INSERT INTO connection_timeout_seconds, troubleshooting_url, motd_file, - login_before_ready, + startup_script_behavior, startup_script_timeout_seconds, shutdown_script, shutdown_script_timeout_seconds diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index c42f40a85b..f0de9939bf 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -1187,6 +1187,11 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid. } } + // Set the default in case it was not provided (e.g. echo provider). + if prAgent.GetStartupScriptBehavior() == "" { + prAgent.StartupScriptBehavior = string(codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking) + } + agentID := uuid.New() dbAgent, err := db.InsertWorkspaceAgent(ctx, database.InsertWorkspaceAgentParams{ ID: agentID, @@ -1207,7 +1212,7 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid. ConnectionTimeoutSeconds: prAgent.GetConnectionTimeoutSeconds(), TroubleshootingURL: prAgent.GetTroubleshootingUrl(), MOTDFile: prAgent.GetMotdFile(), - LoginBeforeReady: prAgent.GetLoginBeforeReady(), + StartupScriptBehavior: database.StartupScriptBehavior(prAgent.GetStartupScriptBehavior()), StartupScriptTimeoutSeconds: prAgent.GetStartupScriptTimeoutSeconds(), ShutdownScript: sql.NullString{ String: prAgent.ShutdownScript, diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 6d9e1ffb3f..cc05ecc73d 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -1126,7 +1126,8 @@ func convertWorkspaceAgent(derpMap *tailcfg.DERPMap, coordinator tailnet.Coordin ConnectionTimeoutSeconds: dbAgent.ConnectionTimeoutSeconds, TroubleshootingURL: troubleshootingURL, LifecycleState: codersdk.WorkspaceAgentLifecycle(dbAgent.LifecycleState), - LoginBeforeReady: dbAgent.LoginBeforeReady, + LoginBeforeReady: dbAgent.StartupScriptBehavior == database.StartupScriptBehaviorNonBlocking, + StartupScriptBehavior: codersdk.WorkspaceAgentStartupScriptBehavior(dbAgent.StartupScriptBehavior), StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds, ShutdownScript: dbAgent.ShutdownScript.String, ShutdownScriptTimeoutSeconds: dbAgent.ShutdownScriptTimeoutSeconds, diff --git a/codersdk/workspaceagents.go b/codersdk/workspaceagents.go index c633d5f074..dcede6a069 100644 --- a/codersdk/workspaceagents.go +++ b/codersdk/workspaceagents.go @@ -76,6 +76,20 @@ var WorkspaceAgentLifecycleOrder = []WorkspaceAgentLifecycle{ WorkspaceAgentLifecycleOff, } +// WorkspaceAgentStartupScriptBehavior defines whether or not the startup script +// should be considered blocking or non-blocking. The blocking behavior means +// that the agent will not be considered ready until the startup script has +// completed and, for example, SSH connections will wait for the agent to be +// ready (can be overridden). +// +// Presently, non-blocking is the default, but this may change in the future. +type WorkspaceAgentStartupScriptBehavior string + +const ( + WorkspaceAgentStartupScriptBehaviorBlocking WorkspaceAgentStartupScriptBehavior = "blocking" + WorkspaceAgentStartupScriptBehaviorNonBlocking WorkspaceAgentStartupScriptBehavior = "non-blocking" +) + type WorkspaceAgentMetadataResult struct { CollectedAt time.Time `json:"collected_at" format:"date-time"` // Age is the number of seconds since the metadata was collected. @@ -127,8 +141,9 @@ type WorkspaceAgent struct { DERPLatency map[string]DERPRegion `json:"latency,omitempty"` ConnectionTimeoutSeconds int32 `json:"connection_timeout_seconds"` TroubleshootingURL string `json:"troubleshooting_url"` - // LoginBeforeReady if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). - LoginBeforeReady bool `json:"login_before_ready"` + // Deprecated: Use StartupScriptBehavior instead. + LoginBeforeReady bool `json:"login_before_ready"` + StartupScriptBehavior WorkspaceAgentStartupScriptBehavior `json:"startup_script_behavior"` // StartupScriptTimeoutSeconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. StartupScriptTimeoutSeconds int32 `json:"startup_script_timeout_seconds"` ShutdownScript string `json:"shutdown_script,omitempty"` diff --git a/docs/api/agents.md b/docs/api/agents.md index 835d95e049..b748a2b299 100644 --- a/docs/api/agents.md +++ b/docs/api/agents.md @@ -472,6 +472,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent} \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", diff --git a/docs/api/builds.md b/docs/api/builds.md index d61c8276bd..e58f77251a 100644 --- a/docs/api/builds.md +++ b/docs/api/builds.md @@ -109,6 +109,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -262,6 +263,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -556,6 +558,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/res "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -594,99 +597,102 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/res Status Code **200** -| Name | Type | Required | Restrictions | Description | -| ------------------------------------ | -------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `[array item]` | array | false | | | -| `» agents` | array | false | | | -| `»» apps` | array | false | | | -| `»»» command` | string | false | | | -| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | -| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | -| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | -| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | -| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | -| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | -| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | -| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | -| `»»» id` | string(uuid) | false | | | -| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | -| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | -| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | -| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | -| `»» architecture` | string | false | | | -| `»» connection_timeout_seconds` | integer | false | | | -| `»» created_at` | string(date-time) | false | | | -| `»» directory` | string | false | | | -| `»» disconnected_at` | string(date-time) | false | | | -| `»» environment_variables` | object | false | | | -| `»»» [any property]` | string | false | | | -| `»» expanded_directory` | string | false | | | -| `»» first_connected_at` | string(date-time) | false | | | -| `»» id` | string(uuid) | false | | | -| `»» instance_id` | string | false | | | -| `»» last_connected_at` | string(date-time) | false | | | -| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | -| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | -| `»»»» latency_ms` | number | false | | | -| `»»»» preferred` | boolean | false | | | -| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | -| `»» login_before_ready` | boolean | false | | »login before ready if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). | -| `»» name` | string | false | | | -| `»» operating_system` | string | false | | | -| `»» resource_id` | string(uuid) | false | | | -| `»» shutdown_script` | string | false | | | -| `»» shutdown_script_timeout_seconds` | integer | false | | | -| `»» startup_logs_length` | integer | false | | | -| `»» startup_logs_overflowed` | boolean | false | | | -| `»» startup_script` | string | false | | | -| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | -| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | -| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | -| `»» troubleshooting_url` | string | false | | | -| `»» updated_at` | string(date-time) | false | | | -| `»» version` | string | false | | | -| `» created_at` | string(date-time) | false | | | -| `» daily_cost` | integer | false | | | -| `» hide` | boolean | false | | | -| `» icon` | string | false | | | -| `» id` | string(uuid) | false | | | -| `» job_id` | string(uuid) | false | | | -| `» metadata` | array | false | | | -| `»» key` | string | false | | | -| `»» sensitive` | boolean | false | | | -| `»» value` | string | false | | | -| `» name` | string | false | | | -| `» type` | string | false | | | -| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[array item]` | array | false | | | +| `» agents` | array | false | | | +| `»» apps` | array | false | | | +| `»»» command` | string | false | | | +| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | +| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | +| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | +| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | +| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | +| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | +| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | +| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | +| `»»» id` | string(uuid) | false | | | +| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | +| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | +| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | +| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | +| `»» architecture` | string | false | | | +| `»» connection_timeout_seconds` | integer | false | | | +| `»» created_at` | string(date-time) | false | | | +| `»» directory` | string | false | | | +| `»» disconnected_at` | string(date-time) | false | | | +| `»» environment_variables` | object | false | | | +| `»»» [any property]` | string | false | | | +| `»» expanded_directory` | string | false | | | +| `»» first_connected_at` | string(date-time) | false | | | +| `»» id` | string(uuid) | false | | | +| `»» instance_id` | string | false | | | +| `»» last_connected_at` | string(date-time) | false | | | +| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | +| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | +| `»»»» latency_ms` | number | false | | | +| `»»»» preferred` | boolean | false | | | +| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | +| `»» login_before_ready` | boolean | false | | Deprecated: Use StartupScriptBehavior instead. | +| `»» name` | string | false | | | +| `»» operating_system` | string | false | | | +| `»» resource_id` | string(uuid) | false | | | +| `»» shutdown_script` | string | false | | | +| `»» shutdown_script_timeout_seconds` | integer | false | | | +| `»» startup_logs_length` | integer | false | | | +| `»» startup_logs_overflowed` | boolean | false | | | +| `»» startup_script` | string | false | | | +| `»» startup_script_behavior` | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false | | | +| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | +| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | +| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | +| `»» troubleshooting_url` | string | false | | | +| `»» updated_at` | string(date-time) | false | | | +| `»» version` | string | false | | | +| `» created_at` | string(date-time) | false | | | +| `» daily_cost` | integer | false | | | +| `» hide` | boolean | false | | | +| `» icon` | string | false | | | +| `» id` | string(uuid) | false | | | +| `» job_id` | string(uuid) | false | | | +| `» metadata` | array | false | | | +| `»» key` | string | false | | | +| `»» sensitive` | boolean | false | | | +| `»» value` | string | false | | | +| `» name` | string | false | | | +| `» type` | string | false | | | +| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | #### Enumerated Values -| Property | Value | -| ---------------------- | ------------------ | -| `health` | `disabled` | -| `health` | `initializing` | -| `health` | `healthy` | -| `health` | `unhealthy` | -| `sharing_level` | `owner` | -| `sharing_level` | `authenticated` | -| `sharing_level` | `public` | -| `lifecycle_state` | `created` | -| `lifecycle_state` | `starting` | -| `lifecycle_state` | `start_timeout` | -| `lifecycle_state` | `start_error` | -| `lifecycle_state` | `ready` | -| `lifecycle_state` | `shutting_down` | -| `lifecycle_state` | `shutdown_timeout` | -| `lifecycle_state` | `shutdown_error` | -| `lifecycle_state` | `off` | -| `status` | `connecting` | -| `status` | `connected` | -| `status` | `disconnected` | -| `status` | `timeout` | -| `subsystem` | `envbox` | -| `workspace_transition` | `start` | -| `workspace_transition` | `stop` | -| `workspace_transition` | `delete` | +| Property | Value | +| ------------------------- | ------------------ | +| `health` | `disabled` | +| `health` | `initializing` | +| `health` | `healthy` | +| `health` | `unhealthy` | +| `sharing_level` | `owner` | +| `sharing_level` | `authenticated` | +| `sharing_level` | `public` | +| `lifecycle_state` | `created` | +| `lifecycle_state` | `starting` | +| `lifecycle_state` | `start_timeout` | +| `lifecycle_state` | `start_error` | +| `lifecycle_state` | `ready` | +| `lifecycle_state` | `shutting_down` | +| `lifecycle_state` | `shutdown_timeout` | +| `lifecycle_state` | `shutdown_error` | +| `lifecycle_state` | `off` | +| `startup_script_behavior` | `blocking` | +| `startup_script_behavior` | `non-blocking` | +| `status` | `connecting` | +| `status` | `connected` | +| `status` | `disconnected` | +| `status` | `timeout` | +| `subsystem` | `envbox` | +| `workspace_transition` | `start` | +| `workspace_transition` | `stop` | +| `workspace_transition` | `delete` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -797,6 +803,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -955,6 +962,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -1004,155 +1012,158 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \ Status Code **200** -| Name | Type | Required | Restrictions | Description | -| ------------------------------------- | -------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `[array item]` | array | false | | | -| `» build_number` | integer | false | | | -| `» created_at` | string(date-time) | false | | | -| `» daily_cost` | integer | false | | | -| `» deadline` | string(date-time) | false | | | -| `» id` | string(uuid) | false | | | -| `» initiator_id` | string(uuid) | false | | | -| `» initiator_name` | string | false | | | -| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | | -| `»» canceled_at` | string(date-time) | false | | | -| `»» completed_at` | string(date-time) | false | | | -| `»» created_at` | string(date-time) | false | | | -| `»» error` | string | false | | | -| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | | -| `»» file_id` | string(uuid) | false | | | -| `»» id` | string(uuid) | false | | | -| `»» started_at` | string(date-time) | false | | | -| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | | -| `»» tags` | object | false | | | -| `»»» [any property]` | string | false | | | -| `»» worker_id` | string(uuid) | false | | | -| `» max_deadline` | string(date-time) | false | | | -| `» reason` | [codersdk.BuildReason](schemas.md#codersdkbuildreason) | false | | | -| `» resources` | array | false | | | -| `»» agents` | array | false | | | -| `»»» apps` | array | false | | | -| `»»»» command` | string | false | | | -| `»»»» display_name` | string | false | | »»»display name is a friendly name for the app. | -| `»»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | -| `»»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | -| `»»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | -| `»»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | -| `»»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | -| `»»»»» url` | string | false | | »»»»url specifies the endpoint to check for the app health. | -| `»»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | -| `»»»» id` | string(uuid) | false | | | -| `»»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | -| `»»»» slug` | string | false | | Slug is a unique identifier within the agent. | -| `»»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | -| `»»»» url` | string | false | | »»»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | -| `»»» architecture` | string | false | | | -| `»»» connection_timeout_seconds` | integer | false | | | -| `»»» created_at` | string(date-time) | false | | | -| `»»» directory` | string | false | | | -| `»»» disconnected_at` | string(date-time) | false | | | -| `»»» environment_variables` | object | false | | | -| `»»»» [any property]` | string | false | | | -| `»»» expanded_directory` | string | false | | | -| `»»» first_connected_at` | string(date-time) | false | | | -| `»»» id` | string(uuid) | false | | | -| `»»» instance_id` | string | false | | | -| `»»» last_connected_at` | string(date-time) | false | | | -| `»»» latency` | object | false | | »»latency is mapped by region name (e.g. "New York City", "Seattle"). | -| `»»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | -| `»»»»» latency_ms` | number | false | | | -| `»»»»» preferred` | boolean | false | | | -| `»»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | -| `»»» login_before_ready` | boolean | false | | »»login before ready if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). | -| `»»» name` | string | false | | | -| `»»» operating_system` | string | false | | | -| `»»» resource_id` | string(uuid) | false | | | -| `»»» shutdown_script` | string | false | | | -| `»»» shutdown_script_timeout_seconds` | integer | false | | | -| `»»» startup_logs_length` | integer | false | | | -| `»»» startup_logs_overflowed` | boolean | false | | | -| `»»» startup_script` | string | false | | | -| `»»» startup_script_timeout_seconds` | integer | false | | »»startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | -| `»»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | -| `»»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | -| `»»» troubleshooting_url` | string | false | | | -| `»»» updated_at` | string(date-time) | false | | | -| `»»» version` | string | false | | | -| `»» created_at` | string(date-time) | false | | | -| `»» daily_cost` | integer | false | | | -| `»» hide` | boolean | false | | | -| `»» icon` | string | false | | | -| `»» id` | string(uuid) | false | | | -| `»» job_id` | string(uuid) | false | | | -| `»» metadata` | array | false | | | -| `»»» key` | string | false | | | -| `»»» sensitive` | boolean | false | | | -| `»»» value` | string | false | | | -| `»» name` | string | false | | | -| `»» type` | string | false | | | -| `»» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | -| `» status` | [codersdk.WorkspaceStatus](schemas.md#codersdkworkspacestatus) | false | | | -| `» template_version_id` | string(uuid) | false | | | -| `» template_version_name` | string | false | | | -| `» transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | -| `» updated_at` | string(date-time) | false | | | -| `» workspace_id` | string(uuid) | false | | | -| `» workspace_name` | string | false | | | -| `» workspace_owner_id` | string(uuid) | false | | | -| `» workspace_owner_name` | string | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[array item]` | array | false | | | +| `» build_number` | integer | false | | | +| `» created_at` | string(date-time) | false | | | +| `» daily_cost` | integer | false | | | +| `» deadline` | string(date-time) | false | | | +| `» id` | string(uuid) | false | | | +| `» initiator_id` | string(uuid) | false | | | +| `» initiator_name` | string | false | | | +| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | | +| `»» canceled_at` | string(date-time) | false | | | +| `»» completed_at` | string(date-time) | false | | | +| `»» created_at` | string(date-time) | false | | | +| `»» error` | string | false | | | +| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | | +| `»» file_id` | string(uuid) | false | | | +| `»» id` | string(uuid) | false | | | +| `»» started_at` | string(date-time) | false | | | +| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | | +| `»» tags` | object | false | | | +| `»»» [any property]` | string | false | | | +| `»» worker_id` | string(uuid) | false | | | +| `» max_deadline` | string(date-time) | false | | | +| `» reason` | [codersdk.BuildReason](schemas.md#codersdkbuildreason) | false | | | +| `» resources` | array | false | | | +| `»» agents` | array | false | | | +| `»»» apps` | array | false | | | +| `»»»» command` | string | false | | | +| `»»»» display_name` | string | false | | »»»display name is a friendly name for the app. | +| `»»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | +| `»»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | +| `»»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | +| `»»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | +| `»»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | +| `»»»»» url` | string | false | | »»»»url specifies the endpoint to check for the app health. | +| `»»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | +| `»»»» id` | string(uuid) | false | | | +| `»»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | +| `»»»» slug` | string | false | | Slug is a unique identifier within the agent. | +| `»»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | +| `»»»» url` | string | false | | »»»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | +| `»»» architecture` | string | false | | | +| `»»» connection_timeout_seconds` | integer | false | | | +| `»»» created_at` | string(date-time) | false | | | +| `»»» directory` | string | false | | | +| `»»» disconnected_at` | string(date-time) | false | | | +| `»»» environment_variables` | object | false | | | +| `»»»» [any property]` | string | false | | | +| `»»» expanded_directory` | string | false | | | +| `»»» first_connected_at` | string(date-time) | false | | | +| `»»» id` | string(uuid) | false | | | +| `»»» instance_id` | string | false | | | +| `»»» last_connected_at` | string(date-time) | false | | | +| `»»» latency` | object | false | | »»latency is mapped by region name (e.g. "New York City", "Seattle"). | +| `»»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | +| `»»»»» latency_ms` | number | false | | | +| `»»»»» preferred` | boolean | false | | | +| `»»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | +| `»»» login_before_ready` | boolean | false | | Deprecated: Use StartupScriptBehavior instead. | +| `»»» name` | string | false | | | +| `»»» operating_system` | string | false | | | +| `»»» resource_id` | string(uuid) | false | | | +| `»»» shutdown_script` | string | false | | | +| `»»» shutdown_script_timeout_seconds` | integer | false | | | +| `»»» startup_logs_length` | integer | false | | | +| `»»» startup_logs_overflowed` | boolean | false | | | +| `»»» startup_script` | string | false | | | +| `»»» startup_script_behavior` | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false | | | +| `»»» startup_script_timeout_seconds` | integer | false | | »»startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | +| `»»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | +| `»»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | +| `»»» troubleshooting_url` | string | false | | | +| `»»» updated_at` | string(date-time) | false | | | +| `»»» version` | string | false | | | +| `»» created_at` | string(date-time) | false | | | +| `»» daily_cost` | integer | false | | | +| `»» hide` | boolean | false | | | +| `»» icon` | string | false | | | +| `»» id` | string(uuid) | false | | | +| `»» job_id` | string(uuid) | false | | | +| `»» metadata` | array | false | | | +| `»»» key` | string | false | | | +| `»»» sensitive` | boolean | false | | | +| `»»» value` | string | false | | | +| `»» name` | string | false | | | +| `»» type` | string | false | | | +| `»» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | +| `» status` | [codersdk.WorkspaceStatus](schemas.md#codersdkworkspacestatus) | false | | | +| `» template_version_id` | string(uuid) | false | | | +| `» template_version_name` | string | false | | | +| `» transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | +| `» updated_at` | string(date-time) | false | | | +| `» workspace_id` | string(uuid) | false | | | +| `» workspace_name` | string | false | | | +| `» workspace_owner_id` | string(uuid) | false | | | +| `» workspace_owner_name` | string | false | | | #### Enumerated Values -| Property | Value | -| ---------------------- | ----------------------------- | -| `error_code` | `MISSING_TEMPLATE_PARAMETER` | -| `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | -| `status` | `pending` | -| `status` | `running` | -| `status` | `succeeded` | -| `status` | `canceling` | -| `status` | `canceled` | -| `status` | `failed` | -| `reason` | `initiator` | -| `reason` | `autostart` | -| `reason` | `autostop` | -| `health` | `disabled` | -| `health` | `initializing` | -| `health` | `healthy` | -| `health` | `unhealthy` | -| `sharing_level` | `owner` | -| `sharing_level` | `authenticated` | -| `sharing_level` | `public` | -| `lifecycle_state` | `created` | -| `lifecycle_state` | `starting` | -| `lifecycle_state` | `start_timeout` | -| `lifecycle_state` | `start_error` | -| `lifecycle_state` | `ready` | -| `lifecycle_state` | `shutting_down` | -| `lifecycle_state` | `shutdown_timeout` | -| `lifecycle_state` | `shutdown_error` | -| `lifecycle_state` | `off` | -| `status` | `connecting` | -| `status` | `connected` | -| `status` | `disconnected` | -| `status` | `timeout` | -| `subsystem` | `envbox` | -| `workspace_transition` | `start` | -| `workspace_transition` | `stop` | -| `workspace_transition` | `delete` | -| `status` | `pending` | -| `status` | `starting` | -| `status` | `running` | -| `status` | `stopping` | -| `status` | `stopped` | -| `status` | `failed` | -| `status` | `canceling` | -| `status` | `canceled` | -| `status` | `deleting` | -| `status` | `deleted` | -| `transition` | `start` | -| `transition` | `stop` | -| `transition` | `delete` | +| Property | Value | +| ------------------------- | ----------------------------- | +| `error_code` | `MISSING_TEMPLATE_PARAMETER` | +| `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | +| `status` | `pending` | +| `status` | `running` | +| `status` | `succeeded` | +| `status` | `canceling` | +| `status` | `canceled` | +| `status` | `failed` | +| `reason` | `initiator` | +| `reason` | `autostart` | +| `reason` | `autostop` | +| `health` | `disabled` | +| `health` | `initializing` | +| `health` | `healthy` | +| `health` | `unhealthy` | +| `sharing_level` | `owner` | +| `sharing_level` | `authenticated` | +| `sharing_level` | `public` | +| `lifecycle_state` | `created` | +| `lifecycle_state` | `starting` | +| `lifecycle_state` | `start_timeout` | +| `lifecycle_state` | `start_error` | +| `lifecycle_state` | `ready` | +| `lifecycle_state` | `shutting_down` | +| `lifecycle_state` | `shutdown_timeout` | +| `lifecycle_state` | `shutdown_error` | +| `lifecycle_state` | `off` | +| `startup_script_behavior` | `blocking` | +| `startup_script_behavior` | `non-blocking` | +| `status` | `connecting` | +| `status` | `connected` | +| `status` | `disconnected` | +| `status` | `timeout` | +| `subsystem` | `envbox` | +| `workspace_transition` | `start` | +| `workspace_transition` | `stop` | +| `workspace_transition` | `delete` | +| `status` | `pending` | +| `status` | `starting` | +| `status` | `running` | +| `status` | `stopping` | +| `status` | `stopped` | +| `status` | `failed` | +| `status` | `canceling` | +| `status` | `canceled` | +| `status` | `deleting` | +| `status` | `deleted` | +| `transition` | `start` | +| `transition` | `stop` | +| `transition` | `delete` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -1284,6 +1295,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 8b70dc73bf..d50b1d15e7 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -4499,6 +4499,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -4630,6 +4631,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -4641,39 +4643,40 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in ### Properties -| Name | Type | Required | Restrictions | Description | -| --------------------------------- | -------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `apps` | array of [codersdk.WorkspaceApp](#codersdkworkspaceapp) | false | | | -| `architecture` | string | false | | | -| `connection_timeout_seconds` | integer | false | | | -| `created_at` | string | false | | | -| `directory` | string | false | | | -| `disconnected_at` | string | false | | | -| `environment_variables` | object | false | | | -| » `[any property]` | string | false | | | -| `expanded_directory` | string | false | | | -| `first_connected_at` | string | false | | | -| `id` | string | false | | | -| `instance_id` | string | false | | | -| `last_connected_at` | string | false | | | -| `latency` | object | false | | Latency is mapped by region name (e.g. "New York City", "Seattle"). | -| » `[any property]` | [codersdk.DERPRegion](#codersdkderpregion) | false | | | -| `lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle) | false | | | -| `login_before_ready` | boolean | false | | Login before ready if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). | -| `name` | string | false | | | -| `operating_system` | string | false | | | -| `resource_id` | string | false | | | -| `shutdown_script` | string | false | | | -| `shutdown_script_timeout_seconds` | integer | false | | | -| `startup_logs_length` | integer | false | | | -| `startup_logs_overflowed` | boolean | false | | | -| `startup_script` | string | false | | | -| `startup_script_timeout_seconds` | integer | false | | Startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | -| `status` | [codersdk.WorkspaceAgentStatus](#codersdkworkspaceagentstatus) | false | | | -| `subsystem` | [codersdk.AgentSubsystem](#codersdkagentsubsystem) | false | | | -| `troubleshooting_url` | string | false | | | -| `updated_at` | string | false | | | -| `version` | string | false | | | +| Name | Type | Required | Restrictions | Description | +| --------------------------------- | -------------------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `apps` | array of [codersdk.WorkspaceApp](#codersdkworkspaceapp) | false | | | +| `architecture` | string | false | | | +| `connection_timeout_seconds` | integer | false | | | +| `created_at` | string | false | | | +| `directory` | string | false | | | +| `disconnected_at` | string | false | | | +| `environment_variables` | object | false | | | +| » `[any property]` | string | false | | | +| `expanded_directory` | string | false | | | +| `first_connected_at` | string | false | | | +| `id` | string | false | | | +| `instance_id` | string | false | | | +| `last_connected_at` | string | false | | | +| `latency` | object | false | | Latency is mapped by region name (e.g. "New York City", "Seattle"). | +| » `[any property]` | [codersdk.DERPRegion](#codersdkderpregion) | false | | | +| `lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle) | false | | | +| `login_before_ready` | boolean | false | | Deprecated: Use StartupScriptBehavior instead. | +| `name` | string | false | | | +| `operating_system` | string | false | | | +| `resource_id` | string | false | | | +| `shutdown_script` | string | false | | | +| `shutdown_script_timeout_seconds` | integer | false | | | +| `startup_logs_length` | integer | false | | | +| `startup_logs_overflowed` | boolean | false | | | +| `startup_script` | string | false | | | +| `startup_script_behavior` | [codersdk.WorkspaceAgentStartupScriptBehavior](#codersdkworkspaceagentstartupscriptbehavior) | false | | | +| `startup_script_timeout_seconds` | integer | false | | Startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | +| `status` | [codersdk.WorkspaceAgentStatus](#codersdkworkspaceagentstatus) | false | | | +| `subsystem` | [codersdk.AgentSubsystem](#codersdkagentsubsystem) | false | | | +| `troubleshooting_url` | string | false | | | +| `updated_at` | string | false | | | +| `version` | string | false | | | ## codersdk.WorkspaceAgentConnectionInfo @@ -4841,6 +4844,21 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `level` | [codersdk.LogLevel](#codersdkloglevel) | false | | | | `output` | string | false | | | +## codersdk.WorkspaceAgentStartupScriptBehavior + +```json +"blocking" +``` + +### Properties + +#### Enumerated Values + +| Value | +| -------------- | +| `blocking` | +| `non-blocking` | + ## codersdk.WorkspaceAgentStatus ```json @@ -5023,6 +5041,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -5305,6 +5324,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -5504,6 +5524,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", diff --git a/docs/api/templates.md b/docs/api/templates.md index ff121d5b5a..50275ab168 100644 --- a/docs/api/templates.md +++ b/docs/api/templates.md @@ -1652,6 +1652,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -1690,99 +1691,102 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d Status Code **200** -| Name | Type | Required | Restrictions | Description | -| ------------------------------------ | -------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `[array item]` | array | false | | | -| `» agents` | array | false | | | -| `»» apps` | array | false | | | -| `»»» command` | string | false | | | -| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | -| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | -| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | -| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | -| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | -| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | -| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | -| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | -| `»»» id` | string(uuid) | false | | | -| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | -| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | -| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | -| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | -| `»» architecture` | string | false | | | -| `»» connection_timeout_seconds` | integer | false | | | -| `»» created_at` | string(date-time) | false | | | -| `»» directory` | string | false | | | -| `»» disconnected_at` | string(date-time) | false | | | -| `»» environment_variables` | object | false | | | -| `»»» [any property]` | string | false | | | -| `»» expanded_directory` | string | false | | | -| `»» first_connected_at` | string(date-time) | false | | | -| `»» id` | string(uuid) | false | | | -| `»» instance_id` | string | false | | | -| `»» last_connected_at` | string(date-time) | false | | | -| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | -| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | -| `»»»» latency_ms` | number | false | | | -| `»»»» preferred` | boolean | false | | | -| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | -| `»» login_before_ready` | boolean | false | | »login before ready if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). | -| `»» name` | string | false | | | -| `»» operating_system` | string | false | | | -| `»» resource_id` | string(uuid) | false | | | -| `»» shutdown_script` | string | false | | | -| `»» shutdown_script_timeout_seconds` | integer | false | | | -| `»» startup_logs_length` | integer | false | | | -| `»» startup_logs_overflowed` | boolean | false | | | -| `»» startup_script` | string | false | | | -| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | -| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | -| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | -| `»» troubleshooting_url` | string | false | | | -| `»» updated_at` | string(date-time) | false | | | -| `»» version` | string | false | | | -| `» created_at` | string(date-time) | false | | | -| `» daily_cost` | integer | false | | | -| `» hide` | boolean | false | | | -| `» icon` | string | false | | | -| `» id` | string(uuid) | false | | | -| `» job_id` | string(uuid) | false | | | -| `» metadata` | array | false | | | -| `»» key` | string | false | | | -| `»» sensitive` | boolean | false | | | -| `»» value` | string | false | | | -| `» name` | string | false | | | -| `» type` | string | false | | | -| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[array item]` | array | false | | | +| `» agents` | array | false | | | +| `»» apps` | array | false | | | +| `»»» command` | string | false | | | +| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | +| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | +| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | +| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | +| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | +| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | +| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | +| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | +| `»»» id` | string(uuid) | false | | | +| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | +| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | +| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | +| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | +| `»» architecture` | string | false | | | +| `»» connection_timeout_seconds` | integer | false | | | +| `»» created_at` | string(date-time) | false | | | +| `»» directory` | string | false | | | +| `»» disconnected_at` | string(date-time) | false | | | +| `»» environment_variables` | object | false | | | +| `»»» [any property]` | string | false | | | +| `»» expanded_directory` | string | false | | | +| `»» first_connected_at` | string(date-time) | false | | | +| `»» id` | string(uuid) | false | | | +| `»» instance_id` | string | false | | | +| `»» last_connected_at` | string(date-time) | false | | | +| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | +| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | +| `»»»» latency_ms` | number | false | | | +| `»»»» preferred` | boolean | false | | | +| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | +| `»» login_before_ready` | boolean | false | | Deprecated: Use StartupScriptBehavior instead. | +| `»» name` | string | false | | | +| `»» operating_system` | string | false | | | +| `»» resource_id` | string(uuid) | false | | | +| `»» shutdown_script` | string | false | | | +| `»» shutdown_script_timeout_seconds` | integer | false | | | +| `»» startup_logs_length` | integer | false | | | +| `»» startup_logs_overflowed` | boolean | false | | | +| `»» startup_script` | string | false | | | +| `»» startup_script_behavior` | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false | | | +| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | +| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | +| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | +| `»» troubleshooting_url` | string | false | | | +| `»» updated_at` | string(date-time) | false | | | +| `»» version` | string | false | | | +| `» created_at` | string(date-time) | false | | | +| `» daily_cost` | integer | false | | | +| `» hide` | boolean | false | | | +| `» icon` | string | false | | | +| `» id` | string(uuid) | false | | | +| `» job_id` | string(uuid) | false | | | +| `» metadata` | array | false | | | +| `»» key` | string | false | | | +| `»» sensitive` | boolean | false | | | +| `»» value` | string | false | | | +| `» name` | string | false | | | +| `» type` | string | false | | | +| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | #### Enumerated Values -| Property | Value | -| ---------------------- | ------------------ | -| `health` | `disabled` | -| `health` | `initializing` | -| `health` | `healthy` | -| `health` | `unhealthy` | -| `sharing_level` | `owner` | -| `sharing_level` | `authenticated` | -| `sharing_level` | `public` | -| `lifecycle_state` | `created` | -| `lifecycle_state` | `starting` | -| `lifecycle_state` | `start_timeout` | -| `lifecycle_state` | `start_error` | -| `lifecycle_state` | `ready` | -| `lifecycle_state` | `shutting_down` | -| `lifecycle_state` | `shutdown_timeout` | -| `lifecycle_state` | `shutdown_error` | -| `lifecycle_state` | `off` | -| `status` | `connecting` | -| `status` | `connected` | -| `status` | `disconnected` | -| `status` | `timeout` | -| `subsystem` | `envbox` | -| `workspace_transition` | `start` | -| `workspace_transition` | `stop` | -| `workspace_transition` | `delete` | +| Property | Value | +| ------------------------- | ------------------ | +| `health` | `disabled` | +| `health` | `initializing` | +| `health` | `healthy` | +| `health` | `unhealthy` | +| `sharing_level` | `owner` | +| `sharing_level` | `authenticated` | +| `sharing_level` | `public` | +| `lifecycle_state` | `created` | +| `lifecycle_state` | `starting` | +| `lifecycle_state` | `start_timeout` | +| `lifecycle_state` | `start_error` | +| `lifecycle_state` | `ready` | +| `lifecycle_state` | `shutting_down` | +| `lifecycle_state` | `shutdown_timeout` | +| `lifecycle_state` | `shutdown_error` | +| `lifecycle_state` | `off` | +| `startup_script_behavior` | `blocking` | +| `startup_script_behavior` | `non-blocking` | +| `status` | `connecting` | +| `status` | `connected` | +| `status` | `disconnected` | +| `status` | `timeout` | +| `subsystem` | `envbox` | +| `workspace_transition` | `start` | +| `workspace_transition` | `stop` | +| `workspace_transition` | `delete` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -2029,6 +2033,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/r "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -2067,99 +2072,102 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/r Status Code **200** -| Name | Type | Required | Restrictions | Description | -| ------------------------------------ | -------------------------------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `[array item]` | array | false | | | -| `» agents` | array | false | | | -| `»» apps` | array | false | | | -| `»»» command` | string | false | | | -| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | -| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | -| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | -| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | -| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | -| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | -| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | -| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | -| `»»» id` | string(uuid) | false | | | -| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | -| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | -| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | -| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | -| `»» architecture` | string | false | | | -| `»» connection_timeout_seconds` | integer | false | | | -| `»» created_at` | string(date-time) | false | | | -| `»» directory` | string | false | | | -| `»» disconnected_at` | string(date-time) | false | | | -| `»» environment_variables` | object | false | | | -| `»»» [any property]` | string | false | | | -| `»» expanded_directory` | string | false | | | -| `»» first_connected_at` | string(date-time) | false | | | -| `»» id` | string(uuid) | false | | | -| `»» instance_id` | string | false | | | -| `»» last_connected_at` | string(date-time) | false | | | -| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | -| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | -| `»»»» latency_ms` | number | false | | | -| `»»»» preferred` | boolean | false | | | -| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | -| `»» login_before_ready` | boolean | false | | »login before ready if true, the agent will delay logins until it is ready (e.g. executing startup script has ended). | -| `»» name` | string | false | | | -| `»» operating_system` | string | false | | | -| `»» resource_id` | string(uuid) | false | | | -| `»» shutdown_script` | string | false | | | -| `»» shutdown_script_timeout_seconds` | integer | false | | | -| `»» startup_logs_length` | integer | false | | | -| `»» startup_logs_overflowed` | boolean | false | | | -| `»» startup_script` | string | false | | | -| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | -| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | -| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | -| `»» troubleshooting_url` | string | false | | | -| `»» updated_at` | string(date-time) | false | | | -| `»» version` | string | false | | | -| `» created_at` | string(date-time) | false | | | -| `» daily_cost` | integer | false | | | -| `» hide` | boolean | false | | | -| `» icon` | string | false | | | -| `» id` | string(uuid) | false | | | -| `» job_id` | string(uuid) | false | | | -| `» metadata` | array | false | | | -| `»» key` | string | false | | | -| `»» sensitive` | boolean | false | | | -| `»» value` | string | false | | | -| `» name` | string | false | | | -| `» type` | string | false | | | -| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------ | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[array item]` | array | false | | | +| `» agents` | array | false | | | +| `»» apps` | array | false | | | +| `»»» command` | string | false | | | +| `»»» display_name` | string | false | | »»display name is a friendly name for the app. | +| `»»» external` | boolean | false | | External specifies whether the URL should be opened externally on the client or not. | +| `»»» health` | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth) | false | | | +| `»»» healthcheck` | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck) | false | | Healthcheck specifies the configuration for checking app health. | +| `»»»» interval` | integer | false | | Interval specifies the seconds between each health check. | +| `»»»» threshold` | integer | false | | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". | +| `»»»» url` | string | false | | »»»url specifies the endpoint to check for the app health. | +| `»»» icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | +| `»»» id` | string(uuid) | false | | | +| `»»» sharing_level` | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel) | false | | | +| `»»» slug` | string | false | | Slug is a unique identifier within the agent. | +| `»»» subdomain` | boolean | false | | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. | +| `»»» url` | string | false | | »»url is the address being proxied to inside the workspace. If external is specified, this will be opened on the client. | +| `»» architecture` | string | false | | | +| `»» connection_timeout_seconds` | integer | false | | | +| `»» created_at` | string(date-time) | false | | | +| `»» directory` | string | false | | | +| `»» disconnected_at` | string(date-time) | false | | | +| `»» environment_variables` | object | false | | | +| `»»» [any property]` | string | false | | | +| `»» expanded_directory` | string | false | | | +| `»» first_connected_at` | string(date-time) | false | | | +| `»» id` | string(uuid) | false | | | +| `»» instance_id` | string | false | | | +| `»» last_connected_at` | string(date-time) | false | | | +| `»» latency` | object | false | | »latency is mapped by region name (e.g. "New York City", "Seattle"). | +| `»»» [any property]` | [codersdk.DERPRegion](schemas.md#codersdkderpregion) | false | | | +| `»»»» latency_ms` | number | false | | | +| `»»»» preferred` | boolean | false | | | +| `»» lifecycle_state` | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle) | false | | | +| `»» login_before_ready` | boolean | false | | Deprecated: Use StartupScriptBehavior instead. | +| `»» name` | string | false | | | +| `»» operating_system` | string | false | | | +| `»» resource_id` | string(uuid) | false | | | +| `»» shutdown_script` | string | false | | | +| `»» shutdown_script_timeout_seconds` | integer | false | | | +| `»» startup_logs_length` | integer | false | | | +| `»» startup_logs_overflowed` | boolean | false | | | +| `»» startup_script` | string | false | | | +| `»» startup_script_behavior` | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false | | | +| `»» startup_script_timeout_seconds` | integer | false | | »startup script timeout seconds is the number of seconds to wait for the startup script to complete. If the script does not complete within this time, the agent lifecycle will be marked as start_timeout. | +| `»» status` | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus) | false | | | +| `»» subsystem` | [codersdk.AgentSubsystem](schemas.md#codersdkagentsubsystem) | false | | | +| `»» troubleshooting_url` | string | false | | | +| `»» updated_at` | string(date-time) | false | | | +| `»» version` | string | false | | | +| `» created_at` | string(date-time) | false | | | +| `» daily_cost` | integer | false | | | +| `» hide` | boolean | false | | | +| `» icon` | string | false | | | +| `» id` | string(uuid) | false | | | +| `» job_id` | string(uuid) | false | | | +| `» metadata` | array | false | | | +| `»» key` | string | false | | | +| `»» sensitive` | boolean | false | | | +| `»» value` | string | false | | | +| `» name` | string | false | | | +| `» type` | string | false | | | +| `» workspace_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition) | false | | | #### Enumerated Values -| Property | Value | -| ---------------------- | ------------------ | -| `health` | `disabled` | -| `health` | `initializing` | -| `health` | `healthy` | -| `health` | `unhealthy` | -| `sharing_level` | `owner` | -| `sharing_level` | `authenticated` | -| `sharing_level` | `public` | -| `lifecycle_state` | `created` | -| `lifecycle_state` | `starting` | -| `lifecycle_state` | `start_timeout` | -| `lifecycle_state` | `start_error` | -| `lifecycle_state` | `ready` | -| `lifecycle_state` | `shutting_down` | -| `lifecycle_state` | `shutdown_timeout` | -| `lifecycle_state` | `shutdown_error` | -| `lifecycle_state` | `off` | -| `status` | `connecting` | -| `status` | `connected` | -| `status` | `disconnected` | -| `status` | `timeout` | -| `subsystem` | `envbox` | -| `workspace_transition` | `start` | -| `workspace_transition` | `stop` | -| `workspace_transition` | `delete` | +| Property | Value | +| ------------------------- | ------------------ | +| `health` | `disabled` | +| `health` | `initializing` | +| `health` | `healthy` | +| `health` | `unhealthy` | +| `sharing_level` | `owner` | +| `sharing_level` | `authenticated` | +| `sharing_level` | `public` | +| `lifecycle_state` | `created` | +| `lifecycle_state` | `starting` | +| `lifecycle_state` | `start_timeout` | +| `lifecycle_state` | `start_error` | +| `lifecycle_state` | `ready` | +| `lifecycle_state` | `shutting_down` | +| `lifecycle_state` | `shutdown_timeout` | +| `lifecycle_state` | `shutdown_error` | +| `lifecycle_state` | `off` | +| `startup_script_behavior` | `blocking` | +| `startup_script_behavior` | `non-blocking` | +| `status` | `connecting` | +| `status` | `connected` | +| `status` | `disconnected` | +| `status` | `timeout` | +| `subsystem` | `envbox` | +| `workspace_transition` | `start` | +| `workspace_transition` | `stop` | +| `workspace_transition` | `delete` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/workspaces.md b/docs/api/workspaces.md index f33b5e4c39..3d4724a908 100644 --- a/docs/api/workspaces.md +++ b/docs/api/workspaces.md @@ -133,6 +133,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/member "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -307,6 +308,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -500,6 +502,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", @@ -675,6 +678,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \ "startup_logs_length": 0, "startup_logs_overflowed": true, "startup_script": "string", + "startup_script_behavior": "blocking", "startup_script_timeout_seconds": 0, "status": "connecting", "subsystem": "envbox", diff --git a/docs/cli/ssh.md b/docs/cli/ssh.md index 2ec3ff5beb..7d580b23b0 100644 --- a/docs/cli/ssh.md +++ b/docs/cli/ssh.md @@ -65,7 +65,7 @@ Enable diagnostic logging to file. | Type | bool | | Environment | $CODER_SSH_NO_WAIT | -Specifies whether to wait for a workspace to become ready before logging in (only applicable when the login before ready option has not been enabled). Note that the workspace agent may still be in the process of executing the startup script and the workspace may be in an incomplete state. +Specifies whether to wait for a workspace to become ready before logging in (only applicable when the startup script behavior is blocking). Note that the workspace agent may still be in the process of executing the startup script and the workspace may be in an incomplete state. ### --stdio diff --git a/dogfood/main.tf b/dogfood/main.tf index 218183630e..02afd73de1 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.7.0" + version = "0.8.3" } docker = { source = "kreuzwerker/docker" @@ -91,7 +91,7 @@ resource "coder_agent" "dev" { GITHUB_TOKEN : data.coder_git_auth.github.access_token, OIDC_TOKEN : data.coder_workspace.me.owner_oidc_access_token, } - login_before_ready = false + startup_script_behavior = "blocking" metadata { display_name = "CPU Usage" diff --git a/examples/templates/azure-windows/main.tf b/examples/templates/azure-windows/main.tf index 6bfe25e78e..92f62c1f10 100644 --- a/examples/templates/azure-windows/main.tf +++ b/examples/templates/azure-windows/main.tf @@ -58,10 +58,9 @@ data "coder_parameter" "data_disk_size" { } resource "coder_agent" "main" { - arch = "amd64" - auth = "azure-instance-identity" - os = "windows" - login_before_ready = false + arch = "amd64" + auth = "azure-instance-identity" + os = "windows" } resource "random_password" "admin_password" { diff --git a/provisioner/terraform/resources.go b/provisioner/terraform/resources.go index 026a1fbf89..8832c21ddc 100644 --- a/provisioner/terraform/resources.go +++ b/provisioner/terraform/resources.go @@ -10,6 +10,7 @@ import ( "github.com/coder/terraform-provider-coder/provider" + "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner" "github.com/coder/coder/provisionersdk/proto" ) @@ -24,22 +25,24 @@ type agentMetadata struct { // A mapping of attributes on the "coder_agent" resource. type agentAttributes struct { - Auth string `mapstructure:"auth"` - OperatingSystem string `mapstructure:"os"` - Architecture string `mapstructure:"arch"` - Directory string `mapstructure:"dir"` - ID string `mapstructure:"id"` - Token string `mapstructure:"token"` - Env map[string]string `mapstructure:"env"` - StartupScript string `mapstructure:"startup_script"` - ConnectionTimeoutSeconds int32 `mapstructure:"connection_timeout"` - TroubleshootingURL string `mapstructure:"troubleshooting_url"` - MOTDFile string `mapstructure:"motd_file"` - LoginBeforeReady bool `mapstructure:"login_before_ready"` - StartupScriptTimeoutSeconds int32 `mapstructure:"startup_script_timeout"` - ShutdownScript string `mapstructure:"shutdown_script"` - ShutdownScriptTimeoutSeconds int32 `mapstructure:"shutdown_script_timeout"` - Metadata []agentMetadata `mapstructure:"metadata"` + Auth string `mapstructure:"auth"` + OperatingSystem string `mapstructure:"os"` + Architecture string `mapstructure:"arch"` + Directory string `mapstructure:"dir"` + ID string `mapstructure:"id"` + Token string `mapstructure:"token"` + Env map[string]string `mapstructure:"env"` + StartupScript string `mapstructure:"startup_script"` + ConnectionTimeoutSeconds int32 `mapstructure:"connection_timeout"` + TroubleshootingURL string `mapstructure:"troubleshooting_url"` + MOTDFile string `mapstructure:"motd_file"` + // Deprecated, but remains here for backwards compatibility. + LoginBeforeReady bool `mapstructure:"login_before_ready"` + StartupScriptBehavior string `mapstructure:"startup_script_behavior"` + StartupScriptTimeoutSeconds int32 `mapstructure:"startup_script_timeout"` + ShutdownScript string `mapstructure:"shutdown_script"` + ShutdownScriptTimeoutSeconds int32 `mapstructure:"shutdown_script_timeout"` + Metadata []agentMetadata `mapstructure:"metadata"` } // A mapping of attributes on the "coder_app" resource. @@ -151,10 +154,18 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa } agentNames[tfResource.Name] = struct{}{} - // Handling for provider pre-v0.6.10. - loginBeforeReady := true - if _, ok := tfResource.AttributeValues["login_before_ready"]; ok { - loginBeforeReady = attrs.LoginBeforeReady + // Handling for deprecated attributes. login_before_ready was replaced + // by startup_script_behavior, but we still need to support it for + // backwards compatibility. + startupScriptBehavior := string(codersdk.WorkspaceAgentStartupScriptBehaviorNonBlocking) + if attrs.StartupScriptBehavior != "" { + startupScriptBehavior = attrs.StartupScriptBehavior + } else { + // Handling for provider pre-v0.6.10 (because login_before_ready + // defaulted to true, we must check for its presence). + if _, ok := tfResource.AttributeValues["login_before_ready"]; ok && !attrs.LoginBeforeReady { + startupScriptBehavior = string(codersdk.WorkspaceAgentStartupScriptBehaviorBlocking) + } } var metadata []*proto.Agent_Metadata @@ -179,7 +190,7 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa ConnectionTimeoutSeconds: attrs.ConnectionTimeoutSeconds, TroubleshootingUrl: attrs.TroubleshootingURL, MotdFile: attrs.MOTDFile, - LoginBeforeReady: loginBeforeReady, + StartupScriptBehavior: startupScriptBehavior, StartupScriptTimeoutSeconds: attrs.StartupScriptTimeoutSeconds, ShutdownScript: attrs.ShutdownScript, ShutdownScriptTimeoutSeconds: attrs.ShutdownScriptTimeoutSeconds, diff --git a/provisioner/terraform/resources_test.go b/provisioner/terraform/resources_test.go index 5814417091..ad96c0b0a0 100644 --- a/provisioner/terraform/resources_test.go +++ b/provisioner/terraform/resources_test.go @@ -43,7 +43,7 @@ func TestConvertResources(t *testing.T) { OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -60,7 +60,7 @@ func TestConvertResources(t *testing.T) { OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }, { @@ -78,7 +78,7 @@ func TestConvertResources(t *testing.T) { OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_InstanceId{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -94,7 +94,7 @@ func TestConvertResources(t *testing.T) { OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -111,7 +111,7 @@ func TestConvertResources(t *testing.T) { Architecture: "amd64", Auth: &proto.Agent_Token{}, ConnectionTimeoutSeconds: 120, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", StartupScriptTimeoutSeconds: 300, ShutdownScriptTimeoutSeconds: 300, }, { @@ -121,7 +121,7 @@ func TestConvertResources(t *testing.T) { Auth: &proto.Agent_Token{}, ConnectionTimeoutSeconds: 1, MotdFile: "/etc/motd", - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", StartupScriptTimeoutSeconds: 30, ShutdownScript: "echo bye bye", ShutdownScriptTimeoutSeconds: 30, @@ -132,7 +132,16 @@ func TestConvertResources(t *testing.T) { Auth: &proto.Agent_Token{}, ConnectionTimeoutSeconds: 120, TroubleshootingUrl: "https://coder.com/troubleshoot", - LoginBeforeReady: false, + StartupScriptBehavior: "blocking", + StartupScriptTimeoutSeconds: 300, + ShutdownScriptTimeoutSeconds: 300, + }, { + Name: "dev4", + OperatingSystem: "linux", + Architecture: "amd64", + Auth: &proto.Agent_Token{}, + ConnectionTimeoutSeconds: 120, + StartupScriptBehavior: "blocking", StartupScriptTimeoutSeconds: 300, ShutdownScriptTimeoutSeconds: 300, }}, @@ -171,7 +180,7 @@ func TestConvertResources(t *testing.T) { }, }, Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -195,7 +204,7 @@ func TestConvertResources(t *testing.T) { }, }, Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -235,7 +244,7 @@ func TestConvertResources(t *testing.T) { }}, ShutdownScriptTimeoutSeconds: 300, StartupScriptTimeoutSeconds: 300, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -286,7 +295,7 @@ func TestConvertResources(t *testing.T) { }, }, Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }, @@ -303,7 +312,7 @@ func TestConvertResources(t *testing.T) { StartupScriptTimeoutSeconds: 300, Architecture: "arm64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -360,7 +369,7 @@ func TestConvertResources(t *testing.T) { StartupScriptTimeoutSeconds: 300, Architecture: "arm64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, }}, }}, @@ -411,7 +420,7 @@ func TestConvertResources(t *testing.T) { OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_Token{}, - LoginBeforeReady: true, + StartupScriptBehavior: "non-blocking", ConnectionTimeoutSeconds: 120, StartupScriptTimeoutSeconds: 300, ShutdownScriptTimeoutSeconds: 300, diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf index 78387372f5..978bbb164d 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tf @@ -2,7 +2,7 @@ terraform { required_providers { coder = { source = "coder/coder" - version = "0.6.12" + version = "0.8.3" } } } @@ -18,22 +18,30 @@ resource "coder_agent" "dev2" { connection_timeout = 1 motd_file = "/etc/motd" startup_script_timeout = 30 - login_before_ready = true + startup_script_behavior = "non-blocking" shutdown_script = "echo bye bye" shutdown_script_timeout = 30 } resource "coder_agent" "dev3" { - os = "windows" - arch = "arm64" - troubleshooting_url = "https://coder.com/troubleshoot" - login_before_ready = false + os = "windows" + arch = "arm64" + troubleshooting_url = "https://coder.com/troubleshoot" + startup_script_behavior = "blocking" +} + +resource "coder_agent" "dev4" { + os = "linux" + arch = "amd64" + # Test deprecated login_before_ready=false => startup_script_behavior=blocking. + login_before_ready = false } resource "null_resource" "dev" { depends_on = [ coder_agent.dev1, coder_agent.dev2, - coder_agent.dev3 + coder_agent.dev3, + coder_agent.dev4 ] } diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot index feeca3e949..02839b24d6 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.dot @@ -5,19 +5,23 @@ digraph { "[root] coder_agent.dev1 (expand)" [label = "coder_agent.dev1", shape = "box"] "[root] coder_agent.dev2 (expand)" [label = "coder_agent.dev2", shape = "box"] "[root] coder_agent.dev3 (expand)" [label = "coder_agent.dev3", shape = "box"] + "[root] coder_agent.dev4 (expand)" [label = "coder_agent.dev4", shape = "box"] "[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] "[root] coder_agent.dev1 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] coder_agent.dev2 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] coder_agent.dev3 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] coder_agent.dev4 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev1 (expand)" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev2 (expand)" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev3 (expand)" + "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev4 (expand)" "[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev1 (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev2 (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev3 (expand)" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev4 (expand)" "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)" "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json index eb1c2e3f87..0dcfef92a6 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json @@ -18,15 +18,19 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } }, { "address": "coder_agent.dev2", @@ -42,15 +46,19 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": "/etc/motd", "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, "startup_script": null, + "startup_script_behavior": "non-blocking", "startup_script_timeout": 30, "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } }, { "address": "coder_agent.dev3", @@ -65,16 +73,48 @@ "connection_timeout": 120, "dir": null, "env": null, - "login_before_ready": false, + "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": "blocking", "startup_script_timeout": 300, "troubleshooting_url": "https://coder.com/troubleshoot" }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } + }, + { + "address": "coder_agent.dev4", + "mode": "managed", + "type": "coder_agent", + "name": "dev4", + "provider_name": "registry.terraform.io/coder/coder", + "schema_version": 0, + "values": { + "arch": "amd64", + "auth": "token", + "connection_timeout": 120, + "dir": null, + "env": null, + "login_before_ready": false, + "metadata": [], + "motd_file": null, + "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, + "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, + "troubleshooting_url": null + }, + "sensitive_values": { + "metadata": [] + } }, { "address": "null_resource.dev", @@ -110,21 +150,25 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, "troubleshooting_url": null }, "after_unknown": { "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "metadata": [], "token": true } } @@ -147,21 +191,25 @@ "dir": null, "env": null, "login_before_ready": true, + "metadata": [], "motd_file": "/etc/motd", "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, "startup_script": null, + "startup_script_behavior": "non-blocking", "startup_script_timeout": 30, "troubleshooting_url": null }, "after_unknown": { "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "metadata": [], "token": true } } @@ -183,22 +231,67 @@ "connection_timeout": 120, "dir": null, "env": null, - "login_before_ready": false, + "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": "blocking", "startup_script_timeout": 300, "troubleshooting_url": "https://coder.com/troubleshoot" }, "after_unknown": { "id": true, "init_script": true, + "metadata": [], "token": true }, "before_sensitive": false, "after_sensitive": { + "metadata": [], + "token": true + } + } + }, + { + "address": "coder_agent.dev4", + "mode": "managed", + "type": "coder_agent", + "name": "dev4", + "provider_name": "registry.terraform.io/coder/coder", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "arch": "amd64", + "auth": "token", + "connection_timeout": 120, + "dir": null, + "env": null, + "login_before_ready": false, + "metadata": [], + "motd_file": null, + "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, + "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, + "troubleshooting_url": null + }, + "after_unknown": { + "id": true, + "init_script": true, + "metadata": [], + "token": true + }, + "before_sensitive": false, + "after_sensitive": { + "metadata": [], "token": true } } @@ -230,7 +323,7 @@ "coder": { "name": "coder", "full_name": "registry.terraform.io/coder/coder", - "version_constraint": "0.6.12" + "version_constraint": "0.8.3" }, "null": { "name": "null", @@ -268,9 +361,6 @@ "connection_timeout": { "constant_value": 1 }, - "login_before_ready": { - "constant_value": true - }, "motd_file": { "constant_value": "/etc/motd" }, @@ -283,6 +373,9 @@ "shutdown_script_timeout": { "constant_value": 30 }, + "startup_script_behavior": { + "constant_value": "non-blocking" + }, "startup_script_timeout": { "constant_value": 30 } @@ -299,14 +392,33 @@ "arch": { "constant_value": "arm64" }, + "os": { + "constant_value": "windows" + }, + "startup_script_behavior": { + "constant_value": "blocking" + }, + "troubleshooting_url": { + "constant_value": "https://coder.com/troubleshoot" + } + }, + "schema_version": 0 + }, + { + "address": "coder_agent.dev4", + "mode": "managed", + "type": "coder_agent", + "name": "dev4", + "provider_config_key": "coder", + "expressions": { + "arch": { + "constant_value": "amd64" + }, "login_before_ready": { "constant_value": false }, "os": { - "constant_value": "windows" - }, - "troubleshooting_url": { - "constant_value": "https://coder.com/troubleshoot" + "constant_value": "linux" } }, "schema_version": 0 @@ -321,7 +433,8 @@ "depends_on": [ "coder_agent.dev1", "coder_agent.dev2", - "coder_agent.dev3" + "coder_agent.dev3", + "coder_agent.dev4" ] } ] diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot index feeca3e949..02839b24d6 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.dot @@ -5,19 +5,23 @@ digraph { "[root] coder_agent.dev1 (expand)" [label = "coder_agent.dev1", shape = "box"] "[root] coder_agent.dev2 (expand)" [label = "coder_agent.dev2", shape = "box"] "[root] coder_agent.dev3 (expand)" [label = "coder_agent.dev3", shape = "box"] + "[root] coder_agent.dev4 (expand)" [label = "coder_agent.dev4", shape = "box"] "[root] null_resource.dev (expand)" [label = "null_resource.dev", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] "[root] coder_agent.dev1 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] coder_agent.dev2 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] coder_agent.dev3 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] coder_agent.dev4 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev1 (expand)" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev2 (expand)" "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev3 (expand)" + "[root] null_resource.dev (expand)" -> "[root] coder_agent.dev4 (expand)" "[root] null_resource.dev (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev1 (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev2 (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev3 (expand)" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev4 (expand)" "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.dev (expand)" "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json index ad6eb7118c..01a31f1524 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json @@ -17,19 +17,23 @@ "connection_timeout": 120, "dir": null, "env": null, - "id": "7fd8bb3f-704e-4d85-aaaf-1928a9a4df83", + "id": "ff8b851f-127f-452f-9180-4e619b0093f2", "init_script": "", "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "linux", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": null, "startup_script_timeout": 300, - "token": "ebdd904c-a277-49ec-97cc-e29c7326b475", + "token": "36dbfd5d-adf5-4e3e-9d92-190be56773fa", "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } }, { "address": "coder_agent.dev2", @@ -44,19 +48,23 @@ "connection_timeout": 1, "dir": null, "env": null, - "id": "cd35b6c2-3f81-4857-ac8c-9cc0d1d0f0ee", + "id": "a4951d98-2e07-4144-8942-a6f7584a6da0", "init_script": "", "login_before_ready": true, + "metadata": [], "motd_file": "/etc/motd", "os": "darwin", "shutdown_script": "echo bye bye", "shutdown_script_timeout": 30, "startup_script": null, + "startup_script_behavior": "non-blocking", "startup_script_timeout": 30, - "token": "bbfc3bb1-31c8-42a2-bc5a-3f4ee95eea7b", + "token": "f101a336-401d-4744-848f-437fe635f832", "troubleshooting_url": null }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } }, { "address": "coder_agent.dev3", @@ -71,19 +79,54 @@ "connection_timeout": 120, "dir": null, "env": null, - "id": "7407c159-30e7-4c7c-8187-3bf0f6805515", + "id": "a3e1eaae-4bfd-4240-bc0a-0e940c3dd861", "init_script": "", - "login_before_ready": false, + "login_before_ready": true, + "metadata": [], "motd_file": null, "os": "windows", "shutdown_script": null, "shutdown_script_timeout": 300, "startup_script": null, + "startup_script_behavior": "blocking", "startup_script_timeout": 300, - "token": "080070d7-cb08-4634-aa05-7ee07a193441", + "token": "1551c374-aae3-4be8-8fa2-6082921b837f", "troubleshooting_url": "https://coder.com/troubleshoot" }, - "sensitive_values": {} + "sensitive_values": { + "metadata": [] + } + }, + { + "address": "coder_agent.dev4", + "mode": "managed", + "type": "coder_agent", + "name": "dev4", + "provider_name": "registry.terraform.io/coder/coder", + "schema_version": 0, + "values": { + "arch": "amd64", + "auth": "token", + "connection_timeout": 120, + "dir": null, + "env": null, + "id": "fb94747b-e187-4c69-9c95-fb09c0832664", + "init_script": "", + "login_before_ready": false, + "metadata": [], + "motd_file": null, + "os": "linux", + "shutdown_script": null, + "shutdown_script_timeout": 300, + "startup_script": null, + "startup_script_behavior": null, + "startup_script_timeout": 300, + "token": "714bf65d-92ff-4e7c-adbe-211b15a21085", + "troubleshooting_url": null + }, + "sensitive_values": { + "metadata": [] + } }, { "address": "null_resource.dev", @@ -93,14 +136,15 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "235602507221507275", + "id": "3687348305461113369", "triggers": null }, "sensitive_values": {}, "depends_on": [ "coder_agent.dev1", "coder_agent.dev2", - "coder_agent.dev3" + "coder_agent.dev3", + "coder_agent.dev4" ] } ] diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index dee7dc4534..43a86339f1 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -829,15 +829,16 @@ type Agent struct { // // *Agent_Token // *Agent_InstanceId - Auth isAgent_Auth `protobuf_oneof:"auth"` - ConnectionTimeoutSeconds int32 `protobuf:"varint,11,opt,name=connection_timeout_seconds,json=connectionTimeoutSeconds,proto3" json:"connection_timeout_seconds,omitempty"` - TroubleshootingUrl string `protobuf:"bytes,12,opt,name=troubleshooting_url,json=troubleshootingUrl,proto3" json:"troubleshooting_url,omitempty"` - MotdFile string `protobuf:"bytes,13,opt,name=motd_file,json=motdFile,proto3" json:"motd_file,omitempty"` - LoginBeforeReady bool `protobuf:"varint,14,opt,name=login_before_ready,json=loginBeforeReady,proto3" json:"login_before_ready,omitempty"` + Auth isAgent_Auth `protobuf_oneof:"auth"` + ConnectionTimeoutSeconds int32 `protobuf:"varint,11,opt,name=connection_timeout_seconds,json=connectionTimeoutSeconds,proto3" json:"connection_timeout_seconds,omitempty"` + TroubleshootingUrl string `protobuf:"bytes,12,opt,name=troubleshooting_url,json=troubleshootingUrl,proto3" json:"troubleshooting_url,omitempty"` + MotdFile string `protobuf:"bytes,13,opt,name=motd_file,json=motdFile,proto3" json:"motd_file,omitempty"` + // Field 14 was bool login_before_ready = 14, now removed. StartupScriptTimeoutSeconds int32 `protobuf:"varint,15,opt,name=startup_script_timeout_seconds,json=startupScriptTimeoutSeconds,proto3" json:"startup_script_timeout_seconds,omitempty"` ShutdownScript string `protobuf:"bytes,16,opt,name=shutdown_script,json=shutdownScript,proto3" json:"shutdown_script,omitempty"` ShutdownScriptTimeoutSeconds int32 `protobuf:"varint,17,opt,name=shutdown_script_timeout_seconds,json=shutdownScriptTimeoutSeconds,proto3" json:"shutdown_script_timeout_seconds,omitempty"` Metadata []*Agent_Metadata `protobuf:"bytes,18,rep,name=metadata,proto3" json:"metadata,omitempty"` + StartupScriptBehavior string `protobuf:"bytes,19,opt,name=startup_script_behavior,json=startupScriptBehavior,proto3" json:"startup_script_behavior,omitempty"` } func (x *Agent) Reset() { @@ -970,13 +971,6 @@ func (x *Agent) GetMotdFile() string { return "" } -func (x *Agent) GetLoginBeforeReady() bool { - if x != nil { - return x.LoginBeforeReady - } - return false -} - func (x *Agent) GetStartupScriptTimeoutSeconds() int32 { if x != nil { return x.StartupScriptTimeoutSeconds @@ -1005,6 +999,13 @@ func (x *Agent) GetMetadata() []*Agent_Metadata { return nil } +func (x *Agent) GetStartupScriptBehavior() string { + if x != nil { + return x.StartupScriptBehavior + } + return "" +} + type isAgent_Auth interface { isAgent_Auth() } @@ -2420,7 +2421,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xc7, 0x07, 0x0a, 0x05, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xeb, 0x07, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, @@ -2450,233 +2451,235 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x73, 0x68, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x6f, 0x74, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, - 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1b, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, - 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x12, 0x45, 0x0a, 0x1f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, - 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x73, - 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x1a, 0x8d, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x6d, 0x6f, 0x74, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x43, 0x0a, 0x1e, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x75, 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x1b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x45, 0x0a, 0x1f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, + 0x77, 0x6e, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x1c, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x37, 0x0a, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, + 0x70, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, + 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x1a, 0x8d, + 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, + 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x1a, 0x36, + 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x4a, 0x04, + 0x08, 0x0e, 0x10, 0x0f, 0x52, 0x12, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x65, 0x66, 0x6f, + 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xb5, 0x02, 0x0a, 0x03, 0x41, 0x70, 0x70, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x73, 0x6c, 0x75, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x62, 0x64, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x41, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x22, 0x59, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, + 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xf1, 0x02, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x2a, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x68, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, + 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, + 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, + 0x43, 0x6f, 0x73, 0x74, 0x1a, 0x69, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x06, 0x0a, 0x04, - 0x61, 0x75, 0x74, 0x68, 0x22, 0xb5, 0x02, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, - 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, - 0x63, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x12, 0x3a, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x0b, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x41, 0x0a, - 0x0d, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x59, 0x0a, 0x0b, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, - 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x68, - 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xf1, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x06, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, - 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x04, 0x68, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x73, 0x74, - 0x1a, 0x69, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, 0x85, 0x02, 0x0a, 0x05, - 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0x5e, - 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x73, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, - 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, - 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x91, 0x0d, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x1a, 0xae, 0x04, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, - 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, - 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x1a, 0xad, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, - 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x32, - 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x6f, - 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x1a, 0xa9, 0x02, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x35, 0x0a, 0x06, 0x63, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6c, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x22, + 0x85, 0x02, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x1a, 0x27, 0x0a, 0x07, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x1a, 0x5e, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x4c, + 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, + 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x11, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, + 0x10, 0x03, 0x1a, 0x73, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, + 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, + 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x39, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, + 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91, 0x0d, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xae, 0x04, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, + 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, + 0x0a, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x21, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6f, 0x69, 0x64, + 0x63, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0xad, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x4c, 0x6f, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0xa9, 0x02, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, + 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x0e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x12, 0x4a, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, + 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, + 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x02, + 0x10, 0x03, 0x1a, 0x52, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x53, 0x0a, 0x15, 0x72, 0x69, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x13, 0x72, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x76, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x76, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x12, - 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x47, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x1a, 0x52, - 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, - 0x61, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x1a, 0xb3, 0x01, 0x0a, - 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x50, - 0x6c, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x34, 0x0a, 0x05, 0x61, - 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, + 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x1a, 0x08, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x1a, 0xb3, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, + 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, - 0x79, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x1a, 0xe9, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, - 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, - 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x1a, 0x77, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, - 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, - 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, - 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, - 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, - 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, - 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, - 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, - 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, - 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02, 0x32, 0xa3, - 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x42, - 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x30, 0x01, 0x12, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x28, 0x01, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, + 0x34, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, 0x05, + 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x1a, 0xe9, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, + 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x70, 0x6c, + 0x61, 0x6e, 0x1a, 0x77, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, + 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, + 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, + 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, + 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, + 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, + 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, + 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, + 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, + 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, + 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, + 0x54, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, + 0x10, 0x02, 0x32, 0xa3, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x12, 0x42, 0x0a, 0x05, 0x50, 0x61, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, + 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, 0x64, + 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index e307f4f213..bbbbb81453 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -90,6 +90,9 @@ message Agent { int64 interval = 4; int64 timeout = 5; } + reserved 14; + reserved "login_before_ready"; + string id = 1; string name = 2; map env = 3; @@ -105,11 +108,12 @@ message Agent { int32 connection_timeout_seconds = 11; string troubleshooting_url = 12; string motd_file = 13; - bool login_before_ready = 14; + // Field 14 was bool login_before_ready = 14, now removed. int32 startup_script_timeout_seconds = 15; string shutdown_script = 16; int32 shutdown_script_timeout_seconds = 17; repeated Metadata metadata = 18; + string startup_script_behavior = 19; } enum AppSharingLevel { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index ffc3102ef1..a226cfe264 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1092,6 +1092,7 @@ export interface WorkspaceAgent { readonly connection_timeout_seconds: number readonly troubleshooting_url: string readonly login_before_ready: boolean + readonly startup_script_behavior: WorkspaceAgentStartupScriptBehavior readonly startup_script_timeout_seconds: number readonly shutdown_script?: string readonly shutdown_script_timeout_seconds: number @@ -1562,6 +1563,11 @@ export const WorkspaceAgentLifecycles: WorkspaceAgentLifecycle[] = [ "starting", ] +// From codersdk/workspaceagents.go +export type WorkspaceAgentStartupScriptBehavior = "blocking" | "non-blocking" +export const WorkspaceAgentStartupScriptBehaviors: WorkspaceAgentStartupScriptBehavior[] = + ["blocking", "non-blocking"] + // From codersdk/workspaceagents.go export type WorkspaceAgentStatus = | "connected" diff --git a/site/src/components/Resources/AgentStatus.tsx b/site/src/components/Resources/AgentStatus.tsx index e414f1a06a..2a2256e00d 100644 --- a/site/src/components/Resources/AgentStatus.tsx +++ b/site/src/components/Resources/AgentStatus.tsx @@ -252,44 +252,39 @@ const OffLifecycle: React.FC = () => { const ConnectedStatus: React.FC<{ agent: WorkspaceAgent }> = ({ agent }) => { - // NOTE(mafredri): Keep this behind feature flag for the time-being, - // if login_before_ready is false, the user has updated to - // terraform-provider-coder v0.6.10 and opted in to the functionality. - // - // Remove check once documentation is in place and we do a breaking - // release indicating startup script behavior has changed. - // https://github.com/coder/coder/issues/5749 - if (agent.login_before_ready) { - return + switch (agent.startup_script_behavior) { + case "non-blocking": + return + case "blocking": + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ) } - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - ) } const DisconnectedStatus: React.FC = () => { diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 127879ced7..6697f83c8d 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -498,7 +498,8 @@ export const MockWorkspaceAgent: TypesGen.WorkspaceAgent = { connection_timeout_seconds: 120, troubleshooting_url: "https://coder.com/troubleshoot", lifecycle_state: "starting", - login_before_ready: false, + login_before_ready: false, // Deprecated. + startup_script_behavior: "blocking", startup_logs_length: 0, startup_logs_overflowed: false, startup_script_timeout_seconds: 120,