Browse Source

refactor ecs context creation

Signed-off-by: aiordache <[email protected]>
aiordache 5 years ago
parent
commit
2dcd1a5826
3 changed files with 133 additions and 20 deletions
  1. 1 0
      cli/cmd/context/create_ecs.go
  2. 1 0
      ecs/backend.go
  3. 131 20
      ecs/context.go

+ 1 - 0
cli/cmd/context/create_ecs.go

@@ -45,6 +45,7 @@ func createEcsCommand() *cobra.Command {
 		Short: "Create a context for Amazon ECS",
 		Args:  cobra.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
+			opts.Name = args[0]
 			if localSimulation {
 				return runCreateLocalSimulation(cmd.Context(), args[0], opts)
 			}

+ 1 - 0
ecs/backend.go

@@ -38,6 +38,7 @@ const backendType = store.EcsContextType
 
 // ContextParams options for creating AWS context
 type ContextParams struct {
+	Name        string
 	Description string
 	Region      string
 	Profile     string

+ 131 - 20
ecs/context.go

@@ -26,7 +26,6 @@ import (
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/defaults"
-	"github.com/pkg/errors"
 	"gopkg.in/ini.v1"
 
 	"github.com/docker/compose-cli/context/store"
@@ -34,6 +33,21 @@ import (
 	"github.com/docker/compose-cli/prompt"
 )
 
+type contextElements struct {
+	AccessKey    string
+	SecretKey    string
+	SessionToken string
+	Profile      string
+	Region       string
+}
+
+func (c contextElements) HaveRequiredProps() bool {
+	if c.AccessKey != "" && c.SecretKey != "" { //} && c.Region != "" {
+		return true
+	}
+	return false
+}
+
 type contextCreateAWSHelper struct {
 	user prompt.UI
 }
@@ -44,7 +58,21 @@ func newContextCreateHelper() contextCreateAWSHelper {
 	}
 }
 
-func (h contextCreateAWSHelper) createProfile(name string) error {
+func (h contextCreateAWSHelper) createProfile(name string, c *contextElements) 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
@@ -67,33 +95,114 @@ func (h contextCreateAWSHelper) createContext(profile, region, description strin
 	}, description
 }
 
+func (h contextCreateAWSHelper) ParseEnvVars(c *contextElements) {
+	profile := os.Getenv("AWS_PROFILE")
+	if profile != "" {
+		c.Profile = profile
+	}
+	region := os.Getenv("AWS_REGION")
+	if region != "" {
+		c.Region = region
+	}
+
+	p := credentials.EnvProvider{}
+	creds, err := p.Retrieve()
+	if err != nil {
+		return
+	}
+	c.AccessKey = creds.AccessKeyID
+	c.SecretKey = creds.SecretAccessKey
+	c.SessionToken = creds.SessionToken
+}
+
 func (h contextCreateAWSHelper) createContextData(_ context.Context, opts ContextParams) (interface{}, string, error) {
-	profile := opts.Profile
-	region := opts.Region
+	creds := contextElements{}
 
-	profilesList, err := h.getProfiles()
+	h.ParseEnvVars(&creds)
+
+	options := []string{}
+	if creds.HaveRequiredProps() {
+		options = append(options, "existing AWS environment variables (detected credentials)")
+	}
+	options = append(options, "enter AWS credentials", "use an AWS profile or create a new profile (advanced)")
+	selected, err := h.user.Select("Would you like to create your context based on", options)
 	if err != nil {
+		if err == terminal.InterruptErr {
+			return nil, "", errdefs.ErrCanceled
+		}
 		return nil, "", err
 	}
-	if profile != "" {
-		// validate profile
-		if profile != "default" && !contains(profilesList, profile) {
-			return nil, "", errors.Wrapf(errdefs.ErrNotFound, "profile %q", profile)
+
+	if len(options) == 2 {
+		selected = selected + 1
+	}
+	if selected != 0 {
+		creds = contextElements{}
+	}
+
+	if creds.Region == "" {
+		creds.Region = opts.Region
+	}
+	if creds.Profile == "" {
+		creds.Profile = opts.Profile
+	}
+
+	switch selected {
+	case 0:
+		if creds.Region == "" {
+			// prompt for the region to use with this context
+			creds.Region, err = h.chooseRegion(creds.Region, creds.Profile)
+			if err != nil {
+				return nil, "", err
+			}
 		}
-	} else {
-		// choose profile
-		profile, err = h.chooseProfile(profilesList)
+		if creds.Profile == "" {
+			creds.Profile = opts.Name
+
+		}
+		fmt.Printf("Saving credentials under profile %s\n", creds.Profile)
+		h.createProfile(creds.Profile, &creds)
+	case 1:
+		accessKey, secretKey, err := h.askCredentials()
 		if err != nil {
 			return nil, "", err
 		}
-	}
-	if region == "" {
-		region, err = h.chooseRegion(region, profile)
+		creds.AccessKey = accessKey
+		creds.SecretKey = secretKey
+		// we need a region set -- either read it from profile or prompt user
+
+		// prompt for the region to use with this context
+		creds.Region, err = h.chooseRegion(creds.Region, creds.Profile)
 		if err != nil {
 			return nil, "", err
 		}
+		// save as a profile
+		if creds.Profile == "" {
+			creds.Profile = opts.Name
+		}
+		fmt.Printf("Saving credentials under profile %s\n", creds.Profile)
+		h.createProfile(creds.Profile, &creds)
+
+	case 2:
+		profilesList, err := h.getProfiles()
+		if err != nil {
+			return nil, "", err
+		}
+		// choose profile
+		creds.Profile, err = h.chooseProfile(profilesList)
+		if err != nil {
+			return nil, "", err
+		}
+		if creds.Region == "" {
+			creds.Region, err = h.chooseRegion(creds.Region, creds.Profile)
+			if err != nil {
+				return nil, "", err
+			}
+		}
 	}
-	ecsCtx, descr := h.createContext(profile, region, opts.Description)
+
+	os.Exit(0)
+	ecsCtx, descr := h.createContext(creds.Profile, creds.Region, opts.Description)
 	return ecsCtx, descr, nil
 }
 
@@ -178,14 +287,16 @@ func (h contextCreateAWSHelper) chooseProfile(profiles []string) (string, error)
 		if name == "" {
 			return "", fmt.Errorf("profile name cannot be empty")
 		}
-		return name, h.createProfile(name)
+		return name, h.createProfile(name, nil)
 	}
 	return profile, nil
 }
 
 func (h contextCreateAWSHelper) chooseRegion(region string, profile string) (string, error) {
 	suggestion := region
-
+	if profile == "" {
+		profile = "default"
+	}
 	// only load ~/.aws/config
 	awsConfig := defaults.SharedConfigFilename()
 	configIni, err := ini.Load(awsConfig)
@@ -230,13 +341,13 @@ func (h contextCreateAWSHelper) chooseRegion(region string, profile string) (str
 }
 
 func (h contextCreateAWSHelper) askCredentials() (string, string, error) {
-	confirm, err := h.user.Confirm("Enter AWS credentials", false)
+	/*confirm, err := h.user.Confirm("Enter AWS credentials", false)
 	if err != nil {
 		return "", "", err
 	}
 	if !confirm {
 		return "", "", nil
-	}
+	}*/
 
 	accessKeyID, err := h.user.Input("AWS Access Key ID", "")
 	if err != nil {