From d063b3bb1edb8af6d09426718a2c1c8fe07c5981 Mon Sep 17 00:00:00 2001 From: James Kwon Date: Mon, 20 May 2024 21:25:38 -0400 Subject: [PATCH] implemented vpc lattice api --- README.md | 7 ++ aws/resource_registry.go | 3 + aws/resources/vpc_lattice_service.go | 68 ++++++++++ aws/resources/vpc_lattice_service_network.go | 68 ++++++++++ .../vpc_lattice_service_network_test.go | 108 ++++++++++++++++ .../vpc_lattice_service_network_types.go | 64 ++++++++++ aws/resources/vpc_lattice_service_test.go | 108 ++++++++++++++++ aws/resources/vpc_lattice_service_type.go | 64 ++++++++++ aws/resources/vpc_lattice_target_group.go | 118 ++++++++++++++++++ .../vpc_lattice_target_group_test.go | 1 + .../vpc_lattice_target_group_types.go | 66 ++++++++++ config/config.go | 3 + config/config_test.go | 3 + util/error.go | 10 ++ 14 files changed, 691 insertions(+) create mode 100644 aws/resources/vpc_lattice_service.go create mode 100644 aws/resources/vpc_lattice_service_network.go create mode 100644 aws/resources/vpc_lattice_service_network_test.go create mode 100644 aws/resources/vpc_lattice_service_network_types.go create mode 100644 aws/resources/vpc_lattice_service_test.go create mode 100644 aws/resources/vpc_lattice_service_type.go create mode 100644 aws/resources/vpc_lattice_target_group.go create mode 100644 aws/resources/vpc_lattice_target_group_test.go create mode 100644 aws/resources/vpc_lattice_target_group_types.go diff --git a/README.md b/README.md index 1ba482a9..22e1fe2d 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,9 @@ Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS res | NetworkFirewall | Network Firewall Rule Group | | NetworkFirewall | Network Firewall TLS inspection configuration | | NetworkFirewall | Network Firewall Resource Policy | +| VPCLattice | VPC Lattice Service | +| VPCLattice | VPC Lattice Service Network | +| VPCLattice | VPC Lattice Target Group | > **WARNING:** The RDS APIs also interact with neptune and document db resources. > Running `cloud-nuke aws --resource-type rds` without a config file will remove any neptune and document db resources @@ -627,6 +630,10 @@ of the file that are supported are listed here. | network-firewall-rule-group | NetworkFirewallRuleGroup | ✅ (Firewall Rule group name) | ✅ (First Seen Tag Time) | ✅ | ❌ | | network-firewall-tls-config | NetworkFirewallTLSConfig | ✅ (Firewall TLS config name) | ✅ (First Seen Tag Time) | ✅ | ❌ | | network-firewall-resource-policy | NetworkFirewallResourcePolicy | ✅ (Firewall Resource Policy ARN) | ❌ | ❌ | ❌ | +| vpc-lattice-service | VPCLatticeService | ✅ (VPC Lattice service ARN) | (Creation Time) | ❌ | ✅ | +| vpc-lattice-service-network | VPCLatticeServiceNetwork | ✅ (VPC Lattice service network ARN) | (Creation Time) | ❌ | ✅ | +| vpc-lattice-target-group | VPCLatticeTargetGroup | ✅ (VPC Lattice target group ARN) | (Creation Time) | ❌ | ✅ | + ### Resource Deletion and 'IsNukable' Check Option diff --git a/aws/resource_registry.go b/aws/resource_registry.go index 0d25ae6f..697714fd 100644 --- a/aws/resource_registry.go +++ b/aws/resource_registry.go @@ -141,6 +141,9 @@ func getRegisteredRegionalResources() []AwsResource { &resources.NetworkFirewallRuleGroup{}, &resources.NetworkFirewallTLSConfig{}, &resources.NetworkFirewallResourcePolicy{}, + &resources.VPCLatticeServiceNetwork{}, + &resources.VPCLatticeService{}, + &resources.VPCLatticeTargetGroup{}, } } diff --git a/aws/resources/vpc_lattice_service.go b/aws/resources/vpc_lattice_service.go new file mode 100644 index 00000000..c782bd2c --- /dev/null +++ b/aws/resources/vpc_lattice_service.go @@ -0,0 +1,68 @@ +package resources + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/vpclattice" + "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 (network *VPCLatticeService) getAll(_ context.Context, configObj config.Config) ([]*string, error) { + output, err := network.Client.ListServicesWithContext(network.Context, nil) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + var ids []*string + for _, item := range output.Items { + + if configObj.VPCLatticeService.ShouldInclude(config.ResourceValue{ + Name: item.Name, + Time: item.CreatedAt, + }) { + ids = append(ids, item.Arn) + } + } + + return ids, nil +} + +func (network *VPCLatticeService) nukeAll(identifiers []*string) error { + if len(identifiers) == 0 { + logging.Debugf("No %s to nuke in region %s", network.ResourceServiceName(), network.Region) + return nil + + } + + logging.Debugf("Deleting all %s in region %s", network.ResourceServiceName(), network.Region) + + deletedCount := 0 + for _, id := range identifiers { + + _, err := network.Client.DeleteServiceWithContext(network.Context, &vpclattice.DeleteServiceInput{ + ServiceIdentifier: id, + }) + + // Record status of this resource + e := report.Entry{ + Identifier: aws.StringValue(id), + ResourceType: network.ResourceServiceName(), + Error: err, + } + report.Record(e) + + if err != nil { + logging.Debugf("[Failed] %s", err) + } else { + deletedCount++ + logging.Debugf("Deleted %s: %s", network.ResourceServiceName(), aws.StringValue(id)) + } + } + + logging.Debugf("[OK] %d %s(s) terminated in %s", deletedCount, network.ResourceServiceName(), network.Region) + return nil +} diff --git a/aws/resources/vpc_lattice_service_network.go b/aws/resources/vpc_lattice_service_network.go new file mode 100644 index 00000000..1c409f44 --- /dev/null +++ b/aws/resources/vpc_lattice_service_network.go @@ -0,0 +1,68 @@ +package resources + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/vpclattice" + "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 (network *VPCLatticeServiceNetwork) getAll(_ context.Context, configObj config.Config) ([]*string, error) { + output, err := network.Client.ListServiceNetworksWithContext(network.Context, nil) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + var ids []*string + for _, item := range output.Items { + + if configObj.VPCLatticeServiceNetwork.ShouldInclude(config.ResourceValue{ + Name: item.Name, + Time: item.CreatedAt, + }) { + ids = append(ids, item.Arn) + } + } + + return ids, nil +} + +func (network *VPCLatticeServiceNetwork) nukeAll(identifiers []*string) error { + if len(identifiers) == 0 { + logging.Debugf("No %s to nuke in region %s", network.ResourceServiceName(), network.Region) + return nil + + } + + logging.Debugf("Deleting all %s in region %s", network.ResourceServiceName(), network.Region) + + deletedCount := 0 + for _, id := range identifiers { + + _, err := network.Client.DeleteServiceNetworkWithContext(network.Context, &vpclattice.DeleteServiceNetworkInput{ + ServiceNetworkIdentifier: id, + }) + + // Record status of this resource + e := report.Entry{ + Identifier: aws.StringValue(id), + ResourceType: network.ResourceServiceName(), + Error: err, + } + report.Record(e) + + if err != nil { + logging.Debugf("[Failed] %s", err) + } else { + deletedCount++ + logging.Debugf("Deleted %s: %s", network.ResourceServiceName(), aws.StringValue(id)) + } + } + + logging.Debugf("[OK] %d %s(s) terminated in %s", deletedCount, network.ResourceServiceName(), network.Region) + return nil +} diff --git a/aws/resources/vpc_lattice_service_network_test.go b/aws/resources/vpc_lattice_service_network_test.go new file mode 100644 index 00000000..fcd2d6ba --- /dev/null +++ b/aws/resources/vpc_lattice_service_network_test.go @@ -0,0 +1,108 @@ +package resources_test + +import ( + "context" + "regexp" + "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/vpclattice" + "github.com/aws/aws-sdk-go/service/vpclattice/vpclatticeiface" + "github.com/gruntwork-io/cloud-nuke/aws/resources" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/util" + "github.com/stretchr/testify/require" +) + +type mockedVPCLatticeServiceNetwork struct { + vpclatticeiface.VPCLatticeAPI + DeleteServiceNetworkOutput vpclattice.DeleteServiceNetworkOutput + ListServiceNetworksOutput vpclattice.ListServiceNetworksOutput +} + +func (m mockedVPCLatticeServiceNetwork) ListServiceNetworksWithContext(aws.Context, *vpclattice.ListServiceNetworksInput, ...request.Option) (*vpclattice.ListServiceNetworksOutput, error) { + return &m.ListServiceNetworksOutput, nil +} + +func (m mockedVPCLatticeServiceNetwork) DeleteServiceNetworkWithContext(aws.Context, *vpclattice.DeleteServiceNetworkInput, ...request.Option) (*vpclattice.DeleteServiceNetworkOutput, error) { + return &m.DeleteServiceNetworkOutput, nil +} + +func TestVPCLatticeServiceNetwork_GetAll(t *testing.T) { + + t.Parallel() + + var ( + id1 = "aws-nuke-test-" + util.UniqueID() + id2 = "aws-nuke-test-" + util.UniqueID() + now = time.Now() + ) + + obj := resources.VPCLatticeServiceNetwork{ + Client: mockedVPCLatticeServiceNetwork{ + ListServiceNetworksOutput: vpclattice.ListServiceNetworksOutput{ + Items: []*vpclattice.ServiceNetworkSummary{ + { + Arn: awsgo.String(id1), + Name: awsgo.String(id1), + CreatedAt: aws.Time(now), + }, { + Arn: awsgo.String(id2), + Name: awsgo.String(id2), + CreatedAt: aws.Time(now.Add(1 * time.Hour)), + }, + }, + }, + }, + } + + tests := map[string]struct { + configObj config.ResourceType + expected []string + }{ + "emptyFilter": { + configObj: config.ResourceType{}, + expected: []string{id1, id2}, + }, + "nameExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + NamesRegExp: []config.Expression{{ + RE: *regexp.MustCompile(id2), + }}}, + }, + expected: []string{id1}, + }, + "timeAfterExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + TimeAfter: awsgo.Time(now), + }}, + expected: []string{id1}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + names, err := obj.GetAndSetIdentifiers(context.Background(), config.Config{ + VPCLatticeServiceNetwork: tc.configObj, + }) + require.NoError(t, err) + require.Equal(t, tc.expected, names) + }) + } +} + +func TestVPCLatticeServiceNetwork__NukeAll(t *testing.T) { + t.Parallel() + + obj := resources.VPCLatticeServiceNetwork{ + Client: mockedVPCLatticeServiceNetwork{ + ListServiceNetworksOutput: vpclattice.ListServiceNetworksOutput{}, + }, + } + err := obj.Nuke([]string{"test"}) + require.NoError(t, err) +} diff --git a/aws/resources/vpc_lattice_service_network_types.go b/aws/resources/vpc_lattice_service_network_types.go new file mode 100644 index 00000000..730817fa --- /dev/null +++ b/aws/resources/vpc_lattice_service_network_types.go @@ -0,0 +1,64 @@ +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/vpclattice" + "github.com/aws/aws-sdk-go/service/vpclattice/vpclatticeiface" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/go-commons/errors" +) + +type VPCLatticeServiceNetwork struct { + BaseAwsResource + Client vpclatticeiface.VPCLatticeAPI + Region string + ARNs []string +} + +func (n *VPCLatticeServiceNetwork) Init(session *session.Session) { + n.Client = vpclattice.New(session) +} + +// ResourceName - the simple name of the aws resource +func (n *VPCLatticeServiceNetwork) ResourceName() string { + return "vpc-lattice-service-network" +} + +// ResourceIdentifiers - the arns of the aws certificate manager certificates +func (n *VPCLatticeServiceNetwork) ResourceIdentifiers() []string { + return n.ARNs +} + +func (n *VPCLatticeServiceNetwork) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { + return configObj.VPCLatticeServiceNetwork +} + +func (n *VPCLatticeServiceNetwork) ResourceServiceName() string { + return "VPC Lattice Service Network" +} + +func (n *VPCLatticeServiceNetwork) MaxBatchSize() int { + return maxBatchSize +} + +func (n *VPCLatticeServiceNetwork) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { + identifiers, err := n.getAll(c, configObj) + if err != nil { + return nil, err + } + + n.ARNs = awsgo.StringValueSlice(identifiers) + return n.ARNs, nil +} + +// Nuke - nuke 'em all!!! +func (n *VPCLatticeServiceNetwork) Nuke(arns []string) error { + if err := n.nukeAll(awsgo.StringSlice(arns)); err != nil { + return errors.WithStackTrace(err) + } + + return nil +} diff --git a/aws/resources/vpc_lattice_service_test.go b/aws/resources/vpc_lattice_service_test.go new file mode 100644 index 00000000..074dcf89 --- /dev/null +++ b/aws/resources/vpc_lattice_service_test.go @@ -0,0 +1,108 @@ +package resources_test + +import ( + "context" + "regexp" + "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/vpclattice" + "github.com/aws/aws-sdk-go/service/vpclattice/vpclatticeiface" + "github.com/gruntwork-io/cloud-nuke/aws/resources" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/util" + "github.com/stretchr/testify/require" +) + +type mockedVPCLatticeService struct { + vpclatticeiface.VPCLatticeAPI + ListServicesOutput vpclattice.ListServicesOutput + DeleteServiceOutput vpclattice.DeleteServiceOutput +} + +func (m mockedVPCLatticeService) ListServicesWithContext(aws.Context, *vpclattice.ListServicesInput, ...request.Option) (*vpclattice.ListServicesOutput, error) { + return &m.ListServicesOutput, nil +} + +func (m mockedVPCLatticeService) DeleteServiceWithContext(aws.Context, *vpclattice.DeleteServiceInput, ...request.Option) (*vpclattice.DeleteServiceOutput, error) { + return &m.DeleteServiceOutput, nil +} + +func TestVPCLatticeService_GetAll(t *testing.T) { + + t.Parallel() + + var ( + id1 = "aws-nuke-test-" + util.UniqueID() + id2 = "aws-nuke-test-" + util.UniqueID() + now = time.Now() + ) + + obj := resources.VPCLatticeService{ + Client: mockedVPCLatticeService{ + ListServicesOutput: vpclattice.ListServicesOutput{ + Items: []*vpclattice.ServiceSummary{ + { + Arn: awsgo.String(id1), + Name: awsgo.String(id1), + CreatedAt: aws.Time(now), + }, { + Arn: awsgo.String(id2), + Name: awsgo.String(id2), + CreatedAt: aws.Time(now.Add(1 * time.Hour)), + }, + }, + }, + }, + } + + tests := map[string]struct { + configObj config.ResourceType + expected []string + }{ + "emptyFilter": { + configObj: config.ResourceType{}, + expected: []string{id1, id2}, + }, + "nameExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + NamesRegExp: []config.Expression{{ + RE: *regexp.MustCompile(id2), + }}}, + }, + expected: []string{id1}, + }, + "timeAfterExclusionFilter": { + configObj: config.ResourceType{ + ExcludeRule: config.FilterRule{ + TimeAfter: awsgo.Time(now), + }}, + expected: []string{id1}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + names, err := obj.GetAndSetIdentifiers(context.Background(), config.Config{ + VPCLatticeService: tc.configObj, + }) + require.NoError(t, err) + require.Equal(t, tc.expected, names) + }) + } +} + +func TestVPCLatticeService_NukeAll(t *testing.T) { + t.Parallel() + + obj := resources.VPCLatticeService{ + Client: mockedVPCLatticeService{ + ListServicesOutput: vpclattice.ListServicesOutput{}, + }, + } + err := obj.Nuke([]string{"test"}) + require.NoError(t, err) +} diff --git a/aws/resources/vpc_lattice_service_type.go b/aws/resources/vpc_lattice_service_type.go new file mode 100644 index 00000000..df2ba270 --- /dev/null +++ b/aws/resources/vpc_lattice_service_type.go @@ -0,0 +1,64 @@ +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/vpclattice" + "github.com/aws/aws-sdk-go/service/vpclattice/vpclatticeiface" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/go-commons/errors" +) + +type VPCLatticeService struct { + BaseAwsResource + Client vpclatticeiface.VPCLatticeAPI + Region string + ARNs []string +} + +func (n *VPCLatticeService) Init(session *session.Session) { + n.Client = vpclattice.New(session) +} + +// ResourceName - the simple name of the aws resource +func (n *VPCLatticeService) ResourceName() string { + return "vpc-lattice-service" +} + +// ResourceIdentifiers - the arns of the aws certificate manager certificates +func (n *VPCLatticeService) ResourceIdentifiers() []string { + return n.ARNs +} + +func (n *VPCLatticeService) ResourceServiceName() string { + return "VPC Lattice Service" +} + +func (n *VPCLatticeService) MaxBatchSize() int { + return maxBatchSize +} + +func (n *VPCLatticeService) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { + return configObj.VPCLatticeService +} + +func (n *VPCLatticeService) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { + identifiers, err := n.getAll(c, configObj) + if err != nil { + return nil, err + } + + n.ARNs = awsgo.StringValueSlice(identifiers) + return n.ARNs, nil +} + +// Nuke - nuke 'em all!!! +func (n *VPCLatticeService) Nuke(arns []string) error { + if err := n.nukeAll(awsgo.StringSlice(arns)); err != nil { + return errors.WithStackTrace(err) + } + + return nil +} diff --git a/aws/resources/vpc_lattice_target_group.go b/aws/resources/vpc_lattice_target_group.go new file mode 100644 index 00000000..9e27b3cf --- /dev/null +++ b/aws/resources/vpc_lattice_target_group.go @@ -0,0 +1,118 @@ +package resources + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/vpclattice" + "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 (network *VPCLatticeTargetGroup) getAll(_ context.Context, configObj config.Config) ([]*string, error) { + output, err := network.Client.ListTargetGroupsWithContext(network.Context, nil) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + var ids []*string + for _, item := range output.Items { + + if configObj.VPCLatticeTargetGroup.ShouldInclude(config.ResourceValue{ + Name: item.Name, + Time: item.CreatedAt, + }) { + ids = append(ids, item.Arn) + // also keep the complete info about the target groups as the target group assoiation needs to be nuked before removing it + network.TargetGroups[aws.StringValue(item.Arn)] = item + } + } + + return ids, nil +} + +func (network *VPCLatticeTargetGroup) nukeTargets(identifier *string) error { + // list the targets associated on the target group + output, err := network.Client.ListTargetsWithContext(network.Context, &vpclattice.ListTargetsInput{ + TargetGroupIdentifier: identifier, + }) + if err != nil { + logging.Debugf("[ListTargetsWithContext Failed] %s", err) + return errors.WithStackTrace(err) + } + + var targets []*vpclattice.Target + for _, target := range output.Items { + targets = append(targets, &vpclattice.Target{ + Id: target.Id, + }) + } + + if len(targets) > 0 { + // before deleting the targets, we need to deregister the targets registered with it + _, err = network.Client.DeregisterTargetsWithContext(network.Context, &vpclattice.DeregisterTargetsInput{ + TargetGroupIdentifier: identifier, + Targets: targets, + }) + if err != nil { + logging.Debugf("[DeregisterTargetsWithContext Failed] %s", err) + return errors.WithStackTrace(err) + } + } + + return nil +} + +func (network *VPCLatticeTargetGroup) nuke(identifier *string) error { + + var err error + err = network.nukeTargets(identifier) + if err != nil { + return errors.WithStackTrace(err) + } + + // delete the target group + _, err = network.Client.DeleteTargetGroupWithContext(network.Context, &vpclattice.DeleteTargetGroupInput{ + TargetGroupIdentifier: identifier, + }) + if err != nil { + return errors.WithStackTrace(err) + } + + return nil +} +func (network *VPCLatticeTargetGroup) nukeAll(identifiers []*string) error { + if len(identifiers) == 0 { + logging.Debugf("No %s to nuke in region %s", network.ResourceServiceName(), network.Region) + return nil + + } + + logging.Debugf("Deleting all %s in region %s", network.ResourceServiceName(), network.Region) + + deletedCount := 0 + for _, id := range identifiers { + + err := network.nuke(id) + + // Record status of this resource + e := report.Entry{ + Identifier: aws.StringValue(id), + ResourceType: network.ResourceServiceName(), + Error: err, + } + report.Record(e) + + if err != nil { + logging.Debugf("[Failed] %s", err) + } else { + deletedCount++ + logging.Debugf("Deleted %s: %s", network.ResourceServiceName(), aws.StringValue(id)) + } + } + + logging.Debugf("[OK] %d %s(s) terminated in %s", deletedCount, network.ResourceServiceName(), network.Region) + return nil +} diff --git a/aws/resources/vpc_lattice_target_group_test.go b/aws/resources/vpc_lattice_target_group_test.go new file mode 100644 index 00000000..98394b73 --- /dev/null +++ b/aws/resources/vpc_lattice_target_group_test.go @@ -0,0 +1 @@ +package resources_test diff --git a/aws/resources/vpc_lattice_target_group_types.go b/aws/resources/vpc_lattice_target_group_types.go new file mode 100644 index 00000000..d9cb1da2 --- /dev/null +++ b/aws/resources/vpc_lattice_target_group_types.go @@ -0,0 +1,66 @@ +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/vpclattice" + "github.com/aws/aws-sdk-go/service/vpclattice/vpclatticeiface" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/go-commons/errors" +) + +type VPCLatticeTargetGroup struct { + BaseAwsResource + Client vpclatticeiface.VPCLatticeAPI + Region string + ARNs []string + TargetGroups map[string]*vpclattice.TargetGroupSummary +} + +func (n *VPCLatticeTargetGroup) Init(session *session.Session) { + n.Client = vpclattice.New(session) + n.TargetGroups = make(map[string]*vpclattice.TargetGroupSummary) +} + +// ResourceName - the simple name of the aws resource +func (n *VPCLatticeTargetGroup) ResourceName() string { + return "vpc-lattice-target-group" +} + +// ResourceIdentifiers - the arns of the aws certificate manager certificates +func (n *VPCLatticeTargetGroup) ResourceIdentifiers() []string { + return n.ARNs +} + +func (n *VPCLatticeTargetGroup) ResourceServiceName() string { + return "VPC Lattice Target Group" +} + +func (n *VPCLatticeTargetGroup) MaxBatchSize() int { + return maxBatchSize +} + +func (n *VPCLatticeTargetGroup) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { + return configObj.VPCLatticeTargetGroup +} + +func (n *VPCLatticeTargetGroup) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { + identifiers, err := n.getAll(c, configObj) + if err != nil { + return nil, err + } + + n.ARNs = awsgo.StringValueSlice(identifiers) + return n.ARNs, nil +} + +// Nuke - nuke 'em all!!! +func (n *VPCLatticeTargetGroup) Nuke(arns []string) error { + if err := n.nukeAll(awsgo.StringSlice(arns)); err != nil { + return errors.WithStackTrace(err) + } + + return nil +} diff --git a/config/config.go b/config/config.go index b1f7a882..4018b337 100644 --- a/config/config.go +++ b/config/config.go @@ -112,6 +112,9 @@ type Config struct { NetworkFirewallRuleGroup ResourceType `yaml:"NetworkFirewallRuleGroup"` NetworkFirewallTLSConfig ResourceType `yaml:"NetworkFirewallTLSConfig"` NetworkFirewallResourcePolicy ResourceType `yaml:"NetworkFirewallResourcePolicy"` + VPCLatticeServiceNetwork ResourceType `yaml:"VPCLatticeServiceNetwork"` + VPCLatticeService ResourceType `yaml:"VPCLatticeService"` + VPCLatticeTargetGroup ResourceType `yaml:"VPCLatticeTargetGroup"` } func (c *Config) addTimeAfterFilter(timeFilter *time.Time, fieldName string) { diff --git a/config/config_test.go b/config/config_test.go index bf25053c..5b508fa7 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -110,6 +110,9 @@ func emptyConfig() *Config { ResourceType{FilterRule{}, FilterRule{}, ""}, ResourceType{FilterRule{}, FilterRule{}, ""}, ResourceType{FilterRule{}, FilterRule{}, ""}, + ResourceType{FilterRule{}, FilterRule{}, ""}, + ResourceType{FilterRule{}, FilterRule{}, ""}, + ResourceType{FilterRule{}, FilterRule{}, ""}, } } diff --git a/util/error.go b/util/error.go index ec13d5de..53e41fbc 100644 --- a/util/error.go +++ b/util/error.go @@ -6,6 +6,7 @@ import ( "time" "github.com/aws/aws-sdk-go/aws/awserr" + commonErr "github.com/gruntwork-io/go-commons/errors" ) var ErrInSufficientPermission = errors.New("error:INSUFFICIENT_PERMISSION") @@ -32,6 +33,15 @@ func TransformAWSError(err error) error { return ErrContextExecutionTimeout } + // check the error is wrapped with errors.WithStackTrace(), then we can't check the actuall error is aws. So handling the situation here + // as unwrap the error and check the underhood error type is awserr + // NOTE : is this is not checked, then it will not print `error:EXECUTION_TIMEOUT` if the error is wrapped with WithStackTrace + if err := commonErr.Unwrap(err); err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "RequestCanceled" { + return ErrContextExecutionTimeout + } + } + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "InvalidNetworkInterfaceID.NotFound" { return ErrInterfaceIDNotFound }