diff --git a/internal/cmd/ceapi.go b/internal/cmd/ceapi.go index c58b8161..0c5ca004 100644 --- a/internal/cmd/ceapi.go +++ b/internal/cmd/ceapi.go @@ -32,6 +32,11 @@ func lookupUserOrgs(user *coder.User, orgs []coder.Organization) []coder.Organiz return userOrgs } +// getAllWorkspaces gets all workspaces for all users, on all providers. +func getAllWorkspaces(ctx context.Context, client coder.Client) ([]coder.Workspace, error) { + return client.Workspaces(ctx) +} + // getWorkspaces returns all workspaces for the user. func getWorkspaces(ctx context.Context, client coder.Client, email string) ([]coder.Workspace, error) { user, err := client.UserByEmail(ctx, email) diff --git a/internal/cmd/workspaces.go b/internal/cmd/workspaces.go index ff70b64d..f4dd7e0f 100644 --- a/internal/cmd/workspaces.go +++ b/internal/cmd/workspaces.go @@ -70,6 +70,7 @@ const ( func lsWorkspacesCommand() *cobra.Command { var ( + all bool outputFmt string user string provider string @@ -85,16 +86,19 @@ func lsWorkspacesCommand() *cobra.Command { if err != nil { return err } - workspaces, err := getWorkspaces(ctx, client, user) + + var workspaces []coder.Workspace + switch { + case all: + workspaces, err = getAllWorkspaces(ctx, client) + case provider != "": + workspaces, err = getWorkspacesByProvider(ctx, client, provider, user) + default: + workspaces, err = getWorkspaces(ctx, client, user) + } if err != nil { return err } - if provider != "" { - workspaces, err = getWorkspacesByProvider(ctx, client, provider, user) - if err != nil { - return err - } - } if len(workspaces) < 1 { clog.LogInfo("no workspaces found") workspaces = []coder.Workspace{} // ensures that json output still marshals @@ -124,6 +128,7 @@ func lsWorkspacesCommand() *cobra.Command { }, } + cmd.Flags().BoolVar(&all, "all", false, "Get workspaces for all users (admin only)") cmd.Flags().StringVar(&user, "user", coder.Me, "Specify the user whose resources to target") cmd.Flags().StringVarP(&outputFmt, "output", "o", humanOutput, "human | json") cmd.Flags().StringVarP(&provider, "provider", "p", "", "Filter workspaces by a particular workspace provider name.") @@ -210,7 +215,7 @@ func (*wsPinger) logSuccess(timeStr, msg string) { fmt.Printf("%s: %s\n", color.New(color.Bold, color.FgGreen).Sprint(timeStr), msg) } -// Only return fatal errors +// Only return fatal errors. func (w *wsPinger) ping(ctx context.Context) error { ctx, cancelFunc := context.WithTimeout(ctx, time.Second*15) defer cancelFunc() diff --git a/internal/cmd/workspaces_test.go b/internal/cmd/workspaces_test.go index 5dd3d01b..89e5fd08 100644 --- a/internal/cmd/workspaces_test.go +++ b/internal/cmd/workspaces_test.go @@ -29,6 +29,34 @@ func Test_workspaces_ls(t *testing.T) { res.stdoutUnmarshals(t, &workspaces) } +func Test_workspaces_ls_all(t *testing.T) { + skipIfNoAuth(t) + for _, test := range []struct { + name string + command []string + assert func(r result) + }{ + { + name: "simple list", + command: []string{"workspaces", "ls", "--all"}, + assert: func(r result) { r.success(t) }, + }, + { + name: "list as json", + command: []string{"workspaces", "ls", "--all", "--output", "json"}, + assert: func(r result) { + var workspaces []coder.Workspace + r.stdoutUnmarshals(t, &workspaces) + }, + }, + } { + test := test + t.Run(test.name, func(t *testing.T) { + test.assert(execute(t, nil, test.command...)) + }) + } +} + func Test_workspaces_ls_by_provider(t *testing.T) { skipIfNoAuth(t) for _, test := range []struct {