Repository: gruntwork-io/cloud-nuke
Pull request #722 (2024-06-15 21:50:44)

add support for nuking app runner service(s).
## Description

Fixes #000.

add support for cleaning up [App Runner Services](https://aws.amazon.com/apprunner/)

## TODOs

Read the [Gruntwork contribution guidelines](https://gruntwork.notion.site/Gruntwork-Coding-Methodology-02fdcd6e4b004e818553684760bf691e).

- [x] Update the docs.
- [x] Run the relevant tests successfully, including pre-commit checks.
- [x] Ensure any 3rd party code adheres with our [license policy](https://www.notion.so/gruntwork/Gruntwork-licenses-and-open-source-usage-policy-f7dece1f780341c7b69c1763f22b1378) or delete this line if its not applicable.
- [x] Include release notes. If this PR is backward incompatible, include a migration guide.
- [ ] Attention Grunts - if this PR adds support for a new resource, ensure the `nuke_sandbox` and `nuke_phxdevops` jobs in `.circleci/config.yml` have been updated with appropriate exclusions (either directly in the job or via the `.circleci/nuke_config.yml` file) to prevent nuking IAM roles, groups, resources, etc that are important for the test accounts.


## Release Notes (draft)

<!-- One-line description of the PR that can be included in the final release notes. -->
Added support for nuking `app runner service(s)`.

### Migration Guide

<!-- Important: If you made any backward incompatible changes, then you must write a migration guide! -->




Patch:
diff --git a/README.md b/README.md
index 07c70c5..e3f9053 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS res
 
 | Resource Family         | Resource type                                            |
 |-------------------------|----------------------------------------------------------|
+| App Runner              | Service                                                  |
 | EC2                     | Auto scaling groups                                      |
 | EC2                     | Elastic Load Balancers (v1 and v2)                       |
 | EC2                     | EBS Volumes                                              |
@@ -547,6 +548,7 @@ of the file that are supported are listed here.
 | apigatewayv2                | APIGatewayV2                 | ✅ (API Name)                          | ✅ (Created Time)                    | ❌    |    ✅   |
 | accessanalyzer              | AccessAnalyzer               | ✅ (Analyzer Name)                     | ✅ (Created Time)                    | ❌    |    ✅   |
 | asg                         | AutoScalingGroup             | ✅ (ASG Name)                          | ✅ (Created Time)                    | ✅    |    ✅   |
+| app-runner-service          | AppRunnerService             | ✅ (App Runner Service Name)           | ✅ (Created Time)                    | ❌    |    ✅   |
 | backup-vault                | BackupVault                  | ✅ (Backup Vault Name)                 | ✅ (Created Time)                    | ❌    |    ✅   |
 | cloudwatch-alarm            | CloudWatchAlarm              | ✅ (Alarm Name)                        | ✅ (AlarmConfigurationUpdated Time)  | ❌    |    ✅   |
 | cloudwatch-dashboard        | CloudWatchDashboard          | ✅ (Dashboard Name)                    | ✅ (LastModified Time)               | ❌    |    ✅   |
diff --git a/aws/resource_registry.go b/aws/resource_registry.go
index 0232d65..5aeda87 100644
--- a/aws/resource_registry.go
+++ b/aws/resource_registry.go
@@ -58,6 +58,7 @@ func getRegisteredRegionalResources() []AwsResource {
 		&resources.ApiGateway{},
 		&resources.ApiGatewayV2{},
 		&resources.ASGroups{},
+		&resources.AppRunnerService{},
 		&resources.BackupVault{},
 		&resources.CloudtrailTrail{},
 		&resources.CloudWatchAlarms{},
diff --git a/aws/resources/apprunner_service.go b/aws/resources/apprunner_service.go
new file mode 100644
index 0000000..6d21acb
--- /dev/null
+++ b/aws/resources/apprunner_service.go
@@ -0,0 +1,72 @@
+package resources
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/service/apprunner"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/cloud-nuke/logging"
+	"github.com/gruntwork-io/cloud-nuke/report"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+func (a *AppRunnerService) nukeAll(identifiers []*string) error {
+	if len(identifiers) == 0 {
+		logging.Debugf("[App Runner Service] No App Runner Services found in region %s", a.Region)
+		return nil
+	}
+
+	logging.Debugf("[App Runner Service] Deleting all App Runner Services in region %s", a.Region)
+	var deleted []*string
+
+	for _, identifier := range identifiers {
+		logging.Debugf("[App Runner Service] Deleting App Runner Service %s in region %s", *identifier, a.Region)
+
+		_, err := a.Client.DeleteServiceWithContext(a.Context, &apprunner.DeleteServiceInput{
+			ServiceArn: identifier,
+		})
+		if err != nil {
+			logging.Debugf("[App Runner Service] Error deleting App Runner Service %s in region %s", *identifier, a.Region)
+		} else {
+			deleted = append(deleted, identifier)
+			logging.Debugf("[App Runner Service] Deleted App Runner Service %s in region %s", *identifier, a.Region)
+		}
+
+		e := report.Entry{
+			Identifier:   aws.StringValue(identifier),
+			ResourceType: a.ResourceName(),
+			Error:        err,
+		}
+		report.Record(e)
+	}
+
+	logging.Debugf("[OK] %d App Runner Service(s) nuked in %s", len(deleted), a.Region)
+	return nil
+}
+
+func (a *AppRunnerService) getAll(c context.Context, configObj config.Config) ([]*string, error) {
+	var identifiers []*string
+	paginator := func(output *apprunner.ListServicesOutput, lastPage bool) bool {
+		for _, service := range output.ServiceSummaryList {
+			if configObj.AppRunnerService.ShouldInclude(config.ResourceValue{
+				Name: service.ServiceName,
+				Time: service.CreatedAt,
+			}) {
+				identifiers = append(identifiers, service.ServiceArn)
+			}
+		}
+		return !lastPage
+	}
+
+	param := &apprunner.ListServicesInput{
+		MaxResults: aws.Int64(19),
+	}
+
+	if err := a.Client.ListServicesPagesWithContext(c, param, paginator); err != nil {
+		logging.Debugf("[App Runner Service] Failed to list app runner services: %s", err)
+		return nil, errors.WithStackTrace(err)
+	}
+
+	return identifiers, nil
+}
diff --git a/aws/resources/apprunner_service_types.go b/aws/resources/apprunner_service_types.go
new file mode 100644
index 0000000..8c9e43d
--- /dev/null
+++ b/aws/resources/apprunner_service_types.go
@@ -0,0 +1,51 @@
+package resources
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/apprunner"
+	"github.com/aws/aws-sdk-go/service/apprunner/apprunneriface"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+type AppRunnerService struct {
+	BaseAwsResource
+	Client     apprunneriface.AppRunnerAPI
+	Region     string
+	AppRunners []string
+}
+
+func (a *AppRunnerService) GetAndSetResourceConfig(configObj config.Config) config.ResourceType {
+	return configObj.AppRunnerService
+}
+
+func (a *AppRunnerService) Init(session *session.Session) {
+	a.Client = apprunner.New(session)
+}
+
+func (a *AppRunnerService) ResourceName() string { return "app-runner-service" }
+
+func (a *AppRunnerService) ResourceIdentifiers() []string { return a.AppRunners }
+
+func (a *AppRunnerService) MaxBatchSize() int { return 19 }
+
+func (a *AppRunnerService) Nuke(identifiers []string) error {
+	if err := a.nukeAll(aws.StringSlice(identifiers)); err != nil {
+		return errors.WithStackTrace(err)
+	}
+
+	return nil
+}
+
+func (a *AppRunnerService) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) {
+	identifiers, err := a.getAll(c, configObj)
+	if err != nil {
+		return nil, err
+	}
+
+	a.AppRunners = aws.StringValueSlice(identifiers)
+	return a.AppRunners, nil
+}
diff --git a/config/config.go b/config/config.go
index 5bfa148..e9733fa 100644
--- a/config/config.go
+++ b/config/config.go
@@ -22,6 +22,7 @@ type Config struct {
 	APIGatewayV2                    ResourceType               `yaml:"APIGatewayV2"`
 	AccessAnalyzer                  ResourceType               `yaml:"AccessAnalyzer"`
 	AutoScalingGroup                ResourceType               `yaml:"AutoScalingGroup"`
+	AppRunnerService                ResourceType               `yaml:"AppRunnerService"`
 	BackupVault                     ResourceType               `yaml:"BackupVault"`
 	CloudWatchAlarm                 ResourceType               `yaml:"CloudWatchAlarm"`
 	CloudWatchDashboard             ResourceType               `yaml:"CloudWatchDashboard"`


Test patch:
diff --git a/aws/resources/apprunner_service_test.go b/aws/resources/apprunner_service_test.go
new file mode 100644
index 0000000..4b75d47
--- /dev/null
+++ b/aws/resources/apprunner_service_test.go
@@ -0,0 +1,109 @@
+package resources
+
+import (
+	"context"
+	"fmt"
+	"regexp"
+	"testing"
+	"time"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/service/apprunner"
+	"github.com/aws/aws-sdk-go/service/apprunner/apprunneriface"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+type mockedAppRunnerService struct {
+	apprunneriface.AppRunnerAPI
+	ListServicesOutput  apprunner.ListServicesOutput
+	DeleteServiceOutput apprunner.DeleteServiceOutput
+}
+
+func (m mockedAppRunnerService) ListServicesPagesWithContext(_ aws.Context, _ *apprunner.ListServicesInput, callback func(*apprunner.ListServicesOutput, bool) bool, _ ...request.Option) error {
+	callback(&m.ListServicesOutput, true)
+	return nil
+}
+
+func (m mockedAppRunnerService) DeleteServiceWithContext(aws.Context, *apprunner.DeleteServiceInput, ...request.Option) (*apprunner.DeleteServiceOutput, error) {
+	return &m.DeleteServiceOutput, nil
+}
+
+func Test_AppRunnerService_GetAll(t *testing.T) {
+
+	t.Parallel()
+
+	testName1 := "test-service-1"
+	testName2 := "test-service-2"
+	now := time.Now()
+	service := AppRunnerService{
+		Client: mockedAppRunnerService{
+			ListServicesOutput: apprunner.ListServicesOutput{
+				ServiceSummaryList: []*apprunner.ServiceSummary{
+					{
+						ServiceName: &testName1,
+						ServiceArn:  aws.String(fmt.Sprintf("arn::%s", testName1)),
+						CreatedAt:   &now,
+					},
+					{
+						ServiceName: &testName2,
+						ServiceArn:  aws.String(fmt.Sprintf("arn::%s", testName2)),
+						CreatedAt:   aws.Time(now.Add(1)),
+					},
+				},
+			},
+		},
+	}
+
+	tests := map[string]struct {
+		configObj config.ResourceType
+		expected  []string
+	}{
+		"emptyFilter": {
+			configObj: config.ResourceType{},
+			expected:  []string{fmt.Sprintf("arn::%s", testName1), fmt.Sprintf("arn::%s", testName2)},
+		},
+		"nameExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					NamesRegExp: []config.Expression{{
+						RE: *regexp.MustCompile(testName1),
+					}},
+				}},
+			expected: []string{fmt.Sprintf("arn::%s", testName2)},
+		},
+		"timeAfterExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					TimeAfter: aws.Time(now.Add(-1 * time.Hour)),
+				}},
+			expected: []string{},
+		},
+	}
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			names, err := service.getAll(context.Background(), config.Config{
+				AppRunnerService: tc.configObj,
+			})
+			require.NoError(t, err)
+			require.Equal(t, tc.expected, aws.StringValueSlice(names))
+		})
+	}
+}
+
+func TestAppRunnerService_NukeAll(t *testing.T) {
+
+	t.Parallel()
+
+	testName := "test-app-runner-service"
+	service := AppRunnerService{
+		Client: mockedAppRunnerService{
+			DeleteServiceOutput: apprunner.DeleteServiceOutput{},
+		},
+	}
+
+	err := service.nukeAll([]*string{&testName})
+	assert.NoError(t, err)
+}
diff --git a/config/config_test.go b/config/config_test.go
index 9ffe1db..1d953e7 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -13,107 +13,109 @@ import (
 
 func emptyConfig() *Config {
 	return &Config{
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		KMSCustomerKeyResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
-		ResourceType{FilterRule{}, FilterRule{}, ""},
+		ACM:                             ResourceType{FilterRule{}, FilterRule{}, ""},
+		ACMPCA:                          ResourceType{FilterRule{}, FilterRule{}, ""},
+		AMI:                             ResourceType{FilterRule{}, FilterRule{}, ""},
+		APIGateway:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		APIGatewayV2:                    ResourceType{FilterRule{}, FilterRule{}, ""},
+		AccessAnalyzer:                  ResourceType{FilterRule{}, FilterRule{}, ""},
+		AutoScalingGroup:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		AppRunnerService:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		BackupVault:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		CloudWatchAlarm:                 ResourceType{FilterRule{}, FilterRule{}, ""},
+		CloudWatchDashboard:             ResourceType{FilterRule{}, FilterRule{}, ""},
+		CloudWatchLogGroup:              ResourceType{FilterRule{}, FilterRule{}, ""},
+		CloudtrailTrail:                 ResourceType{FilterRule{}, FilterRule{}, ""},
+		CodeDeployApplications:          ResourceType{FilterRule{}, FilterRule{}, ""},
+		ConfigServiceRecorder:           ResourceType{FilterRule{}, FilterRule{}, ""},
+		ConfigServiceRule:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		DBGlobalClusters:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		DBClusters:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		DBInstances:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		DBGlobalClusterMemberships:      ResourceType{FilterRule{}, FilterRule{}, ""},
+		DBSubnetGroups:                  ResourceType{FilterRule{}, FilterRule{}, ""},
+		DynamoDB:                        ResourceType{FilterRule{}, FilterRule{}, ""},
+		EBSVolume:                       ResourceType{FilterRule{}, FilterRule{}, ""},
+		ElasticBeanstalk:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2:                             ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2DedicatedHosts:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2DHCPOption:                   ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2KeyPairs:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2IPAM:                         ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2IPAMPool:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2IPAMResourceDiscovery:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2IPAMScope:                    ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2Endpoint:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		EC2Subnet:                       EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
+		EgressOnlyInternetGateway:       ResourceType{FilterRule{}, FilterRule{}, ""},
+		ECRRepository:                   ResourceType{FilterRule{}, FilterRule{}, ""},
+		ECSCluster:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		ECSService:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		EKSCluster:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		ELBv1:                           ResourceType{FilterRule{}, FilterRule{}, ""},
+		ELBv2:                           ResourceType{FilterRule{}, FilterRule{}, ""},
+		ElasticFileSystem:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		ElasticIP:                       ResourceType{FilterRule{}, FilterRule{}, ""},
+		Elasticache:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		ElasticacheParameterGroups:      ResourceType{FilterRule{}, FilterRule{}, ""},
+		ElasticacheSubnetGroups:         ResourceType{FilterRule{}, FilterRule{}, ""},
+		GuardDuty:                       ResourceType{FilterRule{}, FilterRule{}, ""},
+		IAMGroups:                       ResourceType{FilterRule{}, FilterRule{}, ""},
+		IAMPolicies:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		IAMRoles:                        ResourceType{FilterRule{}, FilterRule{}, ""},
+		IAMServiceLinkedRoles:           ResourceType{FilterRule{}, FilterRule{}, ""},
+		IAMUsers:                        ResourceType{FilterRule{}, FilterRule{}, ""},
+		KMSCustomerKeys:                 KMSCustomerKeyResourceType{false, ResourceType{}},
+		KinesisStream:                   ResourceType{FilterRule{}, FilterRule{}, ""},
+		KinesisFirehose:                 ResourceType{FilterRule{}, FilterRule{}, ""},
+		LambdaFunction:                  ResourceType{FilterRule{}, FilterRule{}, ""},
+		LambdaLayer:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		LaunchConfiguration:             ResourceType{FilterRule{}, FilterRule{}, ""},
+		LaunchTemplate:                  ResourceType{FilterRule{}, FilterRule{}, ""},
+		MacieMember:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		MSKCluster:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		NatGateway:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		OIDCProvider:                    ResourceType{FilterRule{}, FilterRule{}, ""},
+		OpenSearchDomain:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		Redshift:                        ResourceType{FilterRule{}, FilterRule{}, ""},
+		RdsSnapshot:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		RdsParameterGroup:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		RdsProxy:                        ResourceType{FilterRule{}, FilterRule{}, ""},
+		S3:                              ResourceType{FilterRule{}, FilterRule{}, ""},
+		S3AccessPoint:                   ResourceType{FilterRule{}, FilterRule{}, ""},
+		S3ObjectLambdaAccessPoint:       ResourceType{FilterRule{}, FilterRule{}, ""},
+		S3MultiRegionAccessPoint:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		SESIdentity:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		SESConfigurationSet:             ResourceType{FilterRule{}, FilterRule{}, ""},
+		SESReceiptRuleSet:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		SESReceiptFilter:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		SESEmailTemplates:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		SNS:                             ResourceType{FilterRule{}, FilterRule{}, ""},
+		SQS:                             ResourceType{FilterRule{}, FilterRule{}, ""},
+		SageMakerNotebook:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		SecretsManagerSecrets:           ResourceType{FilterRule{}, FilterRule{}, ""},
+		SecurityHub:                     ResourceType{FilterRule{}, FilterRule{}, ""},
+		Snapshots:                       ResourceType{FilterRule{}, FilterRule{}, ""},
+		TransitGateway:                  ResourceType{FilterRule{}, FilterRule{}, ""},
+		TransitGatewayRouteTable:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		TransitGatewaysVpcAttachment:    ResourceType{FilterRule{}, FilterRule{}, ""},
+		TransitGatewayPeeringAttachment: ResourceType{FilterRule{}, FilterRule{}, ""},
+		VPC:                             EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
+		Route53HostedZone:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		Route53CIDRCollection:           ResourceType{FilterRule{}, FilterRule{}, ""},
+		Route53TrafficPolicy:            ResourceType{FilterRule{}, FilterRule{}, ""},
+		InternetGateway:                 ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkACL:                      ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkInterface:                ResourceType{FilterRule{}, FilterRule{}, ""},
+		SecurityGroup:                   EC2ResourceType{false, ResourceType{FilterRule{}, FilterRule{}, ""}},
+		NetworkFirewall:                 ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkFirewallPolicy:           ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkFirewallRuleGroup:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkFirewallTLSConfig:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		NetworkFirewallResourcePolicy:   ResourceType{FilterRule{}, FilterRule{}, ""},
+		VPCLatticeServiceNetwork:        ResourceType{FilterRule{}, FilterRule{}, ""},
+		VPCLatticeService:               ResourceType{FilterRule{}, FilterRule{}, ""},
+		VPCLatticeTargetGroup:           ResourceType{FilterRule{}, FilterRule{}, ""},
 	}
 }