mirror of https://github.com/coder/coder.git
feat(agent): Add shutdown lifecycle states and shutdown_script support (#6139)
* feat(api): Add agent shutdown lifecycle states * feat(agent): Add shutdown_script support * feat(agent): Add shutdown_script timeout * feat(site): Support new agent lifecycle states --- Co-authored-by: Marcin Tojek <marcin@coder.com>
This commit is contained in:
parent
02100c64b5
commit
22e3ff96be
132
agent/agent.go
132
agent/agent.go
|
@ -121,6 +121,7 @@ func New(options Options) io.Closer {
|
|||
logDir: options.LogDir,
|
||||
tempDir: options.TempDir,
|
||||
lifecycleUpdate: make(chan struct{}, 1),
|
||||
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
|
||||
connStatsChan: make(chan *agentsdk.Stats, 1),
|
||||
}
|
||||
a.init(ctx)
|
||||
|
@ -149,9 +150,10 @@ type agent struct {
|
|||
sessionToken atomic.Pointer[string]
|
||||
sshServer *ssh.Server
|
||||
|
||||
lifecycleUpdate chan struct{}
|
||||
lifecycleMu sync.Mutex // Protects following.
|
||||
lifecycleState codersdk.WorkspaceAgentLifecycle
|
||||
lifecycleUpdate chan struct{}
|
||||
lifecycleReported chan codersdk.WorkspaceAgentLifecycle
|
||||
lifecycleMu sync.RWMutex // Protects following.
|
||||
lifecycleState codersdk.WorkspaceAgentLifecycle
|
||||
|
||||
network *tailnet.Conn
|
||||
connStatsChan chan *agentsdk.Stats
|
||||
|
@ -207,9 +209,9 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
|
|||
}
|
||||
|
||||
for r := retry.New(time.Second, 15*time.Second); r.Wait(ctx); {
|
||||
a.lifecycleMu.Lock()
|
||||
a.lifecycleMu.RLock()
|
||||
state := a.lifecycleState
|
||||
a.lifecycleMu.Unlock()
|
||||
a.lifecycleMu.RUnlock()
|
||||
|
||||
if state == lastReported {
|
||||
break
|
||||
|
@ -222,6 +224,11 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
|
|||
})
|
||||
if err == nil {
|
||||
lastReported = state
|
||||
select {
|
||||
case a.lifecycleReported <- state:
|
||||
case <-a.lifecycleReported:
|
||||
a.lifecycleReported <- state
|
||||
}
|
||||
break
|
||||
}
|
||||
if xerrors.Is(err, context.Canceled) || xerrors.Is(err, context.DeadlineExceeded) {
|
||||
|
@ -233,13 +240,20 @@ func (a *agent) reportLifecycleLoop(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// setLifecycle sets the lifecycle state and notifies the lifecycle loop.
|
||||
// The state is only updated if it's a valid state transition.
|
||||
func (a *agent) setLifecycle(ctx context.Context, state codersdk.WorkspaceAgentLifecycle) {
|
||||
a.lifecycleMu.Lock()
|
||||
defer a.lifecycleMu.Unlock()
|
||||
|
||||
a.logger.Debug(ctx, "set lifecycle state", slog.F("state", state), slog.F("previous", a.lifecycleState))
|
||||
|
||||
lastState := a.lifecycleState
|
||||
if slices.Index(codersdk.WorkspaceAgentLifecycleOrder, lastState) > slices.Index(codersdk.WorkspaceAgentLifecycleOrder, state) {
|
||||
a.logger.Warn(ctx, "attempted to set lifecycle state to a previous state", slog.F("last", lastState), slog.F("state", state))
|
||||
a.lifecycleMu.Unlock()
|
||||
return
|
||||
}
|
||||
a.lifecycleState = state
|
||||
a.logger.Debug(ctx, "set lifecycle state", slog.F("state", state), slog.F("last", lastState))
|
||||
a.lifecycleMu.Unlock()
|
||||
|
||||
select {
|
||||
case a.lifecycleUpdate <- struct{}{}:
|
||||
default:
|
||||
|
@ -299,9 +313,10 @@ func (a *agent) run(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
lifecycleState := codersdk.WorkspaceAgentLifecycleReady
|
||||
scriptDone := make(chan error, 1)
|
||||
scriptStart := time.Now()
|
||||
err := a.trackConnGoroutine(func() {
|
||||
err = a.trackConnGoroutine(func() {
|
||||
defer close(scriptDone)
|
||||
scriptDone <- a.runStartupScript(ctx, metadata.StartupScript)
|
||||
})
|
||||
|
@ -329,16 +344,17 @@ func (a *agent) run(ctx context.Context) error {
|
|||
if errors.Is(err, context.Canceled) {
|
||||
return
|
||||
}
|
||||
execTime := time.Since(scriptStart)
|
||||
lifecycleStatus := codersdk.WorkspaceAgentLifecycleReady
|
||||
if err != nil {
|
||||
a.logger.Warn(ctx, "startup script failed", slog.F("execution_time", execTime), slog.Error(err))
|
||||
lifecycleStatus = codersdk.WorkspaceAgentLifecycleStartError
|
||||
} else {
|
||||
a.logger.Info(ctx, "startup script completed", slog.F("execution_time", execTime))
|
||||
// Only log if there was a startup script.
|
||||
if metadata.StartupScript != "" {
|
||||
execTime := time.Since(scriptStart)
|
||||
if err != nil {
|
||||
a.logger.Warn(ctx, "startup script failed", slog.F("execution_time", execTime), slog.Error(err))
|
||||
lifecycleState = codersdk.WorkspaceAgentLifecycleStartError
|
||||
} else {
|
||||
a.logger.Info(ctx, "startup script completed", slog.F("execution_time", execTime))
|
||||
}
|
||||
}
|
||||
|
||||
a.setLifecycle(ctx, lifecycleStatus)
|
||||
a.setLifecycle(ctx, lifecycleState)
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -606,14 +622,22 @@ func (a *agent) runCoordinator(ctx context.Context, network *tailnet.Conn) error
|
|||
}
|
||||
|
||||
func (a *agent) runStartupScript(ctx context.Context, script string) error {
|
||||
return a.runScript(ctx, "startup", script)
|
||||
}
|
||||
|
||||
func (a *agent) runShutdownScript(ctx context.Context, script string) error {
|
||||
return a.runScript(ctx, "shutdown", script)
|
||||
}
|
||||
|
||||
func (a *agent) runScript(ctx context.Context, lifecycle, script string) error {
|
||||
if script == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
a.logger.Info(ctx, "running startup script", slog.F("script", script))
|
||||
writer, err := a.filesystem.OpenFile(filepath.Join(a.logDir, "coder-startup-script.log"), os.O_CREATE|os.O_RDWR, 0o600)
|
||||
a.logger.Info(ctx, "running script", slog.F("lifecycle", lifecycle), slog.F("script", script))
|
||||
writer, err := a.filesystem.OpenFile(filepath.Join(a.logDir, fmt.Sprintf("coder-%s-script.log", lifecycle)), os.O_CREATE|os.O_RDWR, 0o600)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("open startup script log file: %w", err)
|
||||
return xerrors.Errorf("open %s script log file: %w", lifecycle, err)
|
||||
}
|
||||
defer func() {
|
||||
_ = writer.Close()
|
||||
|
@ -774,7 +798,7 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
|
|||
|
||||
rawMetadata := a.metadata.Load()
|
||||
if rawMetadata == nil {
|
||||
return nil, xerrors.Errorf("no metadata was provided: %w", err)
|
||||
return nil, xerrors.Errorf("no metadata was provided")
|
||||
}
|
||||
metadata, valid := rawMetadata.(agentsdk.Metadata)
|
||||
if !valid {
|
||||
|
@ -1290,13 +1314,73 @@ func (a *agent) Close() error {
|
|||
if a.isClosed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
a.setLifecycle(ctx, codersdk.WorkspaceAgentLifecycleShuttingDown)
|
||||
|
||||
lifecycleState := codersdk.WorkspaceAgentLifecycleOff
|
||||
if metadata, ok := a.metadata.Load().(agentsdk.Metadata); ok && metadata.ShutdownScript != "" {
|
||||
scriptDone := make(chan error, 1)
|
||||
scriptStart := time.Now()
|
||||
go func() {
|
||||
defer close(scriptDone)
|
||||
scriptDone <- a.runShutdownScript(ctx, metadata.ShutdownScript)
|
||||
}()
|
||||
|
||||
var timeout <-chan time.Time
|
||||
// If timeout is zero, an older version of the coder
|
||||
// provider was used. Otherwise a timeout is always > 0.
|
||||
if metadata.ShutdownScriptTimeout > 0 {
|
||||
t := time.NewTimer(metadata.ShutdownScriptTimeout)
|
||||
defer t.Stop()
|
||||
timeout = t.C
|
||||
}
|
||||
|
||||
var err error
|
||||
select {
|
||||
case err = <-scriptDone:
|
||||
case <-timeout:
|
||||
a.logger.Warn(ctx, "shutdown script timed out")
|
||||
a.setLifecycle(ctx, codersdk.WorkspaceAgentLifecycleShutdownTimeout)
|
||||
err = <-scriptDone // The script can still complete after a timeout.
|
||||
}
|
||||
execTime := time.Since(scriptStart)
|
||||
if err != nil {
|
||||
a.logger.Warn(ctx, "shutdown script failed", slog.F("execution_time", execTime), slog.Error(err))
|
||||
lifecycleState = codersdk.WorkspaceAgentLifecycleShutdownError
|
||||
} else {
|
||||
a.logger.Info(ctx, "shutdown script completed", slog.F("execution_time", execTime))
|
||||
}
|
||||
}
|
||||
|
||||
// Set final state and wait for it to be reported because context
|
||||
// cancellation will stop the report loop.
|
||||
a.setLifecycle(ctx, lifecycleState)
|
||||
|
||||
// Wait for the lifecycle to be reported, but don't wait forever so
|
||||
// that we don't break user expectations.
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
lifecycleWaitLoop:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
break lifecycleWaitLoop
|
||||
case s := <-a.lifecycleReported:
|
||||
if s == lifecycleState {
|
||||
break lifecycleWaitLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(a.closed)
|
||||
a.closeCancel()
|
||||
_ = a.sshServer.Close()
|
||||
if a.network != nil {
|
||||
_ = a.network.Close()
|
||||
}
|
||||
_ = a.sshServer.Close()
|
||||
a.connCloseWait.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ func TestAgent_Stats_SSH(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
conn, _, stats, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
//nolint:dogsled
|
||||
conn, _, stats, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
|
||||
sshClient, err := conn.SSHClient(ctx)
|
||||
require.NoError(t, err)
|
||||
|
@ -85,7 +86,8 @@ func TestAgent_Stats_ReconnectingPTY(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
conn, _, stats, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
//nolint:dogsled
|
||||
conn, _, stats, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
|
||||
ptyConn, err := conn.ReconnectingPTY(ctx, uuid.New(), 128, 128, "/bin/bash")
|
||||
require.NoError(t, err)
|
||||
|
@ -114,7 +116,8 @@ func TestAgent_Stats_Magic(t *testing.T) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
conn, _, stats, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
//nolint:dogsled
|
||||
conn, _, stats, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
sshClient, err := conn.SSHClient(ctx)
|
||||
require.NoError(t, err)
|
||||
defer sshClient.Close()
|
||||
|
@ -572,7 +575,7 @@ func TestAgent_SFTP(t *testing.T) {
|
|||
home = "/" + strings.ReplaceAll(home, "\\", "/")
|
||||
}
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
conn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
sshClient, err := conn.SSHClient(ctx)
|
||||
require.NoError(t, err)
|
||||
defer sshClient.Close()
|
||||
|
@ -604,7 +607,7 @@ func TestAgent_SCP(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
conn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
sshClient, err := conn.SSHClient(ctx)
|
||||
require.NoError(t, err)
|
||||
defer sshClient.Close()
|
||||
|
@ -709,7 +712,7 @@ func TestAgent_StartupScript(t *testing.T) {
|
|||
}
|
||||
content := "output"
|
||||
//nolint:dogsled
|
||||
_, _, _, fs := setupAgent(t, agentsdk.Metadata{
|
||||
_, _, _, fs, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "echo " + content,
|
||||
}, 0)
|
||||
var gotContent string
|
||||
|
@ -740,10 +743,10 @@ func TestAgent_StartupScript(t *testing.T) {
|
|||
func TestAgent_Lifecycle(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("Timeout", func(t *testing.T) {
|
||||
t.Run("StartTimeout", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "sleep 5",
|
||||
StartupScriptTimeout: time.Nanosecond,
|
||||
}, 0)
|
||||
|
@ -769,10 +772,10 @@ func TestAgent_Lifecycle(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("Error", func(t *testing.T) {
|
||||
t.Run("StartError", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "false",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
}, 0)
|
||||
|
@ -801,7 +804,7 @@ func TestAgent_Lifecycle(t *testing.T) {
|
|||
t.Run("Ready", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "true",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
}, 0)
|
||||
|
@ -826,6 +829,191 @@ func TestAgent_Lifecycle(t *testing.T) {
|
|||
require.Equal(t, want, got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ShuttingDown", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _, closer := setupAgent(t, agentsdk.Metadata{
|
||||
ShutdownScript: "sleep 5",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
}, 0)
|
||||
|
||||
var ready []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
ready = client.getLifecycleStates()
|
||||
return len(ready) > 0 && ready[len(ready)-1] == codersdk.WorkspaceAgentLifecycleReady
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
// Start close asynchronously so that we an inspect the state.
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
err := closer.Close()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
<-done
|
||||
})
|
||||
|
||||
want := []codersdk.WorkspaceAgentLifecycle{
|
||||
codersdk.WorkspaceAgentLifecycleShuttingDown,
|
||||
}
|
||||
|
||||
var got []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
got = client.getLifecycleStates()[len(ready):]
|
||||
return len(got) > 0 && got[len(got)-1] == want[len(want)-1]
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
|
||||
t.Run("ShutdownTimeout", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _, closer := setupAgent(t, agentsdk.Metadata{
|
||||
ShutdownScript: "sleep 5",
|
||||
ShutdownScriptTimeout: time.Nanosecond,
|
||||
}, 0)
|
||||
|
||||
var ready []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
ready = client.getLifecycleStates()
|
||||
return len(ready) > 0 && ready[len(ready)-1] == codersdk.WorkspaceAgentLifecycleReady
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
// Start close asynchronously so that we an inspect the state.
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
err := closer.Close()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
<-done
|
||||
})
|
||||
|
||||
want := []codersdk.WorkspaceAgentLifecycle{
|
||||
codersdk.WorkspaceAgentLifecycleShuttingDown,
|
||||
codersdk.WorkspaceAgentLifecycleShutdownTimeout,
|
||||
}
|
||||
|
||||
var got []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
got = client.getLifecycleStates()[len(ready):]
|
||||
return len(got) > 0 && got[len(got)-1] == want[len(want)-1]
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
switch len(got) {
|
||||
case 1:
|
||||
// This can happen if lifecycle state updates are
|
||||
// too fast, only the latest one is reported.
|
||||
require.Equal(t, want[1:], got)
|
||||
default:
|
||||
// This is the expected case.
|
||||
require.Equal(t, want, got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ShutdownError", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _, closer := setupAgent(t, agentsdk.Metadata{
|
||||
ShutdownScript: "false",
|
||||
ShutdownScriptTimeout: 30 * time.Second,
|
||||
}, 0)
|
||||
|
||||
var ready []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
ready = client.getLifecycleStates()
|
||||
return len(ready) > 0 && ready[len(ready)-1] == codersdk.WorkspaceAgentLifecycleReady
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
// Start close asynchronously so that we an inspect the state.
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
err := closer.Close()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
t.Cleanup(func() {
|
||||
<-done
|
||||
})
|
||||
|
||||
want := []codersdk.WorkspaceAgentLifecycle{
|
||||
codersdk.WorkspaceAgentLifecycleShuttingDown,
|
||||
codersdk.WorkspaceAgentLifecycleShutdownError,
|
||||
}
|
||||
|
||||
var got []codersdk.WorkspaceAgentLifecycle
|
||||
assert.Eventually(t, func() bool {
|
||||
got = client.getLifecycleStates()[len(ready):]
|
||||
return len(got) > 0 && got[len(got)-1] == want[len(want)-1]
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
switch len(got) {
|
||||
case 1:
|
||||
// This can happen if lifecycle state updates are
|
||||
// too fast, only the latest one is reported.
|
||||
require.Equal(t, want[1:], got)
|
||||
default:
|
||||
// This is the expected case.
|
||||
require.Equal(t, want, got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ShutdownScriptOnce", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expected := "this-is-shutdown"
|
||||
client := &client{
|
||||
t: t,
|
||||
agentID: uuid.New(),
|
||||
metadata: agentsdk.Metadata{
|
||||
DERPMap: tailnettest.RunDERPAndSTUN(t),
|
||||
StartupScript: "echo 1",
|
||||
ShutdownScript: "echo " + expected,
|
||||
},
|
||||
statsChan: make(chan *agentsdk.Stats),
|
||||
coordinator: tailnet.NewCoordinator(),
|
||||
}
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
agent := agent.New(agent.Options{
|
||||
Client: client,
|
||||
Logger: slogtest.Make(t, nil).Leveled(slog.LevelInfo),
|
||||
Filesystem: fs,
|
||||
})
|
||||
|
||||
// agent.Close() loads the shutdown script from the agent metadata.
|
||||
// The metadata is populated just before execution of the startup script, so it's mandatory to wait
|
||||
// until the startup starts.
|
||||
require.Eventually(t, func() bool {
|
||||
outputPath := filepath.Join(os.TempDir(), "coder-startup-script.log")
|
||||
content, err := afero.ReadFile(fs, outputPath)
|
||||
if err != nil {
|
||||
t.Logf("read file %q: %s", outputPath, err)
|
||||
return false
|
||||
}
|
||||
return len(content) > 0 // something is in the startup log file
|
||||
}, testutil.WaitShort, testutil.IntervalMedium)
|
||||
|
||||
err := agent.Close()
|
||||
require.NoError(t, err, "agent should be closed successfully")
|
||||
|
||||
outputPath := filepath.Join(os.TempDir(), "coder-shutdown-script.log")
|
||||
logFirstRead, err := afero.ReadFile(fs, outputPath)
|
||||
require.NoError(t, err, "log file should be present")
|
||||
require.Equal(t, expected, string(bytes.TrimSpace(logFirstRead)))
|
||||
|
||||
// Make sure that script can't be executed twice.
|
||||
err = agent.Close()
|
||||
require.NoError(t, err, "don't need to close the agent twice, no effect")
|
||||
|
||||
logSecondRead, err := afero.ReadFile(fs, outputPath)
|
||||
require.NoError(t, err, "log file should be present")
|
||||
require.Equal(t, string(bytes.TrimSpace(logFirstRead)), string(bytes.TrimSpace(logSecondRead)))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAgent_Startup(t *testing.T) {
|
||||
|
@ -834,7 +1022,7 @@ func TestAgent_Startup(t *testing.T) {
|
|||
t.Run("EmptyDirectory", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "true",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
Directory: "",
|
||||
|
@ -848,7 +1036,7 @@ func TestAgent_Startup(t *testing.T) {
|
|||
t.Run("HomeDirectory", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "true",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
Directory: "~",
|
||||
|
@ -864,7 +1052,7 @@ func TestAgent_Startup(t *testing.T) {
|
|||
t.Run("HomeEnvironmentVariable", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
_, client, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
StartupScript: "true",
|
||||
StartupScriptTimeout: 30 * time.Second,
|
||||
Directory: "$HOME",
|
||||
|
@ -891,7 +1079,7 @@ func TestAgent_ReconnectingPTY(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
conn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
id := uuid.New()
|
||||
netConn, err := conn.ReconnectingPTY(ctx, id, 100, 100, "/bin/bash")
|
||||
require.NoError(t, err)
|
||||
|
@ -993,7 +1181,7 @@ func TestAgent_Dial(t *testing.T) {
|
|||
}()
|
||||
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
conn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
require.True(t, conn.AwaitReachable(context.Background()))
|
||||
conn1, err := conn.DialContext(context.Background(), l.Addr().Network(), l.Addr().String())
|
||||
require.NoError(t, err)
|
||||
|
@ -1015,7 +1203,7 @@ func TestAgent_Speedtest(t *testing.T) {
|
|||
defer cancel()
|
||||
derpMap := tailnettest.RunDERPAndSTUN(t)
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
conn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{
|
||||
DERPMap: derpMap,
|
||||
}, 0)
|
||||
defer conn.Close()
|
||||
|
@ -1101,7 +1289,7 @@ func TestAgent_WriteVSCodeConfigs(t *testing.T) {
|
|||
|
||||
func setupSSHCommand(t *testing.T, beforeArgs []string, afterArgs []string) *exec.Cmd {
|
||||
//nolint:dogsled
|
||||
agentConn, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
agentConn, _, _, _, _ := setupAgent(t, agentsdk.Metadata{}, 0)
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(t, err)
|
||||
waitGroup := sync.WaitGroup{}
|
||||
|
@ -1148,7 +1336,7 @@ func setupSSHSession(t *testing.T, options agentsdk.Metadata) *ssh.Session {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
//nolint:dogsled
|
||||
conn, _, _, _ := setupAgent(t, options, 0)
|
||||
conn, _, _, _, _ := setupAgent(t, options, 0)
|
||||
sshClient, err := conn.SSHClient(ctx)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
|
@ -1173,6 +1361,7 @@ func setupAgent(t *testing.T, metadata agentsdk.Metadata, ptyTimeout time.Durati
|
|||
*client,
|
||||
<-chan *agentsdk.Stats,
|
||||
afero.Fs,
|
||||
io.Closer,
|
||||
) {
|
||||
if metadata.DERPMap == nil {
|
||||
metadata.DERPMap = tailnettest.RunDERPAndSTUN(t)
|
||||
|
@ -1233,7 +1422,7 @@ func setupAgent(t *testing.T, metadata agentsdk.Metadata, ptyTimeout time.Durati
|
|||
if !agentConn.AwaitReachable(ctx) {
|
||||
t.Fatal("agent not reachable")
|
||||
}
|
||||
return agentConn, c, statsCh, fs
|
||||
return agentConn, c, statsCh, fs, closer
|
||||
}
|
||||
|
||||
var dialTestPayload = []byte("dean-was-here123")
|
||||
|
|
|
@ -17,7 +17,10 @@ import (
|
|||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
var AgentStartError = xerrors.New("agent startup exited with non-zero exit status")
|
||||
var (
|
||||
AgentStartError = xerrors.New("agent startup exited with non-zero exit status")
|
||||
AgentShuttingDown = xerrors.New("agent is shutting down")
|
||||
)
|
||||
|
||||
type AgentOptions struct {
|
||||
WorkspaceName string
|
||||
|
@ -146,6 +149,10 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
|
|||
case codersdk.WorkspaceAgentLifecycleStartError:
|
||||
showMessage()
|
||||
return AgentStartError
|
||||
case codersdk.WorkspaceAgentLifecycleShuttingDown, codersdk.WorkspaceAgentLifecycleShutdownTimeout,
|
||||
codersdk.WorkspaceAgentLifecycleShutdownError, codersdk.WorkspaceAgentLifecycleOff:
|
||||
showMessage()
|
||||
return AgentShuttingDown
|
||||
default:
|
||||
select {
|
||||
case <-warningShown:
|
||||
|
@ -229,6 +236,22 @@ func waitingMessage(agent codersdk.WorkspaceAgent, opts AgentOptions) (m *messag
|
|||
m.Spin = ""
|
||||
m.Prompt = "The workspace ran into a problem while getting ready, the agent startup script exited with non-zero status."
|
||||
default:
|
||||
switch agent.LifecycleState {
|
||||
case codersdk.WorkspaceAgentLifecycleShutdownTimeout:
|
||||
m.Spin = ""
|
||||
m.Prompt = "The workspace is shutting down, but is taking longer than expected to shut down and the agent shutdown script is still executing."
|
||||
m.Troubleshoot = true
|
||||
case codersdk.WorkspaceAgentLifecycleShutdownError:
|
||||
m.Spin = ""
|
||||
m.Prompt = "The workspace ran into a problem while shutting down, the agent shutdown script exited with non-zero status."
|
||||
m.Troubleshoot = true
|
||||
case codersdk.WorkspaceAgentLifecycleShuttingDown:
|
||||
m.Spin = ""
|
||||
m.Prompt = "The workspace is shutting down."
|
||||
case codersdk.WorkspaceAgentLifecycleOff:
|
||||
m.Spin = ""
|
||||
m.Prompt = "The workspace is not running."
|
||||
}
|
||||
// Not a failure state, no troubleshooting necessary.
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -5198,6 +5198,12 @@ const docTemplate = `{
|
|||
"motd_file": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -8425,6 +8431,12 @@ const docTemplate = `{
|
|||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout_seconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -8462,14 +8474,22 @@ const docTemplate = `{
|
|||
"starting",
|
||||
"start_timeout",
|
||||
"start_error",
|
||||
"ready"
|
||||
"ready",
|
||||
"shutting_down",
|
||||
"shutdown_timeout",
|
||||
"shutdown_error",
|
||||
"off"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"WorkspaceAgentLifecycleCreated",
|
||||
"WorkspaceAgentLifecycleStarting",
|
||||
"WorkspaceAgentLifecycleStartTimeout",
|
||||
"WorkspaceAgentLifecycleStartError",
|
||||
"WorkspaceAgentLifecycleReady"
|
||||
"WorkspaceAgentLifecycleReady",
|
||||
"WorkspaceAgentLifecycleShuttingDown",
|
||||
"WorkspaceAgentLifecycleShutdownTimeout",
|
||||
"WorkspaceAgentLifecycleShutdownError",
|
||||
"WorkspaceAgentLifecycleOff"
|
||||
]
|
||||
},
|
||||
"codersdk.WorkspaceAgentListeningPort": {
|
||||
|
|
|
@ -4587,6 +4587,12 @@
|
|||
"motd_file": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -7592,6 +7598,12 @@
|
|||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"type": "string"
|
||||
},
|
||||
"shutdown_script_timeout_seconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startup_script": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -7624,13 +7636,27 @@
|
|||
},
|
||||
"codersdk.WorkspaceAgentLifecycle": {
|
||||
"type": "string",
|
||||
"enum": ["created", "starting", "start_timeout", "start_error", "ready"],
|
||||
"enum": [
|
||||
"created",
|
||||
"starting",
|
||||
"start_timeout",
|
||||
"start_error",
|
||||
"ready",
|
||||
"shutting_down",
|
||||
"shutdown_timeout",
|
||||
"shutdown_error",
|
||||
"off"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"WorkspaceAgentLifecycleCreated",
|
||||
"WorkspaceAgentLifecycleStarting",
|
||||
"WorkspaceAgentLifecycleStartTimeout",
|
||||
"WorkspaceAgentLifecycleStartError",
|
||||
"WorkspaceAgentLifecycleReady"
|
||||
"WorkspaceAgentLifecycleReady",
|
||||
"WorkspaceAgentLifecycleShuttingDown",
|
||||
"WorkspaceAgentLifecycleShutdownTimeout",
|
||||
"WorkspaceAgentLifecycleShutdownError",
|
||||
"WorkspaceAgentLifecycleOff"
|
||||
]
|
||||
},
|
||||
"codersdk.WorkspaceAgentListeningPort": {
|
||||
|
|
|
@ -2856,6 +2856,7 @@ func (q *fakeQuerier) InsertWorkspaceAgent(_ context.Context, arg database.Inser
|
|||
TroubleshootingURL: arg.TroubleshootingURL,
|
||||
MOTDFile: arg.MOTDFile,
|
||||
LifecycleState: database.WorkspaceAgentLifecycleStateCreated,
|
||||
ShutdownScript: arg.ShutdownScript,
|
||||
}
|
||||
|
||||
q.workspaceAgents = append(q.workspaceAgents, agent)
|
||||
|
|
|
@ -107,7 +107,11 @@ CREATE TYPE workspace_agent_lifecycle_state AS ENUM (
|
|||
'starting',
|
||||
'start_timeout',
|
||||
'start_error',
|
||||
'ready'
|
||||
'ready',
|
||||
'shutting_down',
|
||||
'shutdown_timeout',
|
||||
'shutdown_error',
|
||||
'off'
|
||||
);
|
||||
|
||||
CREATE TYPE workspace_app_health AS ENUM (
|
||||
|
@ -509,7 +513,9 @@ CREATE TABLE workspace_agents (
|
|||
lifecycle_state workspace_agent_lifecycle_state DEFAULT 'created'::workspace_agent_lifecycle_state NOT NULL,
|
||||
login_before_ready boolean DEFAULT true NOT NULL,
|
||||
startup_script_timeout_seconds integer DEFAULT 0 NOT NULL,
|
||||
expanded_directory character varying(4096) DEFAULT ''::character varying NOT NULL
|
||||
expanded_directory character varying(4096) DEFAULT ''::character varying NOT NULL,
|
||||
shutdown_script character varying(65534),
|
||||
shutdown_script_timeout_seconds integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.version IS 'Version tracks the version of the currently running workspace agent. Workspace agents register their version upon start.';
|
||||
|
@ -528,6 +534,10 @@ COMMENT ON COLUMN workspace_agents.startup_script_timeout_seconds IS 'The number
|
|||
|
||||
COMMENT ON COLUMN workspace_agents.expanded_directory IS 'The resolved path of a user-specified directory. e.g. ~/coder -> /home/coder/coder';
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script IS 'Script that is executed before the agent is stopped.';
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script_timeout_seconds IS 'The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.';
|
||||
|
||||
CREATE TABLE workspace_apps (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
ALTER TABLE workspace_agents DROP COLUMN shutdown_script;
|
||||
|
||||
ALTER TABLE workspace_agents DROP COLUMN shutdown_script_timeout_seconds;
|
||||
|
||||
-- We can't drop values from enums, so we have to create a new one and convert the data.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'ready' WHERE lifecycle_state IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off');
|
||||
ALTER TYPE workspace_agent_lifecycle_state RENAME TO workspace_agent_lifecycle_state_old;
|
||||
CREATE TYPE workspace_agent_lifecycle_state AS ENUM ('created', 'starting', 'start_timeout', 'start_error', 'ready');
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state DROP DEFAULT;
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state TYPE workspace_agent_lifecycle_state USING lifecycle_state::text::workspace_agent_lifecycle_state;
|
||||
ALTER TABLE workspace_agents ALTER COLUMN lifecycle_state SET DEFAULT 'created';
|
||||
DROP TYPE workspace_agent_lifecycle_state_old;
|
|
@ -0,0 +1,14 @@
|
|||
ALTER TABLE workspace_agents ADD COLUMN shutdown_script varchar(65534);
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script IS 'Script that is executed before the agent is stopped.';
|
||||
|
||||
-- Disable shutdown script timeouts by default.
|
||||
ALTER TABLE workspace_agents ADD COLUMN shutdown_script_timeout_seconds int4 NOT NULL DEFAULT 0;
|
||||
|
||||
COMMENT ON COLUMN workspace_agents.shutdown_script_timeout_seconds IS 'The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.';
|
||||
|
||||
-- Add enum fields
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutting_down';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutdown_timeout';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'shutdown_error';
|
||||
ALTER TYPE workspace_agent_lifecycle_state ADD VALUE 'off';
|
|
@ -0,0 +1,2 @@
|
|||
-- Set a non-default lifecycle_state.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'ready' WHERE id = '7a1ce5f8-8d00-431c-ad1b-97a846512804';
|
|
@ -0,0 +1,2 @@
|
|||
-- Set lifecycle_state to enum value not available in previous migration.
|
||||
UPDATE workspace_agents SET lifecycle_state = 'off' WHERE id = '7a1ce5f8-8d00-431c-ad1b-97a846512804';
|
|
@ -1014,11 +1014,15 @@ func AllUserStatusValues() []UserStatus {
|
|||
type WorkspaceAgentLifecycleState string
|
||||
|
||||
const (
|
||||
WorkspaceAgentLifecycleStateCreated WorkspaceAgentLifecycleState = "created"
|
||||
WorkspaceAgentLifecycleStateStarting WorkspaceAgentLifecycleState = "starting"
|
||||
WorkspaceAgentLifecycleStateStartTimeout WorkspaceAgentLifecycleState = "start_timeout"
|
||||
WorkspaceAgentLifecycleStateStartError WorkspaceAgentLifecycleState = "start_error"
|
||||
WorkspaceAgentLifecycleStateReady WorkspaceAgentLifecycleState = "ready"
|
||||
WorkspaceAgentLifecycleStateCreated WorkspaceAgentLifecycleState = "created"
|
||||
WorkspaceAgentLifecycleStateStarting WorkspaceAgentLifecycleState = "starting"
|
||||
WorkspaceAgentLifecycleStateStartTimeout WorkspaceAgentLifecycleState = "start_timeout"
|
||||
WorkspaceAgentLifecycleStateStartError WorkspaceAgentLifecycleState = "start_error"
|
||||
WorkspaceAgentLifecycleStateReady WorkspaceAgentLifecycleState = "ready"
|
||||
WorkspaceAgentLifecycleStateShuttingDown WorkspaceAgentLifecycleState = "shutting_down"
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout WorkspaceAgentLifecycleState = "shutdown_timeout"
|
||||
WorkspaceAgentLifecycleStateShutdownError WorkspaceAgentLifecycleState = "shutdown_error"
|
||||
WorkspaceAgentLifecycleStateOff WorkspaceAgentLifecycleState = "off"
|
||||
)
|
||||
|
||||
func (e *WorkspaceAgentLifecycleState) Scan(src interface{}) error {
|
||||
|
@ -1062,7 +1066,11 @@ func (e WorkspaceAgentLifecycleState) Valid() bool {
|
|||
WorkspaceAgentLifecycleStateStarting,
|
||||
WorkspaceAgentLifecycleStateStartTimeout,
|
||||
WorkspaceAgentLifecycleStateStartError,
|
||||
WorkspaceAgentLifecycleStateReady:
|
||||
WorkspaceAgentLifecycleStateReady,
|
||||
WorkspaceAgentLifecycleStateShuttingDown,
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout,
|
||||
WorkspaceAgentLifecycleStateShutdownError,
|
||||
WorkspaceAgentLifecycleStateOff:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -1075,6 +1083,10 @@ func AllWorkspaceAgentLifecycleStateValues() []WorkspaceAgentLifecycleState {
|
|||
WorkspaceAgentLifecycleStateStartTimeout,
|
||||
WorkspaceAgentLifecycleStateStartError,
|
||||
WorkspaceAgentLifecycleStateReady,
|
||||
WorkspaceAgentLifecycleStateShuttingDown,
|
||||
WorkspaceAgentLifecycleStateShutdownTimeout,
|
||||
WorkspaceAgentLifecycleStateShutdownError,
|
||||
WorkspaceAgentLifecycleStateOff,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1547,6 +1559,10 @@ type WorkspaceAgent struct {
|
|||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
// The resolved path of a user-specified directory. e.g. ~/coder -> /home/coder/coder
|
||||
ExpandedDirectory string `db:"expanded_directory" json:"expanded_directory"`
|
||||
// Script that is executed before the agent is stopped.
|
||||
ShutdownScript sql.NullString `db:"shutdown_script" json:"shutdown_script"`
|
||||
// The number of seconds to wait for the shutdown script to complete. If the script does not complete within this time, the agent lifecycle will be marked as shutdown_timeout.
|
||||
ShutdownScriptTimeoutSeconds int32 `db:"shutdown_script_timeout_seconds" json:"shutdown_script_timeout_seconds"`
|
||||
}
|
||||
|
||||
type WorkspaceAgentStat struct {
|
||||
|
|
|
@ -4937,7 +4937,7 @@ func (q *sqlQuerier) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusP
|
|||
|
||||
const getWorkspaceAgentByAuthToken = `-- name: GetWorkspaceAgentByAuthToken :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
|
@ -4976,13 +4976,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByID = `-- name: GetWorkspaceAgentByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
|
@ -5019,13 +5021,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (W
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentByInstanceID = `-- name: GetWorkspaceAgentByInstanceID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
|
@ -5064,13 +5068,15 @@ func (q *sqlQuerier) GetWorkspaceAgentByInstanceID(ctx context.Context, authInst
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceAgentsByResourceIDs = `-- name: GetWorkspaceAgentsByResourceIDs :many
|
||||
SELECT
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
FROM
|
||||
workspace_agents
|
||||
WHERE
|
||||
|
@ -5113,6 +5119,8 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -5128,7 +5136,7 @@ func (q *sqlQuerier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []
|
|||
}
|
||||
|
||||
const getWorkspaceAgentsCreatedAfter = `-- name: GetWorkspaceAgentsCreatedAfter :many
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory FROM workspace_agents WHERE created_at > $1
|
||||
SELECT id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds FROM workspace_agents WHERE created_at > $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceAgent, error) {
|
||||
|
@ -5167,6 +5175,8 @@ func (q *sqlQuerier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, created
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -5202,32 +5212,36 @@ INSERT INTO
|
|||
troubleshooting_url,
|
||||
motd_file,
|
||||
login_before_ready,
|
||||
startup_script_timeout_seconds
|
||||
startup_script_timeout_seconds,
|
||||
shutdown_script,
|
||||
shutdown_script_timeout_seconds
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING id, created_at, updated_at, name, first_connected_at, last_connected_at, disconnected_at, resource_id, auth_token, auth_instance_id, architecture, environment_variables, operating_system, startup_script, instance_metadata, resource_metadata, directory, version, last_connected_replica_id, connection_timeout_seconds, troubleshooting_url, motd_file, lifecycle_state, login_before_ready, startup_script_timeout_seconds, expanded_directory, shutdown_script, shutdown_script_timeout_seconds
|
||||
`
|
||||
|
||||
type InsertWorkspaceAgentParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
ResourceID uuid.UUID `db:"resource_id" json:"resource_id"`
|
||||
AuthToken uuid.UUID `db:"auth_token" json:"auth_token"`
|
||||
AuthInstanceID sql.NullString `db:"auth_instance_id" json:"auth_instance_id"`
|
||||
Architecture string `db:"architecture" json:"architecture"`
|
||||
EnvironmentVariables pqtype.NullRawMessage `db:"environment_variables" json:"environment_variables"`
|
||||
OperatingSystem string `db:"operating_system" json:"operating_system"`
|
||||
StartupScript sql.NullString `db:"startup_script" json:"startup_script"`
|
||||
Directory string `db:"directory" json:"directory"`
|
||||
InstanceMetadata pqtype.NullRawMessage `db:"instance_metadata" json:"instance_metadata"`
|
||||
ResourceMetadata pqtype.NullRawMessage `db:"resource_metadata" json:"resource_metadata"`
|
||||
ConnectionTimeoutSeconds int32 `db:"connection_timeout_seconds" json:"connection_timeout_seconds"`
|
||||
TroubleshootingURL string `db:"troubleshooting_url" json:"troubleshooting_url"`
|
||||
MOTDFile string `db:"motd_file" json:"motd_file"`
|
||||
LoginBeforeReady bool `db:"login_before_ready" json:"login_before_ready"`
|
||||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
ResourceID uuid.UUID `db:"resource_id" json:"resource_id"`
|
||||
AuthToken uuid.UUID `db:"auth_token" json:"auth_token"`
|
||||
AuthInstanceID sql.NullString `db:"auth_instance_id" json:"auth_instance_id"`
|
||||
Architecture string `db:"architecture" json:"architecture"`
|
||||
EnvironmentVariables pqtype.NullRawMessage `db:"environment_variables" json:"environment_variables"`
|
||||
OperatingSystem string `db:"operating_system" json:"operating_system"`
|
||||
StartupScript sql.NullString `db:"startup_script" json:"startup_script"`
|
||||
Directory string `db:"directory" json:"directory"`
|
||||
InstanceMetadata pqtype.NullRawMessage `db:"instance_metadata" json:"instance_metadata"`
|
||||
ResourceMetadata pqtype.NullRawMessage `db:"resource_metadata" json:"resource_metadata"`
|
||||
ConnectionTimeoutSeconds int32 `db:"connection_timeout_seconds" json:"connection_timeout_seconds"`
|
||||
TroubleshootingURL string `db:"troubleshooting_url" json:"troubleshooting_url"`
|
||||
MOTDFile string `db:"motd_file" json:"motd_file"`
|
||||
LoginBeforeReady bool `db:"login_before_ready" json:"login_before_ready"`
|
||||
StartupScriptTimeoutSeconds int32 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
ShutdownScript sql.NullString `db:"shutdown_script" json:"shutdown_script"`
|
||||
ShutdownScriptTimeoutSeconds int32 `db:"shutdown_script_timeout_seconds" json:"shutdown_script_timeout_seconds"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error) {
|
||||
|
@ -5251,6 +5265,8 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
|
|||
arg.MOTDFile,
|
||||
arg.LoginBeforeReady,
|
||||
arg.StartupScriptTimeoutSeconds,
|
||||
arg.ShutdownScript,
|
||||
arg.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
var i WorkspaceAgent
|
||||
err := row.Scan(
|
||||
|
@ -5280,6 +5296,8 @@ func (q *sqlQuerier) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspa
|
|||
&i.LoginBeforeReady,
|
||||
&i.StartupScriptTimeoutSeconds,
|
||||
&i.ExpandedDirectory,
|
||||
&i.ShutdownScript,
|
||||
&i.ShutdownScriptTimeoutSeconds,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
|
@ -58,10 +58,12 @@ INSERT INTO
|
|||
troubleshooting_url,
|
||||
motd_file,
|
||||
login_before_ready,
|
||||
startup_script_timeout_seconds
|
||||
startup_script_timeout_seconds,
|
||||
shutdown_script,
|
||||
shutdown_script_timeout_seconds
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) RETURNING *;
|
||||
|
||||
-- name: UpdateWorkspaceAgentConnectionByID :exec
|
||||
UPDATE
|
||||
|
|
|
@ -1144,6 +1144,11 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
|
|||
MOTDFile: prAgent.GetMotdFile(),
|
||||
LoginBeforeReady: prAgent.GetLoginBeforeReady(),
|
||||
StartupScriptTimeoutSeconds: prAgent.GetStartupScriptTimeoutSeconds(),
|
||||
ShutdownScript: sql.NullString{
|
||||
String: prAgent.ShutdownScript,
|
||||
Valid: prAgent.ShutdownScript != "",
|
||||
},
|
||||
ShutdownScriptTimeoutSeconds: prAgent.GetShutdownScriptTimeoutSeconds(),
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert agent: %w", err)
|
||||
|
|
|
@ -957,6 +957,7 @@ func TestInsertWorkspaceResource(t *testing.T) {
|
|||
Apps: []*sdkproto.App{{
|
||||
Slug: "a",
|
||||
}},
|
||||
ShutdownScript: "shutdown",
|
||||
}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -971,6 +972,7 @@ func TestInsertWorkspaceResource(t *testing.T) {
|
|||
require.Equal(t, "amd64", agent.Architecture)
|
||||
require.Equal(t, "linux", agent.OperatingSystem)
|
||||
require.Equal(t, "value", agent.StartupScript.String)
|
||||
require.Equal(t, "shutdown", agent.ShutdownScript.String)
|
||||
want, err := json.Marshal(map[string]string{
|
||||
"something": "test",
|
||||
})
|
||||
|
|
|
@ -550,6 +550,7 @@ func ConvertWorkspaceAgent(agent database.WorkspaceAgent) WorkspaceAgent {
|
|||
StartupScript: agent.StartupScript.Valid,
|
||||
Directory: agent.Directory != "",
|
||||
ConnectionTimeoutSeconds: agent.ConnectionTimeoutSeconds,
|
||||
ShutdownScript: agent.ShutdownScript.Valid,
|
||||
}
|
||||
if agent.FirstConnectedAt.Valid {
|
||||
snapAgent.FirstConnectedAt = &agent.FirstConnectedAt.Time
|
||||
|
@ -750,6 +751,7 @@ type WorkspaceAgent struct {
|
|||
LastConnectedAt *time.Time `json:"last_connected_at"`
|
||||
DisconnectedAt *time.Time `json:"disconnected_at"`
|
||||
ConnectionTimeoutSeconds int32 `json:"connection_timeout_seconds"`
|
||||
ShutdownScript bool `json:"shutdown_script"`
|
||||
}
|
||||
|
||||
type WorkspaceApp struct {
|
||||
|
|
|
@ -144,15 +144,17 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, agentsdk.Metadata{
|
||||
Apps: convertApps(dbApps),
|
||||
DERPMap: api.DERPMap,
|
||||
GitAuthConfigs: len(api.GitAuthConfigs),
|
||||
EnvironmentVariables: apiAgent.EnvironmentVariables,
|
||||
StartupScript: apiAgent.StartupScript,
|
||||
Directory: apiAgent.Directory,
|
||||
VSCodePortProxyURI: vscodeProxyURI,
|
||||
MOTDFile: workspaceAgent.MOTDFile,
|
||||
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
|
||||
Apps: convertApps(dbApps),
|
||||
DERPMap: api.DERPMap,
|
||||
GitAuthConfigs: len(api.GitAuthConfigs),
|
||||
EnvironmentVariables: apiAgent.EnvironmentVariables,
|
||||
StartupScript: apiAgent.StartupScript,
|
||||
Directory: apiAgent.Directory,
|
||||
VSCodePortProxyURI: vscodeProxyURI,
|
||||
MOTDFile: workspaceAgent.MOTDFile,
|
||||
StartupScriptTimeout: time.Duration(apiAgent.StartupScriptTimeoutSeconds) * time.Second,
|
||||
ShutdownScript: apiAgent.ShutdownScript,
|
||||
ShutdownScriptTimeout: time.Duration(apiAgent.ShutdownScriptTimeoutSeconds) * time.Second,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -803,25 +805,27 @@ func convertWorkspaceAgent(derpMap *tailcfg.DERPMap, coordinator tailnet.Coordin
|
|||
troubleshootingURL = dbAgent.TroubleshootingURL
|
||||
}
|
||||
workspaceAgent := codersdk.WorkspaceAgent{
|
||||
ID: dbAgent.ID,
|
||||
CreatedAt: dbAgent.CreatedAt,
|
||||
UpdatedAt: dbAgent.UpdatedAt,
|
||||
ResourceID: dbAgent.ResourceID,
|
||||
InstanceID: dbAgent.AuthInstanceID.String,
|
||||
Name: dbAgent.Name,
|
||||
Architecture: dbAgent.Architecture,
|
||||
OperatingSystem: dbAgent.OperatingSystem,
|
||||
StartupScript: dbAgent.StartupScript.String,
|
||||
Version: dbAgent.Version,
|
||||
EnvironmentVariables: envs,
|
||||
Directory: dbAgent.Directory,
|
||||
ExpandedDirectory: dbAgent.ExpandedDirectory,
|
||||
Apps: apps,
|
||||
ConnectionTimeoutSeconds: dbAgent.ConnectionTimeoutSeconds,
|
||||
TroubleshootingURL: troubleshootingURL,
|
||||
LifecycleState: codersdk.WorkspaceAgentLifecycle(dbAgent.LifecycleState),
|
||||
LoginBeforeReady: dbAgent.LoginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds,
|
||||
ID: dbAgent.ID,
|
||||
CreatedAt: dbAgent.CreatedAt,
|
||||
UpdatedAt: dbAgent.UpdatedAt,
|
||||
ResourceID: dbAgent.ResourceID,
|
||||
InstanceID: dbAgent.AuthInstanceID.String,
|
||||
Name: dbAgent.Name,
|
||||
Architecture: dbAgent.Architecture,
|
||||
OperatingSystem: dbAgent.OperatingSystem,
|
||||
StartupScript: dbAgent.StartupScript.String,
|
||||
Version: dbAgent.Version,
|
||||
EnvironmentVariables: envs,
|
||||
Directory: dbAgent.Directory,
|
||||
ExpandedDirectory: dbAgent.ExpandedDirectory,
|
||||
Apps: apps,
|
||||
ConnectionTimeoutSeconds: dbAgent.ConnectionTimeoutSeconds,
|
||||
TroubleshootingURL: troubleshootingURL,
|
||||
LifecycleState: codersdk.WorkspaceAgentLifecycle(dbAgent.LifecycleState),
|
||||
LoginBeforeReady: dbAgent.LoginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: dbAgent.StartupScriptTimeoutSeconds,
|
||||
ShutdownScript: dbAgent.ShutdownScript.String,
|
||||
ShutdownScriptTimeoutSeconds: dbAgent.ShutdownScriptTimeoutSeconds,
|
||||
}
|
||||
node := coordinator.Node(dbAgent.ID)
|
||||
if node != nil {
|
||||
|
|
|
@ -1256,6 +1256,10 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
|
|||
{codersdk.WorkspaceAgentLifecycleStartTimeout, false},
|
||||
{codersdk.WorkspaceAgentLifecycleStartError, false},
|
||||
{codersdk.WorkspaceAgentLifecycleReady, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShuttingDown, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShutdownTimeout, false},
|
||||
{codersdk.WorkspaceAgentLifecycleShutdownError, false},
|
||||
{codersdk.WorkspaceAgentLifecycleOff, false},
|
||||
{codersdk.WorkspaceAgentLifecycle("nonexistent_state"), true},
|
||||
{codersdk.WorkspaceAgentLifecycle(""), true},
|
||||
}
|
||||
|
|
|
@ -69,15 +69,17 @@ type Metadata struct {
|
|||
// GitAuthConfigs stores the number of Git configurations
|
||||
// the Coder deployment has. If this number is >0, we
|
||||
// set up special configuration in the workspace.
|
||||
GitAuthConfigs int `json:"git_auth_configs"`
|
||||
VSCodePortProxyURI string `json:"vscode_port_proxy_uri"`
|
||||
Apps []codersdk.WorkspaceApp `json:"apps"`
|
||||
DERPMap *tailcfg.DERPMap `json:"derpmap"`
|
||||
EnvironmentVariables map[string]string `json:"environment_variables"`
|
||||
StartupScript string `json:"startup_script"`
|
||||
StartupScriptTimeout time.Duration `json:"startup_script_timeout"`
|
||||
Directory string `json:"directory"`
|
||||
MOTDFile string `json:"motd_file"`
|
||||
GitAuthConfigs int `json:"git_auth_configs"`
|
||||
VSCodePortProxyURI string `json:"vscode_port_proxy_uri"`
|
||||
Apps []codersdk.WorkspaceApp `json:"apps"`
|
||||
DERPMap *tailcfg.DERPMap `json:"derpmap"`
|
||||
EnvironmentVariables map[string]string `json:"environment_variables"`
|
||||
StartupScript string `json:"startup_script"`
|
||||
StartupScriptTimeout time.Duration `json:"startup_script_timeout"`
|
||||
Directory string `json:"directory"`
|
||||
MOTDFile string `json:"motd_file"`
|
||||
ShutdownScript string `json:"shutdown_script"`
|
||||
ShutdownScriptTimeout time.Duration `json:"shutdown_script_timeout"`
|
||||
}
|
||||
|
||||
// Metadata fetches metadata for the currently authenticated workspace agent.
|
||||
|
|
|
@ -44,13 +44,35 @@ type WorkspaceAgentLifecycle string
|
|||
|
||||
// WorkspaceAgentLifecycle enums.
|
||||
const (
|
||||
WorkspaceAgentLifecycleCreated WorkspaceAgentLifecycle = "created"
|
||||
WorkspaceAgentLifecycleStarting WorkspaceAgentLifecycle = "starting"
|
||||
WorkspaceAgentLifecycleStartTimeout WorkspaceAgentLifecycle = "start_timeout"
|
||||
WorkspaceAgentLifecycleStartError WorkspaceAgentLifecycle = "start_error"
|
||||
WorkspaceAgentLifecycleReady WorkspaceAgentLifecycle = "ready"
|
||||
WorkspaceAgentLifecycleCreated WorkspaceAgentLifecycle = "created"
|
||||
WorkspaceAgentLifecycleStarting WorkspaceAgentLifecycle = "starting"
|
||||
WorkspaceAgentLifecycleStartTimeout WorkspaceAgentLifecycle = "start_timeout"
|
||||
WorkspaceAgentLifecycleStartError WorkspaceAgentLifecycle = "start_error"
|
||||
WorkspaceAgentLifecycleReady WorkspaceAgentLifecycle = "ready"
|
||||
WorkspaceAgentLifecycleShuttingDown WorkspaceAgentLifecycle = "shutting_down"
|
||||
WorkspaceAgentLifecycleShutdownTimeout WorkspaceAgentLifecycle = "shutdown_timeout"
|
||||
WorkspaceAgentLifecycleShutdownError WorkspaceAgentLifecycle = "shutdown_error"
|
||||
WorkspaceAgentLifecycleOff WorkspaceAgentLifecycle = "off"
|
||||
)
|
||||
|
||||
// WorkspaceAgentLifecycleOrder is the order in which workspace agent
|
||||
// lifecycle states are expected to be reported during the lifetime of
|
||||
// the agent process. For instance, the agent can go from starting to
|
||||
// ready without reporting timeout or error, but it should not go from
|
||||
// ready to starting. This is merely a hint for the agent process, and
|
||||
// is not enforced by the server.
|
||||
var WorkspaceAgentLifecycleOrder = []WorkspaceAgentLifecycle{
|
||||
WorkspaceAgentLifecycleCreated,
|
||||
WorkspaceAgentLifecycleStarting,
|
||||
WorkspaceAgentLifecycleStartTimeout,
|
||||
WorkspaceAgentLifecycleStartError,
|
||||
WorkspaceAgentLifecycleReady,
|
||||
WorkspaceAgentLifecycleShuttingDown,
|
||||
WorkspaceAgentLifecycleShutdownTimeout,
|
||||
WorkspaceAgentLifecycleShutdownError,
|
||||
WorkspaceAgentLifecycleOff,
|
||||
}
|
||||
|
||||
type WorkspaceAgent struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time"`
|
||||
|
@ -76,9 +98,11 @@ type WorkspaceAgent struct {
|
|||
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 `db:"login_before_ready" json:"login_before_ready"`
|
||||
LoginBeforeReady bool `json:"login_before_ready"`
|
||||
// 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 `db:"startup_script_timeout_seconds" json:"startup_script_timeout_seconds"`
|
||||
StartupScriptTimeoutSeconds int32 `json:"startup_script_timeout_seconds"`
|
||||
ShutdownScript string `json:"shutdown_script,omitempty"`
|
||||
ShutdownScriptTimeoutSeconds int32 `json:"shutdown_script_timeout_seconds"`
|
||||
}
|
||||
|
||||
type DERPRegion struct {
|
||||
|
|
|
@ -369,6 +369,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/metadata \
|
|||
},
|
||||
"git_auth_configs": 0,
|
||||
"motd_file": "string",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout": 0,
|
||||
"vscode_port_proxy_uri": "string"
|
||||
|
@ -515,6 +517,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent} \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
|
|
@ -102,6 +102,8 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -248,6 +250,8 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -537,6 +541,8 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/res
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -575,89 +581,95 @@ 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 | | |
|
||||
| `»» 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 | | |
|
||||
| `»» 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 | | »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_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 | | |
|
||||
| `»» 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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `workspace_transition` | `start` |
|
||||
| `workspace_transition` | `stop` |
|
||||
| `workspace_transition` | `delete` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
|
@ -761,6 +773,8 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -912,6 +926,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -961,141 +977,147 @@ 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 | | |
|
||||
| `»» 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 | | |
|
||||
| `» 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 | | |
|
||||
| `»»» 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 | | |
|
||||
| `»»» 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 | | |
|
||||
| `»» 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 | | |
|
||||
| `» 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_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 | | |
|
||||
| `»»» 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 |
|
||||
| ---------------------- | --------------- |
|
||||
| `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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `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 |
|
||||
| ---------------------- | ------------------ |
|
||||
| `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` |
|
||||
| `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).
|
||||
|
||||
|
@ -1228,6 +1250,8 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
|
|
@ -175,6 +175,8 @@
|
|||
},
|
||||
"git_auth_configs": 0,
|
||||
"motd_file": "string",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout": 0,
|
||||
"vscode_port_proxy_uri": "string"
|
||||
|
@ -183,18 +185,20 @@
|
|||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ------------------------ | ------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `apps` | array of [codersdk.WorkspaceApp](#codersdkworkspaceapp) | false | | |
|
||||
| `derpmap` | [tailcfg.DERPMap](#tailcfgderpmap) | false | | |
|
||||
| `directory` | string | false | | |
|
||||
| `environment_variables` | object | false | | |
|
||||
| » `[any property]` | string | false | | |
|
||||
| `git_auth_configs` | integer | false | | Git auth configs stores the number of Git configurations the Coder deployment has. If this number is >0, we set up special configuration in the workspace. |
|
||||
| `motd_file` | string | false | | |
|
||||
| `startup_script` | string | false | | |
|
||||
| `startup_script_timeout` | integer | false | | |
|
||||
| `vscode_port_proxy_uri` | string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| ------------------------- | ------------------------------------------------------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `apps` | array of [codersdk.WorkspaceApp](#codersdkworkspaceapp) | false | | |
|
||||
| `derpmap` | [tailcfg.DERPMap](#tailcfgderpmap) | false | | |
|
||||
| `directory` | string | false | | |
|
||||
| `environment_variables` | object | false | | |
|
||||
| » `[any property]` | string | false | | |
|
||||
| `git_auth_configs` | integer | false | | Git auth configs stores the number of Git configurations the Coder deployment has. If this number is >0, we set up special configuration in the workspace. |
|
||||
| `motd_file` | string | false | | |
|
||||
| `shutdown_script` | string | false | | |
|
||||
| `shutdown_script_timeout` | integer | false | | |
|
||||
| `startup_script` | string | false | | |
|
||||
| `startup_script_timeout` | integer | false | | |
|
||||
| `vscode_port_proxy_uri` | string | false | | |
|
||||
|
||||
## agentsdk.PostAppHealthsRequest
|
||||
|
||||
|
@ -5357,6 +5361,8 @@ Parameter represents a set value for the scope.
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -5480,6 +5486,8 @@ Parameter represents a set value for the scope.
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -5491,34 +5499,36 @@ Parameter represents a set value for the scope.
|
|||
|
||||
### 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 | | |
|
||||
| `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 | | |
|
||||
| `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 | | 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_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 | | |
|
||||
| `troubleshooting_url` | string | false | | |
|
||||
| `updated_at` | string | false | | |
|
||||
| `version` | string | false | | |
|
||||
|
||||
## codersdk.WorkspaceAgentConnectionInfo
|
||||
|
||||
|
@ -5594,13 +5604,17 @@ Parameter represents a set value for the scope.
|
|||
|
||||
#### Enumerated Values
|
||||
|
||||
| Value |
|
||||
| --------------- |
|
||||
| `created` |
|
||||
| `starting` |
|
||||
| `start_timeout` |
|
||||
| `start_error` |
|
||||
| `ready` |
|
||||
| Value |
|
||||
| ------------------ |
|
||||
| `created` |
|
||||
| `starting` |
|
||||
| `start_timeout` |
|
||||
| `start_error` |
|
||||
| `ready` |
|
||||
| `shutting_down` |
|
||||
| `shutdown_timeout` |
|
||||
| `shutdown_error` |
|
||||
| `off` |
|
||||
|
||||
## codersdk.WorkspaceAgentListeningPort
|
||||
|
||||
|
@ -5815,6 +5829,8 @@ Parameter represents a set value for the scope.
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -5984,6 +6000,8 @@ Parameter represents a set value for the scope.
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -6175,6 +6193,8 @@ Parameter represents a set value for the scope.
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
|
|
@ -1601,6 +1601,8 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -1639,89 +1641,95 @@ 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 | | |
|
||||
| `»» 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 | | |
|
||||
| `»» 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 | | »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_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 | | |
|
||||
| `»» 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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `workspace_transition` | `start` |
|
||||
| `workspace_transition` | `stop` |
|
||||
| `workspace_transition` | `delete` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
|
@ -2018,6 +2026,8 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/r
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -2056,89 +2066,95 @@ 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 | | |
|
||||
| `»» 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 | | |
|
||||
| `»» 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 | | »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_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 | | |
|
||||
| `»» 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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `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` |
|
||||
| `status` | `connecting` |
|
||||
| `status` | `connected` |
|
||||
| `status` | `disconnected` |
|
||||
| `status` | `timeout` |
|
||||
| `workspace_transition` | `start` |
|
||||
| `workspace_transition` | `stop` |
|
||||
| `workspace_transition` | `delete` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
|
|
|
@ -134,6 +134,8 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/member
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -299,6 +301,8 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -483,6 +487,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
@ -649,6 +655,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
|
|||
"name": "string",
|
||||
"operating_system": "string",
|
||||
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
|
||||
"shutdown_script": "string",
|
||||
"shutdown_script_timeout_seconds": 0,
|
||||
"startup_script": "string",
|
||||
"startup_script_timeout_seconds": 0,
|
||||
"status": "connecting",
|
||||
|
|
|
@ -444,8 +444,8 @@ practices:
|
|||
URL](./admin/configure.md#access-url)
|
||||
- Manually connect to the resource and check the agent logs (e.g., `kubectl exec`, `docker exec` or AWS console)
|
||||
- The Coder agent logs are typically stored in `/tmp/coder-agent.log`
|
||||
- The Coder agent startup script logs are typically stored in
|
||||
`/tmp/coder-startup-script.log`
|
||||
- The Coder agent startup script logs are typically stored in `/tmp/coder-startup-script.log`
|
||||
- The Coder agent shutdown script logs are typically stored in `/tmp/coder-shutdown-script.log`
|
||||
- This can also happen if the websockets are not being forwarded correctly when running Coder behind a reverse proxy. [Read our reverse-proxy docs](https://coder.com/docs/v2/latest/admin/configure#tls--reverse-proxy)
|
||||
|
||||
### Agent does not become ready
|
||||
|
|
|
@ -84,10 +84,11 @@ coder update <your workspace name> --always-prompt
|
|||
|
||||
Coder stores macOS and Linux logs at the following locations:
|
||||
|
||||
| Service | Location |
|
||||
| ---------------- | ------------------------------- |
|
||||
| `startup_script` | `/tmp/coder-startup-script.log` |
|
||||
| Agent | `/tmp/coder-agent.log` |
|
||||
| Service | Location |
|
||||
| ----------------- | -------------------------------- |
|
||||
| `startup_script` | `/tmp/coder-startup-script.log` |
|
||||
| `shutdown_script` | `/tmp/coder-shutdown-script.log` |
|
||||
| Agent | `/tmp/coder-agent.log` |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -16,19 +16,21 @@ import (
|
|||
|
||||
// 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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// A mapping of attributes on the "coder_app" resource.
|
||||
|
@ -139,18 +141,20 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*State, error
|
|||
}
|
||||
|
||||
agent := &proto.Agent{
|
||||
Name: tfResource.Name,
|
||||
Id: attrs.ID,
|
||||
Env: attrs.Env,
|
||||
StartupScript: attrs.StartupScript,
|
||||
OperatingSystem: attrs.OperatingSystem,
|
||||
Architecture: attrs.Architecture,
|
||||
Directory: attrs.Directory,
|
||||
ConnectionTimeoutSeconds: attrs.ConnectionTimeoutSeconds,
|
||||
TroubleshootingUrl: attrs.TroubleshootingURL,
|
||||
MotdFile: attrs.MOTDFile,
|
||||
LoginBeforeReady: loginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: attrs.StartupScriptTimeoutSeconds,
|
||||
Name: tfResource.Name,
|
||||
Id: attrs.ID,
|
||||
Env: attrs.Env,
|
||||
StartupScript: attrs.StartupScript,
|
||||
OperatingSystem: attrs.OperatingSystem,
|
||||
Architecture: attrs.Architecture,
|
||||
Directory: attrs.Directory,
|
||||
ConnectionTimeoutSeconds: attrs.ConnectionTimeoutSeconds,
|
||||
TroubleshootingUrl: attrs.TroubleshootingURL,
|
||||
MotdFile: attrs.MOTDFile,
|
||||
LoginBeforeReady: loginBeforeReady,
|
||||
StartupScriptTimeoutSeconds: attrs.StartupScriptTimeoutSeconds,
|
||||
ShutdownScript: attrs.ShutdownScript,
|
||||
ShutdownScriptTimeoutSeconds: attrs.ShutdownScriptTimeoutSeconds,
|
||||
}
|
||||
switch attrs.Auth {
|
||||
case "token":
|
||||
|
|
|
@ -105,31 +105,35 @@ func TestConvertResources(t *testing.T) {
|
|||
Name: "dev",
|
||||
Type: "null_resource",
|
||||
Agents: []*proto.Agent{{
|
||||
Name: "dev1",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
LoginBeforeReady: true,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
Name: "dev1",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
LoginBeforeReady: true,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
ShutdownScriptTimeoutSeconds: 300,
|
||||
}, {
|
||||
Name: "dev2",
|
||||
OperatingSystem: "darwin",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 1,
|
||||
MotdFile: "/etc/motd",
|
||||
LoginBeforeReady: true,
|
||||
StartupScriptTimeoutSeconds: 30,
|
||||
Name: "dev2",
|
||||
OperatingSystem: "darwin",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 1,
|
||||
MotdFile: "/etc/motd",
|
||||
LoginBeforeReady: true,
|
||||
StartupScriptTimeoutSeconds: 30,
|
||||
ShutdownScript: "echo bye bye",
|
||||
ShutdownScriptTimeoutSeconds: 30,
|
||||
}, {
|
||||
Name: "dev3",
|
||||
OperatingSystem: "windows",
|
||||
Architecture: "arm64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
TroubleshootingUrl: "https://coder.com/troubleshoot",
|
||||
LoginBeforeReady: false,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
Name: "dev3",
|
||||
OperatingSystem: "windows",
|
||||
Architecture: "arm64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
TroubleshootingUrl: "https://coder.com/troubleshoot",
|
||||
LoginBeforeReady: false,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
ShutdownScriptTimeoutSeconds: 300,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
|
@ -300,13 +304,14 @@ func TestConvertResources(t *testing.T) {
|
|||
Name: "dev",
|
||||
Type: "null_resource",
|
||||
Agents: []*proto.Agent{{
|
||||
Name: "main",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
LoginBeforeReady: true,
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
Name: "main",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "amd64",
|
||||
Auth: &proto.Agent_Token{},
|
||||
LoginBeforeReady: true,
|
||||
ConnectionTimeoutSeconds: 120,
|
||||
StartupScriptTimeoutSeconds: 300,
|
||||
ShutdownScriptTimeoutSeconds: 300,
|
||||
}},
|
||||
}},
|
||||
gitAuthProviders: []string{"github", "gitlab"},
|
||||
|
|
|
@ -2,7 +2,7 @@ terraform {
|
|||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "0.6.10"
|
||||
version = "0.6.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,14 @@ resource "coder_agent" "dev1" {
|
|||
}
|
||||
|
||||
resource "coder_agent" "dev2" {
|
||||
os = "darwin"
|
||||
arch = "amd64"
|
||||
connection_timeout = 1
|
||||
motd_file = "/etc/motd"
|
||||
startup_script_timeout = 30
|
||||
login_before_ready = true
|
||||
os = "darwin"
|
||||
arch = "amd64"
|
||||
connection_timeout = 1
|
||||
motd_file = "/etc/motd"
|
||||
startup_script_timeout = 30
|
||||
login_before_ready = true
|
||||
shutdown_script = "echo bye bye"
|
||||
shutdown_script_timeout = 30
|
||||
}
|
||||
|
||||
resource "coder_agent" "dev3" {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"motd_file": null,
|
||||
"os": "linux",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"troubleshooting_url": null
|
||||
|
@ -43,7 +44,8 @@
|
|||
"login_before_ready": true,
|
||||
"motd_file": "/etc/motd",
|
||||
"os": "darwin",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script": "echo bye bye",
|
||||
"shutdown_script_timeout": 30,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 30,
|
||||
"troubleshooting_url": null
|
||||
|
@ -67,6 +69,7 @@
|
|||
"motd_file": null,
|
||||
"os": "windows",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"troubleshooting_url": "https://coder.com/troubleshoot"
|
||||
|
@ -110,6 +113,7 @@
|
|||
"motd_file": null,
|
||||
"os": "linux",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"troubleshooting_url": null
|
||||
|
@ -145,7 +149,8 @@
|
|||
"login_before_ready": true,
|
||||
"motd_file": "/etc/motd",
|
||||
"os": "darwin",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script": "echo bye bye",
|
||||
"shutdown_script_timeout": 30,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 30,
|
||||
"troubleshooting_url": null
|
||||
|
@ -182,6 +187,7 @@
|
|||
"motd_file": null,
|
||||
"os": "windows",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"troubleshooting_url": "https://coder.com/troubleshoot"
|
||||
|
@ -224,7 +230,7 @@
|
|||
"coder": {
|
||||
"name": "coder",
|
||||
"full_name": "registry.terraform.io/coder/coder",
|
||||
"version_constraint": "0.6.10"
|
||||
"version_constraint": "0.6.12"
|
||||
},
|
||||
"null": {
|
||||
"name": "null",
|
||||
|
@ -271,6 +277,12 @@
|
|||
"os": {
|
||||
"constant_value": "darwin"
|
||||
},
|
||||
"shutdown_script": {
|
||||
"constant_value": "echo bye bye"
|
||||
},
|
||||
"shutdown_script_timeout": {
|
||||
"constant_value": 30
|
||||
},
|
||||
"startup_script_timeout": {
|
||||
"constant_value": 30
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"motd_file": null,
|
||||
"os": "linux",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"token": "d296a9cd-6f7c-4c6b-b2f3-7a647512efe8",
|
||||
|
@ -48,7 +49,8 @@
|
|||
"login_before_ready": true,
|
||||
"motd_file": "/etc/motd",
|
||||
"os": "darwin",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script": "echo bye bye",
|
||||
"shutdown_script_timeout": 30,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 30,
|
||||
"token": "b1e0fba4-5bba-439f-b3ea-3f6a8ba4d301",
|
||||
|
@ -75,6 +77,7 @@
|
|||
"motd_file": null,
|
||||
"os": "windows",
|
||||
"shutdown_script": null,
|
||||
"shutdown_script_timeout": 300,
|
||||
"startup_script": null,
|
||||
"startup_script_timeout": 300,
|
||||
"token": "238ff017-12ae-403f-b3f8-4dea4dc87a7d",
|
||||
|
|
|
@ -1236,12 +1236,14 @@ 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"`
|
||||
StartupScriptTimeoutSeconds int32 `protobuf:"varint,15,opt,name=startup_script_timeout_seconds,json=startupScriptTimeoutSeconds,proto3" json:"startup_script_timeout_seconds,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"`
|
||||
LoginBeforeReady bool `protobuf:"varint,14,opt,name=login_before_ready,json=loginBeforeReady,proto3" json:"login_before_ready,omitempty"`
|
||||
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"`
|
||||
}
|
||||
|
||||
func (x *Agent) Reset() {
|
||||
|
@ -1388,6 +1390,20 @@ func (x *Agent) GetStartupScriptTimeoutSeconds() int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (x *Agent) GetShutdownScript() string {
|
||||
if x != nil {
|
||||
return x.ShutdownScript
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Agent) GetShutdownScriptTimeoutSeconds() int32 {
|
||||
if x != nil {
|
||||
return x.ShutdownScriptTimeoutSeconds
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type isAgent_Auth interface {
|
||||
isAgent_Auth()
|
||||
}
|
||||
|
@ -2774,7 +2790,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
|
|||
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, 0x8e, 0x05, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02,
|
||||
0x65, 0x6e, 0x22, 0xfe, 0x05, 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, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
|
||||
|
@ -2811,6 +2827,13 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
|
|||
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, 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,
|
||||
|
|
|
@ -142,6 +142,8 @@ message Agent {
|
|||
string motd_file = 13;
|
||||
bool login_before_ready = 14;
|
||||
int32 startup_script_timeout_seconds = 15;
|
||||
string shutdown_script = 16;
|
||||
int32 shutdown_script_timeout_seconds = 17;
|
||||
}
|
||||
|
||||
enum AppSharingLevel {
|
||||
|
|
|
@ -994,6 +994,8 @@ export interface WorkspaceAgent {
|
|||
readonly troubleshooting_url: string
|
||||
readonly login_before_ready: boolean
|
||||
readonly startup_script_timeout_seconds: number
|
||||
readonly shutdown_script?: string
|
||||
readonly shutdown_script_timeout_seconds: number
|
||||
}
|
||||
|
||||
// From codersdk/workspaceagentconn.go
|
||||
|
@ -1295,13 +1297,21 @@ export const ValidationMonotonicOrders: ValidationMonotonicOrder[] = [
|
|||
// From codersdk/workspaceagents.go
|
||||
export type WorkspaceAgentLifecycle =
|
||||
| "created"
|
||||
| "off"
|
||||
| "ready"
|
||||
| "shutdown_error"
|
||||
| "shutdown_timeout"
|
||||
| "shutting_down"
|
||||
| "start_error"
|
||||
| "start_timeout"
|
||||
| "starting"
|
||||
export const WorkspaceAgentLifecycles: WorkspaceAgentLifecycle[] = [
|
||||
"created",
|
||||
"off",
|
||||
"ready",
|
||||
"shutdown_error",
|
||||
"shutdown_timeout",
|
||||
"shutting_down",
|
||||
"start_error",
|
||||
"start_timeout",
|
||||
"starting",
|
||||
|
|
|
@ -3,7 +3,11 @@ import {
|
|||
MockWorkspace,
|
||||
MockWorkspaceAgent,
|
||||
MockWorkspaceAgentConnecting,
|
||||
MockWorkspaceAgentOff,
|
||||
MockWorkspaceAgentOutdated,
|
||||
MockWorkspaceAgentShutdownError,
|
||||
MockWorkspaceAgentShutdownTimeout,
|
||||
MockWorkspaceAgentShuttingDown,
|
||||
MockWorkspaceAgentStartError,
|
||||
MockWorkspaceAgentStarting,
|
||||
MockWorkspaceAgentStartTimeout,
|
||||
|
@ -114,6 +118,38 @@ StartError.args = {
|
|||
showApps: true,
|
||||
}
|
||||
|
||||
export const ShuttingDown = Template.bind({})
|
||||
ShuttingDown.args = {
|
||||
agent: MockWorkspaceAgentShuttingDown,
|
||||
workspace: MockWorkspace,
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
export const ShutdownTimeout = Template.bind({})
|
||||
ShutdownTimeout.args = {
|
||||
agent: MockWorkspaceAgentShutdownTimeout,
|
||||
workspace: MockWorkspace,
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
export const ShutdownError = Template.bind({})
|
||||
ShutdownError.args = {
|
||||
agent: MockWorkspaceAgentShutdownError,
|
||||
workspace: MockWorkspace,
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
export const Off = Template.bind({})
|
||||
Off.args = {
|
||||
agent: MockWorkspaceAgentOff,
|
||||
workspace: MockWorkspace,
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
export const ShowingPortForward = Template.bind({})
|
||||
ShowingPortForward.args = {
|
||||
agent: MockWorkspaceAgent,
|
||||
|
|
|
@ -16,9 +16,10 @@ import Link from "@material-ui/core/Link"
|
|||
// If we think in the agent status and lifecycle into a single enum/state I’d
|
||||
// say we would have: connecting, timeout, disconnected, connected:created,
|
||||
// connected:starting, connected:start_timeout, connected:start_error,
|
||||
// connected:ready
|
||||
// connected:ready, connected:shutting_down, connected:shutdown_timeout,
|
||||
// connected:shutdown_error, connected:off.
|
||||
|
||||
const ReadyLifeCycle: React.FC = () => {
|
||||
const ReadyLifecycle: React.FC = () => {
|
||||
const styles = useStyles()
|
||||
const { t } = useTranslation("workspacePage")
|
||||
|
||||
|
@ -132,6 +133,122 @@ const StartErrorLifecycle: React.FC<{
|
|||
)
|
||||
}
|
||||
|
||||
const ShuttingDownLifecycle: React.FC = () => {
|
||||
const styles = useStyles()
|
||||
const { t } = useTranslation("workspacePage")
|
||||
|
||||
return (
|
||||
<Tooltip title={t("agentStatus.connected.shuttingDown")}>
|
||||
<div
|
||||
role="status"
|
||||
aria-label={t("agentStatus.connected.shuttingDown")}
|
||||
className={combineClasses([styles.status, styles.connecting])}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
const ShutdownTimeoutLifecycle: React.FC<{
|
||||
agent: WorkspaceAgent
|
||||
}> = ({ agent }) => {
|
||||
const { t } = useTranslation("agent")
|
||||
const styles = useStyles()
|
||||
const anchorRef = useRef<SVGSVGElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const id = isOpen ? "timeout-popover" : undefined
|
||||
|
||||
return (
|
||||
<>
|
||||
<WarningRounded
|
||||
ref={anchorRef}
|
||||
onMouseEnter={() => setIsOpen(true)}
|
||||
onMouseLeave={() => setIsOpen(false)}
|
||||
role="status"
|
||||
aria-label={t("status.shutdownTimeout")}
|
||||
className={styles.timeoutWarning}
|
||||
/>
|
||||
<HelpPopover
|
||||
id={id}
|
||||
open={isOpen}
|
||||
anchorEl={anchorRef.current}
|
||||
onOpen={() => setIsOpen(true)}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<HelpTooltipTitle>{t("shutdownTimeoutTooltip.title")}</HelpTooltipTitle>
|
||||
<HelpTooltipText>
|
||||
{t("shutdownTimeoutTooltip.message")}{" "}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={agent.troubleshooting_url}
|
||||
>
|
||||
{t("shutdownTimeoutTooltip.link")}
|
||||
</Link>
|
||||
.
|
||||
</HelpTooltipText>
|
||||
</HelpPopover>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const ShutdownErrorLifecycle: React.FC<{
|
||||
agent: WorkspaceAgent
|
||||
}> = ({ agent }) => {
|
||||
const { t } = useTranslation("agent")
|
||||
const styles = useStyles()
|
||||
const anchorRef = useRef<SVGSVGElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const id = isOpen ? "timeout-popover" : undefined
|
||||
|
||||
return (
|
||||
<>
|
||||
<WarningRounded
|
||||
ref={anchorRef}
|
||||
onMouseEnter={() => setIsOpen(true)}
|
||||
onMouseLeave={() => setIsOpen(false)}
|
||||
role="status"
|
||||
aria-label={t("status.error")}
|
||||
className={styles.errorWarning}
|
||||
/>
|
||||
<HelpPopover
|
||||
id={id}
|
||||
open={isOpen}
|
||||
anchorEl={anchorRef.current}
|
||||
onOpen={() => setIsOpen(true)}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<HelpTooltipTitle>{t("shutdownErrorTooltip.title")}</HelpTooltipTitle>
|
||||
<HelpTooltipText>
|
||||
{t("shutdownErrorTooltip.message")}{" "}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={agent.troubleshooting_url}
|
||||
>
|
||||
{t("shutdownErrorTooltip.link")}
|
||||
</Link>
|
||||
.
|
||||
</HelpTooltipText>
|
||||
</HelpPopover>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const OffLifecycle: React.FC = () => {
|
||||
const styles = useStyles()
|
||||
const { t } = useTranslation("workspacePage")
|
||||
|
||||
return (
|
||||
<Tooltip title={t("agentStatus.connected.off")}>
|
||||
<div
|
||||
role="status"
|
||||
aria-label={t("agentStatus.connected.off")}
|
||||
className={combineClasses([styles.status, styles.disconnected])}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
const ConnectedStatus: React.FC<{
|
||||
agent: WorkspaceAgent
|
||||
}> = ({ agent }) => {
|
||||
|
@ -143,12 +260,12 @@ const ConnectedStatus: React.FC<{
|
|||
// release indicating startup script behavior has changed.
|
||||
// https://github.com/coder/coder/issues/5749
|
||||
if (agent.login_before_ready) {
|
||||
return <ReadyLifeCycle />
|
||||
return <ReadyLifecycle />
|
||||
}
|
||||
return (
|
||||
<ChooseOne>
|
||||
<Cond condition={agent.lifecycle_state === "ready"}>
|
||||
<ReadyLifeCycle />
|
||||
<ReadyLifecycle />
|
||||
</Cond>
|
||||
<Cond condition={agent.lifecycle_state === "start_timeout"}>
|
||||
<StartTimeoutLifecycle agent={agent} />
|
||||
|
@ -156,6 +273,18 @@ const ConnectedStatus: React.FC<{
|
|||
<Cond condition={agent.lifecycle_state === "start_error"}>
|
||||
<StartErrorLifecycle agent={agent} />
|
||||
</Cond>
|
||||
<Cond condition={agent.lifecycle_state === "shutting_down"}>
|
||||
<ShuttingDownLifecycle />
|
||||
</Cond>
|
||||
<Cond condition={agent.lifecycle_state === "shutdown_timeout"}>
|
||||
<ShutdownTimeoutLifecycle agent={agent} />
|
||||
</Cond>
|
||||
<Cond condition={agent.lifecycle_state === "shutdown_error"}>
|
||||
<ShutdownErrorLifecycle agent={agent} />
|
||||
</Cond>
|
||||
<Cond condition={agent.lifecycle_state === "off"}>
|
||||
<OffLifecycle />
|
||||
</Cond>
|
||||
<Cond>
|
||||
<StartingLifecycle />
|
||||
</Cond>
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
"status": {
|
||||
"timeout": "Timeout",
|
||||
"startTimeout": "Start Timeout",
|
||||
"startError": "Error"
|
||||
"startError": "Start Error",
|
||||
"shutdownTimeout": "Stop Timeout",
|
||||
"shutdownError": "Stop Error"
|
||||
},
|
||||
"timeoutTooltip": {
|
||||
"title": "Agent is taking too long to connect",
|
||||
|
@ -27,8 +29,18 @@
|
|||
"link": "Troubleshoot"
|
||||
},
|
||||
"startErrorTooltip": {
|
||||
"title": "Error starting agent",
|
||||
"message": "Something went wrong during the agent start.",
|
||||
"title": "Error starting the agent",
|
||||
"message": "Something went wrong during the agent startup.",
|
||||
"link": "Troubleshoot"
|
||||
},
|
||||
"shutdownTimeoutTooltip": {
|
||||
"title": "Agent is taking too long to stop",
|
||||
"message": "We noticed this agent is taking longer than expected to stop.",
|
||||
"link": "Troubleshoot"
|
||||
},
|
||||
"shutdownErrorTooltip": {
|
||||
"title": "Error stopping the agent",
|
||||
"message": "Something went wrong while trying to stop the agent.",
|
||||
"link": "Troubleshoot"
|
||||
},
|
||||
"unableToConnect": "Unable to connect"
|
||||
|
|
|
@ -39,7 +39,9 @@
|
|||
"agentStatus": {
|
||||
"connected": {
|
||||
"ready": "Ready",
|
||||
"starting": "Starting..."
|
||||
"starting": "Starting...",
|
||||
"shuttingDown": "Stopping...",
|
||||
"off": "Stopped"
|
||||
},
|
||||
"connecting": "Connecting...",
|
||||
"disconnected": "Disconnected",
|
||||
|
|
|
@ -401,6 +401,7 @@ export const MockWorkspaceAgent: TypesGen.WorkspaceAgent = {
|
|||
lifecycle_state: "starting",
|
||||
login_before_ready: false,
|
||||
startup_script_timeout_seconds: 120,
|
||||
shutdown_script_timeout_seconds: 120,
|
||||
}
|
||||
|
||||
export const MockWorkspaceAgentDisconnected: TypesGen.WorkspaceAgent = {
|
||||
|
@ -478,6 +479,34 @@ export const MockWorkspaceAgentStartError: TypesGen.WorkspaceAgent = {
|
|||
lifecycle_state: "start_error",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAgentShuttingDown: TypesGen.WorkspaceAgent = {
|
||||
...MockWorkspaceAgent,
|
||||
id: "test-workspace-agent-shutting-down",
|
||||
name: "a-shutting-down-workspace-agent",
|
||||
lifecycle_state: "shutting_down",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAgentShutdownTimeout: TypesGen.WorkspaceAgent = {
|
||||
...MockWorkspaceAgent,
|
||||
id: "test-workspace-agent-shutdown-timeout",
|
||||
name: "a-workspace-agent-timed-out-while-running-shutdownup-script",
|
||||
lifecycle_state: "shutdown_timeout",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAgentShutdownError: TypesGen.WorkspaceAgent = {
|
||||
...MockWorkspaceAgent,
|
||||
id: "test-workspace-agent-shutdown-error",
|
||||
name: "a-workspace-agent-errored-while-running-shutdownup-script",
|
||||
lifecycle_state: "shutdown_error",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAgentOff: TypesGen.WorkspaceAgent = {
|
||||
...MockWorkspaceAgent,
|
||||
id: "test-workspace-agent-off",
|
||||
name: "a-workspace-agent-is-shut-down",
|
||||
lifecycle_state: "off",
|
||||
}
|
||||
|
||||
export const MockWorkspaceResource: TypesGen.WorkspaceResource = {
|
||||
agents: [
|
||||
MockWorkspaceAgent,
|
||||
|
|
Loading…
Reference in New Issue