Skip to content

Commit c450ebc

Browse files
authored
refactor: migrate 30 AWS resources to generic Resource[C] pattern (#987)
Migrates resources from legacy BaseAwsResource to generic Resource[C]: - Consolidates *_types.go files into main resource files - Uses factory functions (NewXxx) instead of struct instantiation - Standardizes tests with table-driven patterns
1 parent c7a01b5 commit c450ebc

File tree

94 files changed

+2738
-5210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+2738
-5210
lines changed

aws/resource_registry.go

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -53,77 +53,77 @@ func getRegisteredRegionalResources() []AwsResource {
5353
// instances before deleting the VPC.
5454
return []AwsResource{
5555
resources.NewAccessAnalyzer(),
56-
&resources.ACM{},
57-
&resources.ACMPCA{},
58-
&resources.AMIs{},
56+
resources.NewACM(),
57+
resources.NewACMPCA(),
58+
resources.NewAMIs(),
5959
&resources.ApiGateway{},
6060
&resources.ApiGatewayV2{},
6161
&resources.ASGroups{},
62-
&resources.AppRunnerService{},
63-
&resources.BackupVault{},
64-
&resources.ManagedPrometheus{},
65-
&resources.Grafana{},
62+
resources.NewAppRunnerService(),
63+
resources.NewBackupVault(),
64+
resources.NewManagedPrometheus(),
65+
resources.NewGrafana(),
6666
resources.NewEventBridgeSchedule(),
6767
&resources.EventBridgeScheduleGroup{},
68-
&resources.EventBridgeArchive{},
68+
resources.NewEventBridgeArchive(),
6969
&resources.EventBridgeRule{},
7070
&resources.EventBridge{},
71-
&resources.CloudtrailTrail{},
71+
resources.NewCloudtrailTrail(),
7272
&resources.CloudFormationStacks{},
73-
&resources.CloudWatchAlarms{},
73+
resources.NewCloudWatchAlarms(),
7474
resources.NewCloudWatchDashboards(),
7575
resources.NewCloudWatchLogGroups(),
7676
&resources.CloudMapServices{},
7777
&resources.CloudMapNamespaces{},
7878
&resources.CodeDeployApplications{},
79-
&resources.ConfigServiceRecorders{},
79+
resources.NewConfigServiceRecorders(),
8080
&resources.ConfigServiceRule{},
81-
&resources.DataSyncTask{},
82-
&resources.DataSyncLocation{},
83-
&resources.DynamoDB{},
81+
resources.NewDataSyncTask(),
82+
resources.NewDataSyncLocation(),
83+
resources.NewDynamoDB(),
8484
&resources.EBSVolumes{},
85-
&resources.EBApplications{},
85+
resources.NewEBApplications(),
8686
&resources.EC2Instances{},
8787
&resources.EC2DedicatedHosts{},
8888
resources.NewEC2KeyPairs(),
8989
resources.NewEC2PlacementGroups(),
9090
&resources.TransitGateways{},
91-
&resources.TransitGatewaysRouteTables{},
91+
resources.NewTransitGatewaysRouteTables(),
9292
// Note: nuking transitgateway vpc attachement before nuking the vpc since vpc could be associated with it.
93-
&resources.TransitGatewayPeeringAttachment{},
93+
resources.NewTransitGatewayPeeringAttachment(),
9494
&resources.TransitGatewaysVpcAttachment{},
9595
&resources.EC2Endpoints{},
96-
&resources.ECR{},
96+
resources.NewECR(),
9797
&resources.ECSClusters{},
9898
&resources.ECSServices{},
9999
&resources.EgressOnlyInternetGateway{},
100100
&resources.ElasticFileSystem{},
101-
&resources.EIPAddresses{},
101+
resources.NewEIPAddresses(),
102102
&resources.EKSClusters{},
103103
&resources.ElasticCacheServerless{},
104104
&resources.Elasticaches{},
105105
&resources.ElasticacheParameterGroups{},
106106
&resources.ElasticacheSubnetGroups{},
107107
&resources.LoadBalancers{},
108108
&resources.LoadBalancersV2{},
109-
&resources.GuardDuty{},
109+
resources.NewGuardDuty(),
110110
resources.NewKinesisFirehose(),
111111
resources.NewKinesisStreams(),
112112
&resources.KmsCustomerKeys{},
113113
&resources.LambdaFunctions{},
114114
&resources.LambdaLayers{},
115115
resources.NewLaunchConfigs(),
116-
&resources.LaunchTemplates{},
116+
resources.NewLaunchTemplates(),
117117
&resources.MacieMember{},
118118
&resources.MSKCluster{},
119-
&resources.NatGateways{},
119+
resources.NewNatGateways(),
120120
&resources.OpenSearchDomains{},
121121
&resources.DBGlobalClusterMemberships{},
122122
&resources.DBInstances{},
123123
&resources.DBSubnetGroups{},
124124
&resources.DBClusters{},
125-
&resources.RdsProxy{},
126-
&resources.RdsSnapshot{},
125+
resources.NewRdsProxy(),
126+
resources.NewRdsSnapshot(),
127127
&resources.RdsParameterGroup{},
128128
&resources.RedshiftClusters{},
129129
&resources.RedshiftSnapshotCopyGrants{},
@@ -134,16 +134,16 @@ func getRegisteredRegionalResources() []AwsResource {
134134
&resources.SageMakerNotebookInstances{},
135135
&resources.SageMakerStudio{},
136136
&resources.SageMakerEndpoint{},
137-
&resources.SecretsManagerSecrets{},
137+
resources.NewSecretsManagerSecrets(),
138138
&resources.SecurityHub{},
139-
&resources.SesConfigurationSet{},
139+
resources.NewSesConfigurationSet(),
140140
resources.NewSesEmailTemplates(),
141-
&resources.SesIdentities{},
141+
resources.NewSesIdentities(),
142142
&resources.SesReceiptRule{},
143143
&resources.SesReceiptFilter{},
144-
&resources.Snapshots{},
145-
&resources.SNSTopic{},
146-
&resources.SqsQueue{},
144+
resources.NewSnapshots(),
145+
resources.NewSNSTopic(),
146+
resources.NewSqsQueue(),
147147
&resources.EC2IPAMs{},
148148
&resources.EC2IpamScopes{},
149149
&resources.EC2IPAMResourceDiscovery{},

aws/resources/acm.go

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,85 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/aws/aws-sdk-go-v2/aws"
78
"github.com/aws/aws-sdk-go-v2/service/acm"
89
"github.com/aws/aws-sdk-go-v2/service/acm/types"
910
"github.com/gruntwork-io/cloud-nuke/config"
1011
"github.com/gruntwork-io/cloud-nuke/logging"
11-
"github.com/gruntwork-io/cloud-nuke/report"
12-
"github.com/gruntwork-io/go-commons/errors"
12+
"github.com/gruntwork-io/cloud-nuke/resource"
1313
)
1414

15-
// Returns a list of strings of ACM ARNs
16-
func (a *ACM) getAll(c context.Context, configObj config.Config) ([]*string, error) {
15+
// ACMAPI defines the interface for ACM operations.
16+
type ACMAPI interface {
17+
ListCertificates(ctx context.Context, params *acm.ListCertificatesInput, optFns ...func(*acm.Options)) (*acm.ListCertificatesOutput, error)
18+
DeleteCertificate(ctx context.Context, params *acm.DeleteCertificateInput, optFns ...func(*acm.Options)) (*acm.DeleteCertificateOutput, error)
19+
}
20+
21+
// NewACM creates a new ACM resource using the generic resource pattern.
22+
func NewACM() AwsResource {
23+
return NewAwsResource(&resource.Resource[ACMAPI]{
24+
ResourceTypeName: "acm",
25+
BatchSize: 10,
26+
InitClient: WrapAwsInitClient(func(r *resource.Resource[ACMAPI], cfg aws.Config) {
27+
r.Scope.Region = cfg.Region
28+
r.Client = acm.NewFromConfig(cfg)
29+
}),
30+
ConfigGetter: func(c config.Config) config.ResourceType {
31+
return c.ACM
32+
},
33+
Lister: listACMCertificates,
34+
Nuker: resource.SimpleBatchDeleter(deleteACMCertificate),
35+
})
36+
}
37+
38+
// listACMCertificates retrieves all ACM certificates that match the config filters.
39+
func listACMCertificates(ctx context.Context, client ACMAPI, scope resource.Scope, cfg config.ResourceType) ([]*string, error) {
1740
var acmArns []*string
18-
paginator := acm.NewListCertificatesPaginator(a.Client, &acm.ListCertificatesInput{})
41+
paginator := acm.NewListCertificatesPaginator(client, &acm.ListCertificatesInput{})
42+
1943
for paginator.HasMorePages() {
20-
page, err := paginator.NextPage(c)
44+
page, err := paginator.NextPage(ctx)
2145
if err != nil {
22-
return nil, errors.WithStackTrace(err)
46+
return nil, err
2347
}
2448

2549
for _, cert := range page.CertificateSummaryList {
26-
logging.Debug(fmt.Sprintf("Found ACM %s with domain name %s", *cert.CertificateArn, *cert.DomainName))
27-
if a.shouldInclude(cert, configObj) {
28-
logging.Debug(fmt.Sprintf("Including ACM %s", *cert.CertificateArn))
50+
logging.Debugf("Found ACM %s with domain name %s", *cert.CertificateArn, *cert.DomainName)
51+
if shouldIncludeACMCertificate(cert, cfg) {
52+
logging.Debugf("Including ACM %s", *cert.CertificateArn)
2953
acmArns = append(acmArns, cert.CertificateArn)
3054
} else {
31-
logging.Debug(fmt.Sprintf("Skipping ACM %s", *cert.CertificateArn))
55+
logging.Debugf("Skipping ACM %s", *cert.CertificateArn)
3256
}
3357
}
3458
}
3559

3660
return acmArns, nil
3761
}
3862

39-
func (a *ACM) shouldInclude(acm types.CertificateSummary, configObj config.Config) bool {
40-
if acm.InUse != nil && *acm.InUse {
41-
logging.Debug(fmt.Sprintf("ACM %s is in use", *acm.CertificateArn))
63+
// shouldIncludeACMCertificate determines if an ACM certificate should be included based on config filters.
64+
func shouldIncludeACMCertificate(cert types.CertificateSummary, cfg config.ResourceType) bool {
65+
if cert.InUse != nil && *cert.InUse {
66+
logging.Debugf("ACM %s is in use", *cert.CertificateArn)
4267
return false
4368
}
4469

45-
shouldInclude := configObj.ACM.ShouldInclude(config.ResourceValue{
46-
Name: acm.DomainName,
47-
Time: acm.CreatedAt,
70+
shouldInclude := cfg.ShouldInclude(config.ResourceValue{
71+
Name: cert.DomainName,
72+
Time: cert.CreatedAt,
4873
})
49-
logging.Debug(fmt.Sprintf("shouldInclude result for ACM: %s w/ domain name: %s, time: %s, and config: %+v",
50-
*acm.CertificateArn, *acm.DomainName, acm.CreatedAt, configObj.ACM))
74+
logging.Debugf("shouldInclude result for ACM: %s w/ domain name: %s, time: %s, and config: %+v",
75+
aws.ToString(cert.CertificateArn), aws.ToString(cert.DomainName), cert.CreatedAt, cfg)
5176
return shouldInclude
5277
}
5378

54-
// Deletes all ACMs
55-
func (a *ACM) nukeAll(arns []*string) error {
56-
if len(arns) == 0 {
57-
logging.Debugf("No ACMs to nuke in region %s", a.Region)
58-
return nil
59-
}
60-
61-
logging.Debugf("Deleting all ACMs in region %s", a.Region)
62-
deletedCount := 0
63-
for _, acmArn := range arns {
64-
params := &acm.DeleteCertificateInput{
65-
CertificateArn: acmArn,
66-
}
67-
68-
_, err := a.Client.DeleteCertificate(a.Context, params)
69-
if err != nil {
70-
logging.Debugf("[Failed] %s", err)
71-
} else {
72-
deletedCount++
73-
logging.Debugf("Deleted ACM: %s", *acmArn)
74-
}
75-
76-
e := report.Entry{
77-
Identifier: *acmArn,
78-
ResourceType: "ACM",
79-
Error: err,
80-
}
81-
report.Record(e)
79+
// deleteACMCertificate deletes a single ACM certificate.
80+
func deleteACMCertificate(ctx context.Context, client ACMAPI, arn *string) error {
81+
_, err := client.DeleteCertificate(ctx, &acm.DeleteCertificateInput{
82+
CertificateArn: arn,
83+
})
84+
if err != nil {
85+
return fmt.Errorf("failed to delete ACM certificate %s: %w", aws.ToString(arn), err)
8286
}
83-
84-
logging.Debugf("[OK] %d ACM(s) terminated in %s", deletedCount, a.Region)
8587
return nil
8688
}

0 commit comments

Comments
 (0)