mirror of
https://github.com/docker/compose.git
synced 2025-07-23 21:54:40 +02:00
Merge pull request #846 from docker/ecs_context
This commit is contained in:
commit
f66123b34a
@ -18,6 +18,7 @@ package context
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -45,6 +46,10 @@ func createEcsCommand() *cobra.Command {
|
|||||||
Short: "Create a context for Amazon ECS",
|
Short: "Create a context for Amazon ECS",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
opts.Name = args[0]
|
||||||
|
if opts.CredsFromEnv && opts.Profile != "" {
|
||||||
|
return fmt.Errorf("--profile and --from-env flags cannot be set at the same time")
|
||||||
|
}
|
||||||
if localSimulation {
|
if localSimulation {
|
||||||
return runCreateLocalSimulation(cmd.Context(), args[0], opts)
|
return runCreateLocalSimulation(cmd.Context(), args[0], opts)
|
||||||
}
|
}
|
||||||
@ -54,8 +59,8 @@ func createEcsCommand() *cobra.Command {
|
|||||||
|
|
||||||
addDescriptionFlag(cmd, &opts.Description)
|
addDescriptionFlag(cmd, &opts.Description)
|
||||||
cmd.Flags().BoolVar(&localSimulation, "local-simulation", false, "Create context for ECS local simulation endpoints")
|
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.Profile, "profile", "", "Use an existing AWS profile")
|
||||||
cmd.Flags().StringVar(&opts.Region, "region", "", "Region")
|
cmd.Flags().BoolVar(&opts.CredsFromEnv, "from-env", false, "Use AWS environment variables for profile, or credentials and region")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ type AciContext struct {
|
|||||||
|
|
||||||
// EcsContext is the context for the AWS backend
|
// EcsContext is the context for the AWS backend
|
||||||
type EcsContext struct {
|
type EcsContext struct {
|
||||||
Profile string `json:",omitempty"`
|
CredentialsFromEnv bool `json:",omitempty"`
|
||||||
Region string `json:",omitempty"`
|
Profile string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AwsContext is the context for the ecs plugin
|
// AwsContext is the context for the ecs plugin
|
||||||
|
@ -18,6 +18,7 @@ package ecs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/compose"
|
"github.com/docker/compose-cli/api/compose"
|
||||||
"github.com/docker/compose-cli/api/containers"
|
"github.com/docker/compose-cli/api/containers"
|
||||||
@ -38,9 +39,23 @@ const backendType = store.EcsContextType
|
|||||||
|
|
||||||
// ContextParams options for creating AWS context
|
// ContextParams options for creating AWS context
|
||||||
type ContextParams struct {
|
type ContextParams struct {
|
||||||
Description string
|
Name string
|
||||||
Region string
|
Description string
|
||||||
Profile string
|
AccessKey string
|
||||||
|
SecretKey string
|
||||||
|
Profile string
|
||||||
|
Region string
|
||||||
|
CredsFromEnv bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c ContextParams) haveRequiredEnvVars() bool {
|
||||||
|
if c.Profile != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c.AccessKey != "" && c.SecretKey != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -60,11 +75,31 @@ func service(ctx context.Context) (backend.Service, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) {
|
func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) {
|
||||||
|
region := ""
|
||||||
|
profile := ecsCtx.Profile
|
||||||
|
|
||||||
|
if ecsCtx.CredentialsFromEnv {
|
||||||
|
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{
|
sess, err := session.NewSessionWithOptions(session.Options{
|
||||||
Profile: ecsCtx.Profile,
|
Profile: profile,
|
||||||
SharedConfigState: session.SharedConfigEnable,
|
SharedConfigState: session.SharedConfigEnable,
|
||||||
Config: aws.Config{
|
Config: aws.Config{
|
||||||
Region: aws.String(ecsCtx.Region),
|
Region: aws.String(region),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -74,7 +109,7 @@ func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) {
|
|||||||
sdk := newSDK(sess)
|
sdk := newSDK(sess)
|
||||||
return &ecsAPIService{
|
return &ecsAPIService{
|
||||||
ctx: ecsCtx,
|
ctx: ecsCtx,
|
||||||
Region: ecsCtx.Region,
|
Region: region,
|
||||||
aws: sdk,
|
aws: sdk,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
374
ecs/context.go
374
ecs/context.go
@ -20,100 +20,186 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2/terminal"
|
|
||||||
"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"
|
"github.com/docker/compose-cli/context/store"
|
||||||
"github.com/docker/compose-cli/errdefs"
|
"github.com/docker/compose-cli/errdefs"
|
||||||
"github.com/docker/compose-cli/prompt"
|
"github.com/docker/compose-cli/prompt"
|
||||||
|
|
||||||
|
"github.com/AlecAivazis/survey/v2/terminal"
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getEnvVars() ContextParams {
|
||||||
|
c := ContextParams{
|
||||||
|
Profile: os.Getenv("AWS_PROFILE"),
|
||||||
|
Region: os.Getenv("AWS_REGION"),
|
||||||
|
}
|
||||||
|
if c.Region == "" {
|
||||||
|
defaultRegion := os.Getenv("AWS_DEFAULT_REGION")
|
||||||
|
if defaultRegion == "" {
|
||||||
|
defaultRegion = "us-east-1"
|
||||||
|
}
|
||||||
|
c.Region = defaultRegion
|
||||||
|
}
|
||||||
|
|
||||||
|
p := credentials.EnvProvider{}
|
||||||
|
creds, err := p.Retrieve()
|
||||||
|
if err != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
c.AccessKey = creds.AccessKeyID
|
||||||
|
c.SecretKey = creds.SecretAccessKey
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
type contextCreateAWSHelper struct {
|
type contextCreateAWSHelper struct {
|
||||||
user prompt.UI
|
user prompt.UI
|
||||||
|
availableRegions func(opts *ContextParams) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContextCreateHelper() contextCreateAWSHelper {
|
func newContextCreateHelper() contextCreateAWSHelper {
|
||||||
return contextCreateAWSHelper{
|
return contextCreateAWSHelper{
|
||||||
user: prompt.User{},
|
user: prompt.User{},
|
||||||
|
availableRegions: listAvailableRegions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) createProfile(name string) error {
|
|
||||||
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(profile, region, description string) (interface{}, string) {
|
|
||||||
if profile == "default" {
|
|
||||||
profile = ""
|
|
||||||
}
|
|
||||||
description = strings.TrimSpace(
|
|
||||||
fmt.Sprintf("%s (%s)", description, region))
|
|
||||||
return store.EcsContext{
|
|
||||||
Profile: profile,
|
|
||||||
Region: region,
|
|
||||||
}, description
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) createContextData(_ context.Context, opts ContextParams) (interface{}, string, error) {
|
func (h contextCreateAWSHelper) createContextData(_ context.Context, opts ContextParams) (interface{}, string, error) {
|
||||||
profile := opts.Profile
|
if opts.CredsFromEnv {
|
||||||
region := opts.Region
|
// Explicit creation from ENV variables
|
||||||
|
ecsCtx, descr := h.createContext(&opts)
|
||||||
profilesList, err := h.getProfiles()
|
return ecsCtx, descr, nil
|
||||||
if err != nil {
|
} else if opts.AccessKey != "" && opts.SecretKey != "" {
|
||||||
return nil, "", err
|
// Explicit creation using keys
|
||||||
}
|
err := h.createProfileFromCredentials(&opts)
|
||||||
if profile != "" {
|
if err != nil {
|
||||||
// validate profile
|
return nil, "", err
|
||||||
if profile != "default" && !contains(profilesList, profile) {
|
}
|
||||||
return nil, "", errors.Wrapf(errdefs.ErrNotFound, "profile %q", profile)
|
} else if opts.Profile != "" {
|
||||||
|
// Excplicit creation by selecting a profile
|
||||||
|
// check profile exists
|
||||||
|
profilesList, err := getProfiles()
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
if !contains(profilesList, opts.Profile) {
|
||||||
|
return nil, "", errors.Wrapf(errdefs.ErrNotFound, "profile %q not found", opts.Profile)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// choose profile
|
// interactive
|
||||||
profile, err = h.chooseProfile(profilesList)
|
var options []string
|
||||||
|
var actions []func(params *ContextParams) error
|
||||||
|
|
||||||
|
if _, err := os.Stat(getAWSConfigFile()); err == nil {
|
||||||
|
// User has .aws/config file, so we can offer to select one of his profiles
|
||||||
|
options = append(options, "An existing AWS profile")
|
||||||
|
actions = append(actions, h.selectFromLocalProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
options = append(options, "AWS secret and token credentials")
|
||||||
|
actions = append(actions, h.createProfileFromCredentials)
|
||||||
|
|
||||||
|
options = append(options, "AWS environment variables")
|
||||||
|
actions = append(actions, func(params *ContextParams) error {
|
||||||
|
opts.CredsFromEnv = true
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
selected, err := h.user.Select("Create a Docker context using:", options)
|
||||||
|
if err != nil {
|
||||||
|
if err == terminal.InterruptErr {
|
||||||
|
return nil, "", errdefs.ErrCanceled
|
||||||
|
}
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = actions[selected](&opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if region == "" {
|
|
||||||
region, err = h.chooseRegion(region, profile)
|
ecsCtx, descr := h.createContext(&opts)
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ecsCtx, descr := h.createContext(profile, region, opts.Description)
|
|
||||||
return ecsCtx, descr, nil
|
return ecsCtx, descr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) saveCredentials(profile string, accessKeyID string, secretAccessKey string) error {
|
func (h contextCreateAWSHelper) createContext(c *ContextParams) (interface{}, string) {
|
||||||
p := credentials.SharedCredentialsProvider{Profile: profile}
|
var description string
|
||||||
_, err := p.Retrieve()
|
|
||||||
if err == nil {
|
if c.CredsFromEnv {
|
||||||
return fmt.Errorf("credentials already exist")
|
if c.Description == "" {
|
||||||
|
description = "credentials read from environment"
|
||||||
|
}
|
||||||
|
return store.EcsContext{
|
||||||
|
CredentialsFromEnv: c.CredsFromEnv,
|
||||||
|
Profile: c.Profile,
|
||||||
|
}, description
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.(awserr.Error).Code() == "SharedCredsLoad" && err.(awserr.Error).Message() == "failed to load shared credentials file" {
|
if c.Region != "" {
|
||||||
_, err := os.Create(p.Filename)
|
description = strings.TrimSpace(
|
||||||
|
fmt.Sprintf("%s (%s)", c.Description, c.Region))
|
||||||
|
}
|
||||||
|
return store.EcsContext{
|
||||||
|
Profile: c.Profile,
|
||||||
|
}, description
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h contextCreateAWSHelper) selectFromLocalProfile(opts *ContextParams) error {
|
||||||
|
profilesList, err := getProfiles()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.Profile, err = h.chooseProfile(profilesList)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h contextCreateAWSHelper) createProfileFromCredentials(opts *ContextParams) error {
|
||||||
|
if opts.AccessKey == "" || opts.SecretKey == "" {
|
||||||
|
fmt.Println("Retrieve or create AWS Access Key and Secret on https://console.aws.amazon.com/iam/home?#security_credential")
|
||||||
|
accessKey, secretKey, err := h.askCredentials()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.AccessKey = accessKey
|
||||||
|
opts.SecretKey = secretKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Region == "" {
|
||||||
|
err := h.chooseRegion(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
credIni, err := ini.Load(p.Filename)
|
// save as a profile
|
||||||
|
if opts.Profile == "" {
|
||||||
|
opts.Profile = "default"
|
||||||
|
}
|
||||||
|
// context name used as profile name
|
||||||
|
err := h.saveCredentials(opts.Profile, opts.AccessKey, opts.SecretKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return h.saveRegion(opts.Profile, opts.Region)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h contextCreateAWSHelper) saveCredentials(profile string, accessKeyID string, secretAccessKey string) error {
|
||||||
|
file := getAWSCredentialsFile()
|
||||||
|
err := os.MkdirAll(filepath.Dir(file), 0700)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
credIni := ini.Empty()
|
||||||
section, err := credIni.NewSection(profile)
|
section, err := credIni.NewSection(profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -126,15 +212,47 @@ func (h contextCreateAWSHelper) saveCredentials(profile string, accessKeyID stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return credIni.SaveTo(p.Filename)
|
return credIni.SaveTo(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) getProfiles() ([]string, error) {
|
func (h contextCreateAWSHelper) saveRegion(profile, region string) error {
|
||||||
|
if region == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// loads ~/.aws/config
|
||||||
|
awsConfig := getAWSConfigFile()
|
||||||
|
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{}
|
profiles := []string{}
|
||||||
// parse both .aws/credentials and .aws/config for profiles
|
// parse both .aws/credentials and .aws/config for profiles
|
||||||
configFiles := map[string]bool{
|
configFiles := map[string]bool{
|
||||||
defaults.SharedCredentialsFilename(): false,
|
getAWSCredentialsFile(): false,
|
||||||
defaults.SharedConfigFilename(): true,
|
getAWSConfigFile(): true,
|
||||||
}
|
}
|
||||||
for f, prefix := range configFiles {
|
for f, prefix := range configFiles {
|
||||||
sections, err := loadIniFile(f, prefix)
|
sections, err := loadIniFile(f, prefix)
|
||||||
@ -151,11 +269,15 @@ func (h contextCreateAWSHelper) getProfiles() ([]string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sort.Slice(profiles, func(i, j int) bool {
|
||||||
|
return profiles[i] < profiles[j]
|
||||||
|
})
|
||||||
|
|
||||||
return profiles, nil
|
return profiles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) chooseProfile(profiles []string) (string, error) {
|
func (h contextCreateAWSHelper) chooseProfile(profiles []string) (string, error) {
|
||||||
options := []string{"new profile"}
|
options := []string{}
|
||||||
options = append(options, profiles...)
|
options = append(options, profiles...)
|
||||||
|
|
||||||
selected, err := h.user.Select("Select AWS Profile", options)
|
selected, err := h.user.Select("Select AWS Profile", options)
|
||||||
@ -166,78 +288,86 @@ func (h contextCreateAWSHelper) chooseProfile(profiles []string) (string, error)
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
profile := options[selected]
|
profile := options[selected]
|
||||||
if options[selected] == "new profile" {
|
|
||||||
suggestion := ""
|
|
||||||
if !contains(profiles, "default") {
|
|
||||||
suggestion = "default"
|
|
||||||
}
|
|
||||||
name, err := h.user.Input("profile name", suggestion)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if name == "" {
|
|
||||||
return "", fmt.Errorf("profile name cannot be empty")
|
|
||||||
}
|
|
||||||
return name, h.createProfile(name)
|
|
||||||
}
|
|
||||||
return profile, nil
|
return profile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) chooseRegion(region string, profile string) (string, error) {
|
func getRegion(profile string) (string, error) {
|
||||||
suggestion := region
|
if profile == "" {
|
||||||
|
profile = "default"
|
||||||
|
}
|
||||||
// only load ~/.aws/config
|
// only load ~/.aws/config
|
||||||
awsConfig := defaults.SharedConfigFilename()
|
awsConfig := defaults.SharedConfigFilename()
|
||||||
configIni, err := ini.Load(awsConfig)
|
configIni, err := ini.Load(awsConfig)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
configIni = ini.Empty()
|
configIni = ini.Empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProfileRegion := func(p string) string {
|
||||||
|
r := ""
|
||||||
|
section, err := configIni.GetSection(p)
|
||||||
|
if err == nil {
|
||||||
|
reg, err := section.GetKey("region")
|
||||||
|
if err == nil {
|
||||||
|
r = reg.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
if profile != "default" {
|
if profile != "default" {
|
||||||
profile = fmt.Sprintf("profile %s", profile)
|
profile = fmt.Sprintf("profile %s", profile)
|
||||||
}
|
}
|
||||||
section, err := configIni.GetSection(profile)
|
region := getProfileRegion(profile)
|
||||||
if err != nil {
|
if region == "" {
|
||||||
if !strings.Contains(err.Error(), "does not exist") {
|
region = getProfileRegion("default")
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
section, err = configIni.NewSection(profile)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reg, err := section.GetKey("region")
|
|
||||||
if err == nil {
|
|
||||||
suggestion = reg.Value()
|
|
||||||
}
|
|
||||||
// promp user for region
|
|
||||||
region, err = h.user.Input("Region", suggestion)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
if region == "" {
|
if region == "" {
|
||||||
return "", fmt.Errorf("region cannot be empty")
|
// fallback to AWS default
|
||||||
|
region = "us-east-1"
|
||||||
}
|
}
|
||||||
// save selected/typed region under profile in ~/.aws/config
|
return region, nil
|
||||||
_, err = section.NewKey("region", region)
|
}
|
||||||
|
|
||||||
|
func (h contextCreateAWSHelper) chooseRegion(opts *ContextParams) error {
|
||||||
|
regions, err := h.availableRegions(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
return region, configIni.SaveTo(awsConfig)
|
// promp user for region
|
||||||
|
selected, err := h.user.Select("Region", regions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.Region = regions[selected]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listAvailableRegions(opts *ContextParams) ([]string, error) {
|
||||||
|
// Setup SDK with credentials, will also validate those
|
||||||
|
session, err := session.NewSessionWithOptions(session.Options{
|
||||||
|
Config: aws.Config{
|
||||||
|
Credentials: credentials.NewStaticCredentials(opts.AccessKey, opts.SecretKey, ""),
|
||||||
|
Region: aws.String("us-east-1"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
desc, err := ec2.New(session).DescribeRegions(&ec2.DescribeRegionsInput{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var regions []string
|
||||||
|
for _, r := range desc.Regions {
|
||||||
|
regions = append(regions, aws.StringValue(r.RegionName))
|
||||||
|
}
|
||||||
|
return regions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h contextCreateAWSHelper) askCredentials() (string, string, error) {
|
func (h contextCreateAWSHelper) askCredentials() (string, string, error) {
|
||||||
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", "")
|
accessKeyID, err := h.user.Input("AWS Access Key ID", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
@ -277,3 +407,19 @@ func loadIniFile(path string, prefix bool) (map[string]ini.Section, error) {
|
|||||||
}
|
}
|
||||||
return profiles, nil
|
return profiles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAWSConfigFile() string {
|
||||||
|
awsConfig, ok := os.LookupEnv("AWS_CONFIG_FILE")
|
||||||
|
if !ok {
|
||||||
|
awsConfig = defaults.SharedConfigFilename()
|
||||||
|
}
|
||||||
|
return awsConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAWSCredentialsFile() string {
|
||||||
|
awsConfig, ok := os.LookupEnv("AWS_SHARED_CREDENTIALS_FILE")
|
||||||
|
if !ok {
|
||||||
|
awsConfig = defaults.SharedCredentialsFilename()
|
||||||
|
}
|
||||||
|
return awsConfig
|
||||||
|
}
|
||||||
|
173
ecs/context_test.go
Normal file
173
ecs/context_test.go
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker Compose CLI authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ecs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/compose-cli/context/store"
|
||||||
|
"github.com/docker/compose-cli/prompt"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
"gotest.tools/v3/fs"
|
||||||
|
"gotest.tools/v3/golden"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateContextDataFromEnv(t *testing.T) {
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: nil,
|
||||||
|
}
|
||||||
|
data, desc, err := c.createContextData(context.TODO(), ContextParams{
|
||||||
|
Name: "test",
|
||||||
|
CredsFromEnv: true,
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).CredentialsFromEnv, true)
|
||||||
|
assert.Equal(t, desc, "credentials read from environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateContextDataByKeys(t *testing.T) {
|
||||||
|
dir := fs.NewDir(t, "aws")
|
||||||
|
os.Setenv("AWS_CONFIG_FILE", dir.Join("config")) // nolint:errcheck
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", dir.Join("credentials")) // nolint:errcheck
|
||||||
|
|
||||||
|
defer os.Unsetenv("AWS_CONFIG_FILE") // nolint:errcheck
|
||||||
|
defer os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE") // nolint:errcheck
|
||||||
|
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _, err := c.createContextData(context.TODO(), ContextParams{
|
||||||
|
Name: "test",
|
||||||
|
AccessKey: "ABCD",
|
||||||
|
SecretKey: "X&123",
|
||||||
|
Region: "eu-west-3",
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).Profile, "default")
|
||||||
|
|
||||||
|
s := golden.Get(t, dir.Join("config"))
|
||||||
|
golden.Assert(t, string(s), "context/by-keys/config.golden")
|
||||||
|
|
||||||
|
s = golden.Get(t, dir.Join("credentials"))
|
||||||
|
golden.Assert(t, string(s), "context/by-keys/credentials.golden")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateContextDataFromProfile(t *testing.T) {
|
||||||
|
os.Setenv("AWS_CONFIG_FILE", "testdata/context/by-profile/config.golden") // nolint:errcheck
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "testdata/context/by-profile/credentials.golden") // nolint:errcheck
|
||||||
|
|
||||||
|
defer os.Unsetenv("AWS_CONFIG_FILE") // nolint:errcheck
|
||||||
|
defer os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE") // nolint:errcheck
|
||||||
|
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, _, err := c.createContextData(context.TODO(), ContextParams{
|
||||||
|
Name: "test",
|
||||||
|
Profile: "foo",
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).Profile, "foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateContextDataFromEnvInteractive(t *testing.T) {
|
||||||
|
dir := fs.NewDir(t, "aws")
|
||||||
|
os.Setenv("AWS_CONFIG_FILE", dir.Join("config")) // nolint:errcheck
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", dir.Join("credentials")) // nolint:errcheck
|
||||||
|
|
||||||
|
defer os.Unsetenv("AWS_CONFIG_FILE") // nolint:errcheck
|
||||||
|
defer os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE") // nolint:errcheck
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
ui := prompt.NewMockUI(ctrl)
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: ui,
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.EXPECT().Select("Create a Docker context using:", gomock.Any()).Return(1, nil)
|
||||||
|
data, _, err := c.createContextData(context.TODO(), ContextParams{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).CredentialsFromEnv, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateContextDataByKeysInteractive(t *testing.T) {
|
||||||
|
dir := fs.NewDir(t, "aws")
|
||||||
|
os.Setenv("AWS_CONFIG_FILE", dir.Join("config")) // nolint:errcheck
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", dir.Join("credentials")) // nolint:errcheck
|
||||||
|
|
||||||
|
defer os.Unsetenv("AWS_CONFIG_FILE") // nolint:errcheck
|
||||||
|
defer os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE") // nolint:errcheck
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
ui := prompt.NewMockUI(ctrl)
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: ui,
|
||||||
|
availableRegions: func(opts *ContextParams) ([]string, error) {
|
||||||
|
return []string{"us-east-1", "eu-west-3"}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.EXPECT().Select("Create a Docker context using:", gomock.Any()).Return(0, nil)
|
||||||
|
ui.EXPECT().Input("AWS Access Key ID", gomock.Any()).Return("ABCD", nil)
|
||||||
|
ui.EXPECT().Password("Enter AWS Secret Access Key").Return("X&123", nil)
|
||||||
|
ui.EXPECT().Select("Region", []string{"us-east-1", "eu-west-3"}).Return(1, nil)
|
||||||
|
|
||||||
|
data, _, err := c.createContextData(context.TODO(), ContextParams{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).Profile, "default")
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).Profile, "default")
|
||||||
|
|
||||||
|
s := golden.Get(t, dir.Join("config"))
|
||||||
|
golden.Assert(t, string(s), "context/by-keys/config.golden")
|
||||||
|
|
||||||
|
s = golden.Get(t, dir.Join("credentials"))
|
||||||
|
golden.Assert(t, string(s), "context/by-keys/credentials.golden")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateContextDataByProfileInteractive(t *testing.T) {
|
||||||
|
os.Setenv("AWS_CONFIG_FILE", "testdata/context/by-profile/config.golden") // nolint:errcheck
|
||||||
|
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "testdata/context/by-profile/credentials.golden") // nolint:errcheck
|
||||||
|
|
||||||
|
defer os.Unsetenv("AWS_CONFIG_FILE") // nolint:errcheck
|
||||||
|
defer os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE") // nolint:errcheck
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
ui := prompt.NewMockUI(ctrl)
|
||||||
|
c := contextCreateAWSHelper{
|
||||||
|
user: ui,
|
||||||
|
}
|
||||||
|
ui.EXPECT().Select("Create a Docker context using:", gomock.Any()).Return(0, nil)
|
||||||
|
ui.EXPECT().Select("Select AWS Profile", []string{"default", "foo"}).Return(1, nil)
|
||||||
|
|
||||||
|
data, _, err := c.createContextData(context.TODO(), ContextParams{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, data.(store.EcsContext).Profile, "foo")
|
||||||
|
}
|
3
ecs/testdata/context/by-keys/config.golden
vendored
Normal file
3
ecs/testdata/context/by-keys/config.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[profile default]
|
||||||
|
region = eu-west-3
|
||||||
|
|
4
ecs/testdata/context/by-keys/credentials.golden
vendored
Normal file
4
ecs/testdata/context/by-keys/credentials.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[default]
|
||||||
|
aws_access_key_id = ABCD
|
||||||
|
aws_secret_access_key = X&123
|
||||||
|
|
3
ecs/testdata/context/by-profile/config.golden
vendored
Normal file
3
ecs/testdata/context/by-profile/config.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[profile foo]
|
||||||
|
region = eu-west-3
|
||||||
|
|
4
ecs/testdata/context/by-profile/credentials.golden
vendored
Normal file
4
ecs/testdata/context/by-profile/credentials.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[foo]
|
||||||
|
aws_access_key_id = ABCD
|
||||||
|
aws_secret_access_key = X&123
|
||||||
|
|
1
go.sum
1
go.sum
@ -748,6 +748,7 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:generate mockgen -destination=./prompt_mock.go -self_package "github.com/docker/compose-cli/prompt" -package=prompt . UI
|
||||||
|
|
||||||
// UI - prompt user input
|
// UI - prompt user input
|
||||||
type UI interface {
|
type UI interface {
|
||||||
Select(message string, options []string) (int, error)
|
Select(message string, options []string) (int, error)
|
||||||
|
93
prompt/prompt_mock.go
Normal file
93
prompt/prompt_mock.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/docker/compose-cli/prompt (interfaces: UI)
|
||||||
|
|
||||||
|
// Package prompt is a generated GoMock package.
|
||||||
|
package prompt
|
||||||
|
|
||||||
|
import (
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockUI is a mock of UI interface
|
||||||
|
type MockUI struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockUIMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUIMockRecorder is the mock recorder for MockUI
|
||||||
|
type MockUIMockRecorder struct {
|
||||||
|
mock *MockUI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockUI creates a new mock instance
|
||||||
|
func NewMockUI(ctrl *gomock.Controller) *MockUI {
|
||||||
|
mock := &MockUI{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockUIMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use
|
||||||
|
func (m *MockUI) EXPECT() *MockUIMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm mocks base method
|
||||||
|
func (m *MockUI) Confirm(arg0 string, arg1 bool) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Confirm", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm indicates an expected call of Confirm
|
||||||
|
func (mr *MockUIMockRecorder) Confirm(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Confirm", reflect.TypeOf((*MockUI)(nil).Confirm), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input mocks base method
|
||||||
|
func (m *MockUI) Input(arg0, arg1 string) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Input", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input indicates an expected call of Input
|
||||||
|
func (mr *MockUIMockRecorder) Input(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Input", reflect.TypeOf((*MockUI)(nil).Input), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password mocks base method
|
||||||
|
func (m *MockUI) Password(arg0 string) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Password", arg0)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password indicates an expected call of Password
|
||||||
|
func (mr *MockUIMockRecorder) Password(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Password", reflect.TypeOf((*MockUI)(nil).Password), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select mocks base method
|
||||||
|
func (m *MockUI) Select(arg0 string, arg1 []string) (int, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Select", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(int)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select indicates an expected call of Select
|
||||||
|
func (mr *MockUIMockRecorder) Select(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*MockUI)(nil).Select), arg0, arg1)
|
||||||
|
}
|
@ -168,16 +168,15 @@ func setupTest(t *testing.T) (*E2eCLI, string) {
|
|||||||
if localTestProfile != "" {
|
if localTestProfile != "" {
|
||||||
region := os.Getenv("TEST_AWS_REGION")
|
region := os.Getenv("TEST_AWS_REGION")
|
||||||
assert.Check(t, region != "")
|
assert.Check(t, region != "")
|
||||||
res = c.RunDockerCmd("context", "create", "ecs", contextName, "--profile", "default", "--region", region)
|
res = c.RunDockerCmd("context", "create", "ecs", contextName, "--from-env")
|
||||||
} else {
|
} else {
|
||||||
profile := "default"
|
|
||||||
region := os.Getenv("AWS_DEFAULT_REGION")
|
region := os.Getenv("AWS_DEFAULT_REGION")
|
||||||
secretKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
secretKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||||
keyID := os.Getenv("AWS_ACCESS_KEY_ID")
|
keyID := os.Getenv("AWS_ACCESS_KEY_ID")
|
||||||
assert.Check(t, keyID != "")
|
assert.Check(t, keyID != "")
|
||||||
assert.Check(t, secretKey != "")
|
assert.Check(t, secretKey != "")
|
||||||
assert.Check(t, region != "")
|
assert.Check(t, region != "")
|
||||||
res = c.RunDockerCmd("context", "create", "ecs", contextName, "--profile", profile, "--region", region)
|
res = c.RunDockerCmd("context", "create", "ecs", contextName, "--from-env")
|
||||||
}
|
}
|
||||||
res.Assert(t, icmd.Expected{Out: "Successfully created ecs context \"" + contextName + "\""})
|
res.Assert(t, icmd.Expected{Out: "Successfully created ecs context \"" + contextName + "\""})
|
||||||
res = c.RunDockerCmd("context", "use", contextName)
|
res = c.RunDockerCmd("context", "use", contextName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user