From 9a8b1ae2c82bb2dcde4da530b3505870321e0baa Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Thu, 21 Jul 2022 15:33:45 -0700 Subject: [PATCH 1/6] Add location, subscription, and principalID parameters to env new command --- cli/azd/cmd/env.go | 71 ++++++++++------- cli/azd/cmd/init.go | 7 +- cli/azd/cmd/util.go | 182 ++++++++++++++++++++++++++------------------ 3 files changed, 157 insertions(+), 103 deletions(-) diff --git a/cli/azd/cmd/env.go b/cli/azd/cmd/env.go index 64e9a8c2f14..e3ad3d80855 100644 --- a/cli/azd/cmd/env.go +++ b/cli/azd/cmd/env.go @@ -15,6 +15,7 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/output" "github.com/azure/azure-dev/cli/azd/pkg/tools" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) func envCmd(rootOptions *commands.GlobalCommandOptions) *cobra.Command { @@ -169,43 +170,57 @@ func envListCmd(rootOptions *commands.GlobalCommandOptions) *cobra.Command { } func envNewCmd(rootOptions *commands.GlobalCommandOptions) *cobra.Command { - actionFn := func(ctx context.Context, _ *cobra.Command, args []string, azdCtx *environment.AzdContext) error { - askOne := makeAskOne(rootOptions.NoPrompt) - azCli := commands.GetAzCliFromContext(ctx) - - if err := ensureProject(azdCtx.ProjectPath()); err != nil { - return err - } - - if err := tools.EnsureInstalled(ctx, azCli); err != nil { - return err - } - - if len(args) == 1 { - rootOptions.EnvironmentName = args[0] - } - - if _, err := createAndInitEnvironment(ctx, &rootOptions.EnvironmentName, azdCtx, askOne); err != nil { - return fmt.Errorf("creating new environment: %w", err) - } - - if err := azdCtx.SetDefaultEnvironmentName(rootOptions.EnvironmentName); err != nil { - return fmt.Errorf("saving default environment: %w", err) - } - - return nil - } cmd := commands.Build( - commands.ActionFunc(actionFn), + &envNewAction{rootOptions: rootOptions}, rootOptions, "new ", "Create a new environment.", "", ) - cmd.Args = cobra.MaximumNArgs(1) return cmd } +type envNewAction struct { + rootOptions *commands.GlobalCommandOptions + subscription string + location string + principalID string +} + +func (en *envNewAction) SetupFlags(persis *pflag.FlagSet, local *pflag.FlagSet) { + local.StringVar(&en.subscription, "subscription", "", "Name or ID of an Azure subscription to use for the new environment") + local.StringVarP(&en.location, "location", "l", "", "Azure location for the new environment") + local.StringVar(&en.principalID, "principal", "", "Azure Active Directory principal name or ID to use for the new environment") +} + +func (en *envNewAction) Run(ctx context.Context, _ *cobra.Command, args []string, azdCtx *environment.AzdContext) error { + if err := ensureProject(azdCtx.ProjectPath()); err != nil { + return err + } + + azCli := commands.GetAzCliFromContext(ctx) + if err := tools.EnsureInstalled(ctx, azCli); err != nil { + return err + } + + askOne := makeAskOne(en.rootOptions.NoPrompt) + envSpec := environmentSpec{ + environmentName: en.rootOptions.EnvironmentName, + subscription: en.subscription, + location: en.location, + principalID: en.principalID, + } + if _, err := createAndInitEnvironment(ctx, &envSpec, azdCtx, askOne); err != nil { + return fmt.Errorf("creating new environment: %w", err) + } + + if err := azdCtx.SetDefaultEnvironmentName(envSpec.environmentName); err != nil { + return fmt.Errorf("saving default environment: %w", err) + } + + return nil +} + func envRefreshCmd(rootOptions *commands.GlobalCommandOptions) *cobra.Command { actionFn := func(ctx context.Context, cmd *cobra.Command, args []string, azdCtx *environment.AzdContext) error { azCli := commands.GetAzCliFromContext(ctx) diff --git a/cli/azd/cmd/init.go b/cli/azd/cmd/init.go index 79f5b6a2f0b..f6f06d08dea 100644 --- a/cli/azd/cmd/init.go +++ b/cli/azd/cmd/init.go @@ -259,12 +259,15 @@ func (i *initAction) Run(ctx context.Context, _ *cobra.Command, args []string, a } } - _, err = createAndInitEnvironment(ctx, &i.rootOptions.EnvironmentName, azdCtx, askOne) + envSpec := environmentSpec{ + environmentName: i.rootOptions.EnvironmentName, + } + _, err = createAndInitEnvironment(ctx, &envSpec, azdCtx, askOne) if err != nil { return fmt.Errorf("loading environment: %w", err) } - if err := azdCtx.SetDefaultEnvironmentName(i.rootOptions.EnvironmentName); err != nil { + if err := azdCtx.SetDefaultEnvironmentName(envSpec.environmentName); err != nil { return fmt.Errorf("saving default environment: %w", err) } diff --git a/cli/azd/cmd/util.go b/cli/azd/cmd/util.go index 77072138aa6..dd2cd4a774e 100644 --- a/cli/azd/cmd/util.go +++ b/cli/azd/cmd/util.go @@ -27,6 +27,14 @@ import ( type Asker func(p survey.Prompt, response interface{}) error +const ( + manualSubscriptionEntryOption = "Other (enter manually)" +) + +func invalidEnvironmentNameMsg(environmentName string) string { + return fmt.Sprintf("environment name '%s' is invalid (it should contain only alphanumeric characters and hyphens)\n", environmentName) +} + // ensureValidEnvironmentName ensures the environment name is valid, if it is not, an error is printed // and the user is prompted for a new name. func ensureValidEnvironmentName(environmentName *string, askOneFn Asker) error { @@ -40,36 +48,44 @@ func ensureValidEnvironmentName(environmentName *string, askOneFn Asker) error { } if !environment.IsValidEnvironmentName(*environmentName) { - fmt.Printf("environment name '%s' is invalid (it should contain only alphanumeric characters and hyphens)\n", *environmentName) + fmt.Print(invalidEnvironmentNameMsg(*environmentName)) } } return nil } +type environmentSpec struct { + environmentName string + subscription string + location string + principalID string +} + // createEnvironment creates a new named environment. If an environment with this name already // exists, and error is return. -func createAndInitEnvironment(ctx context.Context, environmentName *string, azdCtx *environment.AzdContext, askOne Asker) (environment.Environment, error) { - if *environmentName != "" && !environment.IsValidEnvironmentName(*environmentName) { - fmt.Printf("environment name '%s' is invalid (it should contain only alphanumeric characters and hyphens)\n", *environmentName) - return environment.Environment{}, fmt.Errorf("environment name '%s' is invalid (it should contain only alphanumeric characters and hyphens)", *environmentName) +func createAndInitEnvironment(ctx context.Context, envSpec *environmentSpec, azdCtx *environment.AzdContext, askOne Asker) (environment.Environment, error) { + if envSpec.environmentName != "" && !environment.IsValidEnvironmentName(envSpec.environmentName) { + errMsg := invalidEnvironmentNameMsg(envSpec.environmentName) + fmt.Print(errMsg) + return environment.Environment{}, fmt.Errorf(errMsg) } - if err := ensureValidEnvironmentName(environmentName, askOne); err != nil { + if err := ensureValidEnvironmentName(&envSpec.environmentName, askOne); err != nil { return environment.Environment{}, err } // Ensure the environment does not already exist: - env, err := azdCtx.GetEnvironment(*environmentName) + env, err := azdCtx.GetEnvironment(envSpec.environmentName) switch { case errors.Is(err, os.ErrNotExist): case err != nil: return environment.Environment{}, fmt.Errorf("checking for existing environment: %w", err) case err == nil: - return environment.Environment{}, fmt.Errorf("environment '%s' already exists", *environmentName) + return environment.Environment{}, fmt.Errorf("environment '%s' already exists", envSpec.environmentName) } - if err := ensureEnvironmentInitialized(ctx, *environmentName, &env, askOne); err != nil { + if err := ensureEnvironmentInitialized(ctx, *envSpec, &env, askOne); err != nil { return environment.Environment{}, fmt.Errorf("initializing environment: %w", err) } @@ -134,7 +150,7 @@ func loadOrInitEnvironment(ctx context.Context, environmentName *string, azdCtx return environment.Environment{}, err } - if err := ensureEnvironmentInitialized(ctx, *environmentName, &env, askOne); err != nil { + if err := ensureEnvironmentInitialized(ctx, environmentSpec{environmentName: *environmentName}, &env, askOne); err != nil { return environment.Environment{}, fmt.Errorf("initializing environment: %w", err) } @@ -148,8 +164,9 @@ func loadOrInitEnvironment(ctx context.Context, environmentName *string, azdCtx } // ensureEnvironmentInitialized ensures the environment is initialized, i.e. it contains values for `AZURE_ENV_NAME`, `AZURE_LOCATION`, `AZURE_SUBSCRIPTION_ID` and `AZURE_PRINCIPAL_ID`. -// prompts for any missing values -func ensureEnvironmentInitialized(ctx context.Context, environmentName string, env *environment.Environment, askOne Asker) error { +// It will use the values from the "environment spec" passed in, and prompt for any missing values as necessary. +// Existing environment value are left unchanged, even if the "spec" has different values. +func ensureEnvironmentInitialized(ctx context.Context, envSpec environmentSpec, env *environment.Environment, askOne Asker) error { if env.Values == nil { env.Values = make(map[string]string) } @@ -169,94 +186,77 @@ func ensureEnvironmentInitialized(ctx context.Context, environmentName string, e } if !hasEnvName { - env.SetEnvName(environmentName) + env.SetEnvName(envSpec.environmentName) } - if !hasSubID || !hasPrincipalID || !hasLocation { + needAzureInteraction := (!hasSubID && envSpec.subscription == "") || + (!hasPrincipalID && envSpec.principalID == "") || + (!hasLocation && envSpec.location == "") + if needAzureInteraction { if err := ensureLoggedIn(ctx); err != nil { return fmt.Errorf("logging in: %w", err) } } if !hasLocation { - var location string - location, err := promptLocation(ctx, "Please select an Azure location to use:", askOne) - if err != nil { - return fmt.Errorf("prompting for location: %w", err) + var location = envSpec.location + if location == "" { + var err error + location, err = promptLocation(ctx, "Please select an Azure location to use:", askOne) + if err != nil { + return fmt.Errorf("prompting for location: %w", err) + } } env.Values[environment.LocationEnvVarName] = strings.TrimSpace(location) } - azCli := commands.GetAzCliFromContext(ctx) - if !hasSubID { - subscriptionInfos, err := azCli.ListAccounts(ctx) - if err != nil { - return fmt.Errorf("listing accounts: %w", err) - } - - sort.Sort(azureutil.Subs(subscriptionInfos)) - - // If `AZURE_SUBSCRIPTION_ID` is set in the environment, use it to influence - // the default option in our prompt. Fall back to the what the `az` CLI is - // configured to use if the environment variable is unset. - defaultSubscriptionId := os.Getenv(environment.SubscriptionIdEnvVarName) - if defaultSubscriptionId == "" { - for _, info := range subscriptionInfos { - if info.IsDefault { - defaultSubscriptionId = info.Id - } - } - } - - var subscriptionOptions = make([]string, len(subscriptionInfos)+1) - var defaultSubscription string - - for index, info := range subscriptionInfos { - subscriptionOptions[index] = fmt.Sprintf("%2d. %s (%s)", index+1, info.Name, info.Id) - - if info.Id == defaultSubscriptionId { - defaultSubscription = subscriptionOptions[index] - } - } - - subscriptionOptions[len(subscriptionOptions)-1] = "Other (enter manually)" - - var subscriptionId string + var subscriptionId string = envSpec.subscription - for env.GetSubscriptionId() == "" { - var subscriptionSelection string - err := askOne(&survey.Select{ - Message: "Please select an Azure Subscription to use:", - Options: subscriptionOptions, - Default: defaultSubscription, - }, &subscriptionSelection) + if subscriptionId == "" { + subscriptionOptions, defaultSubscription, err := getSubscriptionOptions(ctx) if err != nil { - return fmt.Errorf("reading subscription id: %w", err) + return err } - if subscriptionSelection == "Other (enter manually)" { - err = askOne(&survey.Input{ - Message: "Enter an Azure Subscription to use:", - }, &subscriptionId) + + for subscriptionId == "" { + var subscriptionSelection string + err := askOne(&survey.Select{ + Message: "Please select an Azure Subscription to use:", + Options: subscriptionOptions, + Default: defaultSubscription, + }, &subscriptionSelection) if err != nil { return fmt.Errorf("reading subscription id: %w", err) } - } else { - subscriptionId = subscriptionSelection[len(subscriptionSelection)-len("(059cdffa-0e5b-47d8-ad4b-f13fd9099f21)")+1 : len(subscriptionSelection)-1] + if subscriptionSelection == "Other (enter manually)" { + err = askOne(&survey.Input{ + Message: "Enter an Azure Subscription to use:", + }, &subscriptionId) + if err != nil { + return fmt.Errorf("reading subscription id: %w", err) + } + } else { + subscriptionId = subscriptionSelection[len(subscriptionSelection)-len("(059cdffa-0e5b-47d8-ad4b-f13fd9099f21)")+1 : len(subscriptionSelection)-1] + } } - - env.Values[environment.SubscriptionIdEnvVarName] = strings.TrimSpace(subscriptionId) } + + env.Values[environment.SubscriptionIdEnvVarName] = strings.TrimSpace(subscriptionId) } if !hasPrincipalID { - principalId, err := azureutil.GetCurrentPrincipalId(ctx) - if err != nil { - return fmt.Errorf("fetching current user information: %w", err) + principalID := envSpec.principalID + if principalID == "" { + var err error + principalID, err = azureutil.GetCurrentPrincipalId(ctx) + if err != nil { + return fmt.Errorf("fetching current user information: %w", err) + } } - env.Values[environment.PrincipalIdEnvVarName] = principalId + env.Values[environment.PrincipalIdEnvVarName] = principalID } if err := env.Save(); err != nil { @@ -266,6 +266,42 @@ func ensureEnvironmentInitialized(ctx context.Context, environmentName string, e return nil } +func getSubscriptionOptions(ctx context.Context) ([]string, string, error) { + azCli := commands.GetAzCliFromContext(ctx) + subscriptionInfos, err := azCli.ListAccounts(ctx) + if err != nil { + return nil, "", fmt.Errorf("listing accounts: %w", err) + } + + sort.Sort(azureutil.Subs(subscriptionInfos)) + + // If `AZURE_SUBSCRIPTION_ID` is set in the environment, use it to influence + // the default option in our prompt. Fall back to the what the `az` CLI is + // configured to use if the environment variable is unset. + defaultSubscriptionId := os.Getenv(environment.SubscriptionIdEnvVarName) + if defaultSubscriptionId == "" { + for _, info := range subscriptionInfos { + if info.IsDefault { + defaultSubscriptionId = info.Id + } + } + } + + var subscriptionOptions = make([]string, len(subscriptionInfos)+1) + var defaultSubscription string = "" + + for index, info := range subscriptionInfos { + subscriptionOptions[index] = fmt.Sprintf("%2d. %s (%s)", index+1, info.Name, info.Id) + + if info.Id == defaultSubscriptionId { + defaultSubscription = subscriptionOptions[index] + } + } + + subscriptionOptions[len(subscriptionOptions)-1] = manualSubscriptionEntryOption + return subscriptionOptions, defaultSubscription, nil +} + func makeAskOne(noPrompt bool) Asker { if noPrompt { return askOneNoPrompt From 65c75517697dd2394d061d782f1e8e8ba618d123 Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Fri, 22 Jul 2022 10:28:28 -0700 Subject: [PATCH 2/6] Fix cspell dictionary loading --- cli/azd/.vscode/settings.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cli/azd/.vscode/settings.json b/cli/azd/.vscode/settings.json index 9cd86bfdab2..05e5dcc8f52 100644 --- a/cli/azd/.vscode/settings.json +++ b/cli/azd/.vscode/settings.json @@ -2,6 +2,8 @@ "go.testTimeout": "10m", "go.lintTool": "golangci-lint", "go.lintOnSave": "package", - "cSpell.import": ["cspell.yaml"] + "cSpell.import": [ + "${workspaceFolder}/.vscode/cspell.yaml" + ] } From fbca6861a9ce2de59f0332d70529d3753b063102 Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Fri, 22 Jul 2022 10:34:45 -0700 Subject: [PATCH 3/6] Address missed constant use opportunity --- cli/azd/cmd/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/cmd/util.go b/cli/azd/cmd/util.go index dd2cd4a774e..53e7cd298eb 100644 --- a/cli/azd/cmd/util.go +++ b/cli/azd/cmd/util.go @@ -230,7 +230,7 @@ func ensureEnvironmentInitialized(ctx context.Context, envSpec environmentSpec, if err != nil { return fmt.Errorf("reading subscription id: %w", err) } - if subscriptionSelection == "Other (enter manually)" { + if subscriptionSelection == manualSubscriptionEntryOption { err = askOne(&survey.Input{ Message: "Enter an Azure Subscription to use:", }, &subscriptionId) From 5e54aa6db35d0035ac502fa0d541093ee195eb3e Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Mon, 25 Jul 2022 09:50:27 -0700 Subject: [PATCH 4/6] Simplify environment update logic --- cli/azd/cmd/env.go | 3 - cli/azd/cmd/util.go | 87 +++++++++++--------------- cli/azd/pkg/environment/environment.go | 8 +++ 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/cli/azd/cmd/env.go b/cli/azd/cmd/env.go index e3ad3d80855..cd73b026d35 100644 --- a/cli/azd/cmd/env.go +++ b/cli/azd/cmd/env.go @@ -184,13 +184,11 @@ type envNewAction struct { rootOptions *commands.GlobalCommandOptions subscription string location string - principalID string } func (en *envNewAction) SetupFlags(persis *pflag.FlagSet, local *pflag.FlagSet) { local.StringVar(&en.subscription, "subscription", "", "Name or ID of an Azure subscription to use for the new environment") local.StringVarP(&en.location, "location", "l", "", "Azure location for the new environment") - local.StringVar(&en.principalID, "principal", "", "Azure Active Directory principal name or ID to use for the new environment") } func (en *envNewAction) Run(ctx context.Context, _ *cobra.Command, args []string, azdCtx *environment.AzdContext) error { @@ -208,7 +206,6 @@ func (en *envNewAction) Run(ctx context.Context, _ *cobra.Command, args []string environmentName: en.rootOptions.EnvironmentName, subscription: en.subscription, location: en.location, - principalID: en.principalID, } if _, err := createAndInitEnvironment(ctx, &envSpec, azdCtx, askOne); err != nil { return fmt.Errorf("creating new environment: %w", err) diff --git a/cli/azd/cmd/util.go b/cli/azd/cmd/util.go index 53e7cd298eb..45f5ee41845 100644 --- a/cli/azd/cmd/util.go +++ b/cli/azd/cmd/util.go @@ -59,7 +59,6 @@ type environmentSpec struct { environmentName string subscription string location string - principalID string } // createEnvironment creates a new named environment. If an environment with this name already @@ -185,78 +184,68 @@ func ensureEnvironmentInitialized(ctx context.Context, envSpec environmentSpec, return nil } - if !hasEnvName { + if !hasEnvName && envSpec.environmentName != "" { env.SetEnvName(envSpec.environmentName) } - needAzureInteraction := (!hasSubID && envSpec.subscription == "") || - (!hasPrincipalID && envSpec.principalID == "") || - (!hasLocation && envSpec.location == "") + needAzureInteraction := !hasSubID || !hasLocation || !hasPrincipalID if needAzureInteraction { if err := ensureLoggedIn(ctx); err != nil { return fmt.Errorf("logging in: %w", err) } } - if !hasLocation { - var location = envSpec.location - if location == "" { - var err error - location, err = promptLocation(ctx, "Please select an Azure location to use:", askOne) - if err != nil { - return fmt.Errorf("prompting for location: %w", err) - } + if !hasSubID && envSpec.subscription != "" { + env.SetSubscriptionId(envSpec.subscription) + } else { + subscriptionOptions, defaultSubscription, err := getSubscriptionOptions(ctx) + if err != nil { + return err } - env.Values[environment.LocationEnvVarName] = strings.TrimSpace(location) - } - - if !hasSubID { - var subscriptionId string = envSpec.subscription - - if subscriptionId == "" { - subscriptionOptions, defaultSubscription, err := getSubscriptionOptions(ctx) + var subscriptionId = "" + for subscriptionId == "" { + var subscriptionSelection string + err := askOne(&survey.Select{ + Message: "Please select an Azure Subscription to use:", + Options: subscriptionOptions, + Default: defaultSubscription, + }, &subscriptionSelection) if err != nil { - return err + return fmt.Errorf("reading subscription id: %w", err) } - for subscriptionId == "" { - var subscriptionSelection string - err := askOne(&survey.Select{ - Message: "Please select an Azure Subscription to use:", - Options: subscriptionOptions, - Default: defaultSubscription, - }, &subscriptionSelection) + if subscriptionSelection == manualSubscriptionEntryOption { + err = askOne(&survey.Input{ + Message: "Enter an Azure Subscription to use:", + }, &subscriptionId) if err != nil { return fmt.Errorf("reading subscription id: %w", err) } - if subscriptionSelection == manualSubscriptionEntryOption { - err = askOne(&survey.Input{ - Message: "Enter an Azure Subscription to use:", - }, &subscriptionId) - if err != nil { - return fmt.Errorf("reading subscription id: %w", err) - } - } else { - subscriptionId = subscriptionSelection[len(subscriptionSelection)-len("(059cdffa-0e5b-47d8-ad4b-f13fd9099f21)")+1 : len(subscriptionSelection)-1] - } + } else { + subscriptionId = subscriptionSelection[len(subscriptionSelection)-len("(00000000-0000-0000-0000-000000000000)")+1 : len(subscriptionSelection)-1] } } - env.Values[environment.SubscriptionIdEnvVarName] = strings.TrimSpace(subscriptionId) + env.SetSubscriptionId(strings.TrimSpace(subscriptionId)) } - if !hasPrincipalID { - principalID := envSpec.principalID - if principalID == "" { - var err error - principalID, err = azureutil.GetCurrentPrincipalId(ctx) - if err != nil { - return fmt.Errorf("fetching current user information: %w", err) - } + if !hasLocation && envSpec.location != "" { + env.SetLocation(envSpec.location) + } else { + location, err := promptLocation(ctx, "Please select an Azure location to use:", askOne) + if err != nil { + return fmt.Errorf("prompting for location: %w", err) } + env.SetLocation(location) + } - env.Values[environment.PrincipalIdEnvVarName] = principalID + if !hasPrincipalID { + principalID, err := azureutil.GetCurrentPrincipalId(ctx) + if err != nil { + return fmt.Errorf("fetching current user information: %w", err) + } + env.SetPrincipalId(principalID) } if err := env.Save(); err != nil { diff --git a/cli/azd/pkg/environment/environment.go b/cli/azd/pkg/environment/environment.go index 4cba20b1d4a..543a855a45b 100644 --- a/cli/azd/pkg/environment/environment.go +++ b/cli/azd/pkg/environment/environment.go @@ -116,3 +116,11 @@ func (e *Environment) GetTenantId() string { func (e *Environment) SetSubscriptionId(id string) { e.Values[SubscriptionIdEnvVarName] = id } + +func (e *Environment) SetLocation(location string) { + e.Values[LocationEnvVarName] = location +} + +func (e *Environment) SetPrincipalId(principalID string) { + e.Values[PrincipalIdEnvVarName] = principalID +} From 4ddc8870695a822a1aef8e90f377bda333e2df44 Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Mon, 25 Jul 2022 09:56:12 -0700 Subject: [PATCH 5/6] Move code around to simplify the diff --- cli/azd/cmd/util.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cli/azd/cmd/util.go b/cli/azd/cmd/util.go index 45f5ee41845..9c4e4a8409b 100644 --- a/cli/azd/cmd/util.go +++ b/cli/azd/cmd/util.go @@ -195,6 +195,16 @@ func ensureEnvironmentInitialized(ctx context.Context, envSpec environmentSpec, } } + if !hasLocation && envSpec.location != "" { + env.SetLocation(envSpec.location) + } else { + location, err := promptLocation(ctx, "Please select an Azure location to use:", askOne) + if err != nil { + return fmt.Errorf("prompting for location: %w", err) + } + env.SetLocation(strings.TrimSpace(location)) + } + if !hasSubID && envSpec.subscription != "" { env.SetSubscriptionId(envSpec.subscription) } else { @@ -230,16 +240,6 @@ func ensureEnvironmentInitialized(ctx context.Context, envSpec environmentSpec, env.SetSubscriptionId(strings.TrimSpace(subscriptionId)) } - if !hasLocation && envSpec.location != "" { - env.SetLocation(envSpec.location) - } else { - location, err := promptLocation(ctx, "Please select an Azure location to use:", askOne) - if err != nil { - return fmt.Errorf("prompting for location: %w", err) - } - env.SetLocation(location) - } - if !hasPrincipalID { principalID, err := azureutil.GetCurrentPrincipalId(ctx) if err != nil { From cf1aeeaa5d274997d5c2de93e9a8a8982435af38 Mon Sep 17 00:00:00 2001 From: Karol Zadora-Przylecki Date: Mon, 25 Jul 2022 13:12:04 -0700 Subject: [PATCH 6/6] Add subscription and location params to init and up commands --- cli/azd/cmd/init.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/azd/cmd/init.go b/cli/azd/cmd/init.go index f6f06d08dea..baf12051e7d 100644 --- a/cli/azd/cmd/init.go +++ b/cli/azd/cmd/init.go @@ -47,6 +47,8 @@ When a template is provided, the sample code is cloned to the current directory. type initAction struct { template templates.Template templateBranch string + subscription string + location string rootOptions *commands.GlobalCommandOptions } @@ -62,6 +64,8 @@ func (i *initAction) SetupFlags( ) { local.StringVarP(&i.template.Name, "template", "t", "", "The template to use when you initialize the project. You can use Full URI, /, or if it's part of the azure-samples organization.") local.StringVarP(&i.templateBranch, "branch", "b", "", "The template branch to initialize from.") + local.StringVar(&i.subscription, "subscription", "", "Name or ID of an Azure subscription to use for the new environment") + local.StringVarP(&i.location, "location", "l", "", "Azure location for the new environment") } func (i *initAction) Run(ctx context.Context, _ *cobra.Command, args []string, azdCtx *environment.AzdContext) error { @@ -261,6 +265,8 @@ func (i *initAction) Run(ctx context.Context, _ *cobra.Command, args []string, a envSpec := environmentSpec{ environmentName: i.rootOptions.EnvironmentName, + subscription: i.subscription, + location: i.location, } _, err = createAndInitEnvironment(ctx, &envSpec, azdCtx, askOne) if err != nil {