@@ -754,7 +754,8 @@ func findWorkspaceAndAgentByHostname(
754
754
hostname = strings .TrimSuffix (hostname , qualifiedSuffix )
755
755
}
756
756
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
758
759
}
759
760
760
761
// watchAndClose ensures closer is called if the context is canceled or
@@ -827,9 +828,10 @@ startWatchLoop:
827
828
}
828
829
829
830
// 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.
831
833
// 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
833
835
var (
834
836
workspace codersdk.Workspace
835
837
// The input will be `owner/name.agent`
@@ -840,27 +842,27 @@ func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *
840
842
841
843
workspace , err = namedWorkspace (ctx , client , workspaceParts [0 ])
842
844
if err != nil {
843
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, err
845
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil , err
844
846
}
845
847
846
848
if workspace .LatestBuild .Transition != codersdk .WorkspaceTransitionStart {
847
849
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" )
849
851
}
850
852
// Autostart the workspace for the user.
851
853
// For some failure modes, return a better message.
852
854
if workspace .LatestBuild .Transition == codersdk .WorkspaceTransitionDelete {
853
855
// 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 )
855
857
}
856
858
if workspace .LatestBuild .Job .Status == codersdk .ProvisionerJobFailed {
857
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {},
859
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil ,
858
860
xerrors .Errorf ("workspace %q is in failed state, unable to autostart the workspace" , workspace .Name )
859
861
}
860
862
// The workspace needs to be stopped before we can start it.
861
863
// It cannot be in any pending or failed state.
862
864
if workspace .LatestBuild .Status != codersdk .WorkspaceStatusStopped {
863
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {},
865
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil ,
864
866
xerrors .Errorf ("workspace must be started; was unable to autostart as the last build job is %q, expected %q" ,
865
867
workspace .LatestBuild .Status ,
866
868
codersdk .WorkspaceStatusStopped ,
@@ -881,48 +883,48 @@ func getWorkspaceAndAgent(ctx context.Context, inv *serpent.Invocation, client *
881
883
case http .StatusForbidden :
882
884
_ , err = startWorkspace (inv , client , workspace , workspaceParameterFlags {}, buildFlags {}, WorkspaceUpdate )
883
885
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 )
885
887
}
886
888
_ , _ = 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." )
887
889
}
888
890
} 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 )
890
892
}
891
893
892
894
// Refresh workspace state so that `outdated`, `build`,`template_*` fields are up-to-date.
893
895
workspace , err = namedWorkspace (ctx , client , workspaceParts [0 ])
894
896
if err != nil {
895
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, err
897
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil , err
896
898
}
897
899
}
898
900
if workspace .LatestBuild .Job .CompletedAt == nil {
899
901
err := cliui .WorkspaceBuild (ctx , inv .Stderr , client , workspace .LatestBuild .ID )
900
902
if err != nil {
901
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, err
903
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil , err
902
904
}
903
905
// Fetch up-to-date build information after completion.
904
906
workspace .LatestBuild , err = client .WorkspaceBuild (ctx , workspace .LatestBuild .ID )
905
907
if err != nil {
906
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, err
908
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil , err
907
909
}
908
910
}
909
911
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 )
911
913
}
912
914
913
915
var agentName string
914
916
if len (workspaceParts ) >= 2 {
915
917
agentName = workspaceParts [1 ]
916
918
}
917
- workspaceAgent , err := getWorkspaceAgent (workspace , agentName )
919
+ workspaceAgent , otherWorkspaceAgents , err := getWorkspaceAgent (workspace , agentName )
918
920
if err != nil {
919
- return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, err
921
+ return codersdk.Workspace {}, codersdk.WorkspaceAgent {}, nil , err
920
922
}
921
923
922
- return workspace , workspaceAgent , nil
924
+ return workspace , workspaceAgent , otherWorkspaceAgents , nil
923
925
}
924
926
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 ) {
926
928
resources := workspace .LatestBuild .Resources
927
929
928
930
var (
@@ -936,22 +938,23 @@ func getWorkspaceAgent(workspace codersdk.Workspace, agentName string) (workspac
936
938
}
937
939
}
938
940
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 )
940
942
}
941
943
slices .Sort (availableNames )
942
944
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 {
945
947
continue
946
948
}
947
- return otherAgent , nil
949
+ otherAgents := slices .Delete (agents , i , i + 1 )
950
+ return agent , otherAgents , nil
948
951
}
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 )
950
953
}
951
954
if len (agents ) == 1 {
952
- return agents [0 ], nil
955
+ return agents [0 ], nil , nil
953
956
}
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 )
955
958
}
956
959
957
960
// Attempt to poll workspace autostop. We write a per-workspace lockfile to
0 commit comments