From f7c66eb06aa7810e03f106131306574d192314c3 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 23 Sep 2022 18:23:07 +0000 Subject: [PATCH] Refactors aws.ParseImage to ParseRegistry This change replaces ParseImage with ParseRegistry to allow URLs that point to the root of an AWS account's ECR registry, instead of forcing all repositories to contain a "/" character. This enables support for using ECR repositories at root level to be used as OCI Helm Repository. Signed-off-by: Ben --- oci/auth/aws/auth.go | 14 +++++++------- oci/auth/aws/auth_test.go | 22 ++++++++++++---------- oci/auth/login/login.go | 8 ++++---- oci/auth/login/login_test.go | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/oci/auth/aws/auth.go b/oci/auth/aws/auth.go index 0442772c3..ca8c61a76 100644 --- a/oci/auth/aws/auth.go +++ b/oci/auth/aws/auth.go @@ -33,13 +33,13 @@ import ( "github.com/fluxcd/pkg/oci" ) -var registryPartRe = regexp.MustCompile(`([0-9+]*).dkr.ecr.([^/.]*)\.(amazonaws\.com[.cn]*)/([^:]+):?(.*)`) +var registryPartRe = regexp.MustCompile(`([0-9+]*).dkr.ecr.([^/.]*)\.(amazonaws\.com[.cn]*)`) -// ParseImage returns the AWS account ID and region and `true` if -// the image repository is hosted in AWS's Elastic Container Registry, +// ParseRegistry returns the AWS account ID and region and `true` if +// the image registry/repository is hosted in AWS's Elastic Container Registry, // otherwise empty strings and `false`. -func ParseImage(image string) (accountId, awsEcrRegion string, ok bool) { - registryParts := registryPartRe.FindAllStringSubmatch(image, -1) +func ParseRegistry(registry string) (accountId, awsEcrRegion string, ok bool) { + registryParts := registryPartRe.FindAllStringSubmatch(registry, -1) if len(registryParts) < 1 || len(registryParts[0]) < 3 { return "", "", false } @@ -108,11 +108,11 @@ func (c *Client) getLoginAuth(accountId, awsEcrRegion string) (authn.AuthConfig, // Login attempts to get the authentication material for ECR. It extracts // the account and region information from the image URI. The caller can ensure -// that the passed image is a valid ECR image using ParseImage(). +// that the passed image is a valid ECR image using ParseRegistry(). func (c *Client) Login(ctx context.Context, autoLogin bool, image string) (authn.Authenticator, error) { if autoLogin { ctrl.LoggerFrom(ctx).Info("logging in to AWS ECR for " + image) - accountId, awsEcrRegion, ok := ParseImage(image) + accountId, awsEcrRegion, ok := ParseRegistry(image) if !ok { return nil, errors.New("failed to parse AWS ECR image, invalid ECR image") } diff --git a/oci/auth/aws/auth_test.go b/oci/auth/aws/auth_test.go index 3ced59fa7..c347443b8 100644 --- a/oci/auth/aws/auth_test.go +++ b/oci/auth/aws/auth_test.go @@ -31,40 +31,42 @@ const ( testValidECRImage = "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1" ) -func TestParseImage(t *testing.T) { +func TestParseRegistry(t *testing.T) { tests := []struct { - image string + registry string wantAccountID string wantRegion string wantOK bool }{ { - image: "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1", + registry: "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1", wantAccountID: "012345678901", wantRegion: "us-east-1", wantOK: true, }, { - image: "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo", + registry: "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo", wantAccountID: "012345678901", wantRegion: "us-east-1", wantOK: true, }, { - image: "012345678901.dkr.ecr.us-east-1.amazonaws.com", - wantOK: false, + registry: "012345678901.dkr.ecr.us-east-1.amazonaws.com", + wantAccountID: "012345678901", + wantRegion: "us-east-1", + wantOK: true, }, { - image: "gcr.io/foo/bar:baz", - wantOK: false, + registry: "gcr.io/foo/bar:baz", + wantOK: false, }, } for _, tt := range tests { - t.Run(tt.image, func(t *testing.T) { + t.Run(tt.registry, func(t *testing.T) { g := NewWithT(t) - accId, region, ok := ParseImage(tt.image) + accId, region, ok := ParseRegistry(tt.registry) g.Expect(ok).To(Equal(tt.wantOK), "unexpected OK") g.Expect(accId).To(Equal(tt.wantAccountID), "unexpected account IDs") g.Expect(region).To(Equal(tt.wantRegion), "unexpected regions") diff --git a/oci/auth/login/login.go b/oci/auth/login/login.go index 83271fb22..ae26ca376 100644 --- a/oci/auth/login/login.go +++ b/oci/auth/login/login.go @@ -28,10 +28,10 @@ import ( "github.com/fluxcd/pkg/oci/auth/gcp" ) -// ImageRegistryProvider analyzes the provided image and returns the identified +// ImageRegistryProvider analyzes the provided registry and returns the identified // container image registry provider. -func ImageRegistryProvider(image string, ref name.Reference) oci.Provider { - _, _, ok := aws.ParseImage(image) +func ImageRegistryProvider(ref name.Reference) oci.Provider { + _, _, ok := aws.ParseRegistry(ref.Context().RegistryStr()) if ok { return oci.ProviderAWS } @@ -95,7 +95,7 @@ func (m *Manager) WithACRClient(c *azure.Client) *Manager { // Login performs authentication against a registry and returns the // authentication material. For generic registry provider, it is no-op. func (m *Manager) Login(ctx context.Context, image string, ref name.Reference, opts ProviderOptions) (authn.Authenticator, error) { - switch ImageRegistryProvider(image, ref) { + switch ImageRegistryProvider(ref) { case oci.ProviderAWS: return m.ecr.Login(ctx, opts.AwsAutoLogin, image) case oci.ProviderGCP: diff --git a/oci/auth/login/login_test.go b/oci/auth/login/login_test.go index a73932756..b85126550 100644 --- a/oci/auth/login/login_test.go +++ b/oci/auth/login/login_test.go @@ -50,7 +50,7 @@ func TestImageRegistryProvider(t *testing.T) { ref, err := name.ParseReference(tt.image) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(ImageRegistryProvider(tt.image, ref)).To(Equal(tt.want)) + g.Expect(ImageRegistryProvider(ref)).To(Equal(tt.want)) }) } }