diff --git a/aws/resources/access_analyzer.go b/aws/resources/access_analyzer.go index ee12609d..fb753019 100644 --- a/aws/resources/access_analyzer.go +++ b/aws/resources/access_analyzer.go @@ -4,7 +4,7 @@ import ( "context" "sync" - "github.com/aws/aws-sdk-go/service/accessanalyzer" + "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/go-commons/errors" @@ -12,23 +12,25 @@ import ( ) func (analyzer *AccessAnalyzer) getAll(c context.Context, configObj config.Config) ([]*string, error) { - allAnalyzers := []*string{} - err := analyzer.Client.ListAnalyzersPagesWithContext( - analyzer.Context, - &accessanalyzer.ListAnalyzersInput{}, - func(page *accessanalyzer.ListAnalyzersOutput, lastPage bool) bool { - for _, analyzer := range page.Analyzers { - if configObj.AccessAnalyzer.ShouldInclude(config.ResourceValue{ - Time: analyzer.CreatedAt, - Name: analyzer.Name, - }) { - allAnalyzers = append(allAnalyzers, analyzer.Name) - } + var allAnalyzers []*string + paginator := accessanalyzer.NewListAnalyzersPaginator(analyzer.Client, &accessanalyzer.ListAnalyzersInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + for _, check := range page.Analyzers { + if configObj.AccessAnalyzer.ShouldInclude(config.ResourceValue{ + Time: check.CreatedAt, + Name: check.Name, + }) { + allAnalyzers = append(allAnalyzers, check.Name) } - return !lastPage - }, - ) - return allAnalyzers, errors.WithStackTrace(err) + } + } + + return allAnalyzers, nil } func (analyzer *AccessAnalyzer) nukeAll(names []*string) error { @@ -76,7 +78,7 @@ func (analyzer *AccessAnalyzer) deleteAccessAnalyzerAsync(wg *sync.WaitGroup, er defer wg.Done() input := &accessanalyzer.DeleteAnalyzerInput{AnalyzerName: analyzerName} - _, err := analyzer.Client.DeleteAnalyzerWithContext( + _, err := analyzer.Client.DeleteAnalyzer( analyzer.Context, input, ) errChan <- err diff --git a/aws/resources/access_analyzer_test.go b/aws/resources/access_analyzer_test.go index f4a36cf8..16bd2543 100644 --- a/aws/resources/access_analyzer_test.go +++ b/aws/resources/access_analyzer_test.go @@ -7,31 +7,27 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/aws" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/accessanalyzer" - "github.com/aws/aws-sdk-go/service/accessanalyzer/accessanalyzeriface" + "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" + "github.com/aws/aws-sdk-go-v2/service/accessanalyzer/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedAccessAnalyzer struct { - accessanalyzeriface.AccessAnalyzerAPI - ListAnalyzersPagesOutput accessanalyzer.ListAnalyzersOutput - DeleteAnalyzerOutput accessanalyzer.DeleteAnalyzerOutput + AccessAnalyzerAPI + ListAnalyzersOutput accessanalyzer.ListAnalyzersOutput + DeleteAnalyzerOutput accessanalyzer.DeleteAnalyzerOutput } -func (m mockedAccessAnalyzer) ListAnalyzersPagesWithContext(_ awsgo.Context, _ *accessanalyzer.ListAnalyzersInput, callback func(*accessanalyzer.ListAnalyzersOutput, bool) bool, _ ...request.Option) error { - callback(&m.ListAnalyzersPagesOutput, true) - return nil +func (m mockedAccessAnalyzer) ListAnalyzers(context.Context, *accessanalyzer.ListAnalyzersInput, ...func(*accessanalyzer.Options)) (*accessanalyzer.ListAnalyzersOutput, error) { + return &m.ListAnalyzersOutput, nil } -func (m mockedAccessAnalyzer) DeleteAnalyzerWithContext(awsgo.Context, *accessanalyzer.DeleteAnalyzerInput, ...request.Option) (*accessanalyzer.DeleteAnalyzerOutput, error) { +func (m mockedAccessAnalyzer) DeleteAnalyzer(ctx context.Context, params *accessanalyzer.DeleteAnalyzerInput, optFns ...func(*accessanalyzer.Options)) (*accessanalyzer.DeleteAnalyzerOutput, error) { return &m.DeleteAnalyzerOutput, nil } func TestAccessAnalyzer_GetAll(t *testing.T) { - t.Parallel() now := time.Now() @@ -39,15 +35,15 @@ func TestAccessAnalyzer_GetAll(t *testing.T) { testName2 := "test2" aa := AccessAnalyzer{ Client: mockedAccessAnalyzer{ - ListAnalyzersPagesOutput: accessanalyzer.ListAnalyzersOutput{ - Analyzers: []*accessanalyzer.AnalyzerSummary{ + ListAnalyzersOutput: accessanalyzer.ListAnalyzersOutput{ + Analyzers: []types.AnalyzerSummary{ { - Name: awsgo.String(testName1), - CreatedAt: awsgo.Time(now), + Name: aws.String(testName1), + CreatedAt: aws.Time(now), }, { - Name: awsgo.String(testName2), - CreatedAt: awsgo.Time(now.Add(1)), + Name: aws.String(testName2), + CreatedAt: aws.Time(now.Add(1)), }, }, }, @@ -79,20 +75,19 @@ func TestAccessAnalyzer_GetAll(t *testing.T) { expected: []string{testName1}, }, } + for name, tc := range tests { t.Run(name, func(t *testing.T) { names, err := aa.getAll(context.Background(), config.Config{ AccessAnalyzer: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) + require.Equal(t, tc.expected, aws.ToStringSlice(names)) }) } - } func TestAccessAnalyzer_NukeAll(t *testing.T) { - t.Parallel() aa := AccessAnalyzer{ @@ -101,6 +96,6 @@ func TestAccessAnalyzer_NukeAll(t *testing.T) { }, } - err := aa.nukeAll([]*string{awsgo.String("test")}) + err := aa.nukeAll([]*string{aws.String("test")}) require.NoError(t, err) } diff --git a/aws/resources/access_analyzer_types.go b/aws/resources/access_analyzer_types.go index f54452ef..9ec4d4fc 100644 --- a/aws/resources/access_analyzer_types.go +++ b/aws/resources/access_analyzer_types.go @@ -3,26 +3,31 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/accessanalyzer" - "github.com/aws/aws-sdk-go/service/accessanalyzer/accessanalyzeriface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type AccessAnalyzerAPI interface { + DeleteAnalyzer(ctx context.Context, params *accessanalyzer.DeleteAnalyzerInput, optFns ...func(*accessanalyzer.Options)) (*accessanalyzer.DeleteAnalyzerOutput, error) + ListAnalyzers(context.Context, *accessanalyzer.ListAnalyzersInput, ...func(*accessanalyzer.Options)) (*accessanalyzer.ListAnalyzersOutput, error) +} + // AccessAnalyzer - represents all AWS secrets manager secrets that should be deleted. type AccessAnalyzer struct { BaseAwsResource - Client accessanalyzeriface.AccessAnalyzerAPI + Client AccessAnalyzerAPI Region string AnalyzerNames []string } -func (analyzer *AccessAnalyzer) Init(session *session.Session) { - analyzer.Client = accessanalyzer.New(session) +func (analyzer *AccessAnalyzer) InitV2(cfg aws.Config) { + analyzer.Client = accessanalyzer.NewFromConfig(cfg) } +func (analyzer *AccessAnalyzer) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (analyzer *AccessAnalyzer) ResourceName() string { return "accessanalyzer" @@ -40,7 +45,7 @@ func (analyzer *AccessAnalyzer) MaxBatchSize() int { return 10 } -// To get the resource configuration +// GetAndSetResourceConfig To get the resource configuration func (analyzer *AccessAnalyzer) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { return configObj.AccessAnalyzer } @@ -51,13 +56,13 @@ func (analyzer *AccessAnalyzer) GetAndSetIdentifiers(c context.Context, configOb return nil, err } - analyzer.AnalyzerNames = awsgo.StringValueSlice(identifiers) + analyzer.AnalyzerNames = aws.ToStringSlice(identifiers) return analyzer.AnalyzerNames, nil } // Nuke - nuke 'em all!!! func (analyzer *AccessAnalyzer) Nuke(identifiers []string) error { - if err := analyzer.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := analyzer.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/acm.go b/aws/resources/acm.go index 53df12b9..33e76e7e 100644 --- a/aws/resources/acm.go +++ b/aws/resources/acm.go @@ -4,7 +4,8 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/service/acm" + "github.com/aws/aws-sdk-go-v2/service/acm" + "github.com/aws/aws-sdk-go-v2/service/acm/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -13,40 +14,29 @@ import ( // Returns a list of strings of ACM ARNs func (a *ACM) getAll(c context.Context, configObj config.Config) ([]*string, error) { + var acmArns []*string + paginator := acm.NewListCertificatesPaginator(a.Client, &acm.ListCertificatesInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } - params := &acm.ListCertificatesInput{} - - acmArns := []*string{} - err := a.Client.ListCertificatesPagesWithContext(a.Context, params, - func(page *acm.ListCertificatesOutput, lastPage bool) bool { - for i := range page.CertificateSummaryList { - logging.Debug(fmt.Sprintf("Found ACM %s with domain name %s", - *page.CertificateSummaryList[i].CertificateArn, *page.CertificateSummaryList[i].DomainName)) - if a.shouldInclude(page.CertificateSummaryList[i], configObj) { - logging.Debug(fmt.Sprintf( - "Including ACM %s", *page.CertificateSummaryList[i].CertificateArn)) - acmArns = append(acmArns, page.CertificateSummaryList[i].CertificateArn) - } else { - logging.Debug(fmt.Sprintf( - "Skipping ACM %s", *page.CertificateSummaryList[i].CertificateArn)) - } + for _, cert := range page.CertificateSummaryList { + logging.Debug(fmt.Sprintf("Found ACM %s with domain name %s", *cert.CertificateArn, *cert.DomainName)) + if a.shouldInclude(cert, configObj) { + logging.Debug(fmt.Sprintf("Including ACM %s", *cert.CertificateArn)) + acmArns = append(acmArns, cert.CertificateArn) + } else { + logging.Debug(fmt.Sprintf("Skipping ACM %s", *cert.CertificateArn)) } - - return !lastPage - }, - ) - if err != nil { - return nil, errors.WithStackTrace(err) + } } return acmArns, nil } -func (a *ACM) shouldInclude(acm *acm.CertificateSummary, configObj config.Config) bool { - if acm == nil { - return false - } - +func (a *ACM) shouldInclude(acm types.CertificateSummary, configObj config.Config) bool { if acm.InUse != nil && *acm.InUse { logging.Debug(fmt.Sprintf("ACM %s is in use", *acm.CertificateArn)) return false @@ -69,14 +59,13 @@ func (a *ACM) nukeAll(arns []*string) error { } logging.Debugf("Deleting all ACMs in region %s", a.Region) - deletedCount := 0 for _, acmArn := range arns { params := &acm.DeleteCertificateInput{ CertificateArn: acmArn, } - _, err := a.Client.DeleteCertificateWithContext(a.Context, params) + _, err := a.Client.DeleteCertificate(a.Context, params) if err != nil { logging.Debugf("[Failed] %s", err) } else { diff --git a/aws/resources/acm_test.go b/aws/resources/acm_test.go index 0bd4a74e..9dc7277a 100644 --- a/aws/resources/acm_test.go +++ b/aws/resources/acm_test.go @@ -6,46 +6,37 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/acm" - "github.com/aws/aws-sdk-go/service/acm/acmiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/acm" + "github.com/aws/aws-sdk-go-v2/service/acm/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedACM struct { - acmiface.ACMAPI - ListCertificatesOutput acm.ListCertificatesOutput + ACMServiceAPI DeleteCertificateOutput acm.DeleteCertificateOutput + ListCertificatesOutput acm.ListCertificatesOutput } -func (m mockedACM) ListCertificatesPagesWithContext( - _ aws.Context, - _ *acm.ListCertificatesInput, - fn func(*acm.ListCertificatesOutput, bool) bool, - _ ...request.Option, -) error { - // Only need to return mocked response output - fn(&m.ListCertificatesOutput, true) - return nil +func (m mockedACM) ListCertificates(ctx context.Context, params *acm.ListCertificatesInput, optFns ...func(*acm.Options)) (*acm.ListCertificatesOutput, error) { + return &m.ListCertificatesOutput, nil } -func (m mockedACM) DeleteCertificateWithContext(_ aws.Context, input *acm.DeleteCertificateInput, _ ...request.Option) (*acm.DeleteCertificateOutput, error) { +func (m mockedACM) DeleteCertificate(ctx context.Context, params *acm.DeleteCertificateInput, optFns ...func(*acm.Options)) (*acm.DeleteCertificateOutput, error) { return &m.DeleteCertificateOutput, nil } func TestACMGetAll(t *testing.T) { - t.Parallel() testDomainName := "test-domain-name" testArn := "test-arn" now := time.Now() - acm := ACM{ + acmService := ACM{ Client: mockedACM{ ListCertificatesOutput: acm.ListCertificatesOutput{ - CertificateSummaryList: []*acm.CertificateSummary{ + CertificateSummaryList: []types.CertificateSummary{ { DomainName: &testDomainName, CreatedAt: &now, @@ -57,12 +48,12 @@ func TestACMGetAll(t *testing.T) { } // without any filters - acms, err := acm.getAll(context.Background(), config.Config{}) + acms, err := acmService.getAll(context.Background(), config.Config{}) require.NoError(t, err) - require.Contains(t, aws.StringValueSlice(acms), testArn) + require.Contains(t, aws.ToStringSlice(acms), testArn) // filtering domain names - acms, err = acm.getAll(context.Background(), config.Config{ + acms, err = acmService.getAll(context.Background(), config.Config{ ACM: config.ResourceType{ ExcludeRule: config.FilterRule{ NamesRegExp: []config.Expression{{ @@ -70,29 +61,28 @@ func TestACMGetAll(t *testing.T) { }}}}, }) require.NoError(t, err) - require.NotContains(t, aws.StringValueSlice(acms), testArn) + require.NotContains(t, aws.ToStringSlice(acms), testArn) // filtering with time - acms, err = acm.getAll(context.Background(), config.Config{ + acms, err = acmService.getAll(context.Background(), config.Config{ ACM: config.ResourceType{ ExcludeRule: config.FilterRule{ TimeAfter: aws.Time(now.Add(-1)), }}, }) require.NoError(t, err) - require.NotContains(t, aws.StringValueSlice(acms), testArn) + require.NotContains(t, aws.ToStringSlice(acms), testArn) } func TestACMGetAll_FilterInUse(t *testing.T) { - t.Parallel() testDomainName := "test-domain-name" testArn := "test-arn" - acm := ACM{ + acmService := ACM{ Client: mockedACM{ ListCertificatesOutput: acm.ListCertificatesOutput{ - CertificateSummaryList: []*acm.CertificateSummary{ + CertificateSummaryList: []types.CertificateSummary{ { DomainName: &testDomainName, InUse: aws.Bool(true), @@ -103,22 +93,21 @@ func TestACMGetAll_FilterInUse(t *testing.T) { }, } - acms, err := acm.getAll(context.Background(), config.Config{}) + acms, err := acmService.getAll(context.Background(), config.Config{}) require.NoError(t, err) require.NotContains(t, acms, testArn) } func TestACMNukeAll(t *testing.T) { - t.Parallel() testDomainName := "test-domain-name" - acm := ACM{ + acmService := ACM{ Client: mockedACM{ DeleteCertificateOutput: acm.DeleteCertificateOutput{}, }, } - err := acm.nukeAll([]*string{&testDomainName}) + err := acmService.nukeAll([]*string{&testDomainName}) require.NoError(t, err) } diff --git a/aws/resources/acm_types.go b/aws/resources/acm_types.go index c0533292..9d14997a 100644 --- a/aws/resources/acm_types.go +++ b/aws/resources/acm_types.go @@ -3,26 +3,31 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/acm" - "github.com/aws/aws-sdk-go/service/acm/acmiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/acm" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) -// ACMPA - represents all ACMPA +type ACMServiceAPI interface { + DeleteCertificate(ctx context.Context, params *acm.DeleteCertificateInput, optFns ...func(*acm.Options)) (*acm.DeleteCertificateOutput, error) + ListCertificates(ctx context.Context, params *acm.ListCertificatesInput, optFns ...func(*acm.Options)) (*acm.ListCertificatesOutput, error) +} + +// ACM - represents all ACM type ACM struct { BaseAwsResource - Client acmiface.ACMAPI + Client ACMServiceAPI Region string ARNs []string } -func (a *ACM) Init(session *session.Session) { - a.Client = acm.New(session) +func (a *ACM) InitV2(cfg aws.Config) { + a.Client = acm.NewFromConfig(cfg) } +func (a *ACM) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (a *ACM) ResourceName() string { return "acm" @@ -38,7 +43,7 @@ func (a *ACM) MaxBatchSize() int { return 10 } -// To get the resource configuration +// GetAndSetResourceConfig To get the resource configuration func (a *ACM) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { return configObj.ACM } @@ -49,13 +54,13 @@ func (a *ACM) GetAndSetIdentifiers(c context.Context, configObj config.Config) ( return nil, err } - a.ARNs = awsgo.StringValueSlice(identifiers) + a.ARNs = aws.ToStringSlice(identifiers) return a.ARNs, nil } // Nuke - nuke 'em all!!! func (a *ACM) Nuke(arns []string) error { - if err := a.nukeAll(awsgo.StringSlice(arns)); err != nil { + if err := a.nukeAll(aws.StringSlice(arns)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/acmpca.go b/aws/resources/acmpca.go index a93bc1de..cb1a8048 100644 --- a/aws/resources/acmpca.go +++ b/aws/resources/acmpca.go @@ -6,8 +6,9 @@ import ( "sync" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/acmpca" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/acmpca" + "github.com/aws/aws-sdk-go-v2/service/acmpca/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -15,34 +16,30 @@ import ( "github.com/hashicorp/go-multierror" ) -// GetAll returns a list of all arns of ACMPCA, which can be deleted. +// GetAll returns a list of all arn's of ACMPCA, which can be deleted. func (ap *ACMPCA) getAll(c context.Context, configObj config.Config) ([]*string, error) { var arns []*string - paginationErr := ap.Client.ListCertificateAuthoritiesPagesWithContext( - ap.Context, - &acmpca.ListCertificateAuthoritiesInput{}, - func(p *acmpca.ListCertificateAuthoritiesOutput, lastPage bool) bool { - for _, ca := range p.CertificateAuthorities { - if ap.shouldInclude(ca, configObj) { - arns = append(arns, ca.Arn) - } + + paginator := acmpca.NewListCertificateAuthoritiesPaginator(ap.Client, &acmpca.ListCertificateAuthoritiesInput{}) + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + for _, ca := range page.CertificateAuthorities { + if ap.shouldInclude(ca, configObj) { + arns = append(arns, ca.Arn) } - return !lastPage - }) - if paginationErr != nil { - return nil, errors.WithStackTrace(paginationErr) + } } return arns, nil } -func (ap *ACMPCA) shouldInclude(ca *acmpca.CertificateAuthority, configObj config.Config) bool { - if ca == nil { - return false - } - - statusSafe := aws.StringValue(ca.Status) - if statusSafe == acmpca.CertificateAuthorityStatusDeleted { +func (ap *ACMPCA) shouldInclude(ca types.CertificateAuthority, configObj config.Config) bool { + statusSafe := ca.Status + if statusSafe == types.CertificateAuthorityStatusDeleted { return false } @@ -50,15 +47,15 @@ func (ap *ACMPCA) shouldInclude(ca *acmpca.CertificateAuthority, configObj confi // unless it was never changed and createAt time is used. var referenceTime time.Time if ca.LastStateChangeAt == nil { - referenceTime = aws.TimeValue(ca.CreatedAt) + referenceTime = aws.ToTime(ca.CreatedAt) } else { - referenceTime = aws.TimeValue(ca.LastStateChangeAt) + referenceTime = aws.ToTime(ca.LastStateChangeAt) } return configObj.ACMPCA.ShouldInclude(config.ResourceValue{Time: &referenceTime}) } -// nukeAll will delete all ACMPCA, which are given by a list of arns. +// nukeAll will delete all ACMPCA, which are given by a list of arn's. func (ap *ACMPCA) nukeAll(arns []*string) error { if len(arns) == 0 { logging.Debugf("No ACMPCA to nuke in region %s", ap.Region) @@ -94,7 +91,7 @@ func (ap *ACMPCA) deleteAsync(wg *sync.WaitGroup, errChan chan error, arn *strin defer wg.Done() logging.Debugf("Fetching details of CA to be deleted for ACMPCA %s in region %s", *arn, ap.Region) - details, detailsErr := ap.Client.DescribeCertificateAuthorityWithContext( + details, detailsErr := ap.Client.DescribeCertificateAuthority( ap.Context, &acmpca.DescribeCertificateAuthorityInput{CertificateAuthorityArn: arn}) if detailsErr != nil { @@ -102,26 +99,26 @@ func (ap *ACMPCA) deleteAsync(wg *sync.WaitGroup, errChan chan error, arn *strin return } if details.CertificateAuthority == nil { - errChan <- fmt.Errorf("could not find CA %s", aws.StringValue(arn)) + errChan <- fmt.Errorf("could not find CA %s", aws.ToString(arn)) return } - if details.CertificateAuthority.Status == nil { - errChan <- fmt.Errorf("could not fetch status for CA %s", aws.StringValue(arn)) + if details.CertificateAuthority.Status == "" { + errChan <- fmt.Errorf("could not fetch status for CA %s", aws.ToString(arn)) return } // find out, whether we have to disable the CA first, prior to deletion. - statusSafe := aws.StringValue(details.CertificateAuthority.Status) - shouldUpdateStatus := statusSafe != acmpca.CertificateAuthorityStatusCreating && - statusSafe != acmpca.CertificateAuthorityStatusPendingCertificate && - statusSafe != acmpca.CertificateAuthorityStatusDisabled && - statusSafe != acmpca.CertificateAuthorityStatusDeleted + statusSafe := details.CertificateAuthority.Status + shouldUpdateStatus := statusSafe != types.CertificateAuthorityStatusCreating && + statusSafe != types.CertificateAuthorityStatusPendingCertificate && + statusSafe != types.CertificateAuthorityStatusDisabled && + statusSafe != types.CertificateAuthorityStatusDeleted if shouldUpdateStatus { logging.Debugf("Setting status to 'DISABLED' for ACMPCA %s in region %s", *arn, ap.Region) - if _, updateStatusErr := ap.Client.UpdateCertificateAuthorityWithContext(ap.Context, &acmpca.UpdateCertificateAuthorityInput{ + if _, updateStatusErr := ap.Client.UpdateCertificateAuthority(ap.Context, &acmpca.UpdateCertificateAuthorityInput{ CertificateAuthorityArn: arn, - Status: aws.String(acmpca.CertificateAuthorityStatusDisabled), + Status: types.CertificateAuthorityStatusDisabled, }); updateStatusErr != nil { errChan <- updateStatusErr return @@ -130,17 +127,17 @@ func (ap *ACMPCA) deleteAsync(wg *sync.WaitGroup, errChan chan error, arn *strin logging.Debugf("Did set status to 'DISABLED' for ACMPCA: %s in region %s", *arn, ap.Region) } - _, deleteErr := ap.Client.DeleteCertificateAuthorityWithContext(ap.Context, &acmpca.DeleteCertificateAuthorityInput{ + _, deleteErr := ap.Client.DeleteCertificateAuthority(ap.Context, &acmpca.DeleteCertificateAuthorityInput{ CertificateAuthorityArn: arn, // the range is 7 to 30 days. // since cloud-nuke should not be used in production, // we assume that the minimum (7 days) is fine. - PermanentDeletionTimeInDays: aws.Int64(7), + PermanentDeletionTimeInDays: aws.Int32(7), }) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(arn), + Identifier: aws.ToString(arn), ResourceType: "ACM Private CA (ACMPCA)", Error: deleteErr, } diff --git a/aws/resources/acmpca_test.go b/aws/resources/acmpca_test.go index 1b2ef953..2bb758b9 100644 --- a/aws/resources/acmpca_test.go +++ b/aws/resources/acmpca_test.go @@ -5,43 +5,38 @@ import ( "testing" "time" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - - "github.com/aws/aws-sdk-go/service/acmpca" - "github.com/aws/aws-sdk-go/service/acmpca/acmpcaiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/acmpca" + "github.com/aws/aws-sdk-go-v2/service/acmpca/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/require" ) type mockedACMPCA struct { - acmpcaiface.ACMPCAAPI - ListCertificateAuthoritiesOutput acmpca.ListCertificateAuthoritiesOutput - DescribeCertificateAuthorityOutput acmpca.DescribeCertificateAuthorityOutput - UpdateCertificateAuthorityOutput acmpca.UpdateCertificateAuthorityOutput - DeleteCertificateAuthorityOutput acmpca.DeleteCertificateAuthorityOutput + ACMPCAServiceAPI + acmpca.DeleteCertificateAuthorityOutput + acmpca.DescribeCertificateAuthorityOutput + acmpca.ListCertificateAuthoritiesOutput + acmpca.UpdateCertificateAuthorityOutput } -func (m mockedACMPCA) ListCertificateAuthoritiesPagesWithContext(_ awsgo.Context, _ *acmpca.ListCertificateAuthoritiesInput, fn func(*acmpca.ListCertificateAuthoritiesOutput, bool) bool, _ ...request.Option) error { - // Only need to return mocked response output - fn(&m.ListCertificateAuthoritiesOutput, true) - return nil +func (m mockedACMPCA) DeleteCertificateAuthority(ctx context.Context, params *acmpca.DeleteCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.DeleteCertificateAuthorityOutput, error) { + return &m.DeleteCertificateAuthorityOutput, nil } -func (m mockedACMPCA) DescribeCertificateAuthorityWithContext(_ awsgo.Context, _ *acmpca.DescribeCertificateAuthorityInput, _ ...request.Option) (*acmpca.DescribeCertificateAuthorityOutput, error) { +func (m mockedACMPCA) DescribeCertificateAuthority(ctx context.Context, params *acmpca.DescribeCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.DescribeCertificateAuthorityOutput, error) { return &m.DescribeCertificateAuthorityOutput, nil } -func (m mockedACMPCA) UpdateCertificateAuthorityWithContext(_ awsgo.Context, _ *acmpca.UpdateCertificateAuthorityInput, _ ...request.Option) (*acmpca.UpdateCertificateAuthorityOutput, error) { - return &m.UpdateCertificateAuthorityOutput, nil +func (m mockedACMPCA) ListCertificateAuthorities(ctx context.Context, params *acmpca.ListCertificateAuthoritiesInput, optFns ...func(*acmpca.Options)) (*acmpca.ListCertificateAuthoritiesOutput, error) { + return &m.ListCertificateAuthoritiesOutput, nil } -func (m mockedACMPCA) DeleteCertificateAuthorityWithContext(_ awsgo.Context, _ *acmpca.DeleteCertificateAuthorityInput, _ ...request.Option) (*acmpca.DeleteCertificateAuthorityOutput, error) { - return &m.DeleteCertificateAuthorityOutput, nil +func (m mockedACMPCA) UpdateCertificateAuthority(ctx context.Context, params *acmpca.UpdateCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.UpdateCertificateAuthorityOutput, error) { + return &m.UpdateCertificateAuthorityOutput, nil } func TestAcmPcaGetAll(t *testing.T) { - t.Parallel() testArn := "test-arn" @@ -49,7 +44,7 @@ func TestAcmPcaGetAll(t *testing.T) { acmPca := ACMPCA{ Client: mockedACMPCA{ ListCertificateAuthoritiesOutput: acmpca.ListCertificateAuthoritiesOutput{ - CertificateAuthorities: []*acmpca.CertificateAuthority{ + CertificateAuthorities: []types.CertificateAuthority{ { CreatedAt: &now, Arn: &testArn, @@ -62,20 +57,20 @@ func TestAcmPcaGetAll(t *testing.T) { // without filters arns, err := acmPca.getAll(context.Background(), config.Config{}) require.NoError(t, err) - require.Contains(t, awsgo.StringValueSlice(arns), testArn) + require.Contains(t, aws.ToStringSlice(arns), testArn) // with exclude after filter arns, err = acmPca.getAll(context.Background(), config.Config{ ACMPCA: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: awsgo.Time(now.Add(-1))}}, + TimeAfter: aws.Time(now.Add(-1))}}, }) + require.NoError(t, err) - require.NotContains(t, awsgo.StringValueSlice(arns), testArn) + require.NotContains(t, aws.ToStringSlice(arns), testArn) } func TestAcmPcaNukeAll_DisabledCA(t *testing.T) { - t.Parallel() testArn := "test-arn" @@ -83,8 +78,8 @@ func TestAcmPcaNukeAll_DisabledCA(t *testing.T) { acmPca := ACMPCA{ Client: mockedACMPCA{ DescribeCertificateAuthorityOutput: acmpca.DescribeCertificateAuthorityOutput{ - CertificateAuthority: &acmpca.CertificateAuthority{ - Status: awsgo.String(acmpca.CertificateAuthorityStatusDisabled), + CertificateAuthority: &types.CertificateAuthority{ + Status: types.CertificateAuthorityStatusDisabled, CreatedAt: &now, Arn: &testArn, }, @@ -98,7 +93,6 @@ func TestAcmPcaNukeAll_DisabledCA(t *testing.T) { } func TestAcmPcaNukeAll_EnabledCA(t *testing.T) { - t.Parallel() testArn := "test-arn" @@ -106,8 +100,8 @@ func TestAcmPcaNukeAll_EnabledCA(t *testing.T) { acmPca := ACMPCA{ Client: mockedACMPCA{ DescribeCertificateAuthorityOutput: acmpca.DescribeCertificateAuthorityOutput{ - CertificateAuthority: &acmpca.CertificateAuthority{ - Status: awsgo.String(acmpca.CertificateAuthorityStatusActive), + CertificateAuthority: &types.CertificateAuthority{ + Status: types.CertificateAuthorityStatusActive, CreatedAt: &now, Arn: &testArn, }, diff --git a/aws/resources/acmpca_types.go b/aws/resources/acmpca_types.go index e7cb67b3..5d7007b4 100644 --- a/aws/resources/acmpca_types.go +++ b/aws/resources/acmpca_types.go @@ -3,26 +3,33 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/acmpca" - "github.com/aws/aws-sdk-go/service/acmpca/acmpcaiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/acmpca" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) -// ACMPA - represents all ACMPA +type ACMPCAServiceAPI interface { + DeleteCertificateAuthority(ctx context.Context, params *acmpca.DeleteCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.DeleteCertificateAuthorityOutput, error) + DescribeCertificateAuthority(ctx context.Context, params *acmpca.DescribeCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.DescribeCertificateAuthorityOutput, error) + ListCertificateAuthorities(ctx context.Context, params *acmpca.ListCertificateAuthoritiesInput, optFns ...func(*acmpca.Options)) (*acmpca.ListCertificateAuthoritiesOutput, error) + UpdateCertificateAuthority(ctx context.Context, params *acmpca.UpdateCertificateAuthorityInput, optFns ...func(*acmpca.Options)) (*acmpca.UpdateCertificateAuthorityOutput, error) +} + +// ACMPCA - represents all ACMPA type ACMPCA struct { BaseAwsResource - Client acmpcaiface.ACMPCAAPI + Client ACMPCAServiceAPI Region string ARNs []string } -func (ap *ACMPCA) Init(session *session.Session) { - ap.Client = acmpca.New(session) +func (ap *ACMPCA) InitV2(cfg aws.Config) { + ap.Client = acmpca.NewFromConfig(cfg) } +func (ap *ACMPCA) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (ap *ACMPCA) ResourceName() string { return "acmpca" @@ -47,13 +54,13 @@ func (ap *ACMPCA) GetAndSetIdentifiers(c context.Context, configObj config.Confi return nil, err } - ap.ARNs = awsgo.StringValueSlice(identifiers) + ap.ARNs = aws.ToStringSlice(identifiers) return ap.ARNs, nil } // Nuke - nuke 'em all!!! func (ap *ACMPCA) Nuke(arns []string) error { - if err := ap.nukeAll(awsgo.StringSlice(arns)); err != nil { + if err := ap.nukeAll(aws.StringSlice(arns)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/ami.go b/aws/resources/ami.go index 9fdcd0f7..5dfe1c0a 100644 --- a/aws/resources/ami.go +++ b/aws/resources/ami.go @@ -4,11 +4,10 @@ import ( "context" "strings" - awsgo "github.com/aws/aws-sdk-go/aws" "github.com/gruntwork-io/cloud-nuke/util" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -17,49 +16,53 @@ import ( // Returns a formatted string of AMI Image ids func (ami *AMIs) getAll(c context.Context, configObj config.Config) ([]*string, error) { - params := &ec2.DescribeImagesInput{ - Owners: []*string{awsgo.String("self")}, - } - - output, err := ami.Client.DescribeImagesWithContext(ami.Context, params) - if err != nil { - return nil, errors.WithStackTrace(err) - } - var imageIds []*string - for _, image := range output.Images { - createdTime, err := util.ParseTimestamp(image.CreationDate) + paginator := ec2.NewDescribeImagesPaginator(ami.Client, &ec2.DescribeImagesInput{ + Owners: []string{"self"}, + }) + + for paginator.HasMorePages() { + page, err := paginator.NextPage(c) if err != nil { - return nil, err + return nil, errors.WithStackTrace(err) } - // Check if the image has a tag that indicates AWS management - isAWSManaged := false - for _, tag := range image.Tags { - if *tag.Key == "aws-managed" && *tag.Value == "true" { - isAWSManaged = true - break + for _, image := range page.Images { + + createdTime, errTimeParse := util.ParseTimestamp(image.CreationDate) + if errTimeParse != nil { + return nil, errTimeParse } - } - // Skip AWS managed images and images created by AWS Backup - if isAWSManaged || strings.HasPrefix(*image.Name, "AwsBackup") { - continue - } + // Check if the image has a tag that indicates AWS management + isAWSManaged := false + for _, tag := range image.Tags { + if *tag.Key == "aws-managed" && *tag.Value == "true" { + isAWSManaged = true + break + } + } + + // Skip AWS managed images and images created by AWS Backup + if isAWSManaged || strings.HasPrefix(*image.Name, "AwsBackup") { + continue + } + + if configObj.AMI.ShouldInclude(config.ResourceValue{ + Name: image.Name, + Time: createdTime, + }) { + imageIds = append(imageIds, image.ImageId) + } - if configObj.AMI.ShouldInclude(config.ResourceValue{ - Name: image.Name, - Time: createdTime, - }) { - imageIds = append(imageIds, image.ImageId) } } // checking the nukable permissions ami.VerifyNukablePermissions(imageIds, func(id *string) error { - _, err := ami.Client.DeregisterImageWithContext(ami.Context, &ec2.DeregisterImageInput{ + _, err := ami.Client.DeregisterImage(ami.Context, &ec2.DeregisterImageInput{ ImageId: id, - DryRun: awsgo.Bool(true), + DryRun: aws.Bool(true), }) return err }) @@ -79,18 +82,18 @@ func (ami *AMIs) nukeAll(imageIds []*string) error { deletedCount := 0 for _, imageID := range imageIds { - if nukable, reason := ami.IsNukable(awsgo.StringValue(imageID)); !nukable { - logging.Debugf("[Skipping] %s nuke because %v", awsgo.StringValue(imageID), reason) + if nukable, reason := ami.IsNukable(aws.ToString(imageID)); !nukable { + logging.Debugf("[Skipping] %s nuke because %v", aws.ToString(imageID), reason) continue } - _, err := ami.Client.DeregisterImageWithContext(ami.Context, &ec2.DeregisterImageInput{ + _, err := ami.Client.DeregisterImage(ami.Context, &ec2.DeregisterImageInput{ ImageId: imageID, }) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(imageID), + Identifier: aws.ToString(imageID), ResourceType: "Amazon Machine Image (AMI)", Error: err, } diff --git a/aws/resources/ami_test.go b/aws/resources/ami_test.go index ec05c4f6..50f814fc 100644 --- a/aws/resources/ami_test.go +++ b/aws/resources/ami_test.go @@ -7,31 +7,27 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/assert" - - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" ) type mockedAMI struct { - ec2iface.EC2API - DescribeImagesOutput ec2.DescribeImagesOutput + AMIsAPI DeregisterImageOutput ec2.DeregisterImageOutput + DescribeImagesOutput ec2.DescribeImagesOutput } -func (m mockedAMI) DescribeImagesWithContext(_ awsgo.Context, _ *ec2.DescribeImagesInput, _ ...request.Option) (*ec2.DescribeImagesOutput, error) { - return &m.DescribeImagesOutput, nil +func (m mockedAMI) DeregisterImage(ctx context.Context, params *ec2.DeregisterImageInput, optFns ...func(*ec2.Options)) (*ec2.DeregisterImageOutput, error) { + return &m.DeregisterImageOutput, nil } -func (m mockedAMI) DeregisterImageWithContext(_ awsgo.Context, _ *ec2.DeregisterImageInput, _ ...request.Option) (*ec2.DeregisterImageOutput, error) { - return &m.DeregisterImageOutput, nil +func (m mockedAMI) DescribeImages(ctx context.Context, params *ec2.DescribeImagesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error) { + return &m.DescribeImagesOutput, nil } func TestAMIGetAll_SkipAWSManaged(t *testing.T) { - t.Parallel() testName := "test-ami" @@ -41,12 +37,12 @@ func TestAMIGetAll_SkipAWSManaged(t *testing.T) { acm := AMIs{ Client: mockedAMI{ DescribeImagesOutput: ec2.DescribeImagesOutput{ - Images: []*ec2.Image{ + Images: []types.Image{ { ImageId: &testImageId1, Name: &testName, - CreationDate: awsgo.String(now.Format("2006-01-02T15:04:05.000Z")), - Tags: []*ec2.Tag{ + CreationDate: aws.String(now.Format("2006-01-02T15:04:05.000Z")), + Tags: []types.Tag{ { Key: aws.String("aws-managed"), Value: aws.String("true"), @@ -56,8 +52,8 @@ func TestAMIGetAll_SkipAWSManaged(t *testing.T) { { ImageId: &testImageId2, Name: aws.String("AwsBackup_Test"), - CreationDate: awsgo.String(now.Format("2006-01-02T15:04:05.000Z")), - Tags: []*ec2.Tag{ + CreationDate: aws.String(now.Format("2006-01-02T15:04:05.000Z")), + Tags: []types.Tag{ { Key: aws.String("aws-managed"), Value: aws.String("true"), @@ -71,12 +67,11 @@ func TestAMIGetAll_SkipAWSManaged(t *testing.T) { amis, err := acm.getAll(context.Background(), config.Config{}) assert.NoError(t, err) - assert.NotContains(t, awsgo.StringValueSlice(amis), testImageId1) - assert.NotContains(t, awsgo.StringValueSlice(amis), testImageId2) + assert.NotContains(t, aws.ToStringSlice(amis), testImageId1) + assert.NotContains(t, aws.ToStringSlice(amis), testImageId2) } func TestAMIGetAll(t *testing.T) { - t.Parallel() testName := "test-ami" @@ -85,10 +80,10 @@ func TestAMIGetAll(t *testing.T) { acm := AMIs{ Client: mockedAMI{ DescribeImagesOutput: ec2.DescribeImagesOutput{ - Images: []*ec2.Image{{ + Images: []types.Image{{ ImageId: &testImageId, Name: &testName, - CreationDate: awsgo.String(now.Format("2006-01-02T15:04:05.000Z")), + CreationDate: aws.String(now.Format("2006-01-02T15:04:05.000Z")), }}, }, }, @@ -97,7 +92,7 @@ func TestAMIGetAll(t *testing.T) { // without filters amis, err := acm.getAll(context.Background(), config.Config{}) assert.NoError(t, err) - assert.Contains(t, awsgo.StringValueSlice(amis), testImageId) + assert.Contains(t, aws.ToStringSlice(amis), testImageId) // with name filter amis, err = acm.getAll(context.Background(), config.Config{ @@ -107,19 +102,18 @@ func TestAMIGetAll(t *testing.T) { RE: *regexp.MustCompile("test-ami"), }}}}}) assert.NoError(t, err) - assert.NotContains(t, awsgo.StringValueSlice(amis), testImageId) + assert.NotContains(t, aws.ToStringSlice(amis), testImageId) // with time filter amis, err = acm.getAll(context.Background(), config.Config{ AMI: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: awsgo.Time(now.Add(-12 * time.Hour))}}}) + TimeAfter: aws.Time(now.Add(-12 * time.Hour))}}}) assert.NoError(t, err) - assert.NotContains(t, awsgo.StringValueSlice(amis), testImageId) + assert.NotContains(t, aws.ToStringSlice(amis), testImageId) } func TestAMINukeAll(t *testing.T) { - t.Parallel() testName := "test-ami" diff --git a/aws/resources/ami_types.go b/aws/resources/ami_types.go index 6d353074..1a7725e8 100644 --- a/aws/resources/ami_types.go +++ b/aws/resources/ami_types.go @@ -3,26 +3,31 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type AMIsAPI interface { + DeregisterImage(ctx context.Context, params *ec2.DeregisterImageInput, optFns ...func(*ec2.Options)) (*ec2.DeregisterImageOutput, error) + DescribeImages(ctx context.Context, params *ec2.DescribeImagesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error) +} + // AMIs - represents all user owned AMIs type AMIs struct { BaseAwsResource - Client ec2iface.EC2API + Client AMIsAPI Region string ImageIds []string } -func (ami *AMIs) Init(session *session.Session) { - ami.Client = ec2.New(session) +func (ami *AMIs) InitV2(cfg aws.Config) { + ami.Client = ec2.NewFromConfig(cfg) } +func (ami *AMIs) IsUsingV2() bool { return true } + // ResourceName - the simple name of the aws resource func (ami *AMIs) ResourceName() string { return "ami" @@ -48,13 +53,13 @@ func (ami *AMIs) GetAndSetIdentifiers(c context.Context, configObj config.Config return nil, err } - ami.ImageIds = awsgo.StringValueSlice(identifiers) + ami.ImageIds = aws.ToStringSlice(identifiers) return ami.ImageIds, nil } // Nuke - nuke 'em all!!! func (ami *AMIs) Nuke(identifiers []string) error { - if err := ami.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := ami.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/apigateway.go b/aws/resources/apigateway.go index 3600b120..c636b931 100644 --- a/aws/resources/apigateway.go +++ b/aws/resources/apigateway.go @@ -4,8 +4,8 @@ import ( "context" "sync" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/apigateway" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigateway" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -14,7 +14,7 @@ import ( ) func (gateway *ApiGateway) getAll(c context.Context, configObj config.Config) ([]*string, error) { - result, err := gateway.Client.GetRestApisWithContext(gateway.Context, &apigateway.GetRestApisInput{}) + result, err := gateway.Client.GetRestApis(c, &apigateway.GetRestApisInput{}) if err != nil { return []*string{}, errors.WithStackTrace(err) } @@ -73,12 +73,12 @@ func (gateway *ApiGateway) getAttachedStageClientCerts(apigwID *string) ([]*stri var clientCerts []*string // remove the client certificate attached with the stages - stages, err := gateway.Client.GetStagesWithContext(gateway.Context, &apigateway.GetStagesInput{ + stages, err := gateway.Client.GetStages(gateway.Context, &apigateway.GetStagesInput{ RestApiId: apigwID, }) if err != nil { - return clientCerts, err + return nil, err } // get the stages attached client certificates for _, stage := range stages.Item { @@ -95,7 +95,7 @@ func (gateway *ApiGateway) removeAttachedClientCertificates(clientCerts []*strin for _, cert := range clientCerts { logging.Debugf("Deleting Client Certificate %s", *cert) - _, err := gateway.Client.DeleteClientCertificateWithContext(gateway.Context, &apigateway.DeleteClientCertificateInput{ + _, err := gateway.Client.DeleteClientCertificate(gateway.Context, &apigateway.DeleteClientCertificateInput{ ClientCertificateId: cert, }) if err != nil { @@ -113,7 +113,7 @@ func (gateway *ApiGateway) nukeAsync( clientCerts, err := gateway.getAttachedStageClientCerts(apigwID) input := &apigateway.DeleteRestApiInput{RestApiId: apigwID} - _, err = gateway.Client.DeleteRestApiWithContext(gateway.Context, input) + _, err = gateway.Client.DeleteRestApi(gateway.Context, input) // When the rest-api endpoint delete successfully, then remove attached client certs if err == nil { @@ -133,10 +133,10 @@ func (gateway *ApiGateway) nukeAsync( if err == nil { logging.Debugf("["+ - "OK] API Gateway (v1) %s deleted in %s", aws.StringValue(apigwID), gateway.Region) + "OK] API Gateway (v1) %s deleted in %s", aws.ToString(apigwID), gateway.Region) return } logging.Debugf( - "[Failed] Error deleting API Gateway (v1) %s in %s", aws.StringValue(apigwID), gateway.Region) + "[Failed] Error deleting API Gateway (v1) %s in %s", aws.ToString(apigwID), gateway.Region) } diff --git a/aws/resources/apigateway_test.go b/aws/resources/apigateway_test.go index 578e74b2..793f16bc 100644 --- a/aws/resources/apigateway_test.go +++ b/aws/resources/apigateway_test.go @@ -5,11 +5,9 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/apigateway" - "github.com/aws/aws-sdk-go/service/apigateway/apigatewayiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigateway" + "github.com/aws/aws-sdk-go-v2/service/apigateway/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/assert" @@ -17,64 +15,61 @@ import ( ) type mockedApiGateway struct { - apigatewayiface.APIGatewayAPI - GetRestApisResp apigateway.GetRestApisOutput - DeleteRestApiResp apigateway.DeleteRestApiOutput + ApiGatewayServiceAPI + GetRestApisOutput apigateway.GetRestApisOutput GetStagesOutput apigateway.GetStagesOutput DeleteClientCertificateOutput apigateway.DeleteClientCertificateOutput + DeleteRestApiOutput apigateway.DeleteRestApiOutput } -func (m mockedApiGateway) GetRestApisWithContext(_ awsgo.Context, _ *apigateway.GetRestApisInput, _ ...request.Option) (*apigateway.GetRestApisOutput, error) { - // Only need to return mocked response output - return &m.GetRestApisResp, nil +func (m mockedApiGateway) GetRestApis(ctx context.Context, params *apigateway.GetRestApisInput, optFns ...func(*apigateway.Options)) (*apigateway.GetRestApisOutput, error) { + return &m.GetRestApisOutput, nil } - -func (m mockedApiGateway) DeleteRestApiWithContext(_ awsgo.Context, _ *apigateway.DeleteRestApiInput, _ ...request.Option) (*apigateway.DeleteRestApiOutput, error) { - // Only need to return mocked response output - return &m.DeleteRestApiResp, nil -} -func (m mockedApiGateway) GetStagesWithContext(_ awsgo.Context, _ *apigateway.GetStagesInput, _ ...request.Option) (*apigateway.GetStagesOutput, error) { +func (m mockedApiGateway) GetStages(ctx context.Context, params *apigateway.GetStagesInput, optFns ...func(*apigateway.Options)) (*apigateway.GetStagesOutput, error) { return &m.GetStagesOutput, nil } -func (m mockedApiGateway) DeleteClientCertificateWithContext(_ awsgo.Context, _ *apigateway.DeleteClientCertificateInput, _ ...request.Option) (*apigateway.DeleteClientCertificateOutput, error) { +func (m mockedApiGateway) DeleteClientCertificate(ctx context.Context, params *apigateway.DeleteClientCertificateInput, optFns ...func(*apigateway.Options)) (*apigateway.DeleteClientCertificateOutput, error) { return &m.DeleteClientCertificateOutput, nil } -func TestAPIGatewayGetAllAndNukeAll(t *testing.T) { +func (m mockedApiGateway) DeleteRestApi(ctx context.Context, params *apigateway.DeleteRestApiInput, optFns ...func(*apigateway.Options)) (*apigateway.DeleteRestApiOutput, error) { + return &m.DeleteRestApiOutput, nil +} +func TestAPIGatewayGetAllAndNukeAll(t *testing.T) { t.Parallel() testApiID := "aws-nuke-test-" + util.UniqueID() apiGateway := ApiGateway{ Client: mockedApiGateway{ - GetRestApisResp: apigateway.GetRestApisOutput{ - Items: []*apigateway.RestApi{ + ApiGatewayServiceAPI: nil, + GetRestApisOutput: apigateway.GetRestApisOutput{ + Items: []types.RestApi{ {Id: aws.String(testApiID)}, }, }, - DeleteRestApiResp: apigateway.DeleteRestApiOutput{}, + DeleteRestApiOutput: apigateway.DeleteRestApiOutput{}, }, } apis, err := apiGateway.getAll(context.Background(), config.Config{}) require.NoError(t, err) - require.Contains(t, awsgo.StringValueSlice(apis), testApiID) + require.Contains(t, aws.ToStringSlice(apis), testApiID) err = apiGateway.nukeAll([]*string{aws.String(testApiID)}) require.NoError(t, err) } func TestAPIGatewayGetAllTimeFilter(t *testing.T) { - t.Parallel() testApiID := "aws-nuke-test-" + util.UniqueID() now := time.Now() apiGateway := ApiGateway{ Client: mockedApiGateway{ - GetRestApisResp: apigateway.GetRestApisOutput{ - Items: []*apigateway.RestApi{{ + GetRestApisOutput: apigateway.GetRestApisOutput{ + Items: []types.RestApi{{ Id: aws.String(testApiID), CreatedDate: aws.Time(now), }}, @@ -91,7 +86,7 @@ func TestAPIGatewayGetAllTimeFilter(t *testing.T) { }, }) require.NoError(t, err) - assert.Contains(t, aws.StringValueSlice(IDs), testApiID) + assert.Contains(t, aws.ToStringSlice(IDs), testApiID) // test API being excluded from the filter apiGwIdsOlder, err := apiGateway.getAll(context.Background(), config.Config{ @@ -102,38 +97,36 @@ func TestAPIGatewayGetAllTimeFilter(t *testing.T) { }, }) require.NoError(t, err) - assert.NotContains(t, aws.StringValueSlice(apiGwIdsOlder), testApiID) + assert.NotContains(t, aws.ToStringSlice(apiGwIdsOlder), testApiID) } func TestNukeAPIGatewayMoreThanOne(t *testing.T) { - t.Parallel() testApiID1 := "aws-nuke-test-" + util.UniqueID() testApiID2 := "aws-nuke-test-" + util.UniqueID() apiGateway := ApiGateway{ Client: mockedApiGateway{ - GetRestApisResp: apigateway.GetRestApisOutput{ - Items: []*apigateway.RestApi{ + GetRestApisOutput: apigateway.GetRestApisOutput{ + Items: []types.RestApi{ {Id: aws.String(testApiID1)}, {Id: aws.String(testApiID2)}, }, }, - DeleteRestApiResp: apigateway.DeleteRestApiOutput{}, + DeleteRestApiOutput: apigateway.DeleteRestApiOutput{}, }, } apis, err := apiGateway.getAll(context.Background(), config.Config{}) require.NoError(t, err) - require.Contains(t, awsgo.StringValueSlice(apis), testApiID1) - require.Contains(t, awsgo.StringValueSlice(apis), testApiID2) + require.Contains(t, aws.ToStringSlice(apis), testApiID1) + require.Contains(t, aws.ToStringSlice(apis), testApiID2) err = apiGateway.nukeAll([]*string{aws.String(testApiID1), aws.String(testApiID2)}) require.NoError(t, err) } func TestNukeAPIGatewayWithCertificates(t *testing.T) { - t.Parallel() testApiID1 := "aws-nuke-test-" + util.UniqueID() @@ -142,28 +135,28 @@ func TestNukeAPIGatewayWithCertificates(t *testing.T) { clientCertID := "aws-client-cert" + util.UniqueID() apiGateway := ApiGateway{ Client: mockedApiGateway{ - GetRestApisResp: apigateway.GetRestApisOutput{ - Items: []*apigateway.RestApi{ + GetRestApisOutput: apigateway.GetRestApisOutput{ + Items: []types.RestApi{ {Id: aws.String(testApiID1)}, {Id: aws.String(testApiID2)}, }, }, GetStagesOutput: apigateway.GetStagesOutput{ - Item: []*apigateway.Stage{ + Item: []types.Stage{ { ClientCertificateId: aws.String(clientCertID), }, }, }, DeleteClientCertificateOutput: apigateway.DeleteClientCertificateOutput{}, - DeleteRestApiResp: apigateway.DeleteRestApiOutput{}, + DeleteRestApiOutput: apigateway.DeleteRestApiOutput{}, }, } apis, err := apiGateway.getAll(context.Background(), config.Config{}) require.NoError(t, err) - require.Contains(t, awsgo.StringValueSlice(apis), testApiID1) - require.Contains(t, awsgo.StringValueSlice(apis), testApiID2) + require.Contains(t, aws.ToStringSlice(apis), testApiID1) + require.Contains(t, aws.ToStringSlice(apis), testApiID2) err = apiGateway.nukeAll([]*string{aws.String(testApiID1), aws.String(testApiID2)}) require.NoError(t, err) diff --git a/aws/resources/apigateway_types.go b/aws/resources/apigateway_types.go index 5a0054cc..55397562 100644 --- a/aws/resources/apigateway_types.go +++ b/aws/resources/apigateway_types.go @@ -3,25 +3,32 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/apigateway" - "github.com/aws/aws-sdk-go/service/apigateway/apigatewayiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigateway" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type ApiGatewayServiceAPI interface { + GetRestApis(ctx context.Context, params *apigateway.GetRestApisInput, optFns ...func(*apigateway.Options)) (*apigateway.GetRestApisOutput, error) + GetStages(ctx context.Context, params *apigateway.GetStagesInput, optFns ...func(*apigateway.Options)) (*apigateway.GetStagesOutput, error) + DeleteClientCertificate(ctx context.Context, params *apigateway.DeleteClientCertificateInput, optFns ...func(*apigateway.Options)) (*apigateway.DeleteClientCertificateOutput, error) + DeleteRestApi(ctx context.Context, params *apigateway.DeleteRestApiInput, optFns ...func(*apigateway.Options)) (*apigateway.DeleteRestApiOutput, error) +} + type ApiGateway struct { BaseAwsResource - Client apigatewayiface.APIGatewayAPI + Client ApiGatewayServiceAPI Region string Ids []string } -func (gateway *ApiGateway) Init(session *session.Session) { - gateway.Client = apigateway.New(session) +func (gateway *ApiGateway) InitV2(cfg aws.Config) { + gateway.Client = apigateway.NewFromConfig(cfg) } +func (gateway *ApiGateway) IsUsingV2() bool { return true } + func (gateway *ApiGateway) ResourceName() string { return "apigateway" } @@ -44,12 +51,12 @@ func (gateway *ApiGateway) GetAndSetIdentifiers(c context.Context, configObj con return nil, err } - gateway.Ids = awsgo.StringValueSlice(identifiers) + gateway.Ids = aws.ToStringSlice(identifiers) return gateway.Ids, nil } func (gateway *ApiGateway) Nuke(identifiers []string) error { - if err := gateway.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := gateway.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/aws/resources/apigatewayv2.go b/aws/resources/apigatewayv2.go index a2e56625..9f71356c 100644 --- a/aws/resources/apigatewayv2.go +++ b/aws/resources/apigatewayv2.go @@ -5,9 +5,8 @@ import ( "fmt" "sync" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/apigatewayv2" - "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -15,13 +14,13 @@ import ( "github.com/hashicorp/go-multierror" ) -func (gw *ApiGatewayV2) getAll(c context.Context, configObj config.Config) ([]*string, error) { - output, err := gw.Client.GetApisWithContext(gw.Context, &apigatewayv2.GetApisInput{}) +func (gw *ApiGatewayV2) getAll(ctx context.Context, configObj config.Config) ([]*string, error) { + output, err := gw.Client.GetApis(gw.Context, &apigatewayv2.GetApisInput{}) if err != nil { return []*string{}, errors.WithStackTrace(err) } - Ids := []*string{} + var Ids []*string for _, restapi := range output.Items { if configObj.APIGatewayV2.ShouldInclude(config.ResourceValue{ Time: restapi.CreatedDate, @@ -45,7 +44,7 @@ func (gw *ApiGatewayV2) nukeAll(identifiers []*string) error { return TooManyApiGatewayV2Err{} } - err := deleteAssociatedApiMappings(gw.Client, identifiers) + err := deleteAssociatedApiMappings(gw.Context, gw.Client, identifiers) if err != nil { return errors.WithStackTrace(err) } @@ -78,7 +77,7 @@ func (gw *ApiGatewayV2) deleteAsync(wg *sync.WaitGroup, errChan chan error, apiI defer wg.Done() input := &apigatewayv2.DeleteApiInput{ApiId: apiId} - _, err := gw.Client.DeleteApiWithContext(gw.Context, input) + _, err := gw.Client.DeleteApi(gw.Context, input) errChan <- err // Record status of this resource @@ -90,21 +89,20 @@ func (gw *ApiGatewayV2) deleteAsync(wg *sync.WaitGroup, errChan chan error, apiI report.Record(e) if err == nil { - logging.Debug(fmt.Sprintf("Successfully deleted API Gateway (v2) %s in %s", aws.StringValue(apiId), gw.Region)) + logging.Debug(fmt.Sprintf("Successfully deleted API Gateway (v2) %s in %s", aws.ToString(apiId), gw.Region)) } else { - logging.Debug(fmt.Sprintf("Failed to delete API Gateway (v2) %s in %s", aws.StringValue(apiId), gw.Region)) + logging.Debug(fmt.Sprintf("Failed to delete API Gateway (v2) %s in %s", aws.ToString(apiId), gw.Region)) } } -func deleteAssociatedApiMappings( - client apigatewayv2iface.ApiGatewayV2API, identifiers []*string) error { +func deleteAssociatedApiMappings(ctx context.Context, client ApiGatewayV2API, identifiers []*string) error { // Convert identifiers to map to check if identifier is in list identifierMap := make(map[string]bool) for _, identifier := range identifiers { identifierMap[*identifier] = true } - domainNames, err := client.GetDomainNames(&apigatewayv2.GetDomainNamesInput{}) + domainNames, err := client.GetDomainNames(ctx, &apigatewayv2.GetDomainNamesInput{}) if err != nil { logging.Debug(fmt.Sprintf("Failed to get domain names: %s", err)) return errors.WithStackTrace(err) @@ -112,7 +110,7 @@ func deleteAssociatedApiMappings( logging.Debug(fmt.Sprintf("Found %d domain names", len(domainNames.Items))) for _, domainName := range domainNames.Items { - apiMappings, err := client.GetApiMappings(&apigatewayv2.GetApiMappingsInput{ + apiMappings, err := client.GetApiMappings(ctx, &apigatewayv2.GetApiMappingsInput{ DomainName: domainName.DomainName, }) if err != nil { @@ -125,7 +123,7 @@ func deleteAssociatedApiMappings( continue } - _, err := client.DeleteApiMapping(&apigatewayv2.DeleteApiMappingInput{ + _, err := client.DeleteApiMapping(ctx, &apigatewayv2.DeleteApiMappingInput{ ApiMappingId: apiMapping.ApiMappingId, DomainName: domainName.DomainName, }) diff --git a/aws/resources/apigatewayv2_test.go b/aws/resources/apigatewayv2_test.go index 561e595d..a0e3ae58 100644 --- a/aws/resources/apigatewayv2_test.go +++ b/aws/resources/apigatewayv2_test.go @@ -6,49 +6,43 @@ import ( "testing" "time" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/apigatewayv2" - "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" + "github.com/aws/aws-sdk-go-v2/service/apigatewayv2/types" "github.com/gruntwork-io/cloud-nuke/config" "github.com/stretchr/testify/assert" ) type mockedApiGatewayV2 struct { - apigatewayv2iface.ApiGatewayV2API + ApiGatewayV2API GetApisOutput apigatewayv2.GetApisOutput - DeleteApiOutput apigatewayv2.DeleteApiOutput GetDomainNamesOutput apigatewayv2.GetDomainNamesOutput GetApiMappingsOutput apigatewayv2.GetApiMappingsOutput + DeleteApiOutput apigatewayv2.DeleteApiOutput DeleteApiMappingOutput apigatewayv2.DeleteApiMappingOutput } -func (m mockedApiGatewayV2) GetApisWithContext(_ awsgo.Context, _ *apigatewayv2.GetApisInput, _ ...request.Option) (*apigatewayv2.GetApisOutput, error) { - // Only need to return mocked response output - return &m.GetApisOutput, nil +func (m mockedApiGatewayV2) DeleteApi(ctx context.Context, params *apigatewayv2.DeleteApiInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.DeleteApiOutput, error) { + return &m.DeleteApiOutput, nil } -func (m mockedApiGatewayV2) DeleteApiWithContext(_ awsgo.Context, _ *apigatewayv2.DeleteApiInput, _ ...request.Option) (*apigatewayv2.DeleteApiOutput, error) { - // Only need to return mocked response output - return &m.DeleteApiOutput, nil +func (m mockedApiGatewayV2) DeleteApiMapping(ctx context.Context, params *apigatewayv2.DeleteApiMappingInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.DeleteApiMappingOutput, error) { + return &m.DeleteApiMappingOutput, nil } -func (m mockedApiGatewayV2) GetDomainNames(_ *apigatewayv2.GetDomainNamesInput) (*apigatewayv2.GetDomainNamesOutput, error) { - return &m.GetDomainNamesOutput, nil +func (m mockedApiGatewayV2) GetApis(ctx context.Context, params *apigatewayv2.GetApisInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetApisOutput, error) { + return &m.GetApisOutput, nil } -func (m mockedApiGatewayV2) GetApiMappings(_ *apigatewayv2.GetApiMappingsInput) (*apigatewayv2.GetApiMappingsOutput, error) { +func (m mockedApiGatewayV2) GetApiMappings(ctx context.Context, params *apigatewayv2.GetApiMappingsInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetApiMappingsOutput, error) { return &m.GetApiMappingsOutput, nil } -func (m mockedApiGatewayV2) DeleteApiMappingWithContext(_ awsgo.Context, _ *apigatewayv2.DeleteApiMappingInput, _ ...request.Option) (*apigatewayv2.DeleteApiMappingOutput, error) { - return &m.DeleteApiMappingOutput, nil +func (m mockedApiGatewayV2) GetDomainNames(ctx context.Context, params *apigatewayv2.GetDomainNamesInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetDomainNamesOutput, error) { + return &m.GetDomainNamesOutput, nil } func TestApiGatewayV2GetAll(t *testing.T) { - t.Parallel() testApiID := "test-api-id" @@ -57,7 +51,7 @@ func TestApiGatewayV2GetAll(t *testing.T) { gw := ApiGatewayV2{ Client: mockedApiGatewayV2{ GetApisOutput: apigatewayv2.GetApisOutput{ - Items: []*apigatewayv2.Api{ + Items: []types.Api{ { ApiId: aws.String(testApiID), Name: aws.String(testApiName), @@ -71,7 +65,7 @@ func TestApiGatewayV2GetAll(t *testing.T) { // empty filter apis, err := gw.getAll(context.Background(), config.Config{}) assert.NoError(t, err) - assert.Contains(t, awsgo.StringValueSlice(apis), testApiID) + assert.Contains(t, aws.ToStringSlice(apis), testApiID) // filter by name apis, err = gw.getAll(context.Background(), config.Config{ @@ -81,33 +75,32 @@ func TestApiGatewayV2GetAll(t *testing.T) { RE: *regexp.MustCompile("test-api-name"), }}}}}) assert.NoError(t, err) - assert.NotContains(t, awsgo.StringValueSlice(apis), testApiID) + assert.NotContains(t, aws.ToStringSlice(apis), testApiID) // filter by date apis, err = gw.getAll(context.Background(), config.Config{ APIGatewayV2: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: awsgo.Time(now.Add(-1))}}}) + TimeAfter: aws.Time(now.Add(-1))}}}) assert.NoError(t, err) - assert.NotContains(t, awsgo.StringValueSlice(apis), testApiID) + assert.NotContains(t, aws.ToStringSlice(apis), testApiID) } func TestApiGatewayV2NukeAll(t *testing.T) { - t.Parallel() gw := ApiGatewayV2{ Client: mockedApiGatewayV2{ DeleteApiOutput: apigatewayv2.DeleteApiOutput{}, GetDomainNamesOutput: apigatewayv2.GetDomainNamesOutput{ - Items: []*apigatewayv2.DomainName{ + Items: []types.DomainName{ { DomainName: aws.String("test-domain-name"), }, }, }, GetApisOutput: apigatewayv2.GetApisOutput{ - Items: []*apigatewayv2.Api{ + Items: []types.Api{ { ApiId: aws.String("test-api-id"), }, diff --git a/aws/resources/apigatewayv2_types.go b/aws/resources/apigatewayv2_types.go index ad56131c..371c37a5 100644 --- a/aws/resources/apigatewayv2_types.go +++ b/aws/resources/apigatewayv2_types.go @@ -3,25 +3,33 @@ package resources import ( "context" - awsgo "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/apigatewayv2" - "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/apigatewayv2" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/go-commons/errors" ) +type ApiGatewayV2API interface { + GetApis(ctx context.Context, params *apigatewayv2.GetApisInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetApisOutput, error) + GetDomainNames(ctx context.Context, params *apigatewayv2.GetDomainNamesInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetDomainNamesOutput, error) + GetApiMappings(ctx context.Context, params *apigatewayv2.GetApiMappingsInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.GetApiMappingsOutput, error) + DeleteApi(ctx context.Context, params *apigatewayv2.DeleteApiInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.DeleteApiOutput, error) + DeleteApiMapping(ctx context.Context, params *apigatewayv2.DeleteApiMappingInput, optFns ...func(*apigatewayv2.Options)) (*apigatewayv2.DeleteApiMappingOutput, error) +} + type ApiGatewayV2 struct { BaseAwsResource - Client apigatewayv2iface.ApiGatewayV2API + Client ApiGatewayV2API Region string Ids []string } -func (gw *ApiGatewayV2) Init(session *session.Session) { - gw.Client = apigatewayv2.New(session) +func (gw *ApiGatewayV2) InitV2(cfg aws.Config) { + gw.Client = apigatewayv2.NewFromConfig(cfg) } +func (gw *ApiGatewayV2) IsUsingV2() bool { return true } + func (gw *ApiGatewayV2) ResourceName() string { return "apigatewayv2" } @@ -44,12 +52,12 @@ func (gw *ApiGatewayV2) GetAndSetIdentifiers(c context.Context, configObj config return nil, err } - gw.Ids = awsgo.StringValueSlice(identifiers) + gw.Ids = aws.ToStringSlice(identifiers) return gw.Ids, nil } func (gw *ApiGatewayV2) Nuke(identifiers []string) error { - if err := gw.nukeAll(awsgo.StringSlice(identifiers)); err != nil { + if err := gw.nukeAll(aws.StringSlice(identifiers)); err != nil { return errors.WithStackTrace(err) } diff --git a/go.mod b/go.mod index 845ed7ee..8eeb1a7b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,12 @@ require ( github.com/aws/aws-sdk-go-v2 v1.32.2 github.com/aws/aws-sdk-go-v2/config v1.27.24 github.com/aws/aws-sdk-go-v2/credentials v1.17.24 + github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.34.2 + github.com/aws/aws-sdk-go-v2/service/acm v1.30.2 + github.com/aws/aws-sdk-go-v2/service/acmpca v1.37.3 github.com/aws/aws-sdk-go-v2/service/amp v1.27.1 + github.com/aws/aws-sdk-go-v2/service/apigateway v1.27.2 + github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.24.2 github.com/aws/aws-sdk-go-v2/service/ec2 v1.184.0 github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7 github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7 diff --git a/go.sum b/go.sum index 89963969..800a8a13 100644 --- a/go.sum +++ b/go.sum @@ -15,7 +15,6 @@ github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYew github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/aws/aws-sdk-go v1.49.13 h1:f4mGztsgnx2dR9r8FQYa9YW/RsKb+N7bgef4UGrOW1Y= github.com/aws/aws-sdk-go v1.49.13/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.16.7/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw= github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= github.com/aws/aws-sdk-go-v2/config v1.27.24 h1:NM9XicZ5o1CBU/MZaHwFtimRpWx9ohAUAqkG6AqSqPo= @@ -24,35 +23,32 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.24 h1:YclAsrnb1/GTQNt2nzv+756Iw4m github.com/aws/aws-sdk-go-v2/credentials v1.17.24/go.mod h1:Hld7tmnAkoBQdTMNYZGzztzKRdA4fCdn9L83LOoigac= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 h1:Aznqksmd6Rfv2HQN9cpqIV/lQRMaIpJkLLaJ1ZI76no= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9/go.mod h1:WQr3MY7AxGNxaqAtsDWn+fBxmd4XvLkzeqQ8P1VM0/w= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14/go.mod h1:kdjrMwHwrC3+FsKhNcCMJ7tUVj/8uSD5CZXeQ4wV6fM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.8/go.mod h1:ZIV8GYoC6WLBW5KGs+o4rsc65/ozd+eQ0L31XF5VDwk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17 h1:Roo69qTpfu8OlJ2Tb7pAYVuF0CpuUMB0IYWwYP/4DZM= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17/go.mod h1:NcWPxQzGM1USQggaTVwz6VpqMZPX1CvDJLDh6jnOCa4= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.34.2 h1:QliYfQlWPSjTZpLjj8dXpV6jRuxMs9DFJ8W1Q+ZHMy8= +github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.34.2/go.mod h1:9bHRHmhoqatAujuRir347sJaGEg6xoV0T3On4DNiJ10= +github.com/aws/aws-sdk-go-v2/service/acm v1.30.2 h1:LNCRNr5Ha6OUcnV4licXm/V9/fUyto85nQdQSscC09g= +github.com/aws/aws-sdk-go-v2/service/acm v1.30.2/go.mod h1:wRBzxEW2vsJMJAuV7yWEHGzo/KycX3t02mUVm6P8qHY= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.37.3 h1:1jmLDJJ3StvfOopWDb/HY9mDSN2e7ZmReww4FTFvNnU= +github.com/aws/aws-sdk-go-v2/service/acmpca v1.37.3/go.mod h1:vWSvubH4BhEG1Vl6lLUVHZzRo7lgIM7/oJpBv6hN5i4= github.com/aws/aws-sdk-go-v2/service/amp v1.27.1 h1:va9j7MGA8jBlQs9KujMlkSdnC26TuEJXv7ywnFjmTZ8= github.com/aws/aws-sdk-go-v2/service/amp v1.27.1/go.mod h1:QhmX7qjomjuHJjCJbW+QRdaCBM42v1eAbWvBVFrT1Vw= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.47.2 h1:81hrDgbXHL44WdY6M/fHGXLlv17qTpOFzutXRVDEk3Y= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.47.2/go.mod h1:VoBcwURHnJVCWuXHdqVuG03i2lUlHJ5DTTqDSyCdEcc= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.27.2 h1:XMdSPyg1ZJsoPIhmOiiSSA4qsk/G2ZGgDNYp3JQOwzk= +github.com/aws/aws-sdk-go-v2/service/apigateway v1.27.2/go.mod h1:dxPkh3eysV7j4JJqodTQijVKlIH0A3MhGJcQpJO1XL4= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.24.2 h1:dLg685y7wusZZjJcZ+c0PhV8+wjTn1xzidvUkondtJM= +github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.24.2/go.mod h1:wwTm1f7PQvrhoXmvPiqalPJ3tUfA5p4TaBs4pu3yOYs= github.com/aws/aws-sdk-go-v2/service/ec2 v1.184.0 h1:SZnuDlml1uFv5ojh+QTxS+Yru89Hr3QYIUwWoY71frI= github.com/aws/aws-sdk-go-v2/service/ec2 v1.184.0/go.mod h1:kYXaB4FzyhEJjvrJ84oPnMElLiEAjGxxUunVW2tBSng= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7 h1:q+xiPu+Dk5MFC20ZjdGGhbihD39Xsih98epvVjnOjyE= github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7/go.mod h1:iQCsmx9LyBMyMEkLCBVqnIAz+rfo6/ss3oLcYn26+no= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.8/go.mod h1:rDVhIMAX9N2r8nWxDUlbubvvaFMnfsm+3jAV7q+rpM4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15 h1:I9zMeF107l0rJrpnHpjEiiTSCKYAIw8mALiXcPsGBiA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15/go.mod h1:9xWJ3Q/S6Ojusz1UIkfycgD1mGirJfLLKqq3LPT7WN8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7 h1:EcPyKUUo3neD2tDFKnq3TR3B9s2uZe9eWgxVQgixdzc= @@ -67,7 +63,6 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWB github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2/go.mod h1:xyFHA4zGxgYkdD73VeezHt3vSKEG9EmFnGwoKlP00u4= github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 h1:+woJ607dllHJQtsnJLi52ycuqHMwlW+Wqm2Ppsfp4nQ= github.com/aws/aws-sdk-go-v2/service/sts v1.30.1/go.mod h1:jiNR3JqT15Dm+QWq2SRgh0x0bCNSRP2L25+CqPNpJlQ= -github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -85,7 +80,6 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= diff --git a/v2_migration_report/output.md b/v2_migration_report/output.md index 7b2e245c..cd3d11fa 100644 --- a/v2_migration_report/output.md +++ b/v2_migration_report/output.md @@ -6,12 +6,12 @@ run `go generate ./...` to refresh this report. | Resource Name | Migrated | |----------------------------------|--------------------| -| accessanalyzer | | -| acm | | -| acmpca | | -| ami | | -| apigateway | | -| apigatewayv2 | | +| accessanalyzer | :white_check_mark: | +| acm | :white_check_mark: | +| acmpca | :white_check_mark: | +| ami | :white_check_mark: | +| apigateway | :white_check_mark: | +| apigatewayv2 | :white_check_mark: | | app-runner-service | | | asg | | | backup-vault | |