Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add profile flag to root init command #642

Merged
merged 6 commits into from
Feb 17, 2020

Conversation

bvtujo
Copy link
Contributor

@bvtujo bvtujo commented Feb 7, 2020

Resolves #317

Adds a profile flag to root init command to be used by the implicit call to env init.
If no profile is specified and the user opts to deploy a test env, prompt them to select from the list of available profiles. If a profile is specified, deploy the test env into that profile.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

This commit adds a profile flag to `ecs-preview init` which is passed
into the implicit call to `ecs-preview env init`. If the user does not
specify a profile, ask them to select a profile.
@bvtujo bvtujo requested a review from a team as a code owner February 7, 2020 01:07
@bvtujo
Copy link
Contributor Author

bvtujo commented Feb 7, 2020

More unit tests forthcoming once I dig more into how mocks work

@@ -221,6 +227,9 @@ func (o *initOpts) deployEnv() error {
// User chose not to deploy the application, exit.
return nil
}
if err := o.initEnv.Ask(); err != nil {
Copy link
Contributor

@iamhopaul123 iamhopaul123 Feb 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we need this. initEnv.Ask() is used to get EnvName and EnvProfile in an interactive way. However, init by default (if not pass in value using flags) is supposed to provide an easy way for users to spin up their apps easily. That's the reason why we default EnvName to be "test" and EnvProfile to be "default" since in most cases for new projects they are set to be these values.

Also we always have value for EnvName, the Ask() command is just used to get the profile name (asking for env name will be skipped).

@@ -274,6 +283,7 @@ func BuildInitCmd() *cobra.Command {
return nil
}),
}
cmd.Flags().StringVar(&vars.profile, profileFlag, "", profileFlagDescription)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be nice to give default value for the flag as "default" so that we can remove the initEnv.Ask() and simplify the workflow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, we can set that default in init but leave it empty in env init

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if we set the default value for the flag to be "default" then in the initEnv.Ask() it won't ask user to select since o.EnvProfile will not be an empty string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make this change, but I'd like to make sure we document it somewhere. Is there a good spot that we can stick a line in the env init calls that will remind the user "hey, this will deploy to your default profile; if that's not cool, choose no and then run env deploy later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could simply modify the initShouldDeployPrompt to the following:
"Would you like to deploy a test environment? (This will deploy to your default profile if not otherwise specified with the --profile flag)" but that's not dynamic, and it seems like we could do better by only printing off a warning line when the user hasn't specified a profile.

@iamhopaul123 iamhopaul123 requested a review from a team February 11, 2020 18:05
@@ -77,10 +78,15 @@ func newInitOpts(vars initVars) (*initOpts, error) {
if err != nil {
return nil, err
}
profileSess, err := sessProvider.FromProfile(vars.profile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason why this doesn't error when vars.profile="" is this:

// If not set and environment variables are not set the "default"
// (DefaultSharedConfigProfile) will be used as the profile to load the
// session config from.

So right now it's creating a session with the default profile which is slightly misleading.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intuition says that we should just not set this field until o.initEnv.Ask() is executed.

@@ -221,6 +227,9 @@ func (o *initOpts) deployEnv() error {
// User chose not to deploy the application, exit.
return nil
}
if err := o.initEnv.Ask(); err != nil {
return err
}
return o.initEnv.Execute()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While trying to understand how come this worked, I realized that we have a bug in "env init" :|

Right now the value from askEnvProfile in env_init.go gets ignored inside Execute. So even if you choose a different profile than "default", we pick up only "default".
https://github.com/aws/amazon-ecs-cli-v2/blob/b223142e566e3bd123b541ff8cc500d4b3a113fb/internal/pkg/cli/env_init.go#L120

We should change the code so that we initialize envDeployer and envIdentity only after the EnvProfile value is set.

Here is a sample way of how to do it in env_delete.go:
https://github.com/aws/amazon-ecs-cli-v2/blob/b223142e566e3bd123b541ff8cc500d4b3a113fb/internal/pkg/cli/env_delete.go#L60

@bvtujo
Copy link
Contributor Author

bvtujo commented Feb 15, 2020

Behavior has been updated to not ask for a profile when running ecs-preview init without a profile flag specified.

I've also refactored the existing env deploy code to only initialize profile clients AFTER the user is prompted for a profile to deploy to, right at the beginning of Execute.

This seems to work; I was able to get ecs-preview init --profile personal to deploy test to my personal aws account.

Is there a way to avoid repeating myself in the initProfileClients method?

@efekarakus efekarakus changed the title feat: Add profile flag to root init command feat: add profile flag to root init command Feb 17, 2020
Copy link
Contributor

@iamhopaul123 iamhopaul123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM except that we need to find a good way to avoid the repetition.

profileConfig: cfg,
prog: spin,
identity: id,

initProfileClients: func(o *initEnvOpts) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure but maybe we can define this function outside of the struct to make it a variable so that we can reuse that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 yeah like @iamhopaul123 says, we can do:

var initEnvProfileClients = func(o *initEnvOpts) error {
   // your function
}

and then while initializing the structs:

   initProfileClients: initEnvProfileClients,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in the latest commit.

Copy link
Contributor

@efekarakus efekarakus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good thank you!

initProfileClients: func(o *initEnvOpts) error {
profileSess, err := session.NewProvider().FromProfile(o.EnvProfile)
if err != nil {
return fmt.Errorf("Cannot create session from profile %s: %w", o.EnvProfile, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return fmt.Errorf("Cannot create session from profile %s: %w", o.EnvProfile, err)
return fmt.Errorf("create session from profile %s: %w", o.EnvProfile, err)

The recommended guideline for error strings from Go:

Error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation, since they are usually printed following other context.

https://github.com/golang/go/wiki/CodeReviewComments#error-strings

Another one that we follow is avoiding words like "failed" or "cannot" in error strings as usually they're redundant in the context of errors :)

https://github.com/uber-go/guide/blob/master/style.md#error-wrapping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, thanks for the links!

Copy link
Contributor

@efekarakus efekarakus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Contributor

@iamhopaul123 iamhopaul123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@bvtujo bvtujo merged commit b369d1e into aws:master Feb 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Init workflow missing profile flag
3 participants