From b04218a29fd6164534aea27656512154dae35dc8 Mon Sep 17 00:00:00 2001 From: James Kwon Date: Fri, 19 Apr 2024 19:23:31 -0400 Subject: [PATCH] refactored ec2_vpc --- aws/aws.go | 17 -- aws/query_test.go | 11 +- aws/resources/access_analyzer.go | 7 + aws/resources/access_analyzer_test.go | 5 +- aws/resources/acm.go | 7 + aws/resources/acm_test.go | 7 +- aws/resources/acmpca.go | 8 + aws/resources/acmpca_test.go | 7 +- aws/resources/ami.go | 7 + aws/resources/ami_test.go | 7 +- aws/resources/apigateway.go | 9 + aws/resources/apigateway_test.go | 9 +- aws/resources/apigatewayv2.go | 15 +- aws/resources/apigatewayv2_test.go | 5 +- aws/resources/asg.go | 12 ++ aws/resources/asg_test.go | 5 +- aws/resources/backup_vault.go | 7 + aws/resources/backup_vault_test.go | 5 +- aws/resources/cloudtrail.go | 7 + aws/resources/cloudtrail_test.go | 5 +- aws/resources/cloudwatch_alarm.go | 17 ++ aws/resources/cloudwatch_alarm_test.go | 7 +- aws/resources/cloudwatch_dashboard.go | 10 +- aws/resources/cloudwatch_dashboard_test.go | 5 +- aws/resources/cloudwatch_loggroup.go | 7 + aws/resources/cloudwatch_loggroup_test.go | 5 +- aws/resources/codedeploy_application.go | 7 + aws/resources/codedeploy_application_test.go | 3 +- aws/resources/config_recorder.go | 7 + aws/resources/config_recorder_test.go | 5 +- aws/resources/config_service_test.go | 5 +- aws/resources/dynamodb.go | 7 + aws/resources/dynamodb_test.go | 5 +- aws/resources/ebs.go | 27 ++- aws/resources/ebs_test.go | 6 +- aws/resources/ec2.go | 17 ++ aws/resources/ec2_dedicated_host.go | 12 ++ aws/resources/ec2_dedicated_host_test.go | 5 +- aws/resources/ec2_dhcp_option.go | 27 ++- aws/resources/ec2_dhcp_option_test.go | 5 +- aws/resources/ec2_egress_only_igw.go | 31 ++- aws/resources/ec2_egress_only_igw_test.go | 49 ++--- aws/resources/ec2_endpoints.go | 69 ++++++- aws/resources/ec2_endpoints_test.go | 5 +- aws/resources/ec2_internet_gateway.go | 130 ++++++------ aws/resources/ec2_internet_gateway_test.go | 47 ++--- aws/resources/ec2_internet_gateway_types.go | 12 +- aws/resources/ec2_key_pair.go | 7 + aws/resources/ec2_key_pair_test.go | 5 +- aws/resources/ec2_network_acl.go | 100 ++++++---- aws/resources/ec2_network_acl_test.go | 3 + aws/resources/ec2_network_interface.go | 77 ++++---- aws/resources/ec2_network_interface_test.go | 62 +++--- aws/resources/ec2_subnet.go | 39 ++-- aws/resources/ec2_subnet_test.go | 5 +- aws/resources/ec2_test.go | 5 +- aws/resources/ec2_vpc.go | 185 ++++++------------ aws/resources/ec2_vpc_test.go | 5 +- aws/resources/ecr.go | 7 + aws/resources/ecr_test.go | 5 +- aws/resources/ecs_cluster.go | 8 + aws/resources/ecs_cluster_test.go | 7 +- aws/resources/ecs_service.go | 32 +++ aws/resources/ecs_service_test.go | 5 +- aws/resources/efs.go | 7 + aws/resources/efs_test.go | 5 +- aws/resources/eip.go | 16 +- aws/resources/eip_test.go | 5 +- aws/resources/eks.go | 7 + aws/resources/eks_test.go | 5 +- aws/resources/elasticache.go | 17 ++ aws/resources/elasticache_test.go | 5 +- aws/resources/elb.go | 7 + aws/resources/elb_test.go | 5 +- aws/resources/elbv2.go | 7 + aws/resources/elbv2_test.go | 5 +- aws/resources/guardduty.go | 7 + aws/resources/guardduty_test.go | 5 +- aws/resources/iam.go | 5 + aws/resources/iam_group.go | 5 + aws/resources/iam_group_test.go | 5 +- aws/resources/iam_policy.go | 5 + aws/resources/iam_policy_test.go | 5 +- aws/resources/iam_role.go | 5 + aws/resources/iam_role_test.go | 5 +- aws/resources/iam_service_linked_role.go | 5 + aws/resources/iam_service_linked_role_test.go | 5 +- aws/resources/iam_test.go | 5 +- aws/resources/kinesis_stream.go | 8 + aws/resources/kinesis_stream_test.go | 5 +- aws/resources/kms_customer_key.go | 7 + aws/resources/kms_customer_key_test.go | 5 +- aws/resources/lambda.go | 7 + aws/resources/lambda_layer.go | 7 + aws/resources/lambda_layer_test.go | 5 +- aws/resources/lambda_test.go | 5 +- aws/resources/launch_config.go | 7 + aws/resources/launch_config_test.go | 5 +- aws/resources/launch_template.go | 7 + aws/resources/launch_template_test.go | 5 +- aws/resources/macie.go | 32 +++ aws/resources/macie_test.go | 5 +- aws/resources/nat_gateway.go | 47 +++-- aws/resources/nat_gateway_test.go | 5 +- aws/resources/nat_gateway_types.go | 10 +- aws/resources/oidc_provider.go | 5 + aws/resources/oidc_provider_test.go | 5 +- aws/resources/opensearch.go | 7 + aws/resources/opensearch_test.go | 5 +- aws/resources/rds.go | 12 ++ aws/resources/rds_cluster.go | 7 + aws/resources/rds_cluster_test.go | 5 +- aws/resources/rds_snapshot_test.go | 5 +- aws/resources/rds_subnet_group.go | 7 + aws/resources/rds_subnet_group_test.go | 5 +- aws/resources/rds_test.go | 5 +- aws/resources/redshift.go | 12 ++ aws/resources/redshift_test.go | 5 +- aws/resources/route53_cidr_collection_test.go | 5 +- aws/resources/route53_hostedzone_test.go | 5 +- aws/resources/route53_traffic_policy_test.go | 5 +- aws/resources/s3.go | 18 +- aws/resources/s3_access_point_test.go | 5 +- .../s3_multi_region_access_point_test.go | 5 +- .../s3_object_lambda_access_point_test.go | 5 +- aws/resources/s3_test.go | 5 +- aws/resources/sagemaker_notebook_instance.go | 26 +++ .../sagemaker_notebook_instance_test.go | 5 +- aws/resources/secrets_manager.go | 7 + aws/resources/secrets_manager_test.go | 5 +- aws/resources/security_group.go | 96 ++++----- aws/resources/security_group_test.go | 3 +- aws/resources/security_hub.go | 33 +++- aws/resources/security_hub_test.go | 5 +- aws/resources/snapshot.go | 12 +- aws/resources/snapshot_test.go | 5 +- aws/resources/sns.go | 8 + aws/resources/sns_test.go | 6 +- aws/resources/sqs.go | 11 +- aws/resources/sqs_test.go | 5 +- aws/resources/transit_gateway.go | 7 + aws/resources/transit_gateway_test.go | 17 +- commands/cli_test.go | 5 +- 143 files changed, 1328 insertions(+), 642 deletions(-) diff --git a/aws/aws.go b/aws/aws.go index 66020c20..c54e23ec 100644 --- a/aws/aws.go +++ b/aws/aws.go @@ -63,15 +63,6 @@ func GetAllResources(c context.Context, query *Query, configObj config.Config) ( identifiers, err := (*resource).GetAndSetIdentifiers(c, configObj) if err != nil { logging.Errorf("Unable to retrieve %v, %v", (*resource).ResourceName(), err) - - // Reporting resource-level failures encountered during the GetIdentifiers phase - // Note: This is useful to understand which resources are failing more often than others. - telemetry.TrackEvent(commonTelemetry.EventContext{ - EventName: fmt.Sprintf("error:GetIdentifiers:%s", (*resource).ResourceName()), - }, map[string]interface{}{ - "region": region, - }) - ge := report.GeneralError{ Error: err, Description: fmt.Sprintf("Unable to retrieve %s", (*resource).ResourceName()), @@ -164,14 +155,6 @@ func nukeAllResourcesInRegion(account *AwsAccountResources, region string, bar * // of the current job.Since we handle each individual resource deletion error within its own resource-specific code, // we can safely discard this error _ = err - - // Report to telemetry - aggregated metrics of failures per resources. - // Note: This is useful to understand which resources are failing more often than others. - telemetry.TrackEvent(commonTelemetry.EventContext{ - EventName: fmt.Sprintf("error:Nuke:%s", (*awsResource).ResourceName()), - }, map[string]interface{}{ - "region": region, - }) } if i != len(batches)-1 { diff --git a/aws/query_test.go b/aws/query_test.go index 8cc4b4cd..49c3620a 100644 --- a/aws/query_test.go +++ b/aws/query_test.go @@ -44,16 +44,7 @@ func TestNewQueryAcceptsValidExcludeAfterEntries(t *testing.T) { for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - _, err := NewQuery( - tc.Regions, - tc.ExcludeRegions, - tc.ResourceTypes, - tc.ExcludeResourceTypes, - tc.ExcludeAfter, - tc.IncludeAfter, - false, - nil, - false) + _, err := NewQuery(tc.Regions, tc.ExcludeRegions, tc.ResourceTypes, tc.ExcludeResourceTypes, tc.ExcludeAfter, tc.IncludeAfter, false, nil) require.NoError(t, err) }) } diff --git a/aws/resources/access_analyzer.go b/aws/resources/access_analyzer.go index c45eac16..bb3e86f7 100644 --- a/aws/resources/access_analyzer.go +++ b/aws/resources/access_analyzer.go @@ -5,7 +5,9 @@ import ( "github.com/aws/aws-sdk-go/service/accessanalyzer" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "sync" ) @@ -62,6 +64,11 @@ func (analyzer *AccessAnalyzer) nukeAll(names []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Access Analyzer", + }, map[string]interface{}{ + "region": analyzer.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/access_analyzer_test.go b/aws/resources/access_analyzer_test.go index 847e65f6..262fcaea 100644 --- a/aws/resources/access_analyzer_test.go +++ b/aws/resources/access_analyzer_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/accessanalyzer" "github.com/aws/aws-sdk-go/service/accessanalyzer/accessanalyzeriface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -29,7 +30,7 @@ func (m mockedAccessAnalyzer) DeleteAnalyzer(input *accessanalyzer.DeleteAnalyze } func TestAccessAnalyzer_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -90,7 +91,7 @@ func TestAccessAnalyzer_GetAll(t *testing.T) { } func TestAccessAnalyzer_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() aa := AccessAnalyzer{ diff --git a/aws/resources/acm.go b/aws/resources/acm.go index b6bc682c..1f7e9369 100644 --- a/aws/resources/acm.go +++ b/aws/resources/acm.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a list of strings of ACM ARNs @@ -78,6 +80,11 @@ func (a *ACM) nukeAll(arns []*string) error { _, err := a.Client.DeleteCertificate(params) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ACM", + }, map[string]interface{}{ + "region": a.Region, + }) } else { deletedCount++ logging.Debugf("Deleted ACM: %s", *acmArn) diff --git a/aws/resources/acm_test.go b/aws/resources/acm_test.go index b4726aa6..c6c64bec 100644 --- a/aws/resources/acm_test.go +++ b/aws/resources/acm_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/acm" "github.com/aws/aws-sdk-go/service/acm/acmiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -31,7 +32,7 @@ func (m mockedACM) DeleteCertificate(input *acm.DeleteCertificateInput) (*acm.De } func TestACMGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testDomainName := "test-domain-name" @@ -79,7 +80,7 @@ func TestACMGetAll(t *testing.T) { } func TestACMGetAll_FilterInUse(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testDomainName := "test-domain-name" @@ -104,7 +105,7 @@ func TestACMGetAll_FilterInUse(t *testing.T) { } func TestACMNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testDomainName := "test-domain-name" diff --git a/aws/resources/acmpca.go b/aws/resources/acmpca.go index 7b0cda43..b9ef7ad8 100644 --- a/aws/resources/acmpca.go +++ b/aws/resources/acmpca.go @@ -6,6 +6,9 @@ import ( "sync" "time" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/acmpca" "github.com/gruntwork-io/cloud-nuke/config" @@ -81,6 +84,11 @@ func (ap *ACMPCA) nukeAll(arns []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ACMPCA", + }, map[string]interface{}{ + "region": ap.Region, + }) } } diff --git a/aws/resources/acmpca_test.go b/aws/resources/acmpca_test.go index 39580100..8260524c 100644 --- a/aws/resources/acmpca_test.go +++ b/aws/resources/acmpca_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/acmpca" "github.com/aws/aws-sdk-go/service/acmpca/acmpcaiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -44,7 +45,7 @@ func (m mockedACMPCA) DeleteCertificateAuthority( } func TestAcmPcaGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn := "test-arn" @@ -78,7 +79,7 @@ func TestAcmPcaGetAll(t *testing.T) { } func TestAcmPcaNukeAll_DisabledCA(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn := "test-arn" @@ -101,7 +102,7 @@ func TestAcmPcaNukeAll_DisabledCA(t *testing.T) { } func TestAcmPcaNukeAll_EnabledCA(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn := "test-arn" diff --git a/aws/resources/ami.go b/aws/resources/ami.go index 31a202ac..9af14d5c 100644 --- a/aws/resources/ami.go +++ b/aws/resources/ami.go @@ -4,6 +4,7 @@ import ( "context" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "strings" "github.com/aws/aws-sdk-go/aws" @@ -11,6 +12,7 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" ) @@ -84,6 +86,11 @@ func (ami *AMIs) nukeAll(imageIds []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking AMI", + }, map[string]interface{}{ + "region": ami.Region, + }) } else { deletedCount++ logging.Debugf("Deleted AMI: %s", *imageID) diff --git a/aws/resources/ami_test.go b/aws/resources/ami_test.go index 1217e3f3..c7374ef2 100644 --- a/aws/resources/ami_test.go +++ b/aws/resources/ami_test.go @@ -5,6 +5,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/assert" "regexp" "testing" @@ -29,7 +30,7 @@ func (m mockedAMI) DeregisterImage(input *ec2.DeregisterImageInput) (*ec2.Deregi } func TestAMIGetAll_SkipAWSManaged(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-ami" @@ -74,7 +75,7 @@ func TestAMIGetAll_SkipAWSManaged(t *testing.T) { } func TestAMIGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-ami" @@ -117,7 +118,7 @@ func TestAMIGetAll(t *testing.T) { } func TestAMINukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-ami" diff --git a/aws/resources/apigateway.go b/aws/resources/apigateway.go index cd914e81..f443a876 100644 --- a/aws/resources/apigateway.go +++ b/aws/resources/apigateway.go @@ -4,11 +4,14 @@ import ( "context" "sync" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/apigateway" "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" "github.com/hashicorp/go-multierror" ) @@ -59,6 +62,12 @@ func (gateway *ApiGateway) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking API Gateway", + }, map[string]interface{}{ + "region": gateway.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/apigateway_test.go b/aws/resources/apigateway_test.go index ecd9f67c..60083cbe 100644 --- a/aws/resources/apigateway_test.go +++ b/aws/resources/apigateway_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/apigateway" "github.com/aws/aws-sdk-go/service/apigateway/apigatewayiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -41,7 +42,7 @@ func (m mockedApiGateway) DeleteClientCertificate(*apigateway.DeleteClientCertif } func TestAPIGatewayGetAllAndNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testApiID := "aws-nuke-test-" + util.UniqueID() @@ -65,7 +66,7 @@ func TestAPIGatewayGetAllAndNukeAll(t *testing.T) { } func TestAPIGatewayGetAllTimeFilter(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testApiID := "aws-nuke-test-" + util.UniqueID() @@ -105,7 +106,7 @@ func TestAPIGatewayGetAllTimeFilter(t *testing.T) { } func TestNukeAPIGatewayMoreThanOne(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testApiID1 := "aws-nuke-test-" + util.UniqueID() @@ -132,7 +133,7 @@ func TestNukeAPIGatewayMoreThanOne(t *testing.T) { } func TestNukeAPIGatewayWithCertificates(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testApiID1 := "aws-nuke-test-" + util.UniqueID() diff --git a/aws/resources/apigatewayv2.go b/aws/resources/apigatewayv2.go index 2e3fd71a..420ce590 100644 --- a/aws/resources/apigatewayv2.go +++ b/aws/resources/apigatewayv2.go @@ -3,15 +3,19 @@ package resources import ( "context" "fmt" + "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface" + "github.com/gruntwork-io/cloud-nuke/logging" + "sync" + + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "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/gruntwork-io/cloud-nuke/config" - "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" "github.com/hashicorp/go-multierror" - "sync" ) func (gw *ApiGatewayV2) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -64,6 +68,11 @@ func (gw *ApiGatewayV2) nukeAll(identifiers []*string) error { for _, errChan := range errChans { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking API Gateway V2", + }, map[string]interface{}{ + "region": gw.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/apigatewayv2_test.go b/aws/resources/apigatewayv2_test.go index 351f1cbe..53694d08 100644 --- a/aws/resources/apigatewayv2_test.go +++ b/aws/resources/apigatewayv2_test.go @@ -12,6 +12,7 @@ import ( "github.com/aws/aws-sdk-go/service/apigatewayv2" "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/assert" ) @@ -47,7 +48,7 @@ func (m mockedApiGatewayV2) DeleteApiMapping(*apigatewayv2.DeleteApiMappingInput } func TestApiGatewayV2GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testApiID := "test-api-id" @@ -92,7 +93,7 @@ func TestApiGatewayV2GetAll(t *testing.T) { } func TestApiGatewayV2NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() gw := ApiGatewayV2{ diff --git a/aws/resources/asg.go b/aws/resources/asg.go index 7b8530e1..7ca7cc62 100644 --- a/aws/resources/asg.go +++ b/aws/resources/asg.go @@ -7,8 +7,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a formatted string of ASG Names @@ -60,6 +62,11 @@ func (ag *ASGroups) nukeAll(groupNames []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ASG", + }, map[string]interface{}{ + "region": ag.Region, + }) } else { deletedGroupNames = append(deletedGroupNames, groupName) logging.Debugf("Deleted Auto Scaling Group: %s", *groupName) @@ -72,6 +79,11 @@ func (ag *ASGroups) nukeAll(groupNames []*string) error { }) if err != nil { logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ASG", + }, map[string]interface{}{ + "region": ag.Region, + }) return errors.WithStackTrace(err) } } diff --git a/aws/resources/asg_test.go b/aws/resources/asg_test.go index 48eb0cef..713e0e30 100644 --- a/aws/resources/asg_test.go +++ b/aws/resources/asg_test.go @@ -3,6 +3,7 @@ package resources import ( "context" "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -32,7 +33,7 @@ func (m mockedASGroups) WaitUntilGroupNotExists(input *autoscaling.DescribeAutoS } func TestAutoScalingGroupGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "cloud-nuke-test" @@ -71,7 +72,7 @@ func TestAutoScalingGroupGetAll(t *testing.T) { } func TestAutoScalingGroupNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ag := ASGroups{ diff --git a/aws/resources/backup_vault.go b/aws/resources/backup_vault.go index 12a516d4..e6ec3d23 100644 --- a/aws/resources/backup_vault.go +++ b/aws/resources/backup_vault.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (bv *BackupVault) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -57,6 +59,11 @@ func (bv *BackupVault) nukeAll(names []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking BackupVault", + }, map[string]interface{}{ + "region": bv.Region, + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted backup vault: %s", aws.StringValue(name)) diff --git a/aws/resources/backup_vault_test.go b/aws/resources/backup_vault_test.go index 6650070b..b48945e4 100644 --- a/aws/resources/backup_vault_test.go +++ b/aws/resources/backup_vault_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/backup" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ func (m mockedBackupVault) DeleteBackupVault(*backup.DeleteBackupVaultInput) (*b } func TestBackupVaultGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-backup-vault-1" @@ -90,7 +91,7 @@ func TestBackupVaultGetAll(t *testing.T) { } func TestBackupVaultNuke(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() bv := BackupVault{ diff --git a/aws/resources/cloudtrail.go b/aws/resources/cloudtrail.go index d8e9a4cf..595aab72 100644 --- a/aws/resources/cloudtrail.go +++ b/aws/resources/cloudtrail.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (ct *CloudtrailTrail) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -60,6 +62,11 @@ func (ct *CloudtrailTrail) nukeAll(arns []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudtrail", + }, map[string]interface{}{ + "region": ct.Region, + }) } else { deletedArns = append(deletedArns, arn) logging.Debugf("Deleted Cloudtrail Trail: %s", aws.StringValue(arn)) diff --git a/aws/resources/cloudtrail_test.go b/aws/resources/cloudtrail_test.go index 6fc8e757..21df38e7 100644 --- a/aws/resources/cloudtrail_test.go +++ b/aws/resources/cloudtrail_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/cloudtrail" "github.com/aws/aws-sdk-go/service/cloudtrail/cloudtrailiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -27,7 +28,7 @@ func (m mockedCloudTrail) DeleteTrail(input *cloudtrail.DeleteTrailInput) (*clou } func TestCloudTrailGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -80,7 +81,7 @@ func TestCloudTrailGetAll(t *testing.T) { } func TestCloudTrailNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ct := CloudtrailTrail{ diff --git a/aws/resources/cloudwatch_alarm.go b/aws/resources/cloudwatch_alarm.go index cb7f3cd8..66e10160 100644 --- a/aws/resources/cloudwatch_alarm.go +++ b/aws/resources/cloudwatch_alarm.go @@ -7,8 +7,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (cw *CloudWatchAlarms) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -66,6 +68,11 @@ func (cw *CloudWatchAlarms) nukeAll(identifiers []*string) error { }) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudwatch Alarm Dependency", + }, map[string]interface{}{ + "region": cw.Region, + }) } var compositeAlarmNames []*string @@ -78,6 +85,11 @@ func (cw *CloudWatchAlarms) nukeAll(identifiers []*string) error { }) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudwatch Composite Alarm", + }, map[string]interface{}{ + "region": cw.Region, + }) } // Note: for composite alarms, we need to delete one by one according to the documentation @@ -108,6 +120,11 @@ func (cw *CloudWatchAlarms) nukeAll(identifiers []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudwatch Alarm", + }, map[string]interface{}{ + "region": cw.Region, + }) return errors.WithStackTrace(err) } diff --git a/aws/resources/cloudwatch_alarm_test.go b/aws/resources/cloudwatch_alarm_test.go index 39371aad..7ac36cd3 100644 --- a/aws/resources/cloudwatch_alarm_test.go +++ b/aws/resources/cloudwatch_alarm_test.go @@ -3,6 +3,7 @@ package resources import ( "context" "github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -38,7 +39,7 @@ func (m mockedCloudWatchAlarms) DeleteAlarms(input *cloudwatch.DeleteAlarmsInput } func TestCloudWatchAlarm_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -92,7 +93,7 @@ func TestCloudWatchAlarm_GetAll(t *testing.T) { } func TestCloudWatchAlarms_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -114,7 +115,7 @@ func TestCloudWatchAlarms_NukeAll(t *testing.T) { } func TestCloudWatchCompositeAlarms_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testCompositeAlaram1 := "test-name1" diff --git a/aws/resources/cloudwatch_dashboard.go b/aws/resources/cloudwatch_dashboard.go index 968393b0..f04d733e 100644 --- a/aws/resources/cloudwatch_dashboard.go +++ b/aws/resources/cloudwatch_dashboard.go @@ -4,10 +4,13 @@ import ( "context" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/cloudwatch" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "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 (cwdb *CloudWatchDashboards) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -60,6 +63,11 @@ func (cwdb *CloudWatchDashboards) nukeAll(identifiers []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudwatch Dashboard", + }, map[string]interface{}{ + "region": cwdb.Region, + }) return errors.WithStackTrace(err) } diff --git a/aws/resources/cloudwatch_dashboard_test.go b/aws/resources/cloudwatch_dashboard_test.go index 0acbb5ba..ecccf4ff 100644 --- a/aws/resources/cloudwatch_dashboard_test.go +++ b/aws/resources/cloudwatch_dashboard_test.go @@ -3,6 +3,7 @@ package resources import ( "context" "github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -29,7 +30,7 @@ func (m mockedCloudWatchDashboard) DeleteDashboards(input *cloudwatch.DeleteDash } func TestCloudWatchDashboard_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -89,7 +90,7 @@ func TestCloudWatchDashboard_GetAll(t *testing.T) { } func TestCloudWatchDashboard_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() cw := CloudWatchDashboards{ Client: mockedCloudWatchDashboard{ diff --git a/aws/resources/cloudwatch_loggroup.go b/aws/resources/cloudwatch_loggroup.go index a28de289..fef06ed0 100644 --- a/aws/resources/cloudwatch_loggroup.go +++ b/aws/resources/cloudwatch_loggroup.go @@ -2,6 +2,8 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "time" @@ -78,6 +80,11 @@ func (csr *CloudWatchLogGroups) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "OperationAbortedException" { allErrs = multierror.Append(allErrs, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Cloudwatch Log Group", + }, map[string]interface{}{ + "region": csr.Region, + }) } } } diff --git a/aws/resources/cloudwatch_loggroup_test.go b/aws/resources/cloudwatch_loggroup_test.go index 0edcfd0d..9379ef23 100644 --- a/aws/resources/cloudwatch_loggroup_test.go +++ b/aws/resources/cloudwatch_loggroup_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -28,7 +29,7 @@ func (m mockedCloudWatchLogGroup) DeleteLogGroup(input *cloudwatchlogs.DeleteLog } func TestCloudWatchLogGroup_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -89,7 +90,7 @@ func TestCloudWatchLogGroup_GetAll(t *testing.T) { } func TestCloudWatchLogGroup_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() cw := CloudWatchLogGroups{ Client: mockedCloudWatchLogGroup{ diff --git a/aws/resources/codedeploy_application.go b/aws/resources/codedeploy_application.go index 284b118b..f83388f1 100644 --- a/aws/resources/codedeploy_application.go +++ b/aws/resources/codedeploy_application.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "sync" ) @@ -104,6 +106,11 @@ func (cda *CodeDeployApplications) nukeAll(identifiers []string) error { allErrors = multierror.Append(allErrors, err) logging.Errorf("[Failed] Error deleting CodeDeploy Application: %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking CodeDeploy Application", + }, map[string]interface{}{ + "region": cda.Region, + }) } finalErr := allErrors.ErrorOrNil() diff --git a/aws/resources/codedeploy_application_test.go b/aws/resources/codedeploy_application_test.go index 12122ab5..1a2c74f2 100644 --- a/aws/resources/codedeploy_application_test.go +++ b/aws/resources/codedeploy_application_test.go @@ -4,6 +4,7 @@ import ( "context" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/codedeploy/codedeployiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -50,7 +51,7 @@ func (m mockedCodeDeployApplications) DeleteApplication(input *codedeploy.Delete } func TestCodeDeployApplication_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "cloud-nuke-test-1" diff --git a/aws/resources/config_recorder.go b/aws/resources/config_recorder.go index 8a9d149c..5ae42481 100644 --- a/aws/resources/config_recorder.go +++ b/aws/resources/config_recorder.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (csr *ConfigServiceRecorders) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -56,6 +58,11 @@ func (csr *ConfigServiceRecorders) nukeAll(configRecorderNames []string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Config Recorder", + }, map[string]interface{}{ + "region": csr.Region, + }) } else { deletedNames = append(deletedNames, aws.String(configRecorderName)) logging.Debugf("Deleted Config Recorder: %s", configRecorderName) diff --git a/aws/resources/config_recorder_test.go b/aws/resources/config_recorder_test.go index 19afcf60..60ebcf09 100644 --- a/aws/resources/config_recorder_test.go +++ b/aws/resources/config_recorder_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/configservice" "github.com/aws/aws-sdk-go/service/configservice/configserviceiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -26,7 +27,7 @@ func (m mockedConfigServiceRecorders) DeleteConfigurationRecorder(input *configs } func TestConfigServiceRecorder_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-recorder-1" @@ -73,7 +74,7 @@ func TestConfigServiceRecorder_GetAll(t *testing.T) { } func TestConfigServiceRecorder_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() csr := ConfigServiceRecorders{ diff --git a/aws/resources/config_service_test.go b/aws/resources/config_service_test.go index 88207ede..4e1148f8 100644 --- a/aws/resources/config_service_test.go +++ b/aws/resources/config_service_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/configservice" "github.com/aws/aws-sdk-go/service/configservice/configserviceiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -32,7 +33,7 @@ func (m mockedConfigServiceRule) DeleteRemediationConfiguration(input *configser } func TestConfigServiceRule_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-rule-1" @@ -79,7 +80,7 @@ func TestConfigServiceRule_GetAll(t *testing.T) { } func TestConfigServiceRule_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() csr := ConfigServiceRule{ diff --git a/aws/resources/dynamodb.go b/aws/resources/dynamodb.go index 668a7055..5ebdd362 100644 --- a/aws/resources/dynamodb.go +++ b/aws/resources/dynamodb.go @@ -8,6 +8,8 @@ import ( "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/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/gruntwork-io/gruntwork-cli/errors" "log" ) @@ -65,6 +67,11 @@ func (ddb *DynamoDB) nukeAll(tables []*string) error { if err != nil { if aerr, ok := err.(awserr.Error); ok { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking DynamoDB Table", + }, map[string]interface{}{ + "region": ddb.Region, + }) switch aerr.Error() { case dynamodb.ErrCodeInternalServerError: return errors.WithStackTrace(aerr) diff --git a/aws/resources/dynamodb_test.go b/aws/resources/dynamodb_test.go index 204284ba..0fed233b 100644 --- a/aws/resources/dynamodb_test.go +++ b/aws/resources/dynamodb_test.go @@ -3,6 +3,7 @@ package resources import ( "context" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -35,7 +36,7 @@ func (m mockedDynamoDB) DeleteTable(input *dynamodb.DeleteTableInput) (*dynamodb } func TestDynamoDB_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "table1" @@ -103,7 +104,7 @@ func TestDynamoDB_GetAll(t *testing.T) { } func TestDynamoDb_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ddb := DynamoDB{ diff --git a/aws/resources/ebs.go b/aws/resources/ebs.go index 28f03487..d1301731 100644 --- a/aws/resources/ebs.go +++ b/aws/resources/ebs.go @@ -2,13 +2,16 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "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/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" ) @@ -79,10 +82,27 @@ func (ev *EBSVolumes) nukeAll(volumeIds []*string) error { if err != nil { if awsErr, isAwsErr := err.(awserr.Error); isAwsErr && awsErr.Code() == "VolumeInUse" { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EBS Volume", + }, map[string]interface{}{ + "region": ev.Region, + "reason": "VolumeInUse", + }) logging.Debugf("EBS volume %s can't be deleted, it is still attached to an active resource", *volumeID) } else if awsErr, isAwsErr := err.(awserr.Error); isAwsErr && awsErr.Code() == "InvalidVolume.NotFound" { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EBS Volume", + }, map[string]interface{}{ + "region": ev.Region, + "reason": "InvalidVolume.NotFound", + }) logging.Debugf("EBS volume %s has already been deleted", *volumeID) } else { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EBS Volume", + }, map[string]interface{}{ + "region": ev.Region, + }) logging.Debugf("[Failed] %s", err) } } else { @@ -97,6 +117,11 @@ func (ev *EBSVolumes) nukeAll(volumeIds []*string) error { }) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EBS Volume", + }, map[string]interface{}{ + "region": ev.Region, + }) return errors.WithStackTrace(err) } } diff --git a/aws/resources/ebs_test.go b/aws/resources/ebs_test.go index 8f770dc6..2febe076 100644 --- a/aws/resources/ebs_test.go +++ b/aws/resources/ebs_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -33,7 +35,7 @@ func (m mockedEBS) WaitUntilVolumeDeleted(input *ec2.DescribeVolumesInput) error } func TestEBSVolume_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -101,7 +103,7 @@ func TestEBSVolume_GetAll(t *testing.T) { } func TestEBSVolumne_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ev := EBSVolumes{ diff --git a/aws/resources/ec2.go b/aws/resources/ec2.go index db385683..9b92884d 100644 --- a/aws/resources/ec2.go +++ b/aws/resources/ec2.go @@ -6,7 +6,9 @@ import ( "time" "github.com/gruntwork-io/cloud-nuke/externalcreds" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "github.com/pterm/pterm" @@ -134,6 +136,11 @@ func (ei *EC2Instances) nukeAll(instanceIds []*string) error { err := ei.releaseEIPs(instanceIds) if err != nil { logging.Debugf("[Failed EIP release] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Instance EPI release", + }, map[string]interface{}{ + "region": ei.Region, + }) return errors.WithStackTrace(err) } @@ -146,6 +153,11 @@ func (ei *EC2Instances) nukeAll(instanceIds []*string) error { _, err = ei.Client.TerminateInstances(params) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Instance", + }, map[string]interface{}{ + "region": ei.Region, + }) return errors.WithStackTrace(err) } @@ -163,6 +175,11 @@ func (ei *EC2Instances) nukeAll(instanceIds []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Instance", + }, map[string]interface{}{ + "region": ei.Region, + }) return errors.WithStackTrace(err) } diff --git a/aws/resources/ec2_dedicated_host.go b/aws/resources/ec2_dedicated_host.go index 4df74d96..37a8c238 100644 --- a/aws/resources/ec2_dedicated_host.go +++ b/aws/resources/ec2_dedicated_host.go @@ -10,8 +10,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (h *EC2DedicatedHosts) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -84,6 +86,11 @@ func (h *EC2DedicatedHosts) nukeAll(hostIds []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Dedicated Hosts", + }, map[string]interface{}{ + "region": h.Region, + }) return errors.WithStackTrace(err) } @@ -98,6 +105,11 @@ func (h *EC2DedicatedHosts) nukeAll(hostIds []*string) error { } for _, hostFailed := range releaseResult.Unsuccessful { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Dedicated Host", + }, map[string]interface{}{ + "region": h.Region, + }) logging.Debugf("[ERROR] Unable to release dedicated host %s in %s: %s", aws.StringValue(hostFailed.ResourceId), h.Region, aws.StringValue(hostFailed.Error.Message)) e := report.Entry{ Identifier: aws.StringValue(hostFailed.ResourceId), diff --git a/aws/resources/ec2_dedicated_host_test.go b/aws/resources/ec2_dedicated_host_test.go index 3d04fbea..83a14fb1 100644 --- a/aws/resources/ec2_dedicated_host_test.go +++ b/aws/resources/ec2_dedicated_host_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -29,7 +30,7 @@ func (m mockedEC2DedicatedHosts) ReleaseHosts(input *ec2.ReleaseHostsInput) (*ec } func TestEC2DedicatedHosts_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "test-host-id-1" @@ -104,7 +105,7 @@ func TestEC2DedicatedHosts_GetAll(t *testing.T) { } func TestEC2DedicatedHosts_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() h := EC2DedicatedHosts{ diff --git a/aws/resources/ec2_dhcp_option.go b/aws/resources/ec2_dhcp_option.go index 12e22e46..742b3745 100644 --- a/aws/resources/ec2_dhcp_option.go +++ b/aws/resources/ec2_dhcp_option.go @@ -2,8 +2,10 @@ package resources import ( "context" - "github.com/aws/aws-sdk-go/aws" + + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -11,7 +13,7 @@ import ( "github.com/pterm/pterm" ) -func (v *EC2DhcpOption) getAll(c context.Context, configObj config.Config) ([]*string, error) { +func (v *EC2DhcpOption) getAll(_ context.Context, configObj config.Config) ([]*string, error) { var dhcpOptionIds []*string err := v.Client.DescribeDhcpOptionsPages(&ec2.DescribeDhcpOptionsInput{}, func(page *ec2.DescribeDhcpOptionsOutput, lastPage bool) bool { for _, dhcpOption := range page.DhcpOptions { @@ -33,9 +35,8 @@ func (v *EC2DhcpOption) getAll(c context.Context, configObj config.Config) ([]*s func (v *EC2DhcpOption) nukeAll(identifiers []*string) error { for _, identifier := range identifiers { - _, err := v.Client.DeleteDhcpOptions(&ec2.DeleteDhcpOptionsInput{ - DhcpOptionsId: identifier, - }) + + err := nukeDhcpOption(v.Client, identifier) if err != nil { logging.Debugf("Failed to delete DHCP option w/ err: %s.", err) } else { @@ -44,7 +45,7 @@ func (v *EC2DhcpOption) nukeAll(identifiers []*string) error { // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(identifier), + Identifier: awsgo.StringValue(identifier), ResourceType: v.ResourceName(), Error: err, } @@ -53,3 +54,17 @@ func (v *EC2DhcpOption) nukeAll(identifiers []*string) error { return nil } + +func nukeDhcpOption(client ec2iface.EC2API, option *string) error { + logging.Debugf("Deleting DHCP Option %s", awsgo.StringValue(option)) + + _, err := client.DeleteDhcpOptions(&ec2.DeleteDhcpOptionsInput{ + DhcpOptionsId: option, + }) + if err != nil { + logging.Debugf("[Failed] Error deleting DHCP option %s: %s", awsgo.StringValue(option), err) + return errors.WithStackTrace(err) + } + logging.Debugf("[Ok] DHCP Option deleted successfully %s", awsgo.StringValue(option)) + return nil +} diff --git a/aws/resources/ec2_dhcp_option_test.go b/aws/resources/ec2_dhcp_option_test.go index a22fd180..e6c09b05 100644 --- a/aws/resources/ec2_dhcp_option_test.go +++ b/aws/resources/ec2_dhcp_option_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "testing" ) @@ -26,7 +27,7 @@ func (m mockedEC2DhcpOption) DeleteDhcpOptions(input *ec2.DeleteDhcpOptionsInput } func TestEC2DhcpOption_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "test-id-1" @@ -64,7 +65,7 @@ func TestEC2DhcpOption_GetAll(t *testing.T) { } func TestEC2DhcpOption_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() h := EC2DhcpOption{ diff --git a/aws/resources/ec2_egress_only_igw.go b/aws/resources/ec2_egress_only_igw.go index efb8960c..945bdacc 100644 --- a/aws/resources/ec2_egress_only_igw.go +++ b/aws/resources/ec2_egress_only_igw.go @@ -2,10 +2,12 @@ package resources import ( "context" + "fmt" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -18,8 +20,8 @@ func (egigw *EgressOnlyInternetGateway) setFirstSeenTag(eoig ec2.EgressOnlyInter Resources: []*string{eoig.EgressOnlyInternetGatewayId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -97,7 +99,7 @@ func (egigw *EgressOnlyInternetGateway) getAll(_ context.Context, configObj conf egigw.VerifyNukablePermissions(result, func(id *string) error { _, err := egigw.Client.DeleteEgressOnlyInternetGateway(&ec2.DeleteEgressOnlyInternetGatewayInput{ EgressOnlyInternetGatewayId: id, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), }) return err }) @@ -123,13 +125,11 @@ func (egigw *EgressOnlyInternetGateway) nukeAll(ids []*string) error { continue } - _, err := egigw.Client.DeleteEgressOnlyInternetGateway(&ec2.DeleteEgressOnlyInternetGatewayInput{ - EgressOnlyInternetGatewayId: id, - }) + err := nukeEgressOnlyGateway(egigw.Client, id) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Egress Only Internet Gateway", Error: err, } @@ -148,3 +148,18 @@ func (egigw *EgressOnlyInternetGateway) nukeAll(ids []*string) error { return nil } + +func nukeEgressOnlyGateway(client ec2iface.EC2API, gateway *string) error { + logging.Debugf("[Nuke] Egress only gateway %s", awsgo.StringValue(gateway)) + + _, err := client.DeleteEgressOnlyInternetGateway(&ec2.DeleteEgressOnlyInternetGatewayInput{ + EgressOnlyInternetGatewayId: gateway, + }) + if err != nil { + logging.Debug(fmt.Sprintf("[Failed] to delete Egress Only Internet Gateway %s", *gateway)) + return errors.WithStackTrace(err) + } + + logging.Debug(fmt.Sprintf("[Success] deleted Egress Only Internet Gateway %s", *gateway)) + return nil +} diff --git a/aws/resources/ec2_egress_only_igw_test.go b/aws/resources/ec2_egress_only_igw_test.go index e66df38e..738b0dbf 100644 --- a/aws/resources/ec2_egress_only_igw_test.go +++ b/aws/resources/ec2_egress_only_igw_test.go @@ -6,10 +6,11 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ func (m mockedEgressOnlyIgw) DeleteEgressOnlyInternetGateway(_ *ec2.DeleteEgress } func TestEgressOnlyInternetGateway_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -46,26 +47,26 @@ func TestEgressOnlyInternetGateway_GetAll(t *testing.T) { DescribeEgressOnlyInternetGatewaysOutput: ec2.DescribeEgressOnlyInternetGatewaysOutput{ EgressOnlyInternetGateways: []*ec2.EgressOnlyInternetGateway{ { - EgressOnlyInternetGatewayId: aws.String(gateway1), + EgressOnlyInternetGatewayId: awsgo.String(gateway1), Tags: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName1), + Key: awsgo.String("Name"), + Value: awsgo.String(testName1), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now)), }, }, }, { - EgressOnlyInternetGatewayId: aws.String(gateway2), + EgressOnlyInternetGatewayId: awsgo.String(gateway2), Tags: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName2), + Key: awsgo.String("Name"), + Value: awsgo.String(testName2), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now.Add(1 * time.Hour))), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now.Add(1 * time.Hour))), }, }, }, @@ -95,14 +96,14 @@ func TestEgressOnlyInternetGateway_GetAll(t *testing.T) { "timeAfterExclusionFilter": { configObj: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: aws.Time(now), + TimeAfter: awsgo.Time(now), }}, expected: []string{gateway1}, }, "timeBeforeExclusionFilter": { configObj: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeBefore: aws.Time(now.Add(1)), + TimeBefore: awsgo.Time(now.Add(1)), }}, expected: []string{gateway2}, }, @@ -113,14 +114,14 @@ func TestEgressOnlyInternetGateway_GetAll(t *testing.T) { EgressOnlyInternetGateway: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, aws.StringValueSlice(names)) + require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) }) } } func TestEc2EgressOnlyInternetGateway_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -138,20 +139,20 @@ func TestEc2EgressOnlyInternetGateway_NukeAll(t *testing.T) { DescribeEgressOnlyInternetGatewaysOutput: ec2.DescribeEgressOnlyInternetGatewaysOutput{ EgressOnlyInternetGateways: []*ec2.EgressOnlyInternetGateway{ { - EgressOnlyInternetGatewayId: aws.String(gateway1), + EgressOnlyInternetGatewayId: awsgo.String(gateway1), Attachments: []*ec2.InternetGatewayAttachment{ { - State: aws.String("testing-state"), - VpcId: aws.String("test-gateway-vpc"), + State: awsgo.String("testing-state"), + VpcId: awsgo.String("test-gateway-vpc"), }, }, }, { - EgressOnlyInternetGatewayId: aws.String(gateway2), + EgressOnlyInternetGatewayId: awsgo.String(gateway2), Attachments: []*ec2.InternetGatewayAttachment{ { - State: aws.String("testing-state"), - VpcId: aws.String("test-gateway-vpc"), + State: awsgo.String("testing-state"), + VpcId: awsgo.String("test-gateway-vpc"), }, }, }, @@ -162,8 +163,8 @@ func TestEc2EgressOnlyInternetGateway_NukeAll(t *testing.T) { } err := igw.nukeAll([]*string{ - aws.String(gateway1), - aws.String(gateway2), + awsgo.String(gateway1), + awsgo.String(gateway2), }) require.NoError(t, err) } diff --git a/aws/resources/ec2_endpoints.go b/aws/resources/ec2_endpoints.go index 6460dc89..90157bf3 100644 --- a/aws/resources/ec2_endpoints.go +++ b/aws/resources/ec2_endpoints.go @@ -2,15 +2,18 @@ package resources import ( "context" + "fmt" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "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/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/go-commons/retry" ) func (e *EC2Endpoints) setFirstSeenTag(endpoint ec2.VpcEndpoint, value time.Time) error { @@ -18,8 +21,8 @@ func (e *EC2Endpoints) setFirstSeenTag(endpoint ec2.VpcEndpoint, value time.Time Resources: []*string{endpoint.VpcEndpointId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -95,7 +98,7 @@ func (e *EC2Endpoints) getAll(_ context.Context, configObj config.Config) ([]*st e.VerifyNukablePermissions(result, func(id *string) error { _, err := e.Client.DeleteVpcEndpoints(&ec2.DeleteVpcEndpointsInput{ VpcEndpointIds: []*string{id}, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), }) return err }) @@ -118,13 +121,11 @@ func (e *EC2Endpoints) nukeAll(identifiers []*string) error { continue } - _, err := e.Client.DeleteVpcEndpoints(&ec2.DeleteVpcEndpointsInput{ - VpcEndpointIds: []*string{id}, - }) + err := nukeVpcEndpoint(e.Client, []*string{id}) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Vpc Endpoint", Error: err, } @@ -134,7 +135,6 @@ func (e *EC2Endpoints) nukeAll(identifiers []*string) error { logging.Debugf("[Failed] %s", err) } else { deletedAddresses = append(deletedAddresses, id) - logging.Debugf("Deleted Vpc Endpoint: %s", *id) } } @@ -142,3 +142,54 @@ func (e *EC2Endpoints) nukeAll(identifiers []*string) error { return nil } + +func nukeVpcEndpoint(client ec2iface.EC2API, endpointIds []*string) error { + logging.Debugf("Deleting VPC endpoints %s", awsgo.StringValueSlice(endpointIds)) + + _, err := client.DeleteVpcEndpoints(&ec2.DeleteVpcEndpointsInput{ + VpcEndpointIds: endpointIds, + }) + if err != nil { + logging.Debug(fmt.Sprintf("Failed to delete VPC endpoints: %s", err.Error())) + return errors.WithStackTrace(err) + } + + logging.Debug(fmt.Sprintf("Successfully deleted VPC endpoints %s", + awsgo.StringValueSlice(endpointIds))) + + return nil +} + +func waitForVPCEndpointToBeDeleted(client ec2iface.EC2API, vpcID string) error { + return retry.DoWithRetry( + logging.Logger.WithTime(time.Now()), + "Waiting for all VPC endpoints to be deleted", + 10, + 2*time.Second, + func() error { + endpoints, err := client.DescribeVpcEndpoints( + &ec2.DescribeVpcEndpointsInput{ + Filters: []*ec2.Filter{ + { + Name: awsgo.String("vpc-id"), + Values: []*string{awsgo.String(vpcID)}, + }, + { + Name: awsgo.String("vpc-endpoint-state"), + Values: []*string{awsgo.String("deleting")}, + }, + }, + }, + ) + if err != nil { + return err + } + + if len(endpoints.VpcEndpoints) == 0 { + return nil + } + return fmt.Errorf("Not all VPC endpoints deleted.") + }, + ) + return nil +} diff --git a/aws/resources/ec2_endpoints_test.go b/aws/resources/ec2_endpoints_test.go index 8299b5a5..c56dc122 100644 --- a/aws/resources/ec2_endpoints_test.go +++ b/aws/resources/ec2_endpoints_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ func (m mockedEc2VpcEndpoints) DeleteVpcEndpoints(_ *ec2.DeleteVpcEndpointsInput } func TestVcpEndpoint_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -120,7 +121,7 @@ func TestVcpEndpoint_GetAll(t *testing.T) { } func TestEc2Endpoints_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( diff --git a/aws/resources/ec2_internet_gateway.go b/aws/resources/ec2_internet_gateway.go index 5debb9d9..27a92c9d 100644 --- a/aws/resources/ec2_internet_gateway.go +++ b/aws/resources/ec2_internet_gateway.go @@ -2,10 +2,12 @@ package resources import ( "context" + "fmt" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" r "github.com/gruntwork-io/cloud-nuke/report" // Alias the package as 'r' @@ -18,8 +20,8 @@ func (igw *InternetGateway) setFirstSeenTag(gateway ec2.InternetGateway, value t Resources: []*string{gateway.InternetGatewayId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -93,6 +95,11 @@ func (igw *InternetGateway) getAll(_ context.Context, configObj config.Config) ( if shouldIncludeGateway(ig, firstSeenTime, configObj) { identifiers = append(identifiers, ig.InternetGatewayId) + + // get vpc id for this igw and update the map + if len(ig.Attachments) > 0 { + igw.GatewayVPCMap[awsgo.StringValue(ig.InternetGatewayId)] = awsgo.StringValue(ig.Attachments[0].VpcId) + } } } @@ -100,7 +107,7 @@ func (igw *InternetGateway) getAll(_ context.Context, configObj config.Config) ( igw.VerifyNukablePermissions(identifiers, func(id *string) error { params := &ec2.DeleteInternetGatewayInput{ InternetGatewayId: id, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), } _, err := igw.Client.DeleteInternetGateway(params) return err @@ -109,63 +116,6 @@ func (igw *InternetGateway) getAll(_ context.Context, configObj config.Config) ( return identifiers, nil } -func (igw *InternetGateway) nuke(id *string) error { - - // detaching the gateway from attached vpcs - if err := igw.detachInternetGateway(id); err != nil { - return errors.WithStackTrace(err) - } - - // nuking the gateway - if err := igw.nukeInternetGateway(id); err != nil { - return errors.WithStackTrace(err) - } - - return nil -} - -func (igw *InternetGateway) nukeInternetGateway(id *string) error { - logging.Debugf("Deleting Internet gateway %s", *id) - - _, err := igw.Client.DeleteInternetGateway(&ec2.DeleteInternetGatewayInput{ - InternetGatewayId: id, - }) - if err != nil { - logging.Debugf("[Failed] Error deleting internet gateway %s: %s", *id, err) - return errors.WithStackTrace(err) - } - logging.Debugf("[Ok] internet gateway deleted successfully %s", *id) - - return nil -} - -func (igw *InternetGateway) detachInternetGateway(id *string) error { - logging.Debugf("Detaching Internet gateway %s", *id) - - output, err := igw.Client.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{ - InternetGatewayIds: []*string{id}, - }) - if err != nil { - logging.Debugf("[Failed] Error describing internet gateway %s: %s", *id, err) - return errors.WithStackTrace(err) - } - - for _, gateway := range output.InternetGateways { - for _, attachments := range gateway.Attachments { - _, err := igw.Client.DetachInternetGateway(&ec2.DetachInternetGatewayInput{ - InternetGatewayId: id, - VpcId: attachments.VpcId, - }) - if err != nil { - logging.Debugf("[Failed] Error detaching internet gateway %s: %s", *id, err) - return errors.WithStackTrace(err) - } - } - } - logging.Debugf("[Ok] internet gateway detached successfully %s", *id) - return nil -} - func (igw *InternetGateway) nukeAll(identifiers []*string) error { if len(identifiers) == 0 { logging.Debugf("No internet gateway identifiers to nuke in region %s", igw.Region) @@ -184,7 +134,7 @@ func (igw *InternetGateway) nukeAll(identifiers []*string) error { err := igw.nuke(id) // Record status of this resource e := r.Entry{ // Use the 'r' alias to refer to the package - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Internet Gateway", Error: err, } @@ -199,3 +149,59 @@ func (igw *InternetGateway) nukeAll(identifiers []*string) error { return nil } + +func (igw *InternetGateway) nuke(id *string) error { + // get the vpc id for current igw + vpcID, ok := igw.GatewayVPCMap[awsgo.StringValue(id)] + if !ok { + logging.Debug(fmt.Sprintf("Failed to read the vpc Id for %s", + awsgo.StringValue(id))) + return fmt.Errorf("Failed to retrieve the VPC ID for %s, which is mandatory for the internet gateway nuke operation.", + awsgo.StringValue(id)) + } + + err := nukeInternetGateway(igw.Client, id, vpcID) + if err != nil { + return errors.WithStackTrace(err) + } + + return nil +} + +func nukeInternetGateway(client ec2iface.EC2API, gatewayId *string, vpcID string) error { + var err error + logging.Debug(fmt.Sprintf("Detaching Internet Gateway %s", + awsgo.StringValue(gatewayId))) + _, err = client.DetachInternetGateway( + &ec2.DetachInternetGatewayInput{ + InternetGatewayId: gatewayId, + VpcId: awsgo.String(vpcID), + }, + ) + if err != nil { + logging.Debug(fmt.Sprintf("Failed to detach internet gateway %s", + awsgo.StringValue(gatewayId))) + return errors.WithStackTrace(err) + } + logging.Debug(fmt.Sprintf("Successfully detached internet gateway %s", + awsgo.StringValue(gatewayId))) + + // nuking the internet gateway + logging.Debug(fmt.Sprintf("Deleting internet gateway %s", + awsgo.StringValue(gatewayId))) + _, err = client.DeleteInternetGateway( + &ec2.DeleteInternetGatewayInput{ + InternetGatewayId: gatewayId, + }, + ) + if err != nil { + logging.Debug(fmt.Sprintf("Failed to delete internet gateway %s", + awsgo.StringValue(gatewayId))) + return errors.WithStackTrace(err) + } + logging.Debug(fmt.Sprintf("Successfully deleted internet gateway %s", + awsgo.StringValue(gatewayId))) + + return nil + +} diff --git a/aws/resources/ec2_internet_gateway_test.go b/aws/resources/ec2_internet_gateway_test.go index 472a91e2..4dcb5c49 100644 --- a/aws/resources/ec2_internet_gateway_test.go +++ b/aws/resources/ec2_internet_gateway_test.go @@ -6,10 +6,11 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -35,7 +36,7 @@ func (m mockedInternetGateway) DeleteInternetGateway(_ *ec2.DeleteInternetGatewa } func TestEc2InternetGateway_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -52,26 +53,26 @@ func TestEc2InternetGateway_GetAll(t *testing.T) { DescribeInternetGatewaysOutput: ec2.DescribeInternetGatewaysOutput{ InternetGateways: []*ec2.InternetGateway{ { - InternetGatewayId: aws.String(gateway1), + InternetGatewayId: awsgo.String(gateway1), Tags: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName1), + Key: awsgo.String("Name"), + Value: awsgo.String(testName1), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now.Add(1))), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now.Add(1))), }, }, }, { - InternetGatewayId: aws.String(gateway2), + InternetGatewayId: awsgo.String(gateway2), Tags: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName2), + Key: awsgo.String("Name"), + Value: awsgo.String(testName2), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now.Add(1))), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now.Add(1))), }, }, }, @@ -101,7 +102,7 @@ func TestEc2InternetGateway_GetAll(t *testing.T) { "timeAfterExclusionFilter": { configObj: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: aws.Time(now.Add(-1 * time.Hour)), + TimeAfter: awsgo.Time(now.Add(-1 * time.Hour)), }}, expected: []string{}, }, @@ -112,14 +113,14 @@ func TestEc2InternetGateway_GetAll(t *testing.T) { InternetGateway: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, aws.StringValueSlice(names)) + require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) }) } } func TestEc2InternetGateway_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -137,20 +138,20 @@ func TestEc2InternetGateway_NukeAll(t *testing.T) { DescribeInternetGatewaysOutput: ec2.DescribeInternetGatewaysOutput{ InternetGateways: []*ec2.InternetGateway{ { - InternetGatewayId: aws.String(gateway1), + InternetGatewayId: awsgo.String(gateway1), Attachments: []*ec2.InternetGatewayAttachment{ { - State: aws.String("testing-state"), - VpcId: aws.String("test-gateway-vpc"), + State: awsgo.String("testing-state"), + VpcId: awsgo.String("test-gateway-vpc"), }, }, }, { - InternetGatewayId: aws.String(gateway2), + InternetGatewayId: awsgo.String(gateway2), Attachments: []*ec2.InternetGatewayAttachment{ { - State: aws.String("testing-state"), - VpcId: aws.String("test-gateway-vpc"), + State: awsgo.String("testing-state"), + VpcId: awsgo.String("test-gateway-vpc"), }, }, }, @@ -161,8 +162,8 @@ func TestEc2InternetGateway_NukeAll(t *testing.T) { } err := igw.nukeAll([]*string{ - aws.String(gateway1), - aws.String(gateway2), + awsgo.String(gateway1), + awsgo.String(gateway2), }) require.NoError(t, err) } diff --git a/aws/resources/ec2_internet_gateway_types.go b/aws/resources/ec2_internet_gateway_types.go index 3c1fb80b..5b068c94 100644 --- a/aws/resources/ec2_internet_gateway_types.go +++ b/aws/resources/ec2_internet_gateway_types.go @@ -13,14 +13,20 @@ import ( type InternetGateway struct { BaseAwsResource - Client ec2iface.EC2API - Region string - GatewayIds []string + Client ec2iface.EC2API + Region string + GatewayIds []string + GatewayVPCMap map[string]string } func (igw *InternetGateway) Init(session *session.Session) { igw.BaseAwsResource.Init(session) igw.Client = ec2.New(session) + + // Since the nuking of the internet gateway requires the VPC ID, and to avoid redundant API calls for this information within the nuke method, + // we utilize the getAll method to retrieve it. + // This map is used to store the information and access the value within the nuke method. + igw.GatewayVPCMap = make(map[string]string) } func (igw *InternetGateway) ResourceName() string { diff --git a/aws/resources/ec2_key_pair.go b/aws/resources/ec2_key_pair.go index 42616ea0..66fc8338 100644 --- a/aws/resources/ec2_key_pair.go +++ b/aws/resources/ec2_key_pair.go @@ -5,7 +5,9 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/gruntwork-io/gruntwork-cli/errors" "github.com/hashicorp/go-multierror" ) @@ -58,6 +60,11 @@ func (k *EC2KeyPairs) nukeAll(keypairIds []*string) error { var multiErr *multierror.Error for _, keypair := range keypairIds { if err := k.deleteKeyPair(keypair); err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EC2 Key Pair", + }, map[string]interface{}{ + "region": k.Region, + }) logging.Errorf("[Failed] %s", err) multiErr = multierror.Append(multiErr, err) } else { diff --git a/aws/resources/ec2_key_pair_test.go b/aws/resources/ec2_key_pair_test.go index ee68f86b..6b7a80dd 100644 --- a/aws/resources/ec2_key_pair_test.go +++ b/aws/resources/ec2_key_pair_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -28,7 +29,7 @@ func (m mockedEC2KeyPairs) DeleteKeyPair(input *ec2.DeleteKeyPairInput) (*ec2.De } func TestEC2KeyPairs_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -92,7 +93,7 @@ func TestEC2KeyPairs_GetAll(t *testing.T) { } func TestEC2KeyPairs_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() h := EC2KeyPairs{ diff --git a/aws/resources/ec2_network_acl.go b/aws/resources/ec2_network_acl.go index bba7f176..a818e2b1 100644 --- a/aws/resources/ec2_network_acl.go +++ b/aws/resources/ec2_network_acl.go @@ -2,11 +2,11 @@ package resources import ( "context" - "fmt" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -19,8 +19,8 @@ func (nacl *NetworkACL) setFirstSeenTag(networkAcl ec2.NetworkAcl, value time.Ti Resources: []*string{networkAcl.NetworkAclId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -65,9 +65,9 @@ func (nacl *NetworkACL) getAll(_ context.Context, configObj config.Config) ([]*s resp, err := nacl.Client.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ Filters: []*ec2.Filter{ { - Name: aws.String("default"), + Name: awsgo.String("default"), Values: []*string{ - aws.String("false"), // can't able to nuke default nacl + awsgo.String("false"), // can't able to nuke default nacl }, }, }, @@ -82,7 +82,7 @@ func (nacl *NetworkACL) getAll(_ context.Context, configObj config.Config) ([]*s firstSeenTime, err := nacl.getFirstSeenTag(*networkAcl) if err != nil { logging.Errorf( - "Unable to retrieve tags for network acl: %s, with error: %s", aws.StringValue(networkAcl.NetworkAclId), err) + "Unable to retrieve tags for network acl: %s, with error: %s", awsgo.StringValue(networkAcl.NetworkAclId), err) continue } @@ -92,7 +92,7 @@ func (nacl *NetworkACL) getAll(_ context.Context, configObj config.Config) ([]*s firstSeenTime = &now if err := nacl.setFirstSeenTag(*networkAcl, time.Now().UTC()); err != nil { logging.Errorf( - "Unable to apply first seen tag network acl: %s, with error: %s", aws.StringValue(networkAcl.NetworkAclId), err) + "Unable to apply first seen tag network acl: %s, with error: %s", awsgo.StringValue(networkAcl.NetworkAclId), err) continue } } @@ -106,7 +106,7 @@ func (nacl *NetworkACL) getAll(_ context.Context, configObj config.Config) ([]*s nacl.VerifyNukablePermissions(identifiers, func(id *string) error { _, err := nacl.Client.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{ NetworkAclId: id, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), }) return err }) @@ -122,7 +122,7 @@ func (nacl *NetworkACL) nuke(id *string) error { } // nuking the network ACL - if err := nacl.nukeNetworkAcl(id); err != nil { + if err := nukeNetworkAcl(nacl.Client, id); err != nil { return errors.WithStackTrace(err) } @@ -144,7 +144,7 @@ func (nacl *NetworkACL) nukeAssociatedSubnets(id *string) error { } if len(resp.NetworkAcls) == 0 { - logging.Debugf("[Network ACL] Nothing found: %s", aws.StringValue(id)) + logging.Debugf("[Network ACL] Nothing found: %s", awsgo.StringValue(id)) return nil } @@ -158,12 +158,12 @@ func (nacl *NetworkACL) nukeAssociatedSubnets(id *string) error { &ec2.DescribeNetworkAclsInput{ Filters: []*ec2.Filter{ { - Name: aws.String("vpc-id"), + Name: awsgo.String("vpc-id"), Values: []*string{vpcID}, }, { - Name: aws.String("default"), + Name: awsgo.String("default"), Values: []*string{ - aws.String("true"), + awsgo.String("true"), }, }, }, @@ -175,41 +175,19 @@ func (nacl *NetworkACL) nukeAssociatedSubnets(id *string) error { } if len(networkACLs.NetworkAcls) == 0 { - logging.Debugf("[Network ACL] Nothing found to check the default association: %s", aws.StringValue(id)) + logging.Debugf("[Network ACL] Nothing found to check the default association: %s", awsgo.StringValue(id)) return nil } var defaultNetworkAclID *string defaultNetworkAclID = networkACLs.NetworkAcls[0].NetworkAclId - // repalce the association with default - for _, association := range networkAcl.Associations { - logging.Debug(fmt.Sprintf("Found %d network ACL associations to replace", len(networkAcl.Associations))) - _, err := nacl.Client.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: defaultNetworkAclID, - }) - if err != nil { - logging.Debug(fmt.Sprintf("Failed to replace network ACL association: %s to default", - aws.StringValue(association.NetworkAclAssociationId))) - return errors.WithStackTrace(err) - } - logging.Debug(fmt.Sprintf("Successfully replaced network ACL association: %s to default", aws.StringValue(association.NetworkAclAssociationId))) - } - return nil -} - -func (nacl *NetworkACL) nukeNetworkAcl(id *string) error { - logging.Debugf("Deleting network Acl %s", aws.StringValue(id)) - - if _, err := nacl.Client.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{ - NetworkAclId: id, - }); err != nil { - logging.Debugf("An error happened while nuking NACL %s, error %v", aws.StringValue(id), err) - return err + // replace the association with default + err = replaceNetworkAclAssociation(nacl.Client, defaultNetworkAclID, networkAcl.Associations) + if err != nil { + logging.Debugf("Failed to replace network ACL associations: %s", awsgo.StringValue(defaultNetworkAclID)) + return errors.WithStackTrace(err) } - logging.Debugf("[Ok] network acl deleted successfully %s", aws.StringValue(id)) - return nil } @@ -232,7 +210,7 @@ func (nacl *NetworkACL) nukeAll(identifiers []*string) error { // Record status of this resource e := report.Entry{ // Use the 'r' alias to refer to the package - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Network ACL", Error: err, } @@ -247,3 +225,39 @@ func (nacl *NetworkACL) nukeAll(identifiers []*string) error { return nil } + +func replaceNetworkAclAssociation(client ec2iface.EC2API, networkAclId *string, associations []*ec2.NetworkAclAssociation) error { + logging.Debugf("Start replacing network ACL associations: %s", awsgo.StringValue(networkAclId)) + + for _, association := range associations { + logging.Debugf("Found %d network ACL associations to replace", len(associations)) + + _, err := client.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ + AssociationId: association.NetworkAclAssociationId, + NetworkAclId: networkAclId, + }) + if err != nil { + logging.Debugf("Failed to replace network ACL association: %s to default", + awsgo.StringValue(association.NetworkAclAssociationId)) + return errors.WithStackTrace(err) + } + logging.Debugf("Successfully replaced network ACL association: %s to default", + awsgo.StringValue(association.NetworkAclAssociationId)) + } + logging.Debugf("Successfully replaced network ACL associations: %s", awsgo.StringValue(networkAclId)) + return nil +} + +func nukeNetworkAcl(client ec2iface.EC2API, id *string) error { + logging.Debugf("Deleting network Acl %s", awsgo.StringValue(id)) + + if _, err := client.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{ + NetworkAclId: id, + }); err != nil { + logging.Debugf("An error happened while nuking NACL %s, error %v", awsgo.StringValue(id), err) + return err + } + logging.Debugf("[Ok] network acl deleted successfully %s", awsgo.StringValue(id)) + + return nil +} diff --git a/aws/resources/ec2_network_acl_test.go b/aws/resources/ec2_network_acl_test.go index 0d502228..f807754b 100644 --- a/aws/resources/ec2_network_acl_test.go +++ b/aws/resources/ec2_network_acl_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -36,6 +37,7 @@ func (m mockedNetworkACL) ReplaceNetworkAclAssociation(*ec2.ReplaceNetworkAclAss } func TestNetworkAcl_GetAll(t *testing.T) { + telemetry.InitTelemetry("cloud-nuke", "") var ( now = time.Now() @@ -131,6 +133,7 @@ func TestNetworkAcl_GetAll(t *testing.T) { } func TestNetworkAcl_NukeAll(t *testing.T) { + telemetry.InitTelemetry("cloud-nuke", "") var ( testId1 = "acl-09e36c45cbdbfb001" diff --git a/aws/resources/ec2_network_interface.go b/aws/resources/ec2_network_interface.go index 230f9c0a..cfb9d647 100644 --- a/aws/resources/ec2_network_interface.go +++ b/aws/resources/ec2_network_interface.go @@ -4,8 +4,9 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -18,8 +19,8 @@ func (ni *NetworkInterface) setFirstSeenTag(networkInterface ec2.NetworkInterfac Resources: []*string{networkInterface.NetworkInterfaceId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -97,7 +98,7 @@ func (ni *NetworkInterface) getAll(_ context.Context, configObj config.Config) ( ni.VerifyNukablePermissions(identifiers, func(id *string) error { _, err := ni.Client.DeleteNetworkInterface(&ec2.DeleteNetworkInterfaceInput{ NetworkInterfaceId: id, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), }) return err }) @@ -111,7 +112,7 @@ func (ni *NetworkInterface) nuke(id *string) error { return errors.WithStackTrace(err) } // nuking the network interface - if err := ni.nukeNetworkInterface(id); err != nil { + if err := nukeNetworkInterface(ni.Client, id); err != nil { return errors.WithStackTrace(err) } @@ -119,13 +120,13 @@ func (ni *NetworkInterface) nuke(id *string) error { } func (ni *NetworkInterface) detachNetworkInterface(id *string) error { - logging.Debugf("Detaching network interface %s from instances ", aws.StringValue(id)) + logging.Debugf("Detaching network interface %s from instances ", awsgo.StringValue(id)) output, err := ni.Client.DescribeNetworkInterfaces(&ec2.DescribeNetworkInterfacesInput{ NetworkInterfaceIds: []*string{id}, }) if err != nil { - logging.Debugf("[Failed] Error describing network interface %s: %s", aws.StringValue(id), err) + logging.Debugf("[Failed] Error describing network interface %s: %s", awsgo.StringValue(id), err) return errors.WithStackTrace(err) } @@ -139,7 +140,7 @@ func (ni *NetworkInterface) detachNetworkInterface(id *string) error { // nuking the attached instance // this will also remove the network interface if err := ni.nukeInstance(networkInterface.Attachment.InstanceId); err != nil { - logging.Debugf("[Failed] Error nuking the attached instance %s on network interface %s %s", aws.StringValue(networkInterface.Attachment.InstanceId), aws.StringValue(id), err) + logging.Debugf("[Failed] Error nuking the attached instance %s on network interface %s %s", awsgo.StringValue(networkInterface.Attachment.InstanceId), awsgo.StringValue(id), err) return errors.WithStackTrace(err) } } @@ -150,12 +151,12 @@ func (ni *NetworkInterface) detachNetworkInterface(id *string) error { } func (ni *NetworkInterface) releaseEIPs(instance *string) error { - logging.Debugf("Releasing Elastic IP address(s) associated on instance %s", aws.StringValue(instance)) + logging.Debugf("Releasing Elastic IP address(s) associated on instance %s", awsgo.StringValue(instance)) // get the elastic ip's associated with the EC2's output, err := ni.Client.DescribeAddresses(&ec2.DescribeAddressesInput{ Filters: []*ec2.Filter{ { - Name: aws.String("instance-id"), + Name: awsgo.String("instance-id"), Values: []*string{ instance, }, @@ -170,11 +171,11 @@ func (ni *NetworkInterface) releaseEIPs(instance *string) error { if _, err := ni.Client.ReleaseAddress(&ec2.ReleaseAddressInput{ AllocationId: address.AllocationId, }); err != nil { - logging.Debugf("An error happened while releasing the elastic ip address %s, error %v", aws.StringValue(address.AllocationId), err) + logging.Debugf("An error happened while releasing the elastic ip address %s, error %v", awsgo.StringValue(address.AllocationId), err) continue } - logging.Debugf("Released Elastic IP address %s from instance %s", aws.StringValue(address.AllocationId), aws.StringValue(instance)) + logging.Debugf("Released Elastic IP address %s from instance %s", awsgo.StringValue(address.AllocationId), awsgo.StringValue(instance)) } logging.Debugf("[OK] successfully released Elastic IP address(s) associated on instances") @@ -198,7 +199,7 @@ func (ni *NetworkInterface) nukeInstance(id *string) error { return errors.WithStackTrace(err) } - logging.Debugf("[Instance Termination] waiting to terminate instance %s", aws.StringValue(id)) + logging.Debugf("[Instance Termination] waiting to terminate instance %s", awsgo.StringValue(id)) // wait until the instance terminated. if err := ni.Client.WaitUntilInstanceTerminated(&ec2.DescribeInstancesInput{ @@ -207,30 +208,7 @@ func (ni *NetworkInterface) nukeInstance(id *string) error { logging.Debugf("[Instance Termination Waiting] Failed to terminate instance %s : %s", *id, err) return errors.WithStackTrace(err) } - logging.Debugf("[OK] successfully nuked instance %v", aws.StringValue(id)) - - return nil -} - -func (ni *NetworkInterface) nukeNetworkInterface(id *string) error { - logging.Debugf("Deleting network interface %s", aws.StringValue(id)) - - // If the network interface was attached to an instance, then when we remove the instance above, the network interface will also be removed. - // However, when we attempt to nuke the interface here, we may encounter an error such as InvalidNetworkInterfaceID.NotFound. - // In other situations, such as when the network interface hasn't been attached to any instances, we won't encounter this error. - // - // Note: We are handling the situation here by checking the error response from AWS. - - _, err := ni.Client.DeleteNetworkInterface(&ec2.DeleteNetworkInterfaceInput{ - NetworkInterfaceId: id, - }) - - // check the error exists and it is not the interfaceid not found - if err != nil && util.TransformAWSError(err) != util.ErrInterfaceIDNotFound { - logging.Debugf("[Failed] Error deleting network interface %s: %s", aws.StringValue(id), err) - return errors.WithStackTrace(err) - } - logging.Debugf("[Ok] network interface deleted successfully %s", aws.StringValue(id)) + logging.Debugf("[OK] successfully nuked instance %v", awsgo.StringValue(id)) return nil } @@ -254,7 +232,7 @@ func (ni *NetworkInterface) nukeAll(identifiers []*string) error { // Record status of this resource e := report.Entry{ // Use the 'r' alias to refer to the package - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Network Interface", Error: err, } @@ -269,3 +247,26 @@ func (ni *NetworkInterface) nukeAll(identifiers []*string) error { return nil } + +func nukeNetworkInterface(client ec2iface.EC2API, id *string) error { + logging.Debugf("Deleting network interface %s", awsgo.StringValue(id)) + + // If the network interface was attached to an instance, then when we remove the instance above, the network interface will also be removed. + // However, when we attempt to nuke the interface here, we may encounter an error such as InvalidNetworkInterfaceID.NotFound. + // In other situations, such as when the network interface hasn't been attached to any instances, we won't encounter this error. + // + // Note: We are handling the situation here by checking the error response from AWS. + + _, err := client.DeleteNetworkInterface(&ec2.DeleteNetworkInterfaceInput{ + NetworkInterfaceId: id, + }) + + // check the error exists and it is not the interfaceid not found + if err != nil && util.TransformAWSError(err) != util.ErrInterfaceIDNotFound { + logging.Debugf("[Failed] Error deleting network interface %s: %s", awsgo.StringValue(id), err) + return errors.WithStackTrace(err) + } + logging.Debugf("[Ok] network interface deleted successfully %s", awsgo.StringValue(id)) + + return nil +} diff --git a/aws/resources/ec2_network_interface_test.go b/aws/resources/ec2_network_interface_test.go index 6e4c90b2..90105e88 100644 --- a/aws/resources/ec2_network_interface_test.go +++ b/aws/resources/ec2_network_interface_test.go @@ -6,10 +6,11 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -49,6 +50,7 @@ func (m mockedNetworkInterface) WaitUntilInstanceTerminated(*ec2.DescribeInstanc } func TestNetworkInterface_GetAll(t *testing.T) { + telemetry.InitTelemetry("cloud-nuke", "") var ( now = time.Now() @@ -64,28 +66,28 @@ func TestNetworkInterface_GetAll(t *testing.T) { DescribeNetworkInterfacesOutput: ec2.DescribeNetworkInterfacesOutput{ NetworkInterfaces: []*ec2.NetworkInterface{ { - NetworkInterfaceId: aws.String(testId1), + NetworkInterfaceId: awsgo.String(testId1), TagSet: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName1), + Key: awsgo.String("Name"), + Value: awsgo.String(testName1), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now)), }, }, }, { - NetworkInterfaceId: aws.String(testId2), + NetworkInterfaceId: awsgo.String(testId2), TagSet: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName2), + Key: awsgo.String("Name"), + Value: awsgo.String(testName2), }, { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(now.Add(1 * time.Hour))), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(now.Add(1 * time.Hour))), }, }, }, @@ -124,7 +126,7 @@ func TestNetworkInterface_GetAll(t *testing.T) { "timeAfterExclusionFilter": { configObj: config.ResourceType{ ExcludeRule: config.FilterRule{ - TimeAfter: aws.Time(now), + TimeAfter: awsgo.Time(now), }}, expected: []string{ testId1, @@ -137,14 +139,14 @@ func TestNetworkInterface_GetAll(t *testing.T) { NetworkInterface: tc.configObj, }) require.NoError(t, err) - require.Equal(t, tc.expected, aws.StringValueSlice(names)) + require.Equal(t, tc.expected, awsgo.StringValueSlice(names)) }) } } func TestNetworkInterface_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -167,29 +169,29 @@ func TestNetworkInterface_NukeAll(t *testing.T) { DescribeNetworkInterfacesOutput: ec2.DescribeNetworkInterfacesOutput{ NetworkInterfaces: []*ec2.NetworkInterface{ { - NetworkInterfaceId: aws.String(testId1), + NetworkInterfaceId: awsgo.String(testId1), TagSet: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName1), + Key: awsgo.String("Name"), + Value: awsgo.String(testName1), }, }, Attachment: &ec2.NetworkInterfaceAttachment{ - AttachmentId: aws.String("network-attachment-09e36c45cbdbfb001"), - InstanceId: aws.String("ec2-instance-09e36c45cbdbfb001"), + AttachmentId: awsgo.String("network-attachment-09e36c45cbdbfb001"), + InstanceId: awsgo.String("ec2-instance-09e36c45cbdbfb001"), }, }, { - NetworkInterfaceId: aws.String(testId2), + NetworkInterfaceId: awsgo.String(testId2), TagSet: []*ec2.Tag{ { - Key: aws.String("Name"), - Value: aws.String(testName2), + Key: awsgo.String("Name"), + Value: awsgo.String(testName2), }, }, Attachment: &ec2.NetworkInterfaceAttachment{ - AttachmentId: aws.String("network-attachment-09e36c45cbdbfb002"), - InstanceId: aws.String("ec2-instance-09e36c45cbdbfb002"), + AttachmentId: awsgo.String("network-attachment-09e36c45cbdbfb002"), + InstanceId: awsgo.String("ec2-instance-09e36c45cbdbfb002"), }, }, }, @@ -197,12 +199,12 @@ func TestNetworkInterface_NukeAll(t *testing.T) { DescribeAddressesOutput: ec2.DescribeAddressesOutput{ Addresses: []*ec2.Address{ { - AllocationId: aws.String("ec2-addr-alloc-09e36c45cbdbfb001"), - InstanceId: aws.String("ec2-instance-09e36c45cbdbfb001"), + AllocationId: awsgo.String("ec2-addr-alloc-09e36c45cbdbfb001"), + InstanceId: awsgo.String("ec2-instance-09e36c45cbdbfb001"), }, { - AllocationId: aws.String("ec2-addr-alloc-09e36c45cbdbfb002"), - InstanceId: aws.String("ec2-instance-09e36c45cbdbfb002"), + AllocationId: awsgo.String("ec2-addr-alloc-09e36c45cbdbfb002"), + InstanceId: awsgo.String("ec2-instance-09e36c45cbdbfb002"), }, }, }, @@ -212,8 +214,8 @@ func TestNetworkInterface_NukeAll(t *testing.T) { } err := resourceObject.nukeAll([]*string{ - aws.String(testId1), - aws.String(testId2), + awsgo.String(testId1), + awsgo.String(testId2), }) require.NoError(t, err) } diff --git a/aws/resources/ec2_subnet.go b/aws/resources/ec2_subnet.go index bb756418..545f005a 100644 --- a/aws/resources/ec2_subnet.go +++ b/aws/resources/ec2_subnet.go @@ -2,11 +2,13 @@ package resources import ( "context" + "fmt" "strconv" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -19,8 +21,8 @@ func (ec2subnet *EC2Subnet) setFirstSeenTag(sb ec2.Subnet, value time.Time) erro Resources: []*string{sb.SubnetId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -72,9 +74,9 @@ func (ec2subnet *EC2Subnet) getAll(_ context.Context, configObj config.Config) ( err := ec2subnet.Client.DescribeSubnetsPages(&ec2.DescribeSubnetsInput{ Filters: []*ec2.Filter{ { - Name: aws.String("default-for-az"), + Name: awsgo.String("default-for-az"), Values: []*string{ - aws.String(strconv.FormatBool(configObj.EC2Subnet.DefaultOnly)), // convert the bool status into string + awsgo.String(strconv.FormatBool(configObj.EC2Subnet.DefaultOnly)), // convert the bool status into string }, }, }, @@ -115,7 +117,7 @@ func (ec2subnet *EC2Subnet) getAll(_ context.Context, configObj config.Config) ( ec2subnet.VerifyNukablePermissions(result, func(id *string) error { params := &ec2.DeleteSubnetInput{ SubnetId: id, - DryRun: aws.Bool(true), // dry run set as true , checks permission without actually making the request + DryRun: awsgo.Bool(true), // dry run set as true , checks permission without actually making the request } _, err := ec2subnet.Client.DeleteSubnet(params) return err @@ -145,13 +147,10 @@ func (ec2subnet *EC2Subnet) nukeAll(ids []*string) error { continue } - _, err := ec2subnet.Client.DeleteSubnet(&ec2.DeleteSubnetInput{ - SubnetId: id, - }) - + err := nukeSubnet(ec2subnet.Client, id) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Subnet", Error: err, } @@ -169,3 +168,21 @@ func (ec2subnet *EC2Subnet) nukeAll(ids []*string) error { return nil } + +func nukeSubnet(client ec2iface.EC2API, id *string) error { + logging.Debug(fmt.Sprintf("Deleting subnet %s", + awsgo.StringValue(id))) + + _, err := client.DeleteSubnet(&ec2.DeleteSubnetInput{ + SubnetId: id, + }) + if err != nil { + logging.Debug(fmt.Sprintf("Failed to delete subnet %s", + awsgo.StringValue(id))) + return errors.WithStackTrace(err) + } + + logging.Debug(fmt.Sprintf("Successfully deleted subnet %s", + awsgo.StringValue(id))) + return nil +} diff --git a/aws/resources/ec2_subnet_test.go b/aws/resources/ec2_subnet_test.go index 9e7b07f7..eebd5471 100644 --- a/aws/resources/ec2_subnet_test.go +++ b/aws/resources/ec2_subnet_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -29,7 +30,7 @@ func (m mockedEC2Subnets) DeleteSubnet(_ *ec2.DeleteSubnetInput) (*ec2.DeleteSub } func TestEc2Subnets_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() var ( @@ -117,7 +118,7 @@ func TestEc2Subnets_GetAll(t *testing.T) { } func TestEc2Subnet_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() tgw := EC2Subnet{ diff --git a/aws/resources/ec2_test.go b/aws/resources/ec2_test.go index 2f7100fd..b4ff5d01 100644 --- a/aws/resources/ec2_test.go +++ b/aws/resources/ec2_test.go @@ -12,6 +12,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -50,7 +51,7 @@ func (m mockedEC2Instances) ReleaseAddress(input *ec2.ReleaseAddressInput) (*ec2 } func TestEc2Instances_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "testId1" @@ -140,7 +141,7 @@ func TestEc2Instances_GetAll(t *testing.T) { } func TestEc2Instances_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ei := EC2Instances{ diff --git a/aws/resources/ec2_vpc.go b/aws/resources/ec2_vpc.go index 5bddc317..8000d5f2 100644 --- a/aws/resources/ec2_vpc.go +++ b/aws/resources/ec2_vpc.go @@ -4,15 +4,19 @@ import ( "context" cerrors "errors" "fmt" - "github.com/aws/aws-sdk-go-v2/aws" "strconv" "strings" "time" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/util" "github.com/pterm/pterm" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/gruntwork-io/cloud-nuke/config" @@ -125,6 +129,11 @@ func (v *EC2VPCs) nukeAll(vpcIds []string) error { if err != nil { pterm.Error.Println(fmt.Sprintf("Failed to nuke vpc with err: %s", err)) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking VPC", + }, map[string]interface{}{ + "region": v.Region, + }) multierror.Append(multiErr, err) } else { deletedVPCs++ @@ -156,7 +165,7 @@ func nuke(client ec2iface.EC2API, vpcID string) error { return err } - err = nukeNatGateway(client, vpcID) + err = nukeNatGateways(client, vpcID) if err != nil { logging.Debug(fmt.Sprintf("Error cleaning up NAT Gateways for VPC %s: %s", vpcID, err.Error())) return err @@ -168,7 +177,7 @@ func nuke(client ec2iface.EC2API, vpcID string) error { return err } - err = nukeInternetGateway(client, vpcID) + err = nukeInternetGateways(client, vpcID) if err != nil { logging.Debug(fmt.Sprintf("Error cleaning up Internet Gateway for VPC %s: %s", vpcID, err.Error())) return err @@ -209,7 +218,9 @@ func nuke(client ec2iface.EC2API, vpcID string) error { return nil } -func nukeInternetGateway(client ec2iface.EC2API, vpcID string) error { +// nukeVpcInternetGateways +// This function is specifically for VPCs. It retrieves all the internet gateways attached to the given VPC ID and nuke them +func nukeInternetGateways(client ec2iface.EC2API, vpcID string) error { logging.Debug(fmt.Sprintf("Start nuking Internet Gateway for vpc: %s", vpcID)) input := &ec2.DescribeInternetGatewaysInput{ Filters: []*ec2.Filter{ @@ -230,36 +241,13 @@ func nukeInternetGateway(client ec2iface.EC2API, vpcID string) error { return nil } - logging.Debug(fmt.Sprintf("Detaching Internet Gateway %s", - awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) - _, err = client.DetachInternetGateway( - &ec2.DetachInternetGatewayInput{ - InternetGatewayId: igw.InternetGateways[0].InternetGatewayId, - VpcId: awsgo.String(vpcID), - }, - ) - if err != nil { - logging.Debug(fmt.Sprintf("Failed to detach internet gateway %s", - awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) - return errors.WithStackTrace(err) - } - logging.Debug(fmt.Sprintf("Successfully detached internet gateway %s", - awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) - - logging.Debug(fmt.Sprintf("Deleting internet gateway %s", - awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) - _, err = client.DeleteInternetGateway( - &ec2.DeleteInternetGatewayInput{ - InternetGatewayId: igw.InternetGateways[0].InternetGatewayId, - }, - ) + // re-using the method inside internet gateway + err = nukeInternetGateway(client, igw.InternetGateways[0].InternetGatewayId, vpcID) if err != nil { logging.Debug(fmt.Sprintf("Failed to delete internet gateway %s", awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) return errors.WithStackTrace(err) } - logging.Debug(fmt.Sprintf("Successfully deleted internet gateway %s", - awsgo.StringValue(igw.InternetGateways[0].InternetGatewayId))) return nil } @@ -287,18 +275,17 @@ func nukeEgressOnlyGateways(client ec2iface.EC2API, vpcID string) error { } logging.Debug(fmt.Sprintf("Found %d Egress Only Internet Gateways to nuke.", len(allEgressGateways))) - var allErrs *multierror.Error + for _, gateway := range allEgressGateways { - _, err := client.DeleteEgressOnlyInternetGateway( - &ec2.DeleteEgressOnlyInternetGatewayInput{EgressOnlyInternetGatewayId: gateway}) + err := nukeEgressOnlyGateway(client, gateway) if err != nil { - logging.Debug(fmt.Sprintf("Failed to delete Egress Only Internet Gateway %s", *gateway)) - allErrs = multierror.Append(allErrs, errors.WithStackTrace(err)) + logging.Debug(fmt.Sprintf("Failed to delete Egress Only Internet Gateway %s for vpc %s", *gateway, vpcID)) + return errors.WithStackTrace(err) } - - logging.Debug(fmt.Sprintf("Successfully deleted Egress Only Internet Gateway %s", *gateway)) } + logging.Debug(fmt.Sprintf("Successfully deleted Egress Only Internet Gateways for %s", vpcID)) + return nil } @@ -333,9 +320,7 @@ func nukeEndpoints(client ec2iface.EC2API, vpcID string) error { return nil } - _, err := client.DeleteVpcEndpoints(&ec2.DeleteVpcEndpointsInput{ - VpcEndpointIds: endpointIds, - }) + err := nukeVpcEndpoint(client, endpointIds) if err != nil { logging.Debug(fmt.Sprintf("Failed to delete VPC endpoints: %s", err.Error())) return errors.WithStackTrace(err) @@ -349,37 +334,6 @@ func nukeEndpoints(client ec2iface.EC2API, vpcID string) error { return nil } -func waitForVPCEndpointToBeDeleted(client ec2iface.EC2API, vpcID string) error { - for i := 0; i < 30; i++ { - endpoints, err := client.DescribeVpcEndpoints( - &ec2.DescribeVpcEndpointsInput{ - Filters: []*ec2.Filter{ - { - Name: awsgo.String("vpc-id"), - Values: []*string{awsgo.String(vpcID)}, - }, - { - Name: awsgo.String("vpc-endpoint-state"), - Values: []*string{awsgo.String("deleting")}, - }, - }, - }, - ) - if err != nil { - return err - } - - if len(endpoints.VpcEndpoints) == 0 { - return nil - } - - time.Sleep(20 * time.Second) - logging.Debug(fmt.Sprintf("Waiting for VPC endpoints to be deleted...")) - } - - return nil -} - func nukeNetworkInterfaces(client ec2iface.EC2API, vpcID string) error { logging.Debug(fmt.Sprintf("Start nuking network interfaces for vpc: %s", vpcID)) @@ -410,9 +364,7 @@ func nukeNetworkInterfaces(client ec2iface.EC2API, vpcID string) error { continue } - _, err = client.DeleteNetworkInterface(&ec2.DeleteNetworkInterfaceInput{ - NetworkInterfaceId: netInterface.NetworkInterfaceId, - }) + err = nukeNetworkInterface(client, netInterface.NetworkInterfaceId) if err != nil { logging.Debug(fmt.Sprintf("Failed to delete network interface: %s", *netInterface)) return errors.WithStackTrace(err) @@ -437,30 +389,25 @@ func nukeSubnets(client ec2iface.EC2API, vpcID string) error { }, ) - logging.Debug(fmt.Sprintf("Found %d subnets to delete ", len(subnets.Subnets))) - if len(subnets.Subnets) > 0 { - for _, subnet := range subnets.Subnets { - _, err := client.DeleteSubnet( - &ec2.DeleteSubnetInput{ - SubnetId: subnet.SubnetId, - }, - ) - - if err != nil { - logging.Debug(fmt.Sprintf("Failed to delete subnet %s", awsgo.StringValue(subnet.SubnetId))) - return errors.WithStackTrace(err) - } - logging.Debug(fmt.Sprintf("Successfully deleted subnet %s", awsgo.StringValue(subnet.SubnetId))) - } - + if len(subnets.Subnets) == 0 { + logging.Debug(fmt.Sprintf("No subnets found")) return nil } - logging.Debug(fmt.Sprintf("No subnets found")) + logging.Debug(fmt.Sprintf("Found %d subnets to delete ", len(subnets.Subnets))) + for _, subnet := range subnets.Subnets { + err := nukeSubnet(client, subnet.SubnetId) + if err != nil { + logging.Debug(fmt.Sprintf("Failed to delete subnet %s for vpc %s", awsgo.StringValue(subnet.SubnetId), vpcID)) + return errors.WithStackTrace(err) + } + } + logging.Debug(fmt.Sprintf("Successfully deleted subnets for vpc %v", vpcID)) return nil + } -func nukeNatGateway(client ec2iface.EC2API, vpcID string) error { +func nukeNatGateways(client ec2iface.EC2API, vpcID string) error { gateways, err := client.DescribeNatGateways(&ec2.DescribeNatGatewaysInput{ Filter: []*ec2.Filter{ { @@ -482,17 +429,14 @@ func nukeNatGateway(client ec2iface.EC2API, vpcID string) error { continue } - _, err := client.DeleteNatGateway(&ec2.DeleteNatGatewayInput{ - NatGatewayId: gateway.NatGatewayId, - }) + err := nukeNATGateway(client, gateway.NatGatewayId) if err != nil { logging.Debug( - fmt.Sprintf("Failed to delete NAT gateway %s", awsgo.StringValue(gateway.NatGatewayId))) + fmt.Sprintf("Failed to delete NAT gateway %s for vpc %v", awsgo.StringValue(gateway.NatGatewayId), vpcID)) return errors.WithStackTrace(err) } - logging.Debug( - fmt.Sprintf("Successfully deleted NAT gateway %s", awsgo.StringValue(gateway.NatGatewayId))) } + logging.Debugf("Successfully deleted NAT gateways for vpc %s", vpcID) return nil } @@ -554,6 +498,10 @@ func nukeRouteTables(client ec2iface.EC2API, vpcID string) error { // nukeNacls nukes all network ACLs in a VPC except the default one. It replaces all subnet associations with // the default in order to prevent dependency violations. +// You can't delete the ACL if it's associated with any subnets. +// You can't delete the default network ACL. +// +// https://docs.aws.amazon.com/cli/latest/reference/ec2/delete-network-acl.html func nukeNacls(client ec2iface.EC2API, vpcID string) error { logging.Debug(fmt.Sprintf("Start nuking network ACLs for vpc: %s", vpcID)) networkACLs, _ := client.DescribeNetworkAcls( @@ -588,36 +536,19 @@ func nukeNacls(client ec2iface.EC2API, vpcID string) error { continue } - logging.Debug(fmt.Sprintf( - "Start nuking network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId))) - for _, association := range networkACL.Associations { - logging.Debug(fmt.Sprintf( - "Found %d network ACL associations to replace", len(networkACL.Associations))) - _, err := client.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{ - AssociationId: association.NetworkAclAssociationId, - NetworkAclId: defaultNetworkAclID, - }) - if err != nil { - logging.Debug(fmt.Sprintf("Failed to replace network ACL association: %s to default", - awsgo.StringValue(association.NetworkAclAssociationId))) - return errors.WithStackTrace(err) - } - logging.Debug(fmt.Sprintf("Successfully replaced network ACL association: %s to default", - awsgo.StringValue(association.NetworkAclAssociationId))) + logging.Debugf("Start nuking network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId)) + err := replaceNetworkAclAssociation(client, defaultNetworkAclID, networkACL.Associations) + if err != nil { + logging.Debugf("Failed to replace network ACL associations: %s", awsgo.StringValue(networkACL.NetworkAclId)) + return errors.WithStackTrace(err) } - _, err := client.DeleteNetworkAcl( - &ec2.DeleteNetworkAclInput{ - NetworkAclId: networkACL.NetworkAclId, - }, - ) + err = nukeNetworkAcl(client, networkACL.NetworkAclId) if err != nil { - logging.Debug(fmt.Sprintf( - "Failed to delete network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId))) + logging.Debugf("Failed to delete network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId)) return errors.WithStackTrace(err) } - logging.Debug(fmt.Sprintf( - "Successfully deleted network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId))) + logging.Debugf("Successfully deleted network ACL: %s", awsgo.StringValue(networkACL.NetworkAclId)) } return nil @@ -687,11 +618,9 @@ func nukeSecurityGroups(client ec2iface.EC2API, vpcID string) error { for _, securityGroup := range securityGroups.SecurityGroups { if *securityGroup.GroupName != "default" { - _, err := client.DeleteSecurityGroup( - &ec2.DeleteSecurityGroupInput{ - GroupId: securityGroup.GroupId, - }, - ) + logging.Debug(fmt.Sprintf("Deleting Security Group %s for vpc %s", awsgo.StringValue(securityGroup.GroupId), vpcID)) + + err := nukeSecurityGroup(client, securityGroup.GroupId) if err != nil { logging.Debug(fmt.Sprintf( "Successfully deleted security group %s", awsgo.StringValue(securityGroup.GroupId))) @@ -705,6 +634,8 @@ func nukeSecurityGroups(client ec2iface.EC2API, vpcID string) error { return nil } +// default option is not available for this, and it only supports deleting non-default resources +// https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-dhcp-options.html func nukeDhcpOptions(client ec2iface.EC2API, vpcID string) error { // Deletes the specified set of DHCP options. You must disassociate the set of DHCP options before you can delete it. diff --git a/aws/resources/ec2_vpc_test.go b/aws/resources/ec2_vpc_test.go index cbee4bf3..48b69f18 100644 --- a/aws/resources/ec2_vpc_test.go +++ b/aws/resources/ec2_vpc_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ func (m mockedEC2VPCs) DeleteVpc(input *ec2.DeleteVpcInput) (*ec2.DeleteVpcOutpu } func TestEC2VPC_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-vpc-name1" @@ -116,7 +117,7 @@ func TestEC2VPC_GetAll(t *testing.T) { // TODO: Fix this test //func TestEC2VPC_NukeAll(t *testing.T) { -// +// telemetry.InitTelemetry("cloud-nuke", "") // t.Parallel() // // vpc := EC2VPCs{ diff --git a/aws/resources/ecr.go b/aws/resources/ecr.go index 2c47bba0..77e5a98c 100644 --- a/aws/resources/ecr.go +++ b/aws/resources/ecr.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (registry *ECR) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -59,6 +61,11 @@ func (registry *ECR) nukeAll(repositoryNames []string) error { report.Record(e) if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECR Repo", + }, map[string]interface{}{ + "region": registry.Region, + }) logging.Debugf("[Failed] %s", err) } else { diff --git a/aws/resources/ecr_test.go b/aws/resources/ecr_test.go index 3996276b..fa995eb6 100644 --- a/aws/resources/ecr_test.go +++ b/aws/resources/ecr_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ecr" "github.com/aws/aws-sdk-go/service/ecr/ecriface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -28,7 +29,7 @@ func (m mockedECR) DeleteRepository(input *ecr.DeleteRepositoryInput) (*ecr.Dele } func TestECR_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-repo1" @@ -89,7 +90,7 @@ func TestECR_GetAll(t *testing.T) { } func TestECR_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() er := ECR{ diff --git a/aws/resources/ecs_cluster.go b/aws/resources/ecs_cluster.go index 4d4aabc4..66c41b06 100644 --- a/aws/resources/ecs_cluster.go +++ b/aws/resources/ecs_cluster.go @@ -6,6 +6,9 @@ import ( "github.com/gruntwork-io/cloud-nuke/util" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ecs" @@ -185,6 +188,11 @@ func (clusters *ECSClusters) nukeAll(ecsClusterArns []*string) error { if err != nil { logging.Debugf("Error, failed to delete cluster with ARN %s %s", aws.StringValue(clusterArn), err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Cluster", + }, map[string]interface{}{ + "region": clusters.Region, + }) return errors.WithStackTrace(err) } diff --git a/aws/resources/ecs_cluster_test.go b/aws/resources/ecs_cluster_test.go index e9824ee9..da2cc990 100644 --- a/aws/resources/ecs_cluster_test.go +++ b/aws/resources/ecs_cluster_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/ecs" "github.com/aws/aws-sdk-go/service/ecs/ecsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -53,7 +54,7 @@ func (m mockedEC2Cluster) StopTask(*ecs.StopTaskInput) (*ecs.StopTaskOutput, err } func TestEC2Cluster_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn1 := "arn:aws:ecs:us-east-1:123456789012:cluster/cluster1" @@ -140,7 +141,7 @@ func TestEC2Cluster_GetAll(t *testing.T) { } func TestEC2Cluster_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ec := ECSClusters{ @@ -154,7 +155,7 @@ func TestEC2Cluster_NukeAll(t *testing.T) { } func TestEC2ClusterWithTasks_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ec := ECSClusters{ diff --git a/aws/resources/ecs_service.go b/aws/resources/ecs_service.go index 2479dfef..ccdfb76f 100644 --- a/aws/resources/ecs_service.go +++ b/aws/resources/ecs_service.go @@ -2,7 +2,9 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" @@ -114,6 +116,12 @@ func (services *ECSServices) drainEcsServices(ecsServiceArns []*string) []*strin describeServicesOutput, err := services.Client.DescribeServices(describeParams) if err != nil { logging.Errorf("[Failed] Failed to describe service %s: %s", *ecsServiceArn, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Service", + }, map[string]interface{}{ + "region": services.Region, + "reason": "Unable to describe", + }) } else { schedulingStrategy := *describeServicesOutput.Services[0].SchedulingStrategy @@ -128,6 +136,12 @@ func (services *ECSServices) drainEcsServices(ecsServiceArns []*string) []*strin _, err = services.Client.UpdateService(params) if err != nil { logging.Errorf("[Failed] Failed to drain service %s: %s", *ecsServiceArn, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Service", + }, map[string]interface{}{ + "region": services.Region, + "reason": "Unable to drain", + }) } else { requestedDrains = append(requestedDrains, ecsServiceArn) } @@ -151,6 +165,12 @@ func (services *ECSServices) waitUntilServicesDrained(ecsServiceArns []*string) err := services.Client.WaitUntilServicesStable(params) if err != nil { logging.Debugf("[Failed] Failed waiting for service to be stable %s: %s", *ecsServiceArn, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Service", + }, map[string]interface{}{ + "region": services.Region, + "reason": "Failed Waiting for Drain", + }) } else { logging.Debugf("Drained service: %s", *ecsServiceArn) successfullyDrained = append(successfullyDrained, ecsServiceArn) @@ -171,6 +191,12 @@ func (services *ECSServices) deleteEcsServices(ecsServiceArns []*string) []*stri _, err := services.Client.DeleteService(params) if err != nil { logging.Debugf("[Failed] Failed deleting service %s: %s", *ecsServiceArn, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Service", + }, map[string]interface{}{ + "region": services.Region, + "reason": "Unable to Delete", + }) } else { requestedDeletes = append(requestedDeletes, ecsServiceArn) } @@ -200,6 +226,12 @@ func (services *ECSServices) waitUntilServicesDeleted(ecsServiceArns []*string) if err != nil { logging.Debugf("[Failed] Failed waiting for service to be deleted %s: %s", *ecsServiceArn, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking ECS Service", + }, map[string]interface{}{ + "region": services.Region, + "reason": "Failed Waiting for Delete", + }) } else { logging.Debugf("Deleted service: %s", *ecsServiceArn) successfullyDeleted = append(successfullyDeleted, ecsServiceArn) diff --git a/aws/resources/ecs_service_test.go b/aws/resources/ecs_service_test.go index 88b4f0af..591b0af5 100644 --- a/aws/resources/ecs_service_test.go +++ b/aws/resources/ecs_service_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ecs" "github.com/aws/aws-sdk-go/service/ecs/ecsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -50,7 +51,7 @@ func (m mockedEC2Service) WaitUntilServicesInactive(*ecs.DescribeServicesInput) } func TestEC2Service_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn1 := "testArn1" @@ -125,7 +126,7 @@ func TestEC2Service_GetAll(t *testing.T) { } func TestEC2Service_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() es := ECSServices{ diff --git a/aws/resources/efs.go b/aws/resources/efs.go index 7334aeac..99e00b1a 100644 --- a/aws/resources/efs.go +++ b/aws/resources/efs.go @@ -2,6 +2,8 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "time" @@ -59,6 +61,11 @@ func (ef *ElasticFileSystem) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EFS", + }, map[string]interface{}{ + "region": ef.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/efs_test.go b/aws/resources/efs_test.go index 15f32c95..2a8ed99f 100644 --- a/aws/resources/efs_test.go +++ b/aws/resources/efs_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/efs" "github.com/aws/aws-sdk-go/service/efs/efsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -48,7 +49,7 @@ func (m mockedElasticFileSystem) DeleteFileSystem(input *efs.DeleteFileSystemInp } func TestEFS_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "testId1" @@ -113,7 +114,7 @@ func TestEFS_GetAll(t *testing.T) { } func TestEFS_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ef := ElasticFileSystem{ diff --git a/aws/resources/eip.go b/aws/resources/eip.go index 50ad3533..c9325e62 100644 --- a/aws/resources/eip.go +++ b/aws/resources/eip.go @@ -4,6 +4,10 @@ import ( "context" "time" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -11,7 +15,6 @@ import ( "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/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" ) @@ -118,8 +121,19 @@ func (ea *EIPAddresses) nukeAll(allocationIds []*string) error { if awsErr, isAwsErr := err.(awserr.Error); isAwsErr && awsErr.Code() == "AuthFailure" { // TODO: Figure out why we get an AuthFailure logging.Debugf("EIP %s can't be deleted, it is still attached to an active resource", *allocationID) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EIP", + }, map[string]interface{}{ + "region": ea.Region, + "reason": "Still Attached to an Active Resource", + }) } else { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EIP", + }, map[string]interface{}{ + "region": ea.Region, + }) } } else { deletedAllocationIDs = append(deletedAllocationIDs, allocationID) diff --git a/aws/resources/eip_test.go b/aws/resources/eip_test.go index 226f95be..030dd1c9 100644 --- a/aws/resources/eip_test.go +++ b/aws/resources/eip_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" "regexp" @@ -29,7 +30,7 @@ func (m mockedEIPAddresses) ReleaseAddress(*ec2.ReleaseAddressInput) (*ec2.Relea } func TestEIPAddress_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -110,7 +111,7 @@ func TestEIPAddress_GetAll(t *testing.T) { } func TestEIPAddress_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ea := EIPAddresses{ diff --git a/aws/resources/eks.go b/aws/resources/eks.go index 72ae0844..c9c1dc09 100644 --- a/aws/resources/eks.go +++ b/aws/resources/eks.go @@ -7,8 +7,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "sync" ) @@ -250,6 +252,11 @@ func (clusters *EKSClusters) nukeAll(eksClusterNames []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EKS Cluster", + }, map[string]interface{}{ + "region": clusters.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/eks_test.go b/aws/resources/eks_test.go index 397e5f60..4fba7bc6 100644 --- a/aws/resources/eks_test.go +++ b/aws/resources/eks_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/eks" "github.com/aws/aws-sdk-go/service/eks/eksiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -79,7 +80,7 @@ func (m mockedEKSCluster) DeleteCluster(input *eks.DeleteClusterInput) (*eks.Del } func TestEKSClusterGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testClusterName := "test_cluster1" @@ -101,7 +102,7 @@ func TestEKSClusterGetAll(t *testing.T) { } func TestEKSClusterNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testClusterName := "test_cluster1" diff --git a/aws/resources/elasticache.go b/aws/resources/elasticache.go index 79ee44e6..ba249a29 100644 --- a/aws/resources/elasticache.go +++ b/aws/resources/elasticache.go @@ -9,7 +9,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "strings" ) @@ -180,6 +182,11 @@ func (cache *Elasticaches) nukeAll(clusterIds []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Elasticache Cluster", + }, map[string]interface{}{ + "region": cache.Region, + }) } else { deletedClusterIds = append(deletedClusterIds, clusterId) logging.Debugf("Deleted Elasticache cluster: %s", *clusterId) @@ -253,6 +260,11 @@ func (pg *ElasticacheParameterGroups) nukeAll(paramGroupNames []*string) error { report.Record(e) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Elasticache Parameter Group", + }, map[string]interface{}{ + "region": pg.Region, + }) } else { deletedGroupNames = append(deletedGroupNames, pgName) logging.Debugf("Deleted Elasticache parameter group: %s", aws.StringValue(pgName)) @@ -304,6 +316,11 @@ func (sg *ElasticacheSubnetGroups) nukeAll(subnetGroupNames []*string) error { report.Record(e) if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Elasticache Subnet Group", + }, map[string]interface{}{ + "region": sg.Region, + }) } else { deletedGroupNames = append(deletedGroupNames, sgName) logging.Debugf("Deleted Elasticache subnet group: %s", aws.StringValue(sgName)) diff --git a/aws/resources/elasticache_test.go b/aws/resources/elasticache_test.go index 1b611bed..960dad17 100644 --- a/aws/resources/elasticache_test.go +++ b/aws/resources/elasticache_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/elasticache" "github.com/aws/aws-sdk-go/service/elasticache/elasticacheiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -36,7 +37,7 @@ func (m mockedElasticache) WaitUntilReplicationGroupDeleted(input *elasticache.D } func TestElasticache_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -99,7 +100,7 @@ func TestElasticache_GetAll(t *testing.T) { } func TestElasticache_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() diff --git a/aws/resources/elb.go b/aws/resources/elb.go index ce50fd63..74f68a0e 100644 --- a/aws/resources/elb.go +++ b/aws/resources/elb.go @@ -3,6 +3,8 @@ package resources import ( "context" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "time" "github.com/aws/aws-sdk-go/aws" @@ -78,6 +80,11 @@ func (balancer *LoadBalancers) nukeAll(names []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Load Balancer (v1)", + }, map[string]interface{}{ + "region": balancer.Region, + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted ELB: %s", *name) diff --git a/aws/resources/elb_test.go b/aws/resources/elb_test.go index 147b4daf..410b0757 100644 --- a/aws/resources/elb_test.go +++ b/aws/resources/elb_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/elb" "github.com/aws/aws-sdk-go/service/elb/elbiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -29,7 +30,7 @@ func (m mockedLoadBalancers) DeleteLoadBalancer(input *elb.DeleteLoadBalancerInp } func TestElb_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name-1" @@ -89,7 +90,7 @@ func TestElb_GetAll(t *testing.T) { } func TestElb_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() balancer := LoadBalancers{ diff --git a/aws/resources/elbv2.go b/aws/resources/elbv2.go index cd47af59..f7a48a27 100644 --- a/aws/resources/elbv2.go +++ b/aws/resources/elbv2.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a formatted string of ELBv2 Arns @@ -57,6 +59,11 @@ func (balancer *LoadBalancersV2) nukeAll(arns []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Load Balancer V2", + }, map[string]interface{}{ + "region": balancer.Region, + }) } else { deletedArns = append(deletedArns, arn) logging.Debugf("Deleted ELBv2: %s", *arn) diff --git a/aws/resources/elbv2_test.go b/aws/resources/elbv2_test.go index bd15d5a5..c864cc66 100644 --- a/aws/resources/elbv2_test.go +++ b/aws/resources/elbv2_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/elbv2" "github.com/aws/aws-sdk-go/service/elbv2/elbv2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -31,7 +32,7 @@ func (m mockedElbV2) WaitUntilLoadBalancersDeleted(input *elbv2.DescribeLoadBala } func TestElbV2_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name-1" @@ -96,7 +97,7 @@ func TestElbV2_GetAll(t *testing.T) { } func TestElbV2_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() balancer := LoadBalancersV2{ diff --git a/aws/resources/guardduty.go b/aws/resources/guardduty.go index 03c3a28e..e17643ba 100644 --- a/aws/resources/guardduty.go +++ b/aws/resources/guardduty.go @@ -7,8 +7,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) type DetectorOutputWithID struct { @@ -83,6 +85,11 @@ func (gd *GuardDuty) nukeAll(detectorIds []string) error { if err != nil { logging.Debugf("[Failed] %s: %s", detectorId, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking GuardDuty Detector", + }, map[string]interface{}{ + "region": gd.Region, + }) } else { deletedIds = append(deletedIds, detectorId) logging.Debugf("Deleted GuardDuty detector: %s", detectorId) diff --git a/aws/resources/guardduty_test.go b/aws/resources/guardduty_test.go index 2f3629f1..bf516c1a 100644 --- a/aws/resources/guardduty_test.go +++ b/aws/resources/guardduty_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/guardduty" "github.com/aws/aws-sdk-go/service/guardduty/guarddutyiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "testing" "time" @@ -32,7 +33,7 @@ func (m mockedGuardDuty) DeleteDetector(input *guardduty.DeleteDetectorInput) (* } func TestGuardDuty_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "test-detector-id-1" @@ -80,7 +81,7 @@ func TestGuardDuty_GetAll(t *testing.T) { } func TestGuardDuty_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() gd := GuardDuty{ diff --git a/aws/resources/iam.go b/aws/resources/iam.go index f429633e..09980d19 100644 --- a/aws/resources/iam.go +++ b/aws/resources/iam.go @@ -3,7 +3,9 @@ package resources import ( "context" "fmt" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "time" "github.com/aws/aws-sdk-go/aws" @@ -363,6 +365,9 @@ func (iu *IAMUsers) nukeAll(userNames []*string) error { if err != nil { logging.Errorf("[Failed] %s", err) multierror.Append(multiErr, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking IAM User", + }, map[string]interface{}{}) } else { deletedUsers++ logging.Debugf("Deleted IAM User: %s", *userName) diff --git a/aws/resources/iam_group.go b/aws/resources/iam_group.go index d855dd70..edd6cf4c 100644 --- a/aws/resources/iam_group.go +++ b/aws/resources/iam_group.go @@ -7,6 +7,8 @@ import ( "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/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/gruntwork-io/gruntwork-cli/errors" "github.com/hashicorp/go-multierror" "sync" @@ -65,6 +67,9 @@ func (ig *IAMGroups) nukeAll(groupNames []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking IAM Group", + }, map[string]interface{}{}) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/iam_group_test.go b/aws/resources/iam_group_test.go index 04a47225..b0da25b5 100644 --- a/aws/resources/iam_group_test.go +++ b/aws/resources/iam_group_test.go @@ -3,6 +3,7 @@ package resources import ( "context" "github.com/aws/aws-sdk-go/service/iam/iamiface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -61,7 +62,7 @@ func (m mockedIAMGroups) RemoveUserFromGroup(input *iam.RemoveUserFromGroupInput } func TestIamGroups_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "group1" @@ -121,7 +122,7 @@ func TestIamGroups_GetAll(t *testing.T) { } func TestIamGroups_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ig := IAMGroups{ diff --git a/aws/resources/iam_policy.go b/aws/resources/iam_policy.go index 0807c98b..4a6c71c9 100644 --- a/aws/resources/iam_policy.go +++ b/aws/resources/iam_policy.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "sync" ) @@ -67,6 +69,9 @@ func (ip *IAMPolicies) nukeAll(policyArns []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking IAM Policy", + }, map[string]interface{}{}) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/iam_policy_test.go b/aws/resources/iam_policy_test.go index 7733ee5b..98b08e79 100644 --- a/aws/resources/iam_policy_test.go +++ b/aws/resources/iam_policy_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -61,7 +62,7 @@ func (m mockedIAMPolicies) DeletePolicy(input *iam.DeletePolicyInput) (*iam.Dele } func TestIAMPolicy_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "MyPolicy1" @@ -125,7 +126,7 @@ func TestIAMPolicy_GetAll(t *testing.T) { } func TestIAMPolicy_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ip := IAMPolicies{ diff --git a/aws/resources/iam_role.go b/aws/resources/iam_role.go index e9dc7a5b..ee118ee4 100644 --- a/aws/resources/iam_role.go +++ b/aws/resources/iam_role.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/hashicorp/go-multierror" "strings" "sync" @@ -158,6 +160,9 @@ func (ir *IAMRoles) nukeAll(roleNames []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking IAM Role", + }, map[string]interface{}{}) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/iam_role_test.go b/aws/resources/iam_role_test.go index 8349d6d4..64f1d907 100644 --- a/aws/resources/iam_role_test.go +++ b/aws/resources/iam_role_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -63,7 +64,7 @@ func (m mockedIAMRoles) DeleteRole(input *iam.DeleteRoleInput) (*iam.DeleteRoleO } func TestIAMRoles_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-role1" @@ -124,7 +125,7 @@ func TestIAMRoles_GetAll(t *testing.T) { } func TestIAMRoles_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ir := IAMRoles{ diff --git a/aws/resources/iam_service_linked_role.go b/aws/resources/iam_service_linked_role.go index 59e8f3f9..8e37ace3 100644 --- a/aws/resources/iam_service_linked_role.go +++ b/aws/resources/iam_service_linked_role.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "strings" "sync" "time" @@ -113,6 +115,9 @@ func (islr *IAMServiceLinkedRoles) nukeAll(roleNames []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking IAM Service Linked Role", + }, map[string]interface{}{}) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/iam_service_linked_role_test.go b/aws/resources/iam_service_linked_role_test.go index 4419795d..54b8eb9f 100644 --- a/aws/resources/iam_service_linked_role_test.go +++ b/aws/resources/iam_service_linked_role_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -33,7 +34,7 @@ func (m mockedIAMServiceLinkedRoles) GetServiceLinkedRoleDeletionStatus(input *i } func TestIAMServiceLinkedRoles_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -96,7 +97,7 @@ func TestIAMServiceLinkedRoles_GetAll(t *testing.T) { } func TestIAMServiceLinkedRoles_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() islr := IAMServiceLinkedRoles{ diff --git a/aws/resources/iam_test.go b/aws/resources/iam_test.go index 26043c2c..ce75592e 100644 --- a/aws/resources/iam_test.go +++ b/aws/resources/iam_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -119,7 +120,7 @@ func (m mockedIAMUsers) DeleteUser(input *iam.DeleteUserInput) (*iam.DeleteUserO } func TestIAMUsers_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -180,7 +181,7 @@ func TestIAMUsers_GetAll(t *testing.T) { } func TestIAMUsers_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() iu := IAMUsers{ diff --git a/aws/resources/kinesis_stream.go b/aws/resources/kinesis_stream.go index 2ebb34af..39dc6bde 100644 --- a/aws/resources/kinesis_stream.go +++ b/aws/resources/kinesis_stream.go @@ -4,6 +4,9 @@ import ( "context" "sync" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/kinesis" @@ -67,6 +70,11 @@ func (ks *KinesisStreams) nukeAll(identifiers []*string) error { for _, errChan := range errChans { if err := <-errChan; err != nil { if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() != "OperationAbortedException" { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Kinesis Stream", + }, map[string]interface{}{ + "region": ks.Region, + }) allErrs = multierror.Append(allErrs, err) } } diff --git a/aws/resources/kinesis_stream_test.go b/aws/resources/kinesis_stream_test.go index 674882ed..21aaf93e 100644 --- a/aws/resources/kinesis_stream_test.go +++ b/aws/resources/kinesis_stream_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/kinesis" "github.com/aws/aws-sdk-go/service/kinesis/kinesisiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -27,7 +28,7 @@ func (m mockedKinesisClient) DeleteStream(input *kinesis.DeleteStreamInput) (*ki } func TestKinesisStreams_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "stream1" @@ -71,7 +72,7 @@ func TestKinesisStreams_GetAll(t *testing.T) { } func TestKinesisStreams_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ks := KinesisStreams{ diff --git a/aws/resources/kms_customer_key.go b/aws/resources/kms_customer_key.go index adab29b9..487c2786 100644 --- a/aws/resources/kms_customer_key.go +++ b/aws/resources/kms_customer_key.go @@ -2,6 +2,8 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "github.com/gruntwork-io/cloud-nuke/config" @@ -194,6 +196,11 @@ func (kck *KmsCustomerKeys) nukeAll(keyIds []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking KMS Key", + }, map[string]interface{}{ + "region": kck.Region, + }) } } return errors.WithStackTrace(allErrs.ErrorOrNil()) diff --git a/aws/resources/kms_customer_key_test.go b/aws/resources/kms_customer_key_test.go index 0f3cbb34..85e78235 100644 --- a/aws/resources/kms_customer_key_test.go +++ b/aws/resources/kms_customer_key_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -47,7 +48,7 @@ func (m mockedKmsCustomerKeys) DeleteAlias(input *kms.DeleteAliasInput) (*kms.De } func TestKMS_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() key1 := "key1" @@ -139,7 +140,7 @@ func TestKMS_GetAll(t *testing.T) { } func TestKMS_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() kck := KmsCustomerKeys{ diff --git a/aws/resources/lambda.go b/aws/resources/lambda.go index ea6dc06d..a8adb5fa 100644 --- a/aws/resources/lambda.go +++ b/aws/resources/lambda.go @@ -10,6 +10,8 @@ import ( "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/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (lf *LambdaFunctions) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -79,6 +81,11 @@ func (lf *LambdaFunctions) nukeAll(names []*string) error { if err != nil { logging.Errorf("[Failed] %s: %s", *name, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Lambda Function", + }, map[string]interface{}{ + "region": lf.Region, + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted Lambda Function: %s", awsgo.StringValue(name)) diff --git a/aws/resources/lambda_layer.go b/aws/resources/lambda_layer.go index 5ddd77ea..af1ab74e 100644 --- a/aws/resources/lambda_layer.go +++ b/aws/resources/lambda_layer.go @@ -10,6 +10,8 @@ import ( "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/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (ll *LambdaLayers) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -130,6 +132,11 @@ func (ll *LambdaLayers) nukeAll(names []*string) error { if err != nil { logging.Logger.Errorf("[Failed] %s: %s", *params.LayerName, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Lambda Layer", + }, map[string]interface{}{ + "region": ll.Region, + }) } else { deletedNames = append(deletedNames, params.LayerName) logging.Logger.Debugf("Deleted Lambda Layer: %s", awsgo.StringValue(params.LayerName)) diff --git a/aws/resources/lambda_layer_test.go b/aws/resources/lambda_layer_test.go index a32caaa8..ce56ed9f 100644 --- a/aws/resources/lambda_layer_test.go +++ b/aws/resources/lambda_layer_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/lambda" "github.com/aws/aws-sdk-go/service/lambda/lambdaiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -31,7 +32,7 @@ func (m mockedLambdaLayer) ListLayerVersionsPages(input *lambda.ListLayerVersion } func TestLambdaLayer_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-lambda-layer1" @@ -111,7 +112,7 @@ func TestLambdaLayer_GetAll(t *testing.T) { } func TestLambdaLayer_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ll := LambdaLayers{ diff --git a/aws/resources/lambda_test.go b/aws/resources/lambda_test.go index c21a5d01..d9b3d0e1 100644 --- a/aws/resources/lambda_test.go +++ b/aws/resources/lambda_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/lambda" "github.com/aws/aws-sdk-go/service/lambda/lambdaiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -29,7 +30,7 @@ func (m mockedLambda) DeleteFunction(input *lambda.DeleteFunctionInput) (*lambda } func TestLambdaFunction_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-lambda-function1" @@ -95,7 +96,7 @@ func TestLambdaFunction_GetAll(t *testing.T) { } func TestLambdaFunction_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() lf := LambdaFunctions{ diff --git a/aws/resources/launch_config.go b/aws/resources/launch_config.go index 0efd0e08..82787778 100644 --- a/aws/resources/launch_config.go +++ b/aws/resources/launch_config.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a formatted string of Launch config Names @@ -58,6 +60,11 @@ func (lc *LaunchConfigs) nukeAll(configNames []*string) error { if err != nil { logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Launch Configuration", + }, map[string]interface{}{ + "region": lc.Region, + }) } else { deletedConfigNames = append(deletedConfigNames, configName) logging.Debugf("Deleted Launch configuration: %s", *configName) diff --git a/aws/resources/launch_config_test.go b/aws/resources/launch_config_test.go index 104acc73..888d6de1 100644 --- a/aws/resources/launch_config_test.go +++ b/aws/resources/launch_config_test.go @@ -4,6 +4,7 @@ import ( "context" "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -28,7 +29,7 @@ func (m mockedLaunchConfiguration) DeleteLaunchConfiguration(input *autoscaling. } func TestLaunchConfigurations_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-launch-config1" @@ -88,7 +89,7 @@ func TestLaunchConfigurations_GetAll(t *testing.T) { } func TestLaunchConfigurations_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() lc := LaunchConfigs{ diff --git a/aws/resources/launch_template.go b/aws/resources/launch_template.go index 0b1154b1..c23536c5 100644 --- a/aws/resources/launch_template.go +++ b/aws/resources/launch_template.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a formatted string of Launch Template Names @@ -57,6 +59,11 @@ func (lt *LaunchTemplates) nukeAll(templateNames []*string) error { if err != nil { logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Launch Template", + }, map[string]interface{}{ + "region": lt.Region, + }) } else { deletedTemplateNames = append(deletedTemplateNames, templateName) logging.Debugf("Deleted Launch template: %s", *templateName) diff --git a/aws/resources/launch_template_test.go b/aws/resources/launch_template_test.go index 11f7a1f2..32f49d88 100644 --- a/aws/resources/launch_template_test.go +++ b/aws/resources/launch_template_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -27,7 +28,7 @@ func (m mockedLaunchTemplate) DeleteLaunchTemplate(input *ec2.DeleteLaunchTempla } func TestLaunchTemplate_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -87,7 +88,7 @@ func TestLaunchTemplate_GetAll(t *testing.T) { } func TestLaunchTemplate_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() lt := LaunchTemplates{ diff --git a/aws/resources/macie.go b/aws/resources/macie.go index 1fb00c13..cb235704 100644 --- a/aws/resources/macie.go +++ b/aws/resources/macie.go @@ -3,6 +3,8 @@ package resources import ( "context" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "strings" "github.com/aws/aws-sdk-go/aws" @@ -96,11 +98,23 @@ func (mm *MacieMember) nukeAll(identifier []string) error { // Macie cannot be disabled with active member accounts memberAccountIds, err := mm.getAllMacieMembers() if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error finding macie member accounts", + }, map[string]interface{}{ + "region": mm.Region, + "reason": "Error finding macie member accounts", + }) } if err == nil && len(memberAccountIds) > 0 { err = mm.removeMacieMembers(memberAccountIds) if err != nil { logging.Errorf("[Failed] Failed to remove members from macie") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error removing members from macie", + }, map[string]interface{}{ + "region": mm.Region, + "reason": "Unable to remove members", + }) } } @@ -112,6 +126,12 @@ func (mm *MacieMember) nukeAll(identifier []string) error { logging.Debugf("No delegated Macie administrator found to remove.") } else { logging.Errorf("[Failed] Failed to check for administrator account") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error checking for administrator account in Macie", + }, map[string]interface{}{ + "region": mm.Region, + "reason": "Unable to find admin account", + }) } } @@ -120,6 +140,12 @@ func (mm *MacieMember) nukeAll(identifier []string) error { _, err := mm.Client.DisassociateFromAdministratorAccount(&macie2.DisassociateFromAdministratorAccountInput{}) if err != nil { logging.Errorf("[Failed] Failed to disassociate from administrator account") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error disassociating administrator account in Macie", + }, map[string]interface{}{ + "region": mm.Region, + "reason": "Unable to disassociate admin account", + }) } } @@ -127,6 +153,12 @@ func (mm *MacieMember) nukeAll(identifier []string) error { _, err = mm.Client.DisableMacie(&macie2.DisableMacieInput{}) if err != nil { logging.Errorf("[Failed] Failed to disable macie.") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking MACIE", + }, map[string]interface{}{ + "region": mm.Region, + "reason": "Error Nuking MACIE", + }) e := report.Entry{ Identifier: aws.StringValue(&identifier[0]), ResourceType: "Macie", diff --git a/aws/resources/macie_test.go b/aws/resources/macie_test.go index 0bfaffe4..eeb26cef 100644 --- a/aws/resources/macie_test.go +++ b/aws/resources/macie_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/macie2" "github.com/aws/aws-sdk-go/service/macie2/macie2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "testing" "time" @@ -51,7 +52,7 @@ func (m mockedMacie) DisableMacie(input *macie2.DisableMacieInput) (*macie2.Disa } func TestMacie_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -69,7 +70,7 @@ func TestMacie_GetAll(t *testing.T) { } func TestMacie_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() mm := MacieMember{ diff --git a/aws/resources/nat_gateway.go b/aws/resources/nat_gateway.go index 0942893e..2e1c4e6e 100644 --- a/aws/resources/nat_gateway.go +++ b/aws/resources/nat_gateway.go @@ -3,13 +3,17 @@ package resources import ( "context" "fmt" - "github.com/gruntwork-io/cloud-nuke/util" "sync" "time" - "github.com/aws/aws-sdk-go/aws" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" @@ -18,11 +22,10 @@ import ( "github.com/hashicorp/go-multierror" ) -func (ngw *NatGateways) getAll(c context.Context, configObj config.Config) ([]*string, error) { - allNatGateways := []*string{} - input := &ec2.DescribeNatGatewaysInput{} +func (ngw *NatGateways) getAll(_ context.Context, configObj config.Config) ([]*string, error) { + var allNatGateways []*string err := ngw.Client.DescribeNatGatewaysPages( - input, + &ec2.DescribeNatGatewaysInput{}, func(page *ec2.DescribeNatGatewaysOutput, lastPage bool) bool { for _, ngw := range page.NatGateways { if shouldIncludeNatGateway(ngw, configObj) { @@ -32,7 +35,6 @@ func (ngw *NatGateways) getAll(c context.Context, configObj config.Config) ([]*s return !lastPage }, ) - return allNatGateways, errors.WithStackTrace(err) } @@ -41,7 +43,7 @@ func shouldIncludeNatGateway(ngw *ec2.NatGateway, configObj config.Config) bool return false } - ngwState := aws.StringValue(ngw.State) + ngwState := awsgo.StringValue(ngw.State) if ngwState == ec2.NatGatewayStateDeleted || ngwState == ec2.NatGatewayStateDeleting { return false } @@ -55,7 +57,7 @@ func shouldIncludeNatGateway(ngw *ec2.NatGateway, configObj config.Config) bool func getNatGatewayName(ngw *ec2.NatGateway) *string { for _, tag := range ngw.Tags { - if aws.StringValue(tag.Key) == "Name" { + if awsgo.StringValue(tag.Key) == "Name" { return tag.Value } } @@ -95,6 +97,11 @@ func (ngw *NatGateways) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking NAT Gateway", + }, map[string]interface{}{ + "region": ngw.Region, + }) } } finalErr := allErrs.ErrorOrNil() @@ -123,7 +130,7 @@ func (ngw *NatGateways) nukeAll(identifiers []*string) error { return errors.WithStackTrace(err) } for _, ngwID := range identifiers { - logging.Debugf("[OK] NAT Gateway %s was deleted in %s", aws.StringValue(ngwID), ngw.Region) + logging.Debugf("[OK] NAT Gateway %s was deleted in %s", awsgo.StringValue(ngwID), ngw.Region) } return nil } @@ -149,7 +156,7 @@ func (ngw *NatGateways) areAllNatGatewaysDeleted(identifiers []*string) (bool, e continue } - if aws.StringValue(ngw.State) != ec2.NatGatewayStateDeleted { + if awsgo.StringValue(ngw.State) != ec2.NatGatewayStateDeleted { return false, nil } } @@ -162,12 +169,10 @@ func (ngw *NatGateways) areAllNatGatewaysDeleted(identifiers []*string) (bool, e func (ngw *NatGateways) deleteAsync(wg *sync.WaitGroup, errChan chan error, ngwID *string) { defer wg.Done() - input := &ec2.DeleteNatGatewayInput{NatGatewayId: ngwID} - _, err := ngw.Client.DeleteNatGateway(input) - + err := nukeNATGateway(ngw.Client, ngwID) // Record status of this resource e := report.Entry{ - Identifier: aws.StringValue(ngwID), + Identifier: awsgo.StringValue(ngwID), ResourceType: "NAT Gateway", Error: err, } @@ -183,3 +188,15 @@ type TooManyNatErr struct{} func (err TooManyNatErr) Error() string { return "Too many NAT Gateways requested at once." } + +func nukeNATGateway(client ec2iface.EC2API, gateway *string) error { + logging.Debugf("Deleting NAT gateway %s", awsgo.StringValue(gateway)) + + _, err := client.DeleteNatGateway(&ec2.DeleteNatGatewayInput{NatGatewayId: gateway}) + if err != nil { + logging.Debugf("[Failed] Error deleting NAT gateway %s: %s", awsgo.StringValue(gateway), err) + return errors.WithStackTrace(err) + } + logging.Debugf("[Ok] NAT Gateway deleted successfully %s", awsgo.StringValue(gateway)) + return nil +} diff --git a/aws/resources/nat_gateway_test.go b/aws/resources/nat_gateway_test.go index fcaf009d..2dbed128 100644 --- a/aws/resources/nat_gateway_test.go +++ b/aws/resources/nat_gateway_test.go @@ -4,6 +4,7 @@ import ( "context" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -35,7 +36,7 @@ func (m mockedNatGateway) DescribeNatGateways(input *ec2.DescribeNatGatewaysInpu } func TestNatGateway_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "test-nat-gateway-id1" @@ -109,7 +110,7 @@ func TestNatGateway_GetAll(t *testing.T) { } func TestNatGateway_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() ngw := NatGateways{ diff --git a/aws/resources/nat_gateway_types.go b/aws/resources/nat_gateway_types.go index 8431e89a..efdf8f54 100644 --- a/aws/resources/nat_gateway_types.go +++ b/aws/resources/nat_gateway_types.go @@ -33,21 +33,21 @@ func (ngw *NatGateways) ResourceIdentifiers() []string { return ngw.NatGatewayIDs } -func (secret NatGateways) MaxBatchSize() int { +func (ngw *NatGateways) MaxBatchSize() int { // Tentative batch size to ensure AWS doesn't throttle. Note that nat gateway does not support bulk delete, so // we will be deleting this many in parallel using go routines. We conservatively pick 10 here, both to limit // overloading the runtime and to avoid AWS throttling with many API calls. return 10 } -func (secret NatGateways) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { - identifiers, err := secret.getAll(c, configObj) +func (ngw *NatGateways) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { + identifiers, err := ngw.getAll(c, configObj) if err != nil { return nil, err } - secret.NatGatewayIDs = awsgo.StringValueSlice(identifiers) - return secret.NatGatewayIDs, nil + ngw.NatGatewayIDs = awsgo.StringValueSlice(identifiers) + return ngw.NatGatewayIDs, nil } // Nuke - nuke 'em all!!! diff --git a/aws/resources/oidc_provider.go b/aws/resources/oidc_provider.go index 5fd3bed7..f9612158 100644 --- a/aws/resources/oidc_provider.go +++ b/aws/resources/oidc_provider.go @@ -2,6 +2,8 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "time" @@ -158,6 +160,9 @@ func (oidcprovider *OIDCProviders) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking OIDC Provider", + }, map[string]interface{}{}) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/oidc_provider_test.go b/aws/resources/oidc_provider_test.go index f232cfa9..d804e0a0 100644 --- a/aws/resources/oidc_provider_test.go +++ b/aws/resources/oidc_provider_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/iam/iamiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -35,7 +36,7 @@ func (m mockedOIDCProvider) GetOpenIDConnectProvider(input *iam.GetOpenIDConnect } func TestOIDCProvider_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testArn1 := "test-arn1" @@ -102,7 +103,7 @@ func TestOIDCProvider_GetAll(t *testing.T) { } func TestOIDCProvider_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() oidcp := OIDCProviders{ diff --git a/aws/resources/opensearch.go b/aws/resources/opensearch.go index bb68839c..64cc431b 100644 --- a/aws/resources/opensearch.go +++ b/aws/resources/opensearch.go @@ -3,7 +3,9 @@ package resources import ( "context" "fmt" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "time" @@ -165,6 +167,11 @@ func (osd *OpenSearchDomains) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Opensearch", + }, map[string]interface{}{ + "region": osd.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/opensearch_test.go b/aws/resources/opensearch_test.go index cab53246..430da035 100644 --- a/aws/resources/opensearch_test.go +++ b/aws/resources/opensearch_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/opensearchservice" "github.com/aws/aws-sdk-go/service/opensearchservice/opensearchserviceiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" "regexp" @@ -39,7 +40,7 @@ func (m mockedOpenSearch) ListTags(*opensearchservice.ListTagsInput) (*opensearc // Test we can create an OpenSearch Domain, tag it, and then find the tag func TestOpenSearch_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-domain1" @@ -121,7 +122,7 @@ func TestOpenSearch_GetAll(t *testing.T) { } func TestOpenSearch_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() osd := OpenSearchDomains{ diff --git a/aws/resources/rds.go b/aws/resources/rds.go index f338cc73..0bbca8cc 100644 --- a/aws/resources/rds.go +++ b/aws/resources/rds.go @@ -8,8 +8,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (di *DBInstances) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -51,6 +53,11 @@ func (di *DBInstances) nukeAll(names []*string) error { _, err := di.Client.DeleteDBInstance(params) if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking RDS Instance", + }, map[string]interface{}{ + "region": di.Region, + }) logging.Errorf("[Failed] %s: %s", *name, err) } else { deletedNames = append(deletedNames, name) @@ -74,6 +81,11 @@ func (di *DBInstances) nukeAll(names []*string) error { report.Record(e) if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking RDS Instance", + }, map[string]interface{}{ + "region": di.Region, + }) logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } diff --git a/aws/resources/rds_cluster.go b/aws/resources/rds_cluster.go index 6e0cd226..259386f9 100644 --- a/aws/resources/rds_cluster.go +++ b/aws/resources/rds_cluster.go @@ -6,6 +6,7 @@ import ( "time" awsgo "github.com/aws/aws-sdk-go/aws" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -13,6 +14,7 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" ) @@ -82,6 +84,11 @@ func (instance *DBClusters) nukeAll(names []*string) error { if err != nil { logging.Debugf("[Failed] %s: %s", *name, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking RDS Cluster", + }, map[string]interface{}{ + "region": instance.Region, + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted RDS DB Cluster: %s", awsgo.StringValue(name)) diff --git a/aws/resources/rds_cluster_test.go b/aws/resources/rds_cluster_test.go index 4a71c425..54568709 100644 --- a/aws/resources/rds_cluster_test.go +++ b/aws/resources/rds_cluster_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/rds/rdsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/assert" ) @@ -34,7 +35,7 @@ func (m mockedDBClusters) DescribeDBClusters(input *rds.DescribeDBClustersInput) } func TestRDSClusterGetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-db-cluster" @@ -68,7 +69,7 @@ func TestRDSClusterGetAll(t *testing.T) { } func TestRDSClusterNukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-db-cluster" diff --git a/aws/resources/rds_snapshot_test.go b/aws/resources/rds_snapshot_test.go index 7425ee84..144b18c1 100644 --- a/aws/resources/rds_snapshot_test.go +++ b/aws/resources/rds_snapshot_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/rds/rdsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "regexp" @@ -29,7 +30,7 @@ func (m mockedRdsSnapshot) DeleteDBSnapshot(input *rds.DeleteDBSnapshotInput) (* } func TestRdsSnapshot_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name1" @@ -89,7 +90,7 @@ func TestRdsSnapshot_GetAll(t *testing.T) { } func TestRdsSnapshot_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName := "test-db-cluster" diff --git a/aws/resources/rds_subnet_group.go b/aws/resources/rds_subnet_group.go index 13e24f76..cbdf569b 100644 --- a/aws/resources/rds_subnet_group.go +++ b/aws/resources/rds_subnet_group.go @@ -11,7 +11,9 @@ import ( "github.com/aws/aws-sdk-go/service/rds" "github.com/gruntwork-io/cloud-nuke/logging" "github.com/gruntwork-io/cloud-nuke/report" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (dsg *DBSubnetGroups) waitUntilRdsDbSubnetGroupDeleted(name *string) error { @@ -79,6 +81,11 @@ func (dsg *DBSubnetGroups) nukeAll(names []*string) error { if err != nil { logging.Debugf("[Failed] %s: %s", *name, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking RDS DB subnet group", + }, map[string]interface{}{ + "region": dsg.Region, + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted RDS DB subnet group: %s", awsgo.StringValue(name)) diff --git a/aws/resources/rds_subnet_group_test.go b/aws/resources/rds_subnet_group_test.go index 72e55976..6f6bec18 100644 --- a/aws/resources/rds_subnet_group_test.go +++ b/aws/resources/rds_subnet_group_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/rds/rdsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -33,7 +34,7 @@ func (m mockedDBSubnetGroups) DeleteDBSubnetGroup(*rds.DeleteDBSubnetGroupInput) } func TestDBSubnetGroups_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-db-subnet-group1" @@ -84,7 +85,7 @@ func TestDBSubnetGroups_GetAll(t *testing.T) { } func TestDBSubnetGroups_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() dsg := DBSubnetGroups{ diff --git a/aws/resources/rds_test.go b/aws/resources/rds_test.go index d4454e82..7673e6cf 100644 --- a/aws/resources/rds_test.go +++ b/aws/resources/rds_test.go @@ -5,6 +5,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/rds/rdsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "regexp" "testing" "time" @@ -34,7 +35,7 @@ func (m mockedDBInstance) WaitUntilDBInstanceDeleted(*rds.DescribeDBInstancesInp } func TestDBInstances_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-db-instance1" @@ -99,7 +100,7 @@ func TestDBInstances_GetAll(t *testing.T) { } func TestDBInstances_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() di := DBInstances{ diff --git a/aws/resources/redshift.go b/aws/resources/redshift.go index 96ca76e4..344acffe 100644 --- a/aws/resources/redshift.go +++ b/aws/resources/redshift.go @@ -7,7 +7,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (rc *RedshiftClusters) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -44,6 +46,11 @@ func (rc *RedshiftClusters) nukeAll(identifiers []*string) error { SkipFinalClusterSnapshot: aws.Bool(true), }) if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking RedshiftCluster", + }, map[string]interface{}{ + "region": rc.Region, + }) logging.Errorf("[Failed] %s: %s", *id, err) } else { deletedIds = append(deletedIds, id) @@ -62,6 +69,11 @@ func (rc *RedshiftClusters) nukeAll(identifiers []*string) error { } report.Record(e) if err != nil { + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Redshift Cluster", + }, map[string]interface{}{ + "region": rc.Region, + }) logging.Errorf("[Failed] %s", err) return errors.WithStackTrace(err) } diff --git a/aws/resources/redshift_test.go b/aws/resources/redshift_test.go index 818384d6..544b3bef 100644 --- a/aws/resources/redshift_test.go +++ b/aws/resources/redshift_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/redshift" "github.com/aws/aws-sdk-go/service/redshift/redshiftiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -33,7 +34,7 @@ func (m mockedRedshift) WaitUntilClusterDeleted(*redshift.DescribeClustersInput) } func TestRedshiftCluster_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -93,7 +94,7 @@ func TestRedshiftCluster_GetAll(t *testing.T) { } func TestRedshiftCluster_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := RedshiftClusters{ diff --git a/aws/resources/route53_cidr_collection_test.go b/aws/resources/route53_cidr_collection_test.go index b37a161f..2bddf536 100644 --- a/aws/resources/route53_cidr_collection_test.go +++ b/aws/resources/route53_cidr_collection_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go/service/route53/route53iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -35,7 +36,7 @@ func (mock mockedR53CidrCollection) DeleteCidrCollection(_ *route53.DeleteCidrCo } func TestR53CidrCollection_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "d8c6f2db-89dd-5533-f30c-13e28eba8818" @@ -91,7 +92,7 @@ func TestR53CidrCollection_GetAll(t *testing.T) { } func TestR53CidrCollection_Nuke(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := Route53CidrCollection{ diff --git a/aws/resources/route53_hostedzone_test.go b/aws/resources/route53_hostedzone_test.go index 75289941..eb12b12f 100644 --- a/aws/resources/route53_hostedzone_test.go +++ b/aws/resources/route53_hostedzone_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go/service/route53/route53iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -27,7 +28,7 @@ func (mock mockedR53HostedZone) DeleteHostedZone(_ *route53.DeleteHostedZoneInpu } func TestR53HostedZone_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "d8c6f2db-89dd-5533-f30c-13e28eba8818" @@ -83,7 +84,7 @@ func TestR53HostedZone_GetAll(t *testing.T) { } func TestR53HostedZone_Nuke(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := Route53HostedZone{ diff --git a/aws/resources/route53_traffic_policy_test.go b/aws/resources/route53_traffic_policy_test.go index d85be3db..871b590f 100644 --- a/aws/resources/route53_traffic_policy_test.go +++ b/aws/resources/route53_traffic_policy_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go/service/route53/route53iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -27,7 +28,7 @@ func (mock mockedR53TrafficPolicy) DeleteTrafficPolicy(_ *route53.DeleteTrafficP } func TestR53TrafficPolicy_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testId1 := "d8c6f2db-89dd-5533-f30c-13e28eba8818" @@ -86,7 +87,7 @@ func TestR53TrafficPolicy_GetAll(t *testing.T) { } func TestR53TrafficPolicy_Nuke(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := Route53TrafficPolicy{ diff --git a/aws/resources/s3.go b/aws/resources/s3.go index 30c2c028..d912ca15 100644 --- a/aws/resources/s3.go +++ b/aws/resources/s3.go @@ -7,15 +7,20 @@ import ( "sync" "time" + "github.com/gruntwork-io/cloud-nuke/report" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + + "github.com/hashicorp/go-multierror" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/s3" + "github.com/gruntwork-io/go-commons/errors" + "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/cloud-nuke/util" - "github.com/gruntwork-io/go-commons/errors" - "github.com/hashicorp/go-multierror" ) const AwsResourceExclusionTagKey = "cloud-nuke-excluded" @@ -451,6 +456,11 @@ func (sb S3Buckets) nukeAll(bucketNames []*string) (delCount int, err error) { if err != nil { logging.Debugf("[Failed] - %d/%d - Bucket: %s - bucket deletion error - %s", bucketIndex+1, totalCount, *bucketName, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking S3 Bucket", + }, map[string]interface{}{ + "region": sb.Region, + }) } else { deleted = append(deleted, bucketName) logging.Debugf("[OK] - %d/%d - Bucket: %s - deleted", bucketIndex+1, totalCount, *bucketName) diff --git a/aws/resources/s3_access_point_test.go b/aws/resources/s3_access_point_test.go index 8b4e5863..ae03c993 100644 --- a/aws/resources/s3_access_point_test.go +++ b/aws/resources/s3_access_point_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3control" "github.com/aws/aws-sdk-go/service/s3control/s3controliface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func (m mocks3AccessPoint) DeleteAccessPoint(_ *s3control.DeleteAccessPointInput } func TestS3AccessPoint_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName01 := "test-access-point-01" @@ -84,7 +85,7 @@ func TestS3AccessPoint_GetAll(t *testing.T) { } func TestS3AccessPoint_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := S3AccessPoint{ diff --git a/aws/resources/s3_multi_region_access_point_test.go b/aws/resources/s3_multi_region_access_point_test.go index 9a796f22..c3d9effc 100644 --- a/aws/resources/s3_multi_region_access_point_test.go +++ b/aws/resources/s3_multi_region_access_point_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3control" "github.com/aws/aws-sdk-go/service/s3control/s3controliface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -29,7 +30,7 @@ func (m mockS3MultiRegionAccessPoint) DeleteMultiRegionAccessPoint(_ *s3control. } func TestS3MultiRegionAccessPoint_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName01 := "test-access-point-01" @@ -97,7 +98,7 @@ func TestS3MultiRegionAccessPoint_GetAll(t *testing.T) { } func TestS3MultiRegionAccessPoint_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := S3MultiRegionAccessPoint{ diff --git a/aws/resources/s3_object_lambda_access_point_test.go b/aws/resources/s3_object_lambda_access_point_test.go index f1bd8032..fc6f478e 100644 --- a/aws/resources/s3_object_lambda_access_point_test.go +++ b/aws/resources/s3_object_lambda_access_point_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3control" "github.com/aws/aws-sdk-go/service/s3control/s3controliface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func (m mocks3ObjectLambdaAccessPoint) DeleteAccessPointForObjectLambda(_ *s3con } func TestS3ObjectLambdaAccessPoint_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName01 := "test-access-point-01" @@ -84,7 +85,7 @@ func TestS3ObjectLambdaAccessPoint_GetAll(t *testing.T) { } func TestS3ObjectLambdaAccessPoint_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() rc := S3ObjectLambdaAccessPoint{ diff --git a/aws/resources/s3_test.go b/aws/resources/s3_test.go index 67704beb..627b5c90 100644 --- a/aws/resources/s3_test.go +++ b/aws/resources/s3_test.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -64,7 +65,7 @@ func (m mockedS3Buckets) DeleteBucketWithContext(aws.Context, *s3.DeleteBucketIn } func TestS3Bucket_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-bucket-1" @@ -135,7 +136,7 @@ func TestS3Bucket_GetAll(t *testing.T) { } func TestS3Bucket_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() sb := S3Buckets{ diff --git a/aws/resources/sagemaker_notebook_instance.go b/aws/resources/sagemaker_notebook_instance.go index 78a19e83..de8c4b9a 100644 --- a/aws/resources/sagemaker_notebook_instance.go +++ b/aws/resources/sagemaker_notebook_instance.go @@ -8,7 +8,9 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) func (smni *SageMakerNotebookInstances) getAll(c context.Context, configObj config.Config) ([]*string, error) { @@ -46,6 +48,12 @@ func (smni *SageMakerNotebookInstances) nukeAll(names []*string) error { }) if err != nil { logging.Errorf("[Failed] %s: %s", *name, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Sagemaker Notebook Instance", + }, map[string]interface{}{ + "region": smni.Region, + "reason": "Failed to Stop Notebook", + }) } err = smni.Client.WaitUntilNotebookInstanceStopped(&sagemaker.DescribeNotebookInstanceInput{ @@ -53,6 +61,12 @@ func (smni *SageMakerNotebookInstances) nukeAll(names []*string) error { }) if err != nil { logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Sagemaker Notebook Instance", + }, map[string]interface{}{ + "region": smni.Region, + "reason": "Failed waiting for notebook to stop", + }) } _, err = smni.Client.DeleteNotebookInstance(&sagemaker.DeleteNotebookInstanceInput{ @@ -61,6 +75,12 @@ func (smni *SageMakerNotebookInstances) nukeAll(names []*string) error { if err != nil { logging.Errorf("[Failed] %s: %s", *name, err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Sagemaker Notebook Instance", + }, map[string]interface{}{ + "region": smni.Region, + "reason": "Failed to Delete Notebook", + }) } else { deletedNames = append(deletedNames, name) logging.Debugf("Deleted Sagemaker Notebook Instance: %s", awsgo.StringValue(name)) @@ -84,6 +104,12 @@ func (smni *SageMakerNotebookInstances) nukeAll(names []*string) error { if err != nil { logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Sagemaker Notebook Instance", + }, map[string]interface{}{ + "region": smni.Region, + "reason": "Failed waiting for notebook instance to delete", + }) return errors.WithStackTrace(err) } } diff --git a/aws/resources/sagemaker_notebook_instance_test.go b/aws/resources/sagemaker_notebook_instance_test.go index 59bfab58..49c4caf8 100644 --- a/aws/resources/sagemaker_notebook_instance_test.go +++ b/aws/resources/sagemaker_notebook_instance_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/sagemaker" "github.com/aws/aws-sdk-go/service/sagemaker/sagemakeriface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -45,7 +46,7 @@ func (m mockedSageMakerNotebookInstance) DeleteNotebookInstance(input *sagemaker } func TestSageMakerNotebookInstances_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -106,7 +107,7 @@ func TestSageMakerNotebookInstances_GetAll(t *testing.T) { } func TestSageMakerNotebookInstances_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() smni := SageMakerNotebookInstances{ diff --git a/aws/resources/secrets_manager.go b/aws/resources/secrets_manager.go index d66f7d83..ae2d9376 100644 --- a/aws/resources/secrets_manager.go +++ b/aws/resources/secrets_manager.go @@ -2,6 +2,8 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "sync" "time" @@ -75,6 +77,11 @@ func (sms *SecretsManagerSecrets) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Secrets Manager Secret", + }, map[string]interface{}{ + "region": sms.Region, + }) } } return errors.WithStackTrace(allErrs.ErrorOrNil()) diff --git a/aws/resources/secrets_manager_test.go b/aws/resources/secrets_manager_test.go index 77410e94..07b7fb90 100644 --- a/aws/resources/secrets_manager_test.go +++ b/aws/resources/secrets_manager_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "testing" @@ -38,7 +39,7 @@ func (m mockedSecretsManager) RemoveRegionsFromReplication(input *secretsmanager } func TestSecretsManagerSecrets_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testName1 := "test-name-1" @@ -102,7 +103,7 @@ func TestSecretsManagerSecrets_GetAll(t *testing.T) { } func TestSecretsManagerSecrets_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() sms := SecretsManagerSecrets{ diff --git a/aws/resources/security_group.go b/aws/resources/security_group.go index c20abb69..92f0905d 100644 --- a/aws/resources/security_group.go +++ b/aws/resources/security_group.go @@ -2,10 +2,12 @@ package resources import ( "context" + "fmt" "time" - "github.com/aws/aws-sdk-go/aws" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" r "github.com/gruntwork-io/cloud-nuke/report" // Alias the package as 'r' @@ -18,8 +20,8 @@ func (sg *SecurityGroup) setFirstSeenTag(securityGroup ec2.SecurityGroup, value Resources: []*string{securityGroup.GroupId}, Tags: []*ec2.Tag{ { - Key: aws.String(util.FirstSeenTagKey), - Value: aws.String(util.FormatTimestamp(value)), + Key: awsgo.String(util.FirstSeenTagKey), + Value: awsgo.String(util.FormatTimestamp(value)), }, }, }) @@ -73,8 +75,8 @@ func (sg *SecurityGroup) getAll(_ context.Context, configObj config.Config) ([]* logging.Debugf("[default only] Retrieving the default security-groups") filters = []*ec2.Filter{ { - Name: aws.String("group-name"), - Values: aws.StringSlice([]string{"default"}), + Name: awsgo.String("group-name"), + Values: awsgo.StringSlice([]string{"default"}), }, } } @@ -115,7 +117,7 @@ func (sg *SecurityGroup) getAll(_ context.Context, configObj config.Config) ([]* sg.VerifyNukablePermissions(identifiers, func(id *string) error { _, err := sg.Client.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{ GroupId: id, - DryRun: aws.Bool(true), + DryRun: awsgo.Bool(true), }) return err }) @@ -132,12 +134,12 @@ func (sg *SecurityGroup) nuke(id *string) error { // check the nuking is only for default security groups, then nuke and return if sg.NukeOnlyDefault { // RevokeSecurityGroupIngress - if err := sg.RevokeSecurityGroupIngress(*id); err != nil { + if err := revokeSecurityGroupIngress(sg.Client, id); err != nil { return errors.WithStackTrace(err) } // RevokeSecurityGroupEgress - if err := sg.RevokeSecurityGroupEgress(*id); err != nil { + if err := revokeSecurityGroupEgress(sg.Client, id); err != nil { return errors.WithStackTrace(err) } @@ -150,21 +152,22 @@ func (sg *SecurityGroup) nuke(id *string) error { } // nuke the securiy group which is not default one - if err := sg.nukeSecurityGroup(*id); err != nil { + if err := nukeSecurityGroup(sg.Client, id); err != nil { return errors.WithStackTrace(err) } return nil } -func (sg *SecurityGroup) RevokeSecurityGroupIngress(id string) error { - _, err := sg.Client.RevokeSecurityGroupIngress(&ec2.RevokeSecurityGroupIngressInput{ - GroupId: aws.String(id), +func revokeSecurityGroupIngress(client ec2iface.EC2API, id *string) error { + logging.Debug(fmt.Sprintf("Start revoking security groups ingress rule : %s", awsgo.StringValue(id))) + _, err := client.RevokeSecurityGroupIngress(&ec2.RevokeSecurityGroupIngressInput{ + GroupId: id, IpPermissions: []*ec2.IpPermission{ { - IpProtocol: aws.String("-1"), - FromPort: aws.Int64(0), - ToPort: aws.Int64(0), - UserIdGroupPairs: []*ec2.UserIdGroupPair{{GroupId: aws.String(id)}}, + IpProtocol: awsgo.String("-1"), + FromPort: awsgo.Int64(0), + ToPort: awsgo.Int64(0), + UserIdGroupPairs: []*ec2.UserIdGroupPair{{GroupId: id}}, }, }, }) @@ -174,22 +177,24 @@ func (sg *SecurityGroup) RevokeSecurityGroupIngress(id string) error { return nil } - logging.Debugf("[Security Group] Failed to revoke security group ingress associated with security group %s: %s", id, err) + logging.Debugf("[Security Group] Failed to revoke security group ingress associated with security group %s: %s", awsgo.StringValue(id), err) return errors.WithStackTrace(err) } - + logging.Debugf("Successfully revoked security group ingress rule: %s", awsgo.StringValue(id)) return nil } -func (sg *SecurityGroup) RevokeSecurityGroupEgress(id string) error { - _, err := sg.Client.RevokeSecurityGroupEgress(&ec2.RevokeSecurityGroupEgressInput{ - GroupId: aws.String(id), +func revokeSecurityGroupEgress(client ec2iface.EC2API, id *string) error { + logging.Debugf("Start revoking security groups ingress rule : %s", awsgo.StringValue(id)) + + _, err := client.RevokeSecurityGroupEgress(&ec2.RevokeSecurityGroupEgressInput{ + GroupId: (id), IpPermissions: []*ec2.IpPermission{ { - IpProtocol: aws.String("-1"), - FromPort: aws.Int64(0), - ToPort: aws.Int64(0), - IpRanges: []*ec2.IpRange{{CidrIp: aws.String("0.0.0.0/0")}}, + IpProtocol: awsgo.String("-1"), + FromPort: awsgo.Int64(0), + ToPort: awsgo.Int64(0), + IpRanges: []*ec2.IpRange{{CidrIp: awsgo.String("0.0.0.0/0")}}, }, }, }) @@ -199,22 +204,24 @@ func (sg *SecurityGroup) RevokeSecurityGroupEgress(id string) error { return nil } - logging.Debugf("[Security Group] Failed to revoke security group egress associated with security group %s: %s", id, err) + logging.Debugf("[Security Group] Failed to revoke security group egress associated with security group %s: %s", awsgo.StringValue(id), err) return errors.WithStackTrace(err) } + logging.Debugf("Successfully revoked security group egress rule: %s", awsgo.StringValue(id)) + return nil } func (sg *SecurityGroup) RevokeIPv6SecurityGroupEgress(id string) error { _, err := sg.Client.RevokeSecurityGroupEgress(&ec2.RevokeSecurityGroupEgressInput{ - GroupId: aws.String(id), + GroupId: awsgo.String(id), IpPermissions: []*ec2.IpPermission{ { - IpProtocol: aws.String("-1"), - FromPort: aws.Int64(0), - ToPort: aws.Int64(0), - Ipv6Ranges: []*ec2.Ipv6Range{{CidrIpv6: aws.String("::/0")}}, + IpProtocol: awsgo.String("-1"), + FromPort: awsgo.Int64(0), + ToPort: awsgo.Int64(0), + Ipv6Ranges: []*ec2.Ipv6Range{{CidrIpv6: awsgo.String("::/0")}}, }, }, }) @@ -236,8 +243,8 @@ func (sg *SecurityGroup) terminateInstancesAssociatedWithSecurityGroup(id string resp, err := sg.Client.DescribeInstances(&ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ { - Name: aws.String("instance.group-id"), - Values: []*string{aws.String(id)}, + Name: awsgo.String("instance.group-id"), + Values: []*string{awsgo.String(id)}, }, }, }) @@ -248,7 +255,7 @@ func (sg *SecurityGroup) terminateInstancesAssociatedWithSecurityGroup(id string for _, reservation := range resp.Reservations { for _, instance := range reservation.Instances { - instanceID := aws.StringValue(instance.InstanceId) + instanceID := awsgo.StringValue(instance.InstanceId) // Needs to release the elastic ips attached on the instance before nuking if err := sg.releaseEIPs([]*string{instance.InstanceId}); err != nil { @@ -258,7 +265,7 @@ func (sg *SecurityGroup) terminateInstancesAssociatedWithSecurityGroup(id string // terminating the instances which used this security group if _, err := sg.Client.TerminateInstances(&ec2.TerminateInstancesInput{ - InstanceIds: []*string{aws.String(instanceID)}, + InstanceIds: []*string{awsgo.String(instanceID)}, }); err != nil { logging.Debugf("[Failed] Ec2 termination %s", err) return errors.WithStackTrace(err) @@ -268,7 +275,7 @@ func (sg *SecurityGroup) terminateInstancesAssociatedWithSecurityGroup(id string // wait until the instance terminated. if err := sg.Client.WaitUntilInstanceTerminated(&ec2.DescribeInstancesInput{ - InstanceIds: []*string{aws.String(instanceID)}, + InstanceIds: []*string{awsgo.String(instanceID)}, }); err != nil { logging.Debugf("[Security Group] Failed to terminate instance %s associated with security group %s: %s", instanceID, id, err) return errors.WithStackTrace(err) @@ -289,7 +296,7 @@ func (sg *SecurityGroup) releaseEIPs(instanceIds []*string) error { output, err := sg.Client.DescribeAddresses(&ec2.DescribeAddressesInput{ Filters: []*ec2.Filter{ { - Name: aws.String("instance-id"), + Name: awsgo.String("instance-id"), Values: []*string{ instanceID, }, @@ -315,15 +322,16 @@ func (sg *SecurityGroup) releaseEIPs(instanceIds []*string) error { return nil } -func (sg *SecurityGroup) nukeSecurityGroup(id string) error { - if _, err := sg.Client.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{ - GroupId: aws.String(id), +func nukeSecurityGroup(client ec2iface.EC2API, id *string) error { + logging.Debugf("Deleting security group %s", awsgo.StringValue(id)) + + if _, err := client.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{ + GroupId: id, }); err != nil { - logging.Debugf("[Security Group] Failed to delete security group %s: %s", id, err) + logging.Debugf("[Security Group] Failed to delete security group %s: %s", awsgo.StringValue(id), err) return errors.WithStackTrace(err) } - logging.Debugf("Deleted security group %s", id) - + logging.Debugf("Deleted security group %s", awsgo.StringValue(id)) return nil } @@ -346,7 +354,7 @@ func (sg *SecurityGroup) nukeAll(identifiers []*string) error { err := sg.nuke(id) // Record status of this resource e := r.Entry{ - Identifier: aws.StringValue(id), + Identifier: awsgo.StringValue(id), ResourceType: "Security Group", Error: err, } diff --git a/aws/resources/security_group_test.go b/aws/resources/security_group_test.go index aa912c2a..2e9d5cbc 100644 --- a/aws/resources/security_group_test.go +++ b/aws/resources/security_group_test.go @@ -10,6 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/stretchr/testify/require" ) @@ -130,7 +131,7 @@ func TestSecurityGroup_GetAll(t *testing.T) { } func Test_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() er := SecurityGroup{ diff --git a/aws/resources/security_hub.go b/aws/resources/security_hub.go index 849e8a36..cdade3c5 100644 --- a/aws/resources/security_hub.go +++ b/aws/resources/security_hub.go @@ -8,8 +8,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" "strings" ) @@ -100,7 +102,12 @@ func (sh *SecurityHub) nukeAll(securityHubArns []string) error { // Security Hub cannot be disabled with active member accounts memberAccountIds, err := sh.getAllSecurityHubMembers() if err != nil { - return err + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error finding security hub member accounts", + }, map[string]interface{}{ + "region": sh.Region, + "reason": "Error finding security hub member accounts", + }) } // Remove any member accounts if they exist @@ -108,6 +115,12 @@ func (sh *SecurityHub) nukeAll(securityHubArns []string) error { err = sh.removeMembersFromHub(memberAccountIds) if err != nil { logging.Errorf("[Failed] Failed to disassociate members from security hub") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error disassociating members from security hub", + }, map[string]interface{}{ + "region": sh.Region, + "reason": "Unable to disassociate", + }) } } @@ -116,6 +129,12 @@ func (sh *SecurityHub) nukeAll(securityHubArns []string) error { adminAccount, err := sh.Client.GetAdministratorAccount(&securityhub.GetAdministratorAccountInput{}) if err != nil { logging.Errorf("[Failed] Failed to check for administrator account") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error checking for administrator account in security hub", + }, map[string]interface{}{ + "region": sh.Region, + "reason": "Unable to find admin account", + }) } // Disassociate administrator account if it exists @@ -123,6 +142,12 @@ func (sh *SecurityHub) nukeAll(securityHubArns []string) error { _, err := sh.Client.DisassociateFromAdministratorAccount(&securityhub.DisassociateFromAdministratorAccountInput{}) if err != nil { logging.Errorf("[Failed] Failed to disassociate from administrator account") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error disassociating administrator account in security hub", + }, map[string]interface{}{ + "region": sh.Region, + "reason": "Unable to disassociate admin account", + }) } } @@ -130,6 +155,12 @@ func (sh *SecurityHub) nukeAll(securityHubArns []string) error { _, err = sh.Client.DisableSecurityHub(&securityhub.DisableSecurityHubInput{}) if err != nil { logging.Errorf("[Failed] Failed to disable security hub.") + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error disabling security hub", + }, map[string]interface{}{ + "region": sh.Region, + "reason": "Error disabling security hub", + }) e := report.Entry{ Identifier: aws.StringValue(&securityHubArns[0]), ResourceType: "Security Hub", diff --git a/aws/resources/security_hub_test.go b/aws/resources/security_hub_test.go index a25cc3fe..d10eff65 100644 --- a/aws/resources/security_hub_test.go +++ b/aws/resources/security_hub_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/securityhub" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -52,7 +53,7 @@ func (m mockedSecurityHub) DisableSecurityHub(*securityhub.DisableSecurityHubInp } func TestSecurityHub_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -95,7 +96,7 @@ func TestSecurityHub_GetAll(t *testing.T) { } func TestSecurityHub_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() sh := SecurityHub{ diff --git a/aws/resources/snapshot.go b/aws/resources/snapshot.go index 32db2bca..10c2d65d 100644 --- a/aws/resources/snapshot.go +++ b/aws/resources/snapshot.go @@ -2,13 +2,16 @@ package resources import ( "context" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/gruntwork-io/cloud-nuke/util" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" - "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/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" ) @@ -87,6 +90,11 @@ func (s *Snapshots) nukeAll(snapshotIds []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking EBS Snapshot", + }, map[string]interface{}{ + "region": s.Region, + }) } else { deletedSnapshotIDs = append(deletedSnapshotIDs, snapshotID) logging.Debugf("Deleted Snapshot: %s", *snapshotID) diff --git a/aws/resources/snapshot_test.go b/aws/resources/snapshot_test.go index 1de92036..9c8d67bd 100644 --- a/aws/resources/snapshot_test.go +++ b/aws/resources/snapshot_test.go @@ -5,6 +5,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "testing" "time" @@ -28,7 +29,7 @@ func (m mockedSnapshot) DescribeSnapshots(input *ec2.DescribeSnapshotsInput) (*e } func TestSnapshot_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testSnapshot1 := "test-snapshot1" @@ -86,7 +87,7 @@ func TestSnapshot_GetAll(t *testing.T) { } func TestSnapshot_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() s := Snapshots{ diff --git a/aws/resources/sns.go b/aws/resources/sns.go index d5e5509e..3cbacd03 100644 --- a/aws/resources/sns.go +++ b/aws/resources/sns.go @@ -8,6 +8,9 @@ import ( "sync" "time" + "github.com/gruntwork-io/cloud-nuke/telemetry" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" + "github.com/aws/aws-sdk-go/aws" "github.com/gruntwork-io/cloud-nuke/config" "github.com/gruntwork-io/cloud-nuke/logging" @@ -147,6 +150,11 @@ func (s *SNSTopic) nukeAll(identifiers []*string) error { if err := <-errChan; err != nil { allErrs = multierror.Append(allErrs, err) logging.Errorf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking SNS Topic", + }, map[string]interface{}{ + "region": s.Region, + }) } } finalErr := allErrs.ErrorOrNil() diff --git a/aws/resources/sns_test.go b/aws/resources/sns_test.go index c441bebc..fa25a7b1 100644 --- a/aws/resources/sns_test.go +++ b/aws/resources/sns_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/gruntwork-io/cloud-nuke/telemetry" + "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/sns" @@ -38,7 +40,7 @@ func (m mockedSNSTopic) DeleteTopic(input *sns.DeleteTopicInput) (*sns.DeleteTop } func TestSNS_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() testTopic1 := "arn:aws:sns:us-east-1:123456789012:MyTopic1" @@ -106,7 +108,7 @@ func TestSNS_GetAll(t *testing.T) { } func TestSNS_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() s := SNSTopic{ diff --git a/aws/resources/sqs.go b/aws/resources/sqs.go index f9d433d1..33ae949b 100644 --- a/aws/resources/sqs.go +++ b/aws/resources/sqs.go @@ -2,15 +2,17 @@ package resources import ( "context" + "strconv" + "time" "github.com/aws/aws-sdk-go/aws" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/sqs" "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/cloud-nuke/telemetry" "github.com/gruntwork-io/go-commons/errors" - "strconv" - "time" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // Returns a formatted string of SQS Queue URLs @@ -87,6 +89,11 @@ func (sq *SqsQueue) nukeAll(urls []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking SQS Queue", + }, map[string]interface{}{ + "region": sq.Region, + }) } else { deletedUrls = append(deletedUrls, url) logging.Debugf("Deleted SQS Queue: %s", *url) diff --git a/aws/resources/sqs_test.go b/aws/resources/sqs_test.go index 04f37fcb..d68395cf 100644 --- a/aws/resources/sqs_test.go +++ b/aws/resources/sqs_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/sqs" "github.com/aws/aws-sdk-go/service/sqs/sqsiface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" "regexp" "strconv" @@ -38,7 +39,7 @@ func (m mockedSqsQueue) DeleteQueue(*sqs.DeleteQueueInput) (*sqs.DeleteQueueOutp } func TestSqsQueue_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() queue1 := "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue1" @@ -104,7 +105,7 @@ func TestSqsQueue_GetAll(t *testing.T) { } func TestSqsQueue_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() sq := SqsQueue{ diff --git a/aws/resources/transit_gateway.go b/aws/resources/transit_gateway.go index 8f816b8b..b610f10a 100644 --- a/aws/resources/transit_gateway.go +++ b/aws/resources/transit_gateway.go @@ -11,8 +11,10 @@ import ( "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/cloud-nuke/telemetry" "github.com/gruntwork-io/cloud-nuke/util" "github.com/gruntwork-io/go-commons/errors" + commonTelemetry "github.com/gruntwork-io/go-commons/telemetry" ) // [Note 1] : NOTE on the Apporach used:-Using the `dry run` approach on verifying the nuking permission in case of a scoped IAM role. @@ -95,6 +97,11 @@ func (tgw *TransitGateways) nukeAll(ids []*string) error { if err != nil { logging.Debugf("[Failed] %s", err) + telemetry.TrackEvent(commonTelemetry.EventContext{ + EventName: "Error Nuking Transit Gateway Instance", + }, map[string]interface{}{ + "region": tgw.Region, + }) } else { deletedIds = append(deletedIds, id) logging.Debugf("Deleted Transit Gateway: %s", *id) diff --git a/aws/resources/transit_gateway_test.go b/aws/resources/transit_gateway_test.go index 628d1ed8..0be916a8 100644 --- a/aws/resources/transit_gateway_test.go +++ b/aws/resources/transit_gateway_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/telemetry" "github.com/stretchr/testify/require" ) @@ -79,7 +80,7 @@ func (m mockedTransitGatewayVpcAttachment) DeleteTransitGatewayVpcAttachment( } func TestTransitGateways_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -134,7 +135,7 @@ func TestTransitGateways_GetAll(t *testing.T) { } func TestTransitGateways_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() tgw := TransitGateways{ @@ -148,7 +149,7 @@ func TestTransitGateways_NukeAll(t *testing.T) { } func TestTransitGatewayRouteTables_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -200,7 +201,7 @@ func TestTransitGatewayRouteTables_GetAll(t *testing.T) { } func TestTransitGatewayRouteTables_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() tgw := TransitGatewaysRouteTables{ @@ -214,7 +215,7 @@ func TestTransitGatewayRouteTables_NukeAll(t *testing.T) { } func TestTransitGatewayVpcAttachments_GetAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -266,7 +267,7 @@ func TestTransitGatewayVpcAttachments_GetAll(t *testing.T) { } func TestTransitGatewayVpcAttachments_NukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() tgw := TransitGatewaysVpcAttachment{ @@ -280,7 +281,7 @@ func TestTransitGatewayVpcAttachments_NukeAll(t *testing.T) { } func TestTransitGatewayPeeringAttachment_getAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() now := time.Now() @@ -331,7 +332,7 @@ func TestTransitGatewayPeeringAttachment_getAll(t *testing.T) { } func TestTransitGatewayPeeringAttachment_nukeAll(t *testing.T) { - + telemetry.InitTelemetry("cloud-nuke", "") t.Parallel() tgw := TransitGatewayPeeringAttachment{ diff --git a/commands/cli_test.go b/commands/cli_test.go index b7ccf465..7700b9b4 100644 --- a/commands/cli_test.go +++ b/commands/cli_test.go @@ -32,9 +32,8 @@ func TestParseDuration(t *testing.T) { } func TestParseDurationInvalidFormat(t *testing.T) { - value, err := parseDurationParam("") - assert.NoError(t, err) - assert.Nil(t, value) + _, err := parseDurationParam("") + assert.Error(t, err) } func TestListResourceTypes(t *testing.T) {