diff --git a/aws/resources/apigateway.go b/aws/resources/apigateway.go index b7f28383..26ad2439 100644 --- a/aws/resources/apigateway.go +++ b/aws/resources/apigateway.go @@ -22,6 +22,7 @@ func NewApiGateway() AwsResource { ResourceTypeName: "apigateway", BatchSize: 10, InitClient: WrapAwsInitClient(func(r *resource.Resource[ApiGatewayAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = apigateway.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/apigatewayv2.go b/aws/resources/apigatewayv2.go index d19e3e21..37ad9019 100644 --- a/aws/resources/apigatewayv2.go +++ b/aws/resources/apigatewayv2.go @@ -22,6 +22,7 @@ func NewApiGatewayV2() AwsResource { ResourceTypeName: "apigatewayv2", BatchSize: 10, InitClient: WrapAwsInitClient(func(r *resource.Resource[ApiGatewayV2API], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = apigatewayv2.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/dynamodb.go b/aws/resources/dynamodb.go index 56722b26..7a2d610b 100644 --- a/aws/resources/dynamodb.go +++ b/aws/resources/dynamodb.go @@ -26,6 +26,7 @@ func NewDynamoDB() AwsResource { ResourceTypeName: "dynamodb", BatchSize: DefaultBatchSize, // Tentative batch size to ensure AWS doesn't throttle InitClient: WrapAwsInitClient(func(r *resource.Resource[DynamoDBAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = dynamodb.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/ebs.go b/aws/resources/ebs.go index a6f7cd5f..8b798d30 100644 --- a/aws/resources/ebs.go +++ b/aws/resources/ebs.go @@ -25,6 +25,7 @@ func NewEBSVolumes() AwsResource { ResourceTypeName: "ebs", BatchSize: DefaultBatchSize, InitClient: WrapAwsInitClient(func(r *resource.Resource[EBSVolumesAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = ec2.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/ec2_egress_only_igw.go b/aws/resources/ec2_egress_only_igw.go index 8cb2446f..357c04f6 100644 --- a/aws/resources/ec2_egress_only_igw.go +++ b/aws/resources/ec2_egress_only_igw.go @@ -22,6 +22,7 @@ func NewEgressOnlyInternetGateway() AwsResource { ResourceTypeName: "egress-only-internet-gateway", BatchSize: DefaultBatchSize, InitClient: WrapAwsInitClient(func(r *resource.Resource[EgressOnlyIGAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = ec2.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/network_firewall_resource_policy.go b/aws/resources/network_firewall_resource_policy.go index 3d8f2ff5..6510b90d 100644 --- a/aws/resources/network_firewall_resource_policy.go +++ b/aws/resources/network_firewall_resource_policy.go @@ -29,6 +29,7 @@ func NewNetworkFirewallResourcePolicy() AwsResource { ResourceTypeName: "network-firewall-resource-policy", BatchSize: 10, InitClient: WrapAwsInitClient(func(r *resource.Resource[NetworkFirewallResourcePolicyAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = networkfirewall.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/rds.go b/aws/resources/rds.go index 285c9e87..827e2c48 100644 --- a/aws/resources/rds.go +++ b/aws/resources/rds.go @@ -26,6 +26,7 @@ func NewDBInstances() AwsResource { ResourceTypeName: "rds", BatchSize: DefaultBatchSize, InitClient: WrapAwsInitClient(func(r *resource.Resource[DBInstancesAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = rds.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/rds_parameter_group.go b/aws/resources/rds_parameter_group.go index 84f44bf4..b73ab2ac 100644 --- a/aws/resources/rds_parameter_group.go +++ b/aws/resources/rds_parameter_group.go @@ -24,6 +24,7 @@ func NewRdsParameterGroup() AwsResource { ResourceTypeName: "rds-parameter-group", BatchSize: DefaultBatchSize, InitClient: WrapAwsInitClient(func(r *resource.Resource[RdsParameterGroupAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = rds.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/aws/resources/rds_subnet_group.go b/aws/resources/rds_subnet_group.go index 972fe0b3..4d9fda79 100644 --- a/aws/resources/rds_subnet_group.go +++ b/aws/resources/rds_subnet_group.go @@ -24,6 +24,7 @@ func NewDBSubnetGroups() AwsResource { ResourceTypeName: "rds-subnet-group", BatchSize: DefaultBatchSize, InitClient: WrapAwsInitClient(func(r *resource.Resource[DBSubnetGroupsAPI], cfg aws.Config) { + r.Scope.Region = cfg.Region r.Client = rds.NewFromConfig(cfg) }), ConfigGetter: func(c config.Config) config.ResourceType { diff --git a/gcp/resources/adapter.go b/gcp/resources/adapter.go index c5572d2f..6fe38325 100644 --- a/gcp/resources/adapter.go +++ b/gcp/resources/adapter.go @@ -2,12 +2,33 @@ package resources import ( "context" + "fmt" + "time" "github.com/gruntwork-io/cloud-nuke/resource" ) +const ( + DefaultWaitTimeout = 5 * time.Minute + DefaultBatchSize = 50 +) + +// GcpInitClientFunc is the type-safe client initialization function signature. +type GcpInitClientFunc[C any] func(r *resource.Resource[C], projectID string) + +// WrapGcpInitClient converts a GcpInitClientFunc to the generic InitClient signature. +// Panics on type assertion failure since that indicates a programming error. +func WrapGcpInitClient[C any](fn GcpInitClientFunc[C]) func(r *resource.Resource[C], cfg any) { + return func(r *resource.Resource[C], cfg any) { + projectID, ok := cfg.(string) + if !ok { + panic(fmt.Sprintf("WrapGcpInitClient: expected string projectID, got %T", cfg)) + } + fn(r, projectID) + } +} + // GcpResourceAdapter wraps a generic Resource to satisfy the GcpResource interface. -// It provides type-safe Init(string) for GCP's project ID initialization. type GcpResourceAdapter[C any] struct { *resource.Resource[C] } @@ -27,5 +48,4 @@ func (g *GcpResourceAdapter[C]) Nuke(ctx context.Context, identifiers []string) return g.Resource.Nuke(ctx, identifiers) } -// Compile-time interface satisfaction check var _ GcpResource = (*GcpResourceAdapter[any])(nil) diff --git a/gcp/resources/gcs_bucket.go b/gcp/resources/gcs_bucket.go index f008d845..ffd6ce39 100644 --- a/gcp/resources/gcs_bucket.go +++ b/gcp/resources/gcs_bucket.go @@ -18,21 +18,15 @@ import ( func NewGCSBuckets() GcpResource { return NewGcpResource(&resource.Resource[*storage.Client]{ ResourceTypeName: "gcs-bucket", - BatchSize: 50, - InitClient: func(r *resource.Resource[*storage.Client], cfg any) { - projectID, ok := cfg.(string) - if !ok { - logging.Debugf("Invalid config type for GCS client: expected string") - return - } + BatchSize: DefaultBatchSize, + InitClient: WrapGcpInitClient(func(r *resource.Resource[*storage.Client], projectID string) { r.Scope.ProjectID = projectID client, err := storage.NewClient(context.Background()) if err != nil { - logging.Debugf("Failed to create GCS client: %v", err) - return + panic(fmt.Sprintf("failed to create GCS client: %v", err)) } r.Client = client - }, + }), ConfigGetter: func(c config.Config) config.ResourceType { return c.GCSBucket },