Skip to content

Commit 627957c

Browse files
committed
cli: return other agents from getWorkspaceAndAgent
1 parent 4ae42b5 commit 627957c

File tree

8 files changed

+45
-39
lines changed

8 files changed

+45
-39
lines changed

cli/exp_rpty.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func handleRPTY(inv *serpent.Invocation, client *codersdk.Client, args handleRPT
9797
reconnectID = uuid.New()
9898
}
9999

100-
ws, agt, err := getWorkspaceAndAgent(ctx, inv, client, true, args.NamedWorkspace)
100+
ws, agt, _, err := getWorkspaceAndAgent(ctx, inv, client, true, args.NamedWorkspace)
101101
if err != nil {
102102
return err
103103
}

cli/open.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (r *RootCmd) openVSCode() *serpent.Command {
7171
// need to wait for the agent to start.
7272
workspaceQuery := inv.Args[0]
7373
autostart := true
74-
workspace, workspaceAgent, err := getWorkspaceAndAgent(ctx, inv, client, autostart, workspaceQuery)
74+
workspace, workspaceAgent, otherWorkspaceAgents, err := getWorkspaceAndAgent(ctx, inv, client, autostart, workspaceQuery)
7575
if err != nil {
7676
return xerrors.Errorf("get workspace and agent: %w", err)
7777
}
@@ -288,7 +288,7 @@ func (r *RootCmd) openApp() *serpent.Command {
288288
}
289289

290290
workspaceName := inv.Args[0]
291-
ws, agt, err := getWorkspaceAndAgent(ctx, inv, client, false, workspaceName)
291+
ws, agt, _, err := getWorkspaceAndAgent(ctx, inv, client, false, workspaceName)
292292
if err != nil {
293293
var sdkErr *codersdk.Error
294294
if errors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound {
@@ -469,7 +469,7 @@ func waitForAgentCond(ctx context.Context, client *codersdk.Client, workspace co
469469
}
470470

471471
for workspace = range wc {
472-
workspaceAgent, err = getWorkspaceAgent(workspace, workspaceAgent.Name)
472+
workspaceAgent, _, err = getWorkspaceAgent(workspace, workspaceAgent.Name)
473473
if err != nil {
474474
return workspace, workspaceAgent, xerrors.Errorf("get workspace agent: %w", err)
475475
}

cli/ping.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (r *RootCmd) ping() *serpent.Command {
110110
defer notifyCancel()
111111

112112
workspaceName := inv.Args[0]
113-
_, workspaceAgent, err := getWorkspaceAndAgent(
113+
_, workspaceAgent, _, err := getWorkspaceAndAgent(
114114
ctx, inv, client,
115115
false, // Do not autostart for a ping.
116116
workspaceName,

cli/portforward.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (r *RootCmd) portForward() *serpent.Command {
8484
return xerrors.New("no port-forwards requested")
8585
}
8686

87-
workspace, workspaceAgent, err := getWorkspaceAndAgent(ctx, inv, client, !disableAutostart, inv.Args[0])
87+
workspace, workspaceAgent, _, err := getWorkspaceAndAgent(ctx, inv, client, !disableAutostart, inv.Args[0])
8888
if err != nil {
8989
return err
9090
}

cli/speedtest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func (r *RootCmd) speedtest() *serpent.Command {
8383
return xerrors.Errorf("--direct (-d) is incompatible with --%s", varDisableDirect)
8484
}
8585

86-
_, workspaceAgent, err := getWorkspaceAndAgent(ctx, inv, client, false, inv.Args[0])
86+
_, workspaceAgent, _, err := getWorkspaceAndAgent(ctx, inv, client, false, inv.Args[0])
8787
if err != nil {
8888
return err
8989
}

cli/ssh.go

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ func findWorkspaceAndAgentByHostname(
754754
hostname = strings.TrimSuffix(hostname, qualifiedSuffix)
755755
}
756756
hostname = normalizeWorkspaceInput(hostname)
757-
return getWorkspaceAndAgent(ctx, inv, client, !disableAutostart, hostname)
757+
ws, agent, _, err := getWorkspaceAndAgent(ctx, inv, client, !disableAutostart, hostname)
758+
return ws, agent, err
758759
}
759760

760761
// watchAndClose ensures closer is called if the context is canceled or
@@ -827,9 +828,10 @@ startWatchLoop:
827828
}
828829

829830
// getWorkspaceAgent returns the workspace and agent selected using either the
830-
// `<workspace>[.<agent>]` syntax via `in`.
831+
// `<workspace>[.<agent>]` syntax via `in`. It will also return any other agents
832+
// in the workspace as a slice for use in child->parent lookups.
831833
// If autoStart is true, the workspace will be started if it is not already running.
832-
func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *codersdk.Client, autostart bool, input string) (codersdk.Workspace, codersdk.WorkspaceAgent, error) { //nolint:revive
834+
func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *codersdk.Client, autostart bool, input string) (codersdk.Workspace, codersdk.WorkspaceAgent, []codersdk.WorkspaceAgent, error) { //nolint:revive
833835
var (
834836
workspace codersdk.Workspace
835837
// The input will be `owner/name.agent`
@@ -840,27 +842,27 @@ func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *
840842

841843
workspace, err = namedWorkspace(ctx, client, workspaceParts[0])
842844
if err != nil {
843-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, err
845+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err
844846
}
845847

846848
if workspace.LatestBuild.Transition != codersdk.WorkspaceTransitionStart {
847849
if !autostart {
848-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.New("workspace must be started")
850+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, xerrors.New("workspace must be started")
849851
}
850852
// Autostart the workspace for the user.
851853
// For some failure modes, return a better message.
852854
if workspace.LatestBuild.Transition == codersdk.WorkspaceTransitionDelete {
853855
// Any sort of deleting status, we should reject with a nicer error.
854-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("workspace %q is deleted", workspace.Name)
856+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("workspace %q is deleted", workspace.Name)
855857
}
856858
if workspace.LatestBuild.Job.Status == codersdk.ProvisionerJobFailed {
857-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{},
859+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil,
858860
xerrors.Errorf("workspace %q is in failed state, unable to autostart the workspace", workspace.Name)
859861
}
860862
// The workspace needs to be stopped before we can start it.
861863
// It cannot be in any pending or failed state.
862864
if workspace.LatestBuild.Status != codersdk.WorkspaceStatusStopped {
863-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{},
865+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil,
864866
xerrors.Errorf("workspace must be started; was unable to autostart as the last build job is %q, expected %q",
865867
workspace.LatestBuild.Status,
866868
codersdk.WorkspaceStatusStopped,
@@ -881,48 +883,48 @@ func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *
881883
case http.StatusForbidden:
882884
_, err = startWorkspace(inv, client, workspace, workspaceParameterFlags{}, buildFlags{}, WorkspaceUpdate)
883885
if err != nil {
884-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("start workspace with active template version: %w", err)
886+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("start workspace with active template version: %w", err)
885887
}
886888
_, _ = fmt.Fprintln(inv.Stdout, "Unable to start the workspace with template version from last build. Your workspace has been updated to the current active template version.")
887889
}
888890
} else if err != nil {
889-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("start workspace with current template version: %w", err)
891+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("start workspace with current template version: %w", err)
890892
}
891893

892894
// Refresh workspace state so that `outdated`, `build`,`template_*` fields are up-to-date.
893895
workspace, err = namedWorkspace(ctx, client, workspaceParts[0])
894896
if err != nil {
895-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, err
897+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err
896898
}
897899
}
898900
if workspace.LatestBuild.Job.CompletedAt == nil {
899901
err := cliui.WorkspaceBuild(ctx, inv.Stderr, client, workspace.LatestBuild.ID)
900902
if err != nil {
901-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, err
903+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err
902904
}
903905
// Fetch up-to-date build information after completion.
904906
workspace.LatestBuild, err = client.WorkspaceBuild(ctx, workspace.LatestBuild.ID)
905907
if err != nil {
906-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, err
908+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err
907909
}
908910
}
909911
if workspace.LatestBuild.Transition == codersdk.WorkspaceTransitionDelete {
910-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, xerrors.Errorf("workspace %q is being deleted", workspace.Name)
912+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("workspace %q is being deleted", workspace.Name)
911913
}
912914

913915
var agentName string
914916
if len(workspaceParts) >= 2 {
915917
agentName = workspaceParts[1]
916918
}
917-
workspaceAgent, err := getWorkspaceAgent(workspace, agentName)
919+
workspaceAgent, otherWorkspaceAgents, err := getWorkspaceAgent(workspace, agentName)
918920
if err != nil {
919-
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, err
921+
return codersdk.Workspace{}, codersdk.WorkspaceAgent{}, nil, err
920922
}
921923

922-
return workspace, workspaceAgent, nil
924+
return workspace, workspaceAgent, otherWorkspaceAgents, nil
923925
}
924926

925-
func getWorkspaceAgent(workspace codersdk.Workspace, agentName string) (workspaceAgent codersdk.WorkspaceAgent, err error) {
927+
func getWorkspaceAgent(workspace codersdk.Workspace, agentName string) (workspaceAgent codersdk.WorkspaceAgent, otherAgents []codersdk.WorkspaceAgent, err error) {
926928
resources := workspace.LatestBuild.Resources
927929

928930
var (
@@ -936,22 +938,23 @@ func getWorkspaceAgent(workspace codersdk.Workspace, agentName string) (workspac
936938
}
937939
}
938940
if len(agents) == 0 {
939-
return codersdk.WorkspaceAgent{}, xerrors.Errorf("workspace %q has no agents", workspace.Name)
941+
return codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("workspace %q has no agents", workspace.Name)
940942
}
941943
slices.Sort(availableNames)
942944
if agentName != "" {
943-
for _, otherAgent := range agents {
944-
if otherAgent.Name != agentName {
945+
for i, agent := range agents {
946+
if agent.Name != agentName || agent.ID.String() == agentName {
945947
continue
946948
}
947-
return otherAgent, nil
949+
otherAgents := slices.Delete(agents, i, i+1)
950+
return agent, otherAgents, nil
948951
}
949-
return codersdk.WorkspaceAgent{}, xerrors.Errorf("agent not found by name %q, available agents: %v", agentName, availableNames)
952+
return codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("agent not found by name %q, available agents: %v", agentName, availableNames)
950953
}
951954
if len(agents) == 1 {
952-
return agents[0], nil
955+
return agents[0], nil, nil
953956
}
954-
return codersdk.WorkspaceAgent{}, xerrors.Errorf("multiple agents found, please specify the agent name, available agents: %v", availableNames)
957+
return codersdk.WorkspaceAgent{}, nil, xerrors.Errorf("multiple agents found, please specify the agent name, available agents: %v", availableNames)
955958
}
956959

957960
// Attempt to poll workspace autostop. We write a per-workspace lockfile to

cli/ssh_internal_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ func Test_getWorkspaceAgent(t *testing.T) {
376376
agent := createAgent("main")
377377
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{agent})
378378

379-
result, err := getWorkspaceAgent(workspace, "")
379+
result, _, err := getWorkspaceAgent(workspace, "")
380380
require.NoError(t, err)
381381
assert.Equal(t, agent.ID, result.ID)
382382
assert.Equal(t, "main", result.Name)
@@ -388,7 +388,7 @@ func Test_getWorkspaceAgent(t *testing.T) {
388388
agent2 := createAgent("main2")
389389
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{agent1, agent2})
390390

391-
_, err := getWorkspaceAgent(workspace, "")
391+
_, _, err := getWorkspaceAgent(workspace, "")
392392
require.Error(t, err)
393393
assert.Contains(t, err.Error(), "multiple agents found")
394394
assert.Contains(t, err.Error(), "available agents: [main1 main2]")
@@ -400,10 +400,13 @@ func Test_getWorkspaceAgent(t *testing.T) {
400400
agent2 := createAgent("main2")
401401
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{agent1, agent2})
402402

403-
result, err := getWorkspaceAgent(workspace, "main1")
403+
result, other, err := getWorkspaceAgent(workspace, "main1")
404404
require.NoError(t, err)
405405
assert.Equal(t, agent1.ID, result.ID)
406406
assert.Equal(t, "main1", result.Name)
407+
assert.Len(t, other, 1)
408+
assert.Equal(t, agent2.ID, other[0].ID)
409+
assert.Equal(t, "main2", other[0].Name)
407410
})
408411

409412
t.Run("AgentNameSpecified_NotFound", func(t *testing.T) {
@@ -412,7 +415,7 @@ func Test_getWorkspaceAgent(t *testing.T) {
412415
agent2 := createAgent("main2")
413416
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{agent1, agent2})
414417

415-
_, err := getWorkspaceAgent(workspace, "nonexistent")
418+
_, _, err := getWorkspaceAgent(workspace, "nonexistent")
416419
require.Error(t, err)
417420
assert.Contains(t, err.Error(), `agent not found by name "nonexistent"`)
418421
assert.Contains(t, err.Error(), "available agents: [main1 main2]")
@@ -422,7 +425,7 @@ func Test_getWorkspaceAgent(t *testing.T) {
422425
t.Parallel()
423426
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{})
424427

425-
_, err := getWorkspaceAgent(workspace, "")
428+
_, _, err := getWorkspaceAgent(workspace, "")
426429
require.Error(t, err)
427430
assert.Contains(t, err.Error(), `workspace "test-workspace" has no agents`)
428431
})
@@ -435,7 +438,7 @@ func Test_getWorkspaceAgent(t *testing.T) {
435438
agent3 := createAgent("krypton")
436439
workspace := createWorkspaceWithAgents([]codersdk.WorkspaceAgent{agent2, agent1, agent3})
437440

438-
_, err := getWorkspaceAgent(workspace, "nonexistent")
441+
_, _, err := getWorkspaceAgent(workspace, "nonexistent")
439442
require.Error(t, err)
440443
// Available agents should be sorted alphabetically.
441444
assert.Contains(t, err.Error(), "available agents: [clark krypton zod]")

cli/vscodessh.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func (r *RootCmd) vscodeSSH() *serpent.Command {
102102
// will call this command after the workspace is started.
103103
autostart := false
104104

105-
workspace, workspaceAgent, err := getWorkspaceAndAgent(ctx, inv, client, autostart, fmt.Sprintf("%s/%s", owner, name))
105+
workspace, workspaceAgent, _, err := getWorkspaceAndAgent(ctx, inv, client, autostart, fmt.Sprintf("%s/%s", owner, name))
106106
if err != nil {
107107
return xerrors.Errorf("find workspace and agent: %w", err)
108108
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy