Skip to content

Commit 86a518b

Browse files
committed
Merge remote-tracking branch 'origin/main' into james/oss-3364-bump-gcp-sdk
# Conflicts: # go.mod
2 parents 2bedf50 + 99d939d commit 86a518b

23 files changed

Lines changed: 1370 additions & 132 deletions

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ require (
9999
github.com/jackc/pgx/v5 v5.9.0
100100
github.com/lib/pq v1.10.9
101101
github.com/slack-go/slack v0.15.0
102+
google.golang.org/grpc v1.80.0
102103
gopkg.in/yaml.v3 v3.0.1
103-
gotest.tools/v3 v3.5.1
104+
gotest.tools/v3 v3.5.2
104105
)
105106

106107
require (
@@ -208,6 +209,7 @@ require (
208209
github.com/vbatts/tar-split v0.11.3 // indirect
209210
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect
210211
github.com/x448/float16 v0.8.4 // indirect
212+
go.einride.tech/aip v0.83.0 // indirect
211213
go.opencensus.io v0.24.0 // indirect
212214
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
213215
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect
@@ -229,7 +231,6 @@ require (
229231
golang.org/x/tools v0.42.0 // indirect
230232
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
231233
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
232-
google.golang.org/grpc v1.80.0 // indirect
233234
google.golang.org/protobuf v1.36.11 // indirect
234235
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
235236
gopkg.in/inf.v0 v0.9.1 // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfC
551551
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
552552
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
553553
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
554+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
555+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
554556
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
555557
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
556558
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -670,8 +672,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
670672
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
671673
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
672674
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
673-
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
674-
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
675+
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
676+
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
675677
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
676678
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
677679
k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY=

modules/aws/acm.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,28 @@ func GetAcmCertificateArnContextE(t testing.TestingT, ctx context.Context, awsRe
3232
// a mock.
3333
// The ctx parameter supports cancellation and timeouts.
3434
func GetAcmCertificateArnWithClientContextE(t testing.TestingT, ctx context.Context, client AcmAPI, certDomainName string) (string, error) {
35-
result, err := client.ListCertificates(ctx, &acm.ListCertificatesInput{})
36-
if err != nil {
37-
return "", err
38-
}
35+
input := &acm.ListCertificatesInput{}
36+
37+
for {
38+
result, err := client.ListCertificates(ctx, input)
39+
if err != nil {
40+
return "", err
41+
}
3942

40-
for i := range result.CertificateSummaryList {
41-
summary := &result.CertificateSummaryList[i]
43+
for i := range result.CertificateSummaryList {
44+
summary := &result.CertificateSummaryList[i]
4245

43-
if *summary.DomainName == certDomainName {
44-
return *summary.CertificateArn, nil
46+
if *summary.DomainName == certDomainName {
47+
return *summary.CertificateArn, nil
48+
}
49+
}
50+
51+
if result.NextToken == nil || *result.NextToken == "" {
52+
return "", nil
4553
}
46-
}
4754

48-
return "", nil
55+
input.NextToken = result.NextToken
56+
}
4957
}
5058

5159
// GetAcmCertificateArnContext gets the ACM certificate for the given domain name in the given region.

modules/aws/acm_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package aws_test
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"testing"
78

89
awsSDK "github.com/aws/aws-sdk-go-v2/aws"
@@ -14,16 +15,31 @@ import (
1415
)
1516

1617
// mockAcmClient is a test double for aws.AcmAPI that returns canned responses.
18+
// When ListCertificatesPages is non-empty, it returns one page per call in order,
19+
// advancing on each invocation; otherwise it returns ListCertificatesOutput on every call.
1720
type mockAcmClient struct {
1821
ListCertificatesOutput *acm.ListCertificatesOutput
1922
ListCertificatesErr error
23+
ListCertificatesPages []*acm.ListCertificatesOutput
24+
callCount int
2025
}
2126

2227
func (m *mockAcmClient) ListCertificates(_ context.Context, _ *acm.ListCertificatesInput, _ ...func(*acm.Options)) (*acm.ListCertificatesOutput, error) {
2328
if m.ListCertificatesErr != nil {
2429
return nil, m.ListCertificatesErr
2530
}
2631

32+
if len(m.ListCertificatesPages) > 0 {
33+
if m.callCount >= len(m.ListCertificatesPages) {
34+
return nil, fmt.Errorf("mockAcmClient: ListCertificates called %d times but only %d page(s) configured", m.callCount+1, len(m.ListCertificatesPages))
35+
}
36+
37+
page := m.ListCertificatesPages[m.callCount]
38+
m.callCount++
39+
40+
return page, nil
41+
}
42+
2743
return m.ListCertificatesOutput, nil
2844
}
2945

@@ -44,6 +60,18 @@ func TestGetAcmCertificateArnWithClientContextE(t *testing.T) {
4460
},
4561
}
4662

63+
page1 := &acm.ListCertificatesOutput{
64+
CertificateSummaryList: []types.CertificateSummary{
65+
{DomainName: awsSDK.String(domain1), CertificateArn: awsSDK.String(arn1)},
66+
},
67+
NextToken: awsSDK.String("page-2-token"),
68+
}
69+
page2 := &acm.ListCertificatesOutput{
70+
CertificateSummaryList: []types.CertificateSummary{
71+
{DomainName: awsSDK.String(domain2), CertificateArn: awsSDK.String(arn2)},
72+
},
73+
}
74+
4775
tests := map[string]struct {
4876
client *mockAcmClient
4977
query string
@@ -75,6 +103,18 @@ func TestGetAcmCertificateArnWithClientContextE(t *testing.T) {
75103
query: domain1,
76104
expectErr: true,
77105
},
106+
"finds arn on second page via next token": {
107+
client: &mockAcmClient{ListCertificatesPages: []*acm.ListCertificatesOutput{page1, page2}},
108+
query: domain2,
109+
expectedArn: arn2,
110+
},
111+
"stops paginating when last page has no next token": {
112+
// page2 has no NextToken, so the caller must stop after page 2 rather
113+
// than calling the mock a third time and over-running ListCertificatesPages.
114+
client: &mockAcmClient{ListCertificatesPages: []*acm.ListCertificatesOutput{page1, page2}},
115+
query: "nonexistent.example.com",
116+
expectedArn: "",
117+
},
78118
}
79119

80120
for name, tc := range tests {

modules/aws/iam.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,15 @@ func GetIamPolicyDocumentContextE(t testing.TestingT, ctx context.Context, regio
120120
var defaultVersion string
121121

122122
for _, version := range versions.Versions {
123-
if version.IsDefaultVersion {
123+
if version.IsDefaultVersion && version.VersionId != nil {
124124
defaultVersion = *version.VersionId
125125
}
126126
}
127127

128+
if defaultVersion == "" {
129+
return "", fmt.Errorf("no default version found for IAM policy %s", policyARN)
130+
}
131+
128132
document, err := iamClient.GetPolicyVersion(ctx, &iam.GetPolicyVersionInput{
129133
PolicyArn: aws.String(policyARN),
130134
VersionId: aws.String(defaultVersion),

modules/aws/rds.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ func GetOptionGroupNameOfRdsInstanceContextE(t testing.TestingT, ctx context.Con
327327
return "", err
328328
}
329329

330+
if len(dbInstance.OptionGroupMemberships) == 0 {
331+
return "", fmt.Errorf("RDS instance %s in region %s has no option group memberships", dbInstanceID, awsRegion)
332+
}
333+
330334
return aws.ToString(dbInstance.OptionGroupMemberships[0].OptionGroupName), nil
331335
}
332336

@@ -372,6 +376,10 @@ func GetOptionsOfOptionGroupContextE(t testing.TestingT, ctx context.Context, op
372376
return []types.Option{}, err
373377
}
374378

379+
if len(output.OptionGroupsList) == 0 {
380+
return []types.Option{}, fmt.Errorf("no option groups found for name %s in region %s", optionGroupName, awsRegion)
381+
}
382+
375383
return output.OptionGroupsList[0].Options, nil
376384
}
377385

@@ -410,6 +418,10 @@ func GetAllParametersOfRdsInstanceContextE(t testing.TestingT, ctx context.Conte
410418
return []types.Parameter{}, dbInstanceErr
411419
}
412420

421+
if len(dbInstance.DBParameterGroups) == 0 {
422+
return []types.Parameter{}, fmt.Errorf("RDS instance %s in region %s has no parameter groups", dbInstanceID, awsRegion)
423+
}
424+
413425
parameterGroupName := aws.ToString(dbInstance.DBParameterGroups[0].DBParameterGroupName)
414426

415427
rdsClient, err := NewRdsClientContextE(t, ctx, awsRegion)
@@ -481,6 +493,10 @@ func GetRdsInstanceDetailsContextE(t testing.TestingT, ctx context.Context, dbIn
481493
return nil, err
482494
}
483495

496+
if len(output.DBInstances) == 0 {
497+
return nil, fmt.Errorf("RDS instance %s not found in region %s", dbInstanceID, awsRegion)
498+
}
499+
484500
return &output.DBInstances[0], nil
485501
}
486502

modules/aws/rds_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package aws_test
22

33
import (
4-
"fmt"
54
"testing"
65

76
aws "github.com/gruntwork-io/terratest/modules/aws"
@@ -146,7 +145,6 @@ func TestGetRecommendedRdsInstanceTypeErrors(t *testing.T) {
146145
t.Parallel()
147146

148147
_, err := aws.GetRecommendedRdsInstanceTypeE(t, scenerio.region, scenerio.databaseEngine, scenerio.databaseEngineVersion, scenerio.instanceTypes)
149-
fmt.Println(err)
150148
assert.EqualError(t, err, aws.NoRdsInstanceTypeError{InstanceTypeOptions: scenerio.instanceTypes, DatabaseEngine: scenerio.databaseEngine, DatabaseEngineVersion: scenerio.databaseEngineVersion}.Error())
151149
})
152150
}

modules/gcp/cloudbuild.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ func CreateBuildContextE(t testing.TestingT, ctx context.Context, projectID stri
4747

4848
defer func() { _ = service.Close() }()
4949

50+
return CreateBuildWithClient(ctx, service, projectID, build)
51+
}
52+
53+
// CreateBuildWithClient creates a new build blocking until the operation is complete using the
54+
// supplied *cloudbuild.Client. Prefer this variant in unit tests where the client is backed by a
55+
// mock gRPC server.
56+
// The ctx parameter supports cancellation and timeouts.
57+
func CreateBuildWithClient(ctx context.Context, service *cloudbuild.Client, projectID string, build *cloudbuildpb.Build) (*cloudbuildpb.Build, error) {
5058
req := &cloudbuildpb.CreateBuildRequest{
5159
ProjectId: projectID,
5260
Build: build,
@@ -100,6 +108,13 @@ func GetBuildContextE(t testing.TestingT, ctx context.Context, projectID string,
100108

101109
defer func() { _ = service.Close() }()
102110

111+
return GetBuildWithClient(ctx, service, projectID, buildID)
112+
}
113+
114+
// GetBuildWithClient gets the given build using the supplied *cloudbuild.Client. Prefer this variant
115+
// in unit tests where the client is backed by a mock gRPC server.
116+
// The ctx parameter supports cancellation and timeouts.
117+
func GetBuildWithClient(ctx context.Context, service *cloudbuild.Client, projectID string, buildID string) (*cloudbuildpb.Build, error) {
103118
req := &cloudbuildpb.GetBuildRequest{
104119
ProjectId: projectID,
105120
Id: buildID,
@@ -148,6 +163,14 @@ func GetBuildsContextE(t testing.TestingT, ctx context.Context, projectID string
148163

149164
defer func() { _ = service.Close() }()
150165

166+
return GetBuildsWithClient(ctx, service, projectID)
167+
}
168+
169+
// GetBuildsWithClient gets the list of builds for a given project using the supplied
170+
// *cloudbuild.Client. Prefer this variant in unit tests where the client is backed by a mock gRPC
171+
// server.
172+
// The ctx parameter supports cancellation and timeouts.
173+
func GetBuildsWithClient(ctx context.Context, service *cloudbuild.Client, projectID string) ([]*cloudbuildpb.Build, error) {
151174
req := &cloudbuildpb.ListBuildsRequest{
152175
ProjectId: projectID,
153176
}
@@ -205,15 +228,34 @@ func GetBuildsForTriggerContextE(t testing.TestingT, ctx context.Context, projec
205228
return nil, fmt.Errorf("GetBuildsForTriggerContextE.ListBuilds(%s) got error: %w", projectID, err)
206229
}
207230

208-
filteredBuilds := []*cloudbuildpb.Build{}
231+
return filterBuildsByTrigger(builds, triggerID), nil
232+
}
233+
234+
// GetBuildsForTriggerWithClient gets a list of builds for a specific cloud build trigger using the
235+
// supplied *cloudbuild.Client. Prefer this variant in unit tests where the client is backed by a
236+
// mock gRPC server.
237+
// The ctx parameter supports cancellation and timeouts.
238+
func GetBuildsForTriggerWithClient(ctx context.Context, service *cloudbuild.Client, projectID string, triggerID string) ([]*cloudbuildpb.Build, error) {
239+
builds, err := GetBuildsWithClient(ctx, service, projectID)
240+
if err != nil {
241+
return nil, fmt.Errorf("GetBuildsForTriggerContextE.ListBuilds(%s) got error: %w", projectID, err)
242+
}
243+
244+
return filterBuildsByTrigger(builds, triggerID), nil
245+
}
246+
247+
// filterBuildsByTrigger returns the subset of the given builds that were produced by the trigger
248+
// with the given ID.
249+
func filterBuildsByTrigger(builds []*cloudbuildpb.Build, triggerID string) []*cloudbuildpb.Build {
250+
filtered := []*cloudbuildpb.Build{}
209251

210252
for _, build := range builds {
211253
if build.GetBuildTriggerId() == triggerID {
212-
filteredBuilds = append(filteredBuilds, build)
254+
filtered = append(filtered, build)
213255
}
214256
}
215257

216-
return filteredBuilds, nil
258+
return filtered
217259
}
218260

219261
// NewCloudBuildService creates a new Cloud Build service, which is used to make Cloud Build API calls.

0 commit comments

Comments
 (0)