Skip to content

Commit b9650d0

Browse files
authored
feat(aws): add ECR Public repository support (#1852)
Add an ecrpublic module mirroring the ecr module (create, get, force delete, and client constructor) using the aws-sdk-go-v2 ecrpublic service. ECR Public is only available in us-east-1, which the integration test pins. Closes #1288
1 parent 646b00a commit b9650d0

4 files changed

Lines changed: 234 additions & 12 deletions

File tree

go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ require (
7070
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.4.0
7171
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0
7272
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0
73-
github.com/aws/aws-sdk-go-v2 v1.41.6
73+
github.com/aws/aws-sdk-go-v2 v1.42.0
7474
github.com/aws/aws-sdk-go-v2/config v1.32.16
7575
github.com/aws/aws-sdk-go-v2/credentials v1.19.15
7676
github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.17
@@ -80,6 +80,7 @@ require (
8080
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.57.2
8181
github.com/aws/aws-sdk-go-v2/service/ec2 v1.297.1
8282
github.com/aws/aws-sdk-go-v2/service/ecr v1.57.1
83+
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.39.6
8384
github.com/aws/aws-sdk-go-v2/service/ecs v1.78.1
8485
github.com/aws/aws-sdk-go-v2/service/iam v1.53.8
8586
github.com/aws/aws-sdk-go-v2/service/kms v1.50.5
@@ -92,7 +93,7 @@ require (
9293
github.com/aws/aws-sdk-go-v2/service/sqs v1.42.26
9394
github.com/aws/aws-sdk-go-v2/service/ssm v1.68.5
9495
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0
95-
github.com/aws/smithy-go v1.25.0
96+
github.com/aws/smithy-go v1.27.1
9697
github.com/gonvenience/ytbx v1.4.4
9798
github.com/hashicorp/go-getter/v2 v2.2.3
9899
github.com/homeport/dyff v1.6.0
@@ -126,8 +127,8 @@ require (
126127
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
127128
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 // indirect
128129
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect
129-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect
130-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect
130+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect
131+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect
131132
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect
132133
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect
133134
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.14 // indirect

go.sum

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
125125
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
126126
github.com/aws/aws-lambda-go v1.54.0 h1:EGYpdyRGF88xszqlGcBewz811mJeRS+maNlLZXFheII=
127127
github.com/aws/aws-lambda-go v1.54.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
128-
github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg=
129-
github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ=
128+
github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA=
129+
github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg=
130130
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9 h1:adBsCIIpLbLmYnkQU+nAChU5yhVTvu5PerROm+/Kq2A=
131131
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.9/go.mod h1:uOYhgfgThm/ZyAuJGNQ5YgNyOlYfqnGpTHXvk3cpykg=
132132
github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM=
@@ -137,10 +137,10 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8Ou
137137
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg=
138138
github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.17 h1:95y7/EqethAhFwMKJ9cDutzBhsS1h8uBwkJ5rp8pNTU=
139139
github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.17/go.mod h1:77baheqr62SkTw77HWH8qpdWTd2gXKN0xg0qLvDSkpk=
140-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ=
141-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0=
142-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU=
143-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI=
140+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko=
141+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc=
142+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY=
143+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA=
144144
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4=
145145
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U=
146146
github.com/aws/aws-sdk-go-v2/service/acm v1.38.2 h1:ozcwethaFOi2ST9h6MKGq1GAIHP68tjiDqgkWVPwfR8=
@@ -155,6 +155,8 @@ github.com/aws/aws-sdk-go-v2/service/ec2 v1.297.1 h1:9nfacm+uWgbdPaOplvJjxN50qgt
155155
github.com/aws/aws-sdk-go-v2/service/ec2 v1.297.1/go.mod h1:E1pnYwWFZ8N3REmeN9Fe/Zipbpps4HJj8DQGNnLUMYc=
156156
github.com/aws/aws-sdk-go-v2/service/ecr v1.57.1 h1:G/O4muLF2pe1UJBKEyF7J+kdokEEqFJjm42cU68FqH4=
157157
github.com/aws/aws-sdk-go-v2/service/ecr v1.57.1/go.mod h1:KBzTxiBlQ2bB5XT367+t18i3Qe7NZDRyGKxdzN43aOw=
158+
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.39.6 h1:pI1S5+Z8cfN/fImioNCHCWKFgm49ZeBhnjffJfRWHYA=
159+
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.39.6/go.mod h1:VctLEHQ91HQAWosSGqbNykn4OoxuUVGbE+1SachaXa0=
158160
github.com/aws/aws-sdk-go-v2/service/ecs v1.78.1 h1:9zSVr4X6X8JNTxSMip2RORaBB+Mu0/IfzNu3iRWZE9c=
159161
github.com/aws/aws-sdk-go-v2/service/ecs v1.78.1/go.mod h1:1DlTqkp+8uc5At3UXyJAvJXFaWoMmxSHcp2Zdor0qGw=
160162
github.com/aws/aws-sdk-go-v2/service/iam v1.53.8 h1:p0oB4eZfBfBAOasnKvHJOlNcuHVE/ieuWs7uIZgQlyQ=
@@ -195,8 +197,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3Vg
195197
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg=
196198
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds=
197199
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo=
198-
github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U=
199-
github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
200+
github.com/aws/smithy-go v1.27.1 h1:4T340VFndXtADGF52gYa1POyL7s9E4Z1OeZ1hCscIw8=
201+
github.com/aws/smithy-go v1.27.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
200202
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
201203
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
202204
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=

modules/aws/ecrpublic.go

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
goerrors "errors"
6+
7+
"github.com/aws/aws-sdk-go-v2/aws"
8+
"github.com/aws/aws-sdk-go-v2/service/ecrpublic"
9+
"github.com/aws/aws-sdk-go-v2/service/ecrpublic/types"
10+
"github.com/gruntwork-io/go-commons/errors"
11+
"github.com/gruntwork-io/terratest/modules/testing"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
// Note: the ECR Public API is only available in the us-east-1 region, so pass "us-east-1" as the region to these
16+
// functions regardless of where the rest of your infrastructure lives.
17+
18+
// CreateECRPublicRepoContextE creates a new ECR Public Repository.
19+
// The ctx parameter supports cancellation and timeouts.
20+
func CreateECRPublicRepoContextE(t testing.TestingT, ctx context.Context, region string, name string) (*types.Repository, error) {
21+
client, err := NewECRPublicClientContextE(t, ctx, region)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
resp, err := client.CreateRepository(ctx, &ecrpublic.CreateRepositoryInput{RepositoryName: aws.String(name)})
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
return resp.Repository, nil
32+
}
33+
34+
// CreateECRPublicRepoContext creates a new ECR Public Repository.
35+
// This function will fail the test if there is an error.
36+
// The ctx parameter supports cancellation and timeouts.
37+
func CreateECRPublicRepoContext(t testing.TestingT, ctx context.Context, region string, name string) *types.Repository {
38+
t.Helper()
39+
40+
repo, err := CreateECRPublicRepoContextE(t, ctx, region, name)
41+
require.NoError(t, err)
42+
43+
return repo
44+
}
45+
46+
// CreateECRPublicRepoE creates a new ECR Public Repository.
47+
func CreateECRPublicRepoE(t testing.TestingT, region string, name string) (*types.Repository, error) {
48+
return CreateECRPublicRepoContextE(t, context.Background(), region, name)
49+
}
50+
51+
// CreateECRPublicRepo creates a new ECR Public Repository. This will fail the test and stop execution if there is an error.
52+
func CreateECRPublicRepo(t testing.TestingT, region string, name string) *types.Repository {
53+
t.Helper()
54+
55+
return CreateECRPublicRepoContext(t, context.Background(), region, name)
56+
}
57+
58+
// GetECRPublicRepoContextE gets an ECR Public Repository by name.
59+
// An error occurs if a repository with the given name does not exist.
60+
// The ctx parameter supports cancellation and timeouts.
61+
func GetECRPublicRepoContextE(t testing.TestingT, ctx context.Context, region string, name string) (*types.Repository, error) {
62+
client, err := NewECRPublicClientContextE(t, ctx, region)
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
resp, err := client.DescribeRepositories(ctx, &ecrpublic.DescribeRepositoriesInput{RepositoryNames: []string{name}})
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
if len(resp.Repositories) != 1 {
73+
return nil, errors.WithStackTrace(goerrors.New("an unexpected condition occurred. Please file an issue at github.com/gruntwork-io/terratest"))
74+
}
75+
76+
return &resp.Repositories[0], nil
77+
}
78+
79+
// GetECRPublicRepoContext gets an ECR Public Repository by name.
80+
// This function will fail the test if there is an error.
81+
// An error occurs if a repository with the given name does not exist.
82+
// The ctx parameter supports cancellation and timeouts.
83+
func GetECRPublicRepoContext(t testing.TestingT, ctx context.Context, region string, name string) *types.Repository {
84+
t.Helper()
85+
86+
repo, err := GetECRPublicRepoContextE(t, ctx, region, name)
87+
require.NoError(t, err)
88+
89+
return repo
90+
}
91+
92+
// GetECRPublicRepoE gets an ECR Public Repository by name.
93+
// An error occurs if a repository with the given name does not exist.
94+
func GetECRPublicRepoE(t testing.TestingT, region string, name string) (*types.Repository, error) {
95+
return GetECRPublicRepoContextE(t, context.Background(), region, name)
96+
}
97+
98+
// GetECRPublicRepo gets an ECR Public Repository by name. This will fail the test and stop execution if there is an error.
99+
// An error occurs if a repository with the given name does not exist.
100+
func GetECRPublicRepo(t testing.TestingT, region string, name string) *types.Repository {
101+
t.Helper()
102+
103+
return GetECRPublicRepoContext(t, context.Background(), region, name)
104+
}
105+
106+
// DeleteECRPublicRepoContextE force deletes the ECR Public repository, including any images it contains.
107+
// The ctx parameter supports cancellation and timeouts.
108+
func DeleteECRPublicRepoContextE(t testing.TestingT, ctx context.Context, region string, repo *types.Repository) error {
109+
client, err := NewECRPublicClientContextE(t, ctx, region)
110+
if err != nil {
111+
return err
112+
}
113+
114+
_, err = client.DeleteRepository(ctx, &ecrpublic.DeleteRepositoryInput{
115+
RepositoryName: repo.RepositoryName,
116+
Force: true,
117+
})
118+
119+
return err
120+
}
121+
122+
// DeleteECRPublicRepoContext force deletes the ECR Public repository, including any images it contains.
123+
// This function will fail the test if there is an error.
124+
// The ctx parameter supports cancellation and timeouts.
125+
func DeleteECRPublicRepoContext(t testing.TestingT, ctx context.Context, region string, repo *types.Repository) {
126+
t.Helper()
127+
128+
err := DeleteECRPublicRepoContextE(t, ctx, region, repo)
129+
require.NoError(t, err)
130+
}
131+
132+
// DeleteECRPublicRepoE force deletes the ECR Public repository, including any images it contains.
133+
func DeleteECRPublicRepoE(t testing.TestingT, region string, repo *types.Repository) error {
134+
return DeleteECRPublicRepoContextE(t, context.Background(), region, repo)
135+
}
136+
137+
// DeleteECRPublicRepo force deletes the ECR Public repository, including any images it contains.
138+
// This will fail the test and stop execution if there is an error.
139+
func DeleteECRPublicRepo(t testing.TestingT, region string, repo *types.Repository) {
140+
t.Helper()
141+
142+
DeleteECRPublicRepoContext(t, context.Background(), region, repo)
143+
}
144+
145+
// NewECRPublicClientContextE returns a client for the Elastic Container Registry Public.
146+
// The ctx parameter supports cancellation and timeouts.
147+
func NewECRPublicClientContextE(t testing.TestingT, ctx context.Context, region string) (*ecrpublic.Client, error) {
148+
sess, err := NewAuthenticatedSessionContext(ctx, region)
149+
if err != nil {
150+
return nil, err
151+
}
152+
153+
return ecrpublic.NewFromConfig(*sess), nil
154+
}
155+
156+
// NewECRPublicClientContext returns a client for the Elastic Container Registry Public.
157+
// This function will fail the test if there is an error.
158+
// The ctx parameter supports cancellation and timeouts.
159+
func NewECRPublicClientContext(t testing.TestingT, ctx context.Context, region string) *ecrpublic.Client {
160+
t.Helper()
161+
162+
client, err := NewECRPublicClientContextE(t, ctx, region)
163+
require.NoError(t, err)
164+
165+
return client
166+
}
167+
168+
// NewECRPublicClientE returns a client for the Elastic Container Registry Public.
169+
func NewECRPublicClientE(t testing.TestingT, region string) (*ecrpublic.Client, error) {
170+
return NewECRPublicClientContextE(t, context.Background(), region)
171+
}
172+
173+
// NewECRPublicClient returns a client for the Elastic Container Registry Public. This will fail the test and
174+
// stop execution if there is an error.
175+
func NewECRPublicClient(t testing.TestingT, region string) *ecrpublic.Client {
176+
t.Helper()
177+
178+
return NewECRPublicClientContext(t, context.Background(), region)
179+
}

modules/aws/ecrpublic_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package aws_test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
awsSDK "github.com/aws/aws-sdk-go-v2/aws"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
11+
aws "github.com/gruntwork-io/terratest/modules/aws"
12+
"github.com/gruntwork-io/terratest/modules/random"
13+
)
14+
15+
// ecrPublicRegion is fixed because the ECR Public API is only available in us-east-1.
16+
const ecrPublicRegion = "us-east-1"
17+
18+
func TestEcrPublicRepo(t *testing.T) {
19+
t.Parallel()
20+
21+
ecrRepoName := "terratest" + strings.ToLower(random.UniqueID())
22+
23+
repo1, err := aws.CreateECRPublicRepoE(t, ecrPublicRegion, ecrRepoName)
24+
defer aws.DeleteECRPublicRepo(t, ecrPublicRegion, repo1)
25+
26+
require.NoError(t, err)
27+
28+
assert.Equal(t, ecrRepoName, awsSDK.ToString(repo1.RepositoryName))
29+
30+
repo2, err := aws.GetECRPublicRepoE(t, ecrPublicRegion, ecrRepoName)
31+
require.NoError(t, err)
32+
assert.Equal(t, ecrRepoName, awsSDK.ToString(repo2.RepositoryName))
33+
}
34+
35+
func TestGetEcrPublicRepoError(t *testing.T) {
36+
t.Parallel()
37+
38+
_, err := aws.GetECRPublicRepoE(t, ecrPublicRegion, "terratest"+strings.ToLower(random.UniqueID()))
39+
require.Error(t, err)
40+
}

0 commit comments

Comments
 (0)