From de0be8650ede28151f2c56f860447a12207e7b34 Mon Sep 17 00:00:00 2001 From: aiordache Date: Fri, 30 Oct 2020 17:42:57 +0100 Subject: [PATCH] Remove region from contexts and cleanup Signed-off-by: aiordache --- cli/cmd/context/create_ecs.go | 5 +- context/store/contextmetadata.go | 1 - ecs/backend.go | 48 ++++----- ecs/context.go | 167 ++++++++++++++----------------- 4 files changed, 101 insertions(+), 120 deletions(-) diff --git a/cli/cmd/context/create_ecs.go b/cli/cmd/context/create_ecs.go index 1b2cd8bcc..3c35ddee6 100644 --- a/cli/cmd/context/create_ecs.go +++ b/cli/cmd/context/create_ecs.go @@ -55,9 +55,8 @@ func createEcsCommand() *cobra.Command { addDescriptionFlag(cmd, &opts.Description) cmd.Flags().BoolVar(&localSimulation, "local-simulation", false, "Create context for ECS local simulation endpoints") - cmd.Flags().StringVar(&opts.Profile, "profile", "", "Profile") - cmd.Flags().StringVar(&opts.Region, "region", "", "Region") - cmd.Flags().BoolVar(&opts.CredsFromEnv, "from-env", false, "Use credentials and region from environment") + cmd.Flags().StringVar(&opts.Profile, "profile", "", "Use an existing AWS profile") + cmd.Flags().BoolVar(&opts.CredsFromEnv, "from-env", false, "Use AWS environment variables for profile, or credentials and region") return cmd } diff --git a/context/store/contextmetadata.go b/context/store/contextmetadata.go index 6bb191117..a34c83131 100644 --- a/context/store/contextmetadata.go +++ b/context/store/contextmetadata.go @@ -53,7 +53,6 @@ type AciContext struct { type EcsContext struct { CredentialsFromEnv bool `json:",omitempty"` Profile string `json:",omitempty"` - Region string `json:",omitempty"` } // AwsContext is the context for the ecs plugin diff --git a/ecs/backend.go b/ecs/backend.go index dacafe1cb..3831ac458 100644 --- a/ecs/backend.go +++ b/ecs/backend.go @@ -43,20 +43,19 @@ type ContextParams struct { Description string AccessKey string SecretKey string - SessionToken string Profile string Region string CredsFromEnv bool } -func (c ContextParams) haveRequiredCredentials() bool { - if c.AccessKey == "" || c.SecretKey == "" { - return false +func (c ContextParams) haveRequiredEnvVars() bool { + if c.Profile != "" { + return true } - if c.Region == "" && c.Profile == "" { - return false + if c.AccessKey != "" && c.SecretKey != "" { + return true } - return true + return false } func init() { @@ -76,29 +75,26 @@ func service(ctx context.Context) (backend.Service, error) { } func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) { - var region string - var profile string + region := "" + profile := ecsCtx.Profile if ecsCtx.CredentialsFromEnv { - creds := getEnvVars() - if !creds.haveRequiredCredentials() { - return nil, fmt.Errorf(`context requires credentials to be passed as environment variable`) - } - region = creds.Region - profile = creds.Profile - } else { - // get region - profile = ecsCtx.Profile - if ecsCtx.Region != "" { - region = ecsCtx.Region - } else { - r, _, err := getRegion(ecsCtx.Profile) - if err != nil { - return nil, err - } - region = r + env := getEnvVars() + if !env.haveRequiredEnvVars() { + return nil, fmt.Errorf("context requires credentials to be passed as environment variables") } + profile = env.Profile + region = env.Region } + + if region == "" { + r, err := getRegion(profile) + if err != nil { + return nil, err + } + region = r + } + sess, err := session.NewSessionWithOptions(session.Options{ Profile: profile, SharedConfigState: session.SharedConfigEnable, diff --git a/ecs/context.go b/ecs/context.go index a23dfc60f..e91e24b01 100644 --- a/ecs/context.go +++ b/ecs/context.go @@ -34,22 +34,16 @@ import ( ) func getEnvVars() ContextParams { - c := ContextParams{} - - //check profile env vars - profile := os.Getenv("AWS_PROFILE") - if profile != "" { - c.Profile = profile + c := ContextParams{ + Profile: os.Getenv("AWS_PROFILE"), + Region: os.Getenv("AWS_REGION"), } - // check REGION env vars - region := os.Getenv("AWS_REGION") - c.Region = region if c.Region == "" { - region = os.Getenv("AWS_DEFAULT_REGION") - if region == "" { - region = "us-east-1" + defaultRegion := os.Getenv("AWS_DEFAULT_REGION") + if defaultRegion == "" { + defaultRegion = "us-east-1" } - c.Region = region + c.Region = defaultRegion } p := credentials.EnvProvider{} @@ -59,7 +53,6 @@ func getEnvVars() ContextParams { } c.AccessKey = creds.AccessKeyID c.SecretKey = creds.SecretAccessKey - c.SessionToken = creds.SessionToken return c } @@ -73,31 +66,6 @@ func newContextCreateHelper() contextCreateAWSHelper { } } -func (h contextCreateAWSHelper) createProfile(name string, c *ContextParams) error { - if c != nil { - if c.AccessKey != "" && c.SecretKey != "" { - return h.saveCredentials(name, c.AccessKey, c.SecretKey) - } - accessKey, secretKey, err := h.askCredentials() - - if err != nil { - return err - } - c.AccessKey = accessKey - c.SecretKey = secretKey - return h.saveCredentials(name, c.AccessKey, c.SecretKey) - } - - accessKey, secretKey, err := h.askCredentials() - if err != nil { - return err - } - if accessKey != "" && secretKey != "" { - return h.saveCredentials(name, accessKey, secretKey) - } - return nil -} - func (h contextCreateAWSHelper) createContext(c *ContextParams) (interface{}, string) { if c.Profile == "default" { c.Profile = "" @@ -111,7 +79,6 @@ func (h contextCreateAWSHelper) createContext(c *ContextParams) (interface{}, st return store.EcsContext{ CredentialsFromEnv: c.CredsFromEnv, Profile: c.Profile, - Region: c.Region, }, description } @@ -121,7 +88,6 @@ func (h contextCreateAWSHelper) createContext(c *ContextParams) (interface{}, st } return store.EcsContext{ Profile: c.Profile, - Region: c.Region, }, description } @@ -130,28 +96,8 @@ func (h contextCreateAWSHelper) selectFromLocalProfile(opts *ContextParams) erro if err != nil { return err } - // choose profile opts.Profile, err = h.chooseProfile(profilesList) - if err != nil { - return err - } - - if opts.Region == "" { - region, isDefinedInProfile, err := getRegion(opts.Profile) - if err != nil { - return err - } - if isDefinedInProfile { - opts.Region = region - } else { - fmt.Println("No region defined in the profile. Choose the region to use.") - opts.Region, err = h.chooseRegion(opts.Region, opts.Profile) - if err != nil { - return err - } - } - } - return nil + return err } func (h contextCreateAWSHelper) createProfileFromCredentials(opts *ContextParams) error { @@ -171,8 +117,21 @@ func (h contextCreateAWSHelper) createProfileFromCredentials(opts *ContextParams if opts.Profile == "" { opts.Profile = opts.Name } - fmt.Printf("Saving credentials under profile %s\n", opts.Profile) - return h.createProfile(opts.Profile, opts) + // check profile does not already exist + profilesList, err := getProfiles() + if err != nil { + return err + } + if contains(profilesList, opts.Profile) { + return fmt.Errorf("profile %q already exists", opts.Profile) + } + fmt.Printf("Saving to profile %q\n", opts.Profile) + // context name used as profile name + err = h.saveCredentials(opts.Name, opts.AccessKey, opts.SecretKey) + if err != nil { + return err + } + return h.saveRegion(opts.Name, opts.Region) } func (h contextCreateAWSHelper) createContextData(_ context.Context, opts ContextParams) (interface{}, string, error) { @@ -181,12 +140,12 @@ func (h contextCreateAWSHelper) createContextData(_ context.Context, opts Contex return ecsCtx, descr, nil } options := []string{ - "Use AWS credentials from environment", - "Select from existing AWS profiles", - "Create new profile from AWS credentials", + "An existing AWS profile", + "A new AWS profile", + "AWS environment variables", } - selected, err := h.user.Select("Would you like to create your context based on", options) + selected, err := h.user.Select("Create a Docker context using:", options) if err != nil { if err == terminal.InterruptErr { return nil, "", errdefs.ErrCanceled @@ -196,12 +155,12 @@ func (h contextCreateAWSHelper) createContextData(_ context.Context, opts Contex switch selected { case 0: - opts.CredsFromEnv = true - case 1: err = h.selectFromLocalProfile(&opts) - - case 2: + case 1: err = h.createProfileFromCredentials(&opts) + case 2: + opts.CredsFromEnv = true + } if err != nil { return nil, "", err @@ -242,6 +201,38 @@ func (h contextCreateAWSHelper) saveCredentials(profile string, accessKeyID stri return credIni.SaveTo(p.Filename) } +func (h contextCreateAWSHelper) saveRegion(profile, region string) error { + if region == "" { + return nil + } + // loads ~/.aws/config + awsConfig := defaults.SharedConfigFilename() + configIni, err := ini.Load(awsConfig) + if err != nil { + if !os.IsNotExist(err) { + return err + } + configIni = ini.Empty() + } + profile = fmt.Sprintf("profile %s", profile) + section, err := configIni.GetSection(profile) + if err != nil { + if !strings.Contains(err.Error(), "does not exist") { + return err + } + section, err = configIni.NewSection(profile) + if err != nil { + return err + } + } + // save region under profile section in ~/.aws/config + _, err = section.NewKey("region", region) + if err != nil { + return err + } + return configIni.SaveTo(awsConfig) +} + func getProfiles() ([]string, error) { profiles := []string{} // parse both .aws/credentials and .aws/config for profiles @@ -282,7 +273,7 @@ func (h contextCreateAWSHelper) chooseProfile(profiles []string) (string, error) return profile, nil } -func getRegion(profile string) (string, bool, error) { +func getRegion(profile string) (string, error) { if profile == "" { profile = "default" } @@ -291,13 +282,12 @@ func getRegion(profile string) (string, bool, error) { configIni, err := ini.Load(awsConfig) if err != nil { if !os.IsNotExist(err) { - return "", false, err + return "", err } configIni = ini.Empty() } - var f func(string) (string, string) - f = func(p string) (string, string) { + getProfileRegion := func(p string) string { r := "" section, err := configIni.GetSection(p) if err == nil { @@ -306,29 +296,26 @@ func getRegion(profile string) (string, bool, error) { r = reg.Value() } } - if r == "" { - switch p { - case "": - return "us-east-1", "" - case "default": - return f("") - } - return f("default") - } - return r, p + return r } - if profile != "default" { profile = fmt.Sprintf("profile %s", profile) } - region, p := f(profile) - return region, p == profile, nil + region := getProfileRegion(profile) + if region == "" { + region = getProfileRegion("default") + if region == "" { + return "us-east-1", nil + } + return region, nil + } + return region, nil } func (h contextCreateAWSHelper) chooseRegion(region string, profile string) (string, error) { suggestion := region if suggestion == "" { - region, _, err := getRegion(profile) + region, err := getRegion(profile) if err != nil { return "", err }