From dbb0572b676fb4ce69f15fb9fe4e26dab7af77a7 Mon Sep 17 00:00:00 2001 From: Lionello Lunesu Date: Thu, 22 Jan 2026 18:56:17 -0800 Subject: [PATCH] feat: add workspace select command --- src/cmd/cli/command/globals.go | 2 +- src/cmd/cli/command/workspace.go | 24 +++++++++++++++++++++--- src/pkg/cli/client/state.go | 12 ++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/cmd/cli/command/globals.go b/src/cmd/cli/command/globals.go index 7bf2b0c15..2269c9387 100644 --- a/src/cmd/cli/command/globals.go +++ b/src/cmd/cli/command/globals.go @@ -115,7 +115,7 @@ func NewGlobalConfig() *GlobalConfig { hastty := term.IsTerminal() && !pkg.GetenvBool("CI") - tenant := types.TenantNameOrID("") + tenant := client.GetCurrentTenant() if fromEnv, ok := os.LookupEnv("DEFANG_WORKSPACE"); ok { tenant = types.TenantNameOrID(fromEnv) } else if fromEnv, ok := os.LookupEnv("DEFANG_ORG"); ok { diff --git a/src/cmd/cli/command/workspace.go b/src/cmd/cli/command/workspace.go index 7f6a09017..97e624585 100644 --- a/src/cmd/cli/command/workspace.go +++ b/src/cmd/cli/command/workspace.go @@ -9,10 +9,11 @@ import ( "github.com/DefangLabs/defang/src/pkg/cli" "github.com/DefangLabs/defang/src/pkg/cli/client" "github.com/DefangLabs/defang/src/pkg/term" + "github.com/DefangLabs/defang/src/pkg/types" "github.com/spf13/cobra" ) -func ListWorkspaces(cmd *cobra.Command, args []string) error { +func listWorkspaces(cmd *cobra.Command, args []string) error { jsonMode, _ := cmd.Flags().GetBool("json") verbose := global.Verbose @@ -64,7 +65,7 @@ var workspaceCmd = &cobra.Command{ Args: cobra.NoArgs, Annotations: authNeededAnnotation, Short: "Manage workspaces", - RunE: ListWorkspaces, + RunE: listWorkspaces, } var workspaceListCmd = &cobra.Command{ @@ -73,11 +74,28 @@ var workspaceListCmd = &cobra.Command{ Args: cobra.NoArgs, Annotations: authNeededAnnotation, Short: "List available workspaces", - RunE: ListWorkspaces, + RunE: listWorkspaces, +} + +var workspaceSelectCmd = &cobra.Command{ + Use: "select WORKSPACE", + Aliases: []string{"use", "switch"}, + Args: cobra.ExactArgs(1), + // Annotations: authNeededAnnotation, + Short: "Select a workspace to use", + RunE: func(cmd *cobra.Command, args []string) error { + global.Tenant = types.TenantNameOrID(args[0]) + if _, err := cli.ConnectWithTenant(cmd.Context(), global.Cluster, global.Tenant); err != nil { + return err + } + term.Infof("Switched to workspace %q\n", global.Tenant) + return client.SetCurrentTenant(global.Tenant) + }, } func init() { workspaceCmd.Flags().Bool("json", pkg.GetenvBool("DEFANG_JSON"), "print output in JSON format") workspaceListCmd.Flags().Bool("json", pkg.GetenvBool("DEFANG_JSON"), "print output in JSON format") workspaceCmd.AddCommand(workspaceListCmd) + workspaceCmd.AddCommand(workspaceSelectCmd) } diff --git a/src/pkg/cli/client/state.go b/src/pkg/cli/client/state.go index cc89e0d70..6baf068dc 100644 --- a/src/pkg/cli/client/state.go +++ b/src/pkg/cli/client/state.go @@ -6,6 +6,7 @@ import ( "path/filepath" "time" + "github.com/DefangLabs/defang/src/pkg/types" "github.com/google/uuid" ) @@ -20,6 +21,7 @@ var ( type State struct { AnonID string TermsAcceptedAt time.Time + Tenant types.TenantNameOrID } func initState(path string) State { @@ -63,3 +65,13 @@ func AcceptTerms() error { func TermsAccepted() bool { return state.termsAccepted() } + +func SetCurrentTenant(tenant types.TenantNameOrID) error { + state.Tenant = tenant + return state.write(statePath) +} + +func GetCurrentTenant() types.TenantNameOrID { + state = initState(statePath) + return state.Tenant +}