github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cloud/amazon/ecr.go (about) 1 package amazon 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 "github.com/olli-ai/jx/v2/pkg/cloud/amazon/session" 9 10 "github.com/olli-ai/jx/v2/pkg/kube" 11 "k8s.io/client-go/kubernetes" 12 13 "github.com/aws/aws-sdk-go/aws" 14 "github.com/aws/aws-sdk-go/aws/awserr" 15 "github.com/aws/aws-sdk-go/service/ecr" 16 "github.com/aws/aws-sdk-go/service/sts" 17 "github.com/jenkins-x/jx-logging/pkg/log" 18 "github.com/olli-ai/jx/v2/pkg/util" 19 ) 20 21 // GetAccountIDAndRegion returns the current account ID and region 22 func GetAccountIDAndRegion(profile string, region string) (string, string, error) { 23 sess, err := session.NewAwsSession(profile, region) 24 // We nee to get the region from the connected cluster instead of the one configured for the calling user 25 // as it might not be found and it would then use the default (us-west-2) 26 _, region, err = session.GetCurrentlyConnectedRegionAndClusterName() 27 if err != nil { 28 return "", "", err 29 } 30 svc := sts.New(sess) 31 32 input := &sts.GetCallerIdentityInput{} 33 34 result, err := svc.GetCallerIdentity(input) 35 if err != nil { 36 return "", region, err 37 } 38 if result.Account != nil { 39 return *result.Account, region, nil 40 } 41 return "", region, fmt.Errorf("Could not find the AWS Account ID!") 42 } 43 44 // GetContainerRegistryHost 45 func GetContainerRegistryHost() (string, error) { 46 accountId, region, err := GetAccountIDAndRegion("", "") 47 if err != nil { 48 return "", err 49 } 50 return accountId + ".dkr.ecr." + region + ".amazonaws.com", nil 51 } 52 53 /* 54 Deprecated! 55 56 This function is kept for backwards compatibility. AWS region should not be resolved from ECR address, but 57 read from ConfigMap (see RememberRegion function). To keep backwards compatibility with existing installations this 58 function will be kept for a while and it will perform migration to config map. Eventually it will be removed from a 59 codebase. 60 */ 61 //nolint 62 func GetRegionFromContainerRegistryHost(kubeClient kubernetes.Interface, namespace string, dockerRegistry string) string { 63 submatch := regexp.MustCompile(`\.ecr\.(.*)\.amazonaws\.com$`).FindStringSubmatch(dockerRegistry) 64 if len(submatch) > 1 { 65 region := submatch[1] 66 // Migrating jx installations created before AWS region config map 67 kube.RememberRegion(kubeClient, namespace, region) 68 return region 69 } else { 70 return "" 71 } 72 } 73 74 // LazyCreateRegistry lazily creates the ECR registry if it does not already exist 75 func LazyCreateRegistry(kube kubernetes.Interface, namespace string, region string, dockerRegistry string, orgName string, appName string) error { 76 // strip any tag/version from the app name 77 idx := strings.Index(appName, ":") 78 if idx > 0 { 79 appName = appName[0:idx] 80 } 81 repoName := appName 82 if orgName != "" { 83 repoName = orgName + "/" + appName 84 } 85 repoName = strings.ToLower(repoName) 86 log.Logger().Infof("Let's ensure that we have an ECR repository for the Docker image %s", util.ColorInfo(repoName)) 87 if region == "" { 88 region = GetRegionFromContainerRegistryHost(kube, namespace, dockerRegistry) 89 } 90 sess, err := session.NewAwsSession("", region) 91 if err != nil { 92 return err 93 } 94 svc := ecr.New(sess) 95 repoInput := &ecr.DescribeRepositoriesInput{ 96 RepositoryNames: []*string{ 97 aws.String(repoName), 98 }, 99 } 100 result, err := svc.DescribeRepositories(repoInput) 101 if aerr, ok := err.(awserr.Error); !ok || aerr.Code() != ecr.ErrCodeRepositoryNotFoundException { 102 return err 103 } 104 for _, repo := range result.Repositories { 105 name := repo.String() 106 log.Logger().Infof("Found repository: %s", name) 107 if name == repoName { 108 return nil 109 } 110 } 111 createRepoInput := &ecr.CreateRepositoryInput{ 112 RepositoryName: aws.String(repoName), 113 } 114 createResult, err := svc.CreateRepository(createRepoInput) 115 if err != nil { 116 return fmt.Errorf("Failed to create the ECR repository for %s due to: %s", repoName, err) 117 } 118 repo := createResult.Repository 119 if repo != nil { 120 u := repo.RepositoryUri 121 if u != nil { 122 if !strings.HasPrefix(*u, dockerRegistry) { 123 log.Logger().Warnf("Created ECR repository (%s) doesn't match registry configured for team (%s)", 124 util.ColorInfo(*u), util.ColorInfo(dockerRegistry)) 125 } else { 126 log.Logger().Infof("Created ECR repository: %s", util.ColorInfo(*u)) 127 } 128 } 129 } 130 return nil 131 }