package connect import ( "context" "fmt" "os" "strings" "time" "github.com/porter-dev/porter/api/types" "github.com/aws/aws-sdk-go/service/ecr" "github.com/fatih/color" api "github.com/porter-dev/porter/api/client" "github.com/porter-dev/porter/cli/cmd/utils" "github.com/porter-dev/porter/internal/models/integrations" "github.com/porter-dev/porter/cli/cmd/providers/aws" awsLocal "github.com/porter-dev/porter/cli/cmd/providers/aws/local" ) // ECR creates an ECR integration func ECR( client *api.Client, projectID uint, ) (uint, error) { // if project ID is 0, ask the user to set the project ID or create a project if projectID == 0 { return 0, fmt.Errorf("no project set, please run porter project set [id]") } // query for the region region, err := utils.PromptPlaintext(fmt.Sprintf(`Please provide the AWS region where the ECR instance is located. AWS Region: `)) if err != nil { return 0, err } userResp, err := utils.PromptPlaintext( fmt.Sprintf(`Porter can set up an IAM user in your AWS account to connect to this ECR instance automatically. Would you like to proceed? %s `, color.New(color.FgCyan).Sprintf("[y/n]"), ), ) if err != nil { return 0, err } if userResp := strings.ToLower(userResp); userResp == "y" || userResp == "yes" { agent := awsLocal.NewDefaultAgent() creds, err := agent.CreateIAMECRUser(region) if err != nil { color.New(color.FgRed).Fprintf(os.Stderr, "Automatic creation failed, manual input required. Error was: %v\n", err) return ecrManual(client, projectID, region) } waitForAuthorizationToken(region, creds) integration, err := client.CreateAWSIntegration( context.Background(), projectID, &types.CreateAWSRequest{ AWSAccessKeyID: creds.AWSAccessKeyID, AWSSecretAccessKey: creds.AWSSecretAccessKey, AWSRegion: region, }, ) if err != nil { return 0, err } color.New(color.FgGreen).Printf("created aws integration with id %d\n", integration.ID) return linkRegistry(client, projectID, integration.ID) } return ecrManual(client, projectID, region) } func ecrManual( client *api.Client, projectID uint, region string, ) (uint, error) { // if project ID is 0, ask the user to set the project ID or create a project if projectID == 0 { return 0, fmt.Errorf("no project set, please run porter project set [id]") } // query for the access key id accessKeyID, err := utils.PromptPlaintext(fmt.Sprintf(`AWS Access Key ID: `)) if err != nil { return 0, err } // query for the secret access key secretKey, err := utils.PromptPlaintext(fmt.Sprintf(`AWS Secret Access Key: `)) if err != nil { return 0, err } // create the aws integration integration, err := client.CreateAWSIntegration( context.Background(), projectID, &types.CreateAWSRequest{ AWSAccessKeyID: accessKeyID, AWSSecretAccessKey: secretKey, AWSRegion: region, }, ) if err != nil { return 0, err } color.New(color.FgGreen).Printf("created aws integration with id %d\n", integration.ID) return linkRegistry(client, projectID, integration.ID) } func linkRegistry(client *api.Client, projectID uint, intID uint) (uint, error) { // create the registry // query for registry name regName, err := utils.PromptPlaintext(fmt.Sprintf(`Give this registry a name: `)) if err != nil { return 0, err } reg, err := client.CreateRegistry( context.Background(), projectID, &types.CreateRegistryRequest{ Name: regName, AWSIntegrationID: intID, }, ) if err != nil { return 0, err } color.New(color.FgGreen).Printf("created registry with id %d and name %s\n", reg.ID, reg.Name) return reg.ID, nil } func waitForAuthorizationToken(region string, creds *aws.PorterAWSCredentials) error { awsInt := &integrations.AWSIntegration{ AWSRegion: region, AWSAccessKeyID: []byte(creds.AWSAccessKeyID), AWSSecretAccessKey: []byte(creds.AWSSecretAccessKey), } sess, err := awsInt.GetSession() if err != nil { return err } ecrSvc := ecr.New(sess) for i := 0; i < 30; i++ { _, err := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{}) if err == nil { return nil } time.Sleep(2 * time.Second) } return fmt.Errorf("could not get ECR authorization token, please check credentials") }