From 3db0875c171fc6ad7ad011b66eb6cbb90230e7a9 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Tue, 13 Feb 2018 22:55:48 +0100 Subject: [PATCH 01/13] add exclude since option to cli --- commands/cli.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/commands/cli.go b/commands/cli.go index 1f26b03b..7dd57485 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -1,6 +1,7 @@ package commands import ( + "time" "strings" "github.com/gruntwork-io/gruntwork-cli/collections" @@ -27,6 +28,10 @@ func CreateCli(version string) *cli.App { Name: "exclude-region", Usage: "regions to exclude", }, + cli.StringFlag{ + Name: "exclude-since", + Usage: "timestamp (01-02-06 03:04AM) of resources creation date to exclude from", + }, } app.Action = errors.WithPanicHandling(awsNuke) @@ -37,6 +42,7 @@ func CreateCli(version string) *cli.App { func awsNuke(c *cli.Context) error { regions := aws.GetAllRegions() excludedRegions := c.StringSlice("exclude-region") + excludeSince := c.String("exclude-since") for _, excludedRegion := range excludedRegions { if !collections.ListContainsElement(regions, excludedRegion) { @@ -47,6 +53,11 @@ func awsNuke(c *cli.Context) error { } } + _, err := time.Parse("01-02-06 03:04AM", excludeSince) + if err != nil { + return errors.WithStackTrace(err) + } + logging.Logger.Infoln("Retrieving all active AWS resources") account, err := aws.GetAllResources(regions, excludedRegions) From bafe8c674251c2f1b6425cb7b1b8953ac9e5a397 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Wed, 14 Feb 2018 11:34:16 +0100 Subject: [PATCH 02/13] filter resources list result using exclude-since param value --- aws/asg.go | 8 ++++++-- aws/aws.go | 12 ++++++------ aws/ebs.go | 7 +++++-- aws/ec2.go | 10 ++++++---- aws/elb.go | 6 ++++-- aws/elbv2.go | 8 ++++++-- commands/cli.go | 22 ++++++++++++++-------- 7 files changed, 47 insertions(+), 26 deletions(-) diff --git a/aws/asg.go b/aws/asg.go index a7d6298b..bfe19011 100644 --- a/aws/asg.go +++ b/aws/asg.go @@ -1,6 +1,8 @@ package aws import ( + "time" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/autoscaling" @@ -9,7 +11,7 @@ import ( ) // Returns a formatted string of ASG Names -func getAllAutoScalingGroups(session *session.Session, region string) ([]*string, error) { +func getAllAutoScalingGroups(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { svc := autoscaling.New(session) result, err := svc.DescribeAutoScalingGroups(&autoscaling.DescribeAutoScalingGroupsInput{}) if err != nil { @@ -18,7 +20,9 @@ func getAllAutoScalingGroups(session *session.Session, region string) ([]*string var groupNames []*string for _, group := range result.AutoScalingGroups { - groupNames = append(groupNames, group.AutoScalingGroupName) + if excludeSince.Before(*group.CreatedTime) { + groupNames = append(groupNames, group.AutoScalingGroupName) + } } return groupNames, nil diff --git a/aws/aws.go b/aws/aws.go index 5a45a690..34690c54 100644 --- a/aws/aws.go +++ b/aws/aws.go @@ -42,7 +42,7 @@ func getRandomRegion() string { } // GetAllResources - Lists all aws resources -func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountResources, error) { +func GetAllResources(regions []string, excludedRegions []string, excludeSince time.Time) (*AwsAccountResources, error) { account := AwsAccountResources{ Resources: make(map[string]AwsRegionResource), } @@ -68,7 +68,7 @@ func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountRes // because of dependencies between resources // ASG Names - groupNames, err := getAllAutoScalingGroups(session, region) + groupNames, err := getAllAutoScalingGroups(session, region, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } @@ -81,7 +81,7 @@ func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountRes // End ASG Names // LoadBalancer Names - elbNames, err := getAllElbInstances(session, region) + elbNames, err := getAllElbInstances(session, region, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } @@ -94,7 +94,7 @@ func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountRes // End LoadBalancer Names // LoadBalancerV2 Arns - elbv2Arns, err := getAllElbv2Instances(session, region) + elbv2Arns, err := getAllElbv2Instances(session, region, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } @@ -107,7 +107,7 @@ func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountRes // End LoadBalancerV2 Arns // EC2 Instances - instanceIds, err := getAllEc2Instances(session, region) + instanceIds, err := getAllEc2Instances(session, region, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } @@ -120,7 +120,7 @@ func GetAllResources(regions []string, excludedRegions []string) (*AwsAccountRes // End EC2 Instances // EBS Volumes - volumeIds, err := getAllEbsVolumes(session, region) + volumeIds, err := getAllEbsVolumes(session, region, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } diff --git a/aws/ebs.go b/aws/ebs.go index 4f842d67..d72b08ff 100644 --- a/aws/ebs.go +++ b/aws/ebs.go @@ -2,6 +2,7 @@ package aws import ( "strings" + "time" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" @@ -10,7 +11,7 @@ import ( ) // Returns a formatted string of EBS volume ids -func getAllEbsVolumes(session *session.Session, region string) ([]*string, error) { +func getAllEbsVolumes(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { svc := ec2.New(session) result, err := svc.DescribeVolumes(&ec2.DescribeVolumesInput{}) @@ -20,7 +21,9 @@ func getAllEbsVolumes(session *session.Session, region string) ([]*string, error var volumeIds []*string for _, volume := range result.Volumes { - volumeIds = append(volumeIds, volume.VolumeId) + if excludeSince.Before(*volume.CreateTime) { + volumeIds = append(volumeIds, volume.VolumeId) + } } return volumeIds, nil diff --git a/aws/ec2.go b/aws/ec2.go index 786a7415..4884a1cb 100644 --- a/aws/ec2.go +++ b/aws/ec2.go @@ -1,6 +1,8 @@ package aws import ( + "time" + awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" @@ -9,7 +11,7 @@ import ( ) // returns only instance Ids of unprotected ec2 instances -func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutput) ([]*string, error) { +func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutput, excludeSince time.Time) ([]*string, error) { var filteredIds []*string for _, reservation := range output.Reservations { for _, instance := range reservation.Instances { @@ -26,7 +28,7 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp protected := *attr.DisableApiTermination.Value // Exclude protected EC2 instances - if !protected { + if !protected && excludeSince.Before(*instance.LaunchTime) { filteredIds = append(filteredIds, &instanceID) } } @@ -36,7 +38,7 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp } // Returns a formatted string of EC2 instance ids -func getAllEc2Instances(session *session.Session, region string) ([]*string, error) { +func getAllEc2Instances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { svc := ec2.New(session) params := &ec2.DescribeInstancesInput{ @@ -56,7 +58,7 @@ func getAllEc2Instances(session *session.Session, region string) ([]*string, err return nil, errors.WithStackTrace(err) } - instanceIds, err := filterOutProtectedInstances(svc, output) + instanceIds, err := filterOutProtectedInstances(svc, output, excludeSince) if err != nil { return nil, errors.WithStackTrace(err) } diff --git a/aws/elb.go b/aws/elb.go index e0db7950..8f09fbd8 100644 --- a/aws/elb.go +++ b/aws/elb.go @@ -29,7 +29,7 @@ func waitUntilElbDeleted(svc *elb.ELB, input *elb.DescribeLoadBalancersInput) er } // Returns a formatted string of ELB names -func getAllElbInstances(session *session.Session, region string) ([]*string, error) { +func getAllElbInstances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { svc := elb.New(session) result, err := svc.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{}) if err != nil { @@ -38,7 +38,9 @@ func getAllElbInstances(session *session.Session, region string) ([]*string, err var names []*string for _, balancer := range result.LoadBalancerDescriptions { - names = append(names, balancer.LoadBalancerName) + if excludeSince.Before(*balancer.CreatedTime) { + names = append(names, balancer.LoadBalancerName) + } } return names, nil diff --git a/aws/elbv2.go b/aws/elbv2.go index 78fd9cb0..1b44976d 100644 --- a/aws/elbv2.go +++ b/aws/elbv2.go @@ -1,6 +1,8 @@ package aws import ( + "time" + "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/elbv2" "github.com/gruntwork-io/aws-nuke/logging" @@ -8,7 +10,7 @@ import ( ) // Returns a formatted string of ELBv2 Arns -func getAllElbv2Instances(session *session.Session, region string) ([]*string, error) { +func getAllElbv2Instances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { svc := elbv2.New(session) result, err := svc.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{}) if err != nil { @@ -17,7 +19,9 @@ func getAllElbv2Instances(session *session.Session, region string) ([]*string, e var arns []*string for _, balancer := range result.LoadBalancers { - arns = append(arns, balancer.LoadBalancerArn) + if excludeSince.Before(*balancer.CreatedTime) { + arns = append(arns, balancer.LoadBalancerArn) + } } return arns, nil diff --git a/commands/cli.go b/commands/cli.go index 7dd57485..5fcaa9eb 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -1,8 +1,8 @@ package commands import ( - "time" "strings" + "time" "github.com/gruntwork-io/gruntwork-cli/collections" @@ -30,7 +30,7 @@ func CreateCli(version string) *cli.App { }, cli.StringFlag{ Name: "exclude-since", - Usage: "timestamp (01-02-06 03:04AM) of resources creation date to exclude from", + Usage: "timestamp (MM-DD-YY hh:mmAM) of resources creation date to exclude from", }, } app.Action = errors.WithPanicHandling(awsNuke) @@ -42,24 +42,30 @@ func CreateCli(version string) *cli.App { func awsNuke(c *cli.Context) error { regions := aws.GetAllRegions() excludedRegions := c.StringSlice("exclude-region") - excludeSince := c.String("exclude-since") for _, excludedRegion := range excludedRegions { if !collections.ListContainsElement(regions, excludedRegion) { return InvalidFlagError{ - Name: "exclude-regions", + Name: "exclude-regions", Value: excludedRegion, } } } - _, err := time.Parse("01-02-06 03:04AM", excludeSince) - if err != nil { - return errors.WithStackTrace(err) + var excludeSince time.Time + var err error + + if c.String("exclude-since") != "" { + excludeSince, err = time.Parse("01-02-2006 03:04AM", c.String("exclude-since")) + if err != nil { + return errors.WithStackTrace(err) + } + } else { + excludeSince = time.Now() } logging.Logger.Infoln("Retrieving all active AWS resources") - account, err := aws.GetAllResources(regions, excludedRegions) + account, err := aws.GetAllResources(regions, excludedRegions, excludeSince) if err != nil { return errors.WithStackTrace(err) From cc7ff489abc26a38c3d2c6cc1398a3c5b1f4a1c6 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Wed, 14 Feb 2018 11:39:57 +0100 Subject: [PATCH 03/13] update tests to include exclude since param --- aws/asg_test.go | 5 +++-- aws/ebs_test.go | 5 +++-- aws/ec2_test.go | 5 +++-- aws/elb_test.go | 5 +++-- aws/elbv2_test.go | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/aws/asg_test.go b/aws/asg_test.go index a56781f6..8020215a 100644 --- a/aws/asg_test.go +++ b/aws/asg_test.go @@ -2,6 +2,7 @@ package aws import ( "testing" + "time" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -53,7 +54,7 @@ func TestListAutoScalingGroups(t *testing.T) { // clean up after this test defer nukeAllAutoScalingGroups(session, []*string{&groupName}) - groupNames, err := getAllAutoScalingGroups(session, region) + groupNames, err := getAllAutoScalingGroups(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } @@ -89,7 +90,7 @@ func TestNukeAutoScalingGroups(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - groupNames, err := getAllAutoScalingGroups(session, region) + groupNames, err := getAllAutoScalingGroups(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } diff --git a/aws/ebs_test.go b/aws/ebs_test.go index 6e6a10ae..1dc17262 100644 --- a/aws/ebs_test.go +++ b/aws/ebs_test.go @@ -2,6 +2,7 @@ package aws import ( "testing" + "time" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -79,7 +80,7 @@ func TestListEBSVolumes(t *testing.T) { // clean up after this test defer nukeAllEbsVolumes(session, []*string{volume.VolumeId}) - volumeIds, err := getAllEbsVolumes(session, region) + volumeIds, err := getAllEbsVolumes(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of EBS Volumes") } @@ -112,7 +113,7 @@ func TestNukeEBSVolumes(t *testing.T) { if err := nukeAllEbsVolumes(session, volumeIds); err != nil { assert.Fail(t, errors.WithStackTrace(err).Error()) } - volumes, err := getAllEbsVolumes(session, region) + volumes, err := getAllEbsVolumes(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") diff --git a/aws/ec2_test.go b/aws/ec2_test.go index eddc302b..e5b9125c 100644 --- a/aws/ec2_test.go +++ b/aws/ec2_test.go @@ -2,6 +2,7 @@ package aws import ( "testing" + "time" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -129,7 +130,7 @@ func TestListInstances(t *testing.T) { // clean up after this test defer nukeAllEc2Instances(session, []*string{instance.InstanceId}) - instanceIds, err := getAllEc2Instances(session, region) + instanceIds, err := getAllEc2Instances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") @@ -163,7 +164,7 @@ func TestNukeInstances(t *testing.T) { if err := nukeAllEc2Instances(session, instanceIds); err != nil { assert.Fail(t, errors.WithStackTrace(err).Error()) } - instances, err := getAllEc2Instances(session, region) + instances, err := getAllEc2Instances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") diff --git a/aws/elb_test.go b/aws/elb_test.go index 40e3af63..700ece9b 100644 --- a/aws/elb_test.go +++ b/aws/elb_test.go @@ -2,6 +2,7 @@ package aws import ( "testing" + "time" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -51,7 +52,7 @@ func TestListELBs(t *testing.T) { // clean up after this test defer nukeAllElbInstances(session, []*string{&elbName}) - elbNames, err := getAllElbInstances(session, region) + elbNames, err := getAllElbInstances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } @@ -89,7 +90,7 @@ func TestNukeELBs(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - elbNames, err := getAllElbInstances(session, region) + elbNames, err := getAllElbInstances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of ELBs") } diff --git a/aws/elbv2_test.go b/aws/elbv2_test.go index a1055f3a..04a21b52 100644 --- a/aws/elbv2_test.go +++ b/aws/elbv2_test.go @@ -2,6 +2,7 @@ package aws import ( "testing" + "time" awsgo "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -75,7 +76,7 @@ func TestListELBv2(t *testing.T) { // clean up after this test defer nukeAllElbv2Instances(session, []*string{balancer.LoadBalancerArn}) - arns, err := getAllElbv2Instances(session, region) + arns, err := getAllElbv2Instances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of v2 ELBs") } @@ -121,7 +122,7 @@ func TestNukeELBv2(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - arns, err := getAllElbv2Instances(session, region) + arns, err := getAllElbv2Instances(session, region, time.Now()) if err != nil { assert.Fail(t, "Unable to fetch list of v2 ELBs") } From 616fb5da3ffbdf257377bd84712bd5808871a476 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Wed, 14 Feb 2018 13:13:55 +0100 Subject: [PATCH 04/13] fix tests, set exclude since param to the future --- aws/asg.go | 2 +- aws/asg_test.go | 4 ++-- aws/ebs.go | 2 +- aws/ebs_test.go | 4 ++-- aws/ec2.go | 2 +- aws/ec2_test.go | 4 ++-- aws/elb.go | 2 +- aws/elb_test.go | 4 ++-- aws/elbv2.go | 2 +- aws/elbv2_test.go | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/aws/asg.go b/aws/asg.go index bfe19011..f9eef2ce 100644 --- a/aws/asg.go +++ b/aws/asg.go @@ -20,7 +20,7 @@ func getAllAutoScalingGroups(session *session.Session, region string, excludeSin var groupNames []*string for _, group := range result.AutoScalingGroups { - if excludeSince.Before(*group.CreatedTime) { + if excludeSince.After(*group.CreatedTime) { groupNames = append(groupNames, group.AutoScalingGroupName) } } diff --git a/aws/asg_test.go b/aws/asg_test.go index 8020215a..18e2ad9d 100644 --- a/aws/asg_test.go +++ b/aws/asg_test.go @@ -54,7 +54,7 @@ func TestListAutoScalingGroups(t *testing.T) { // clean up after this test defer nukeAllAutoScalingGroups(session, []*string{&groupName}) - groupNames, err := getAllAutoScalingGroups(session, region, time.Now()) + groupNames, err := getAllAutoScalingGroups(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } @@ -90,7 +90,7 @@ func TestNukeAutoScalingGroups(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - groupNames, err := getAllAutoScalingGroups(session, region, time.Now()) + groupNames, err := getAllAutoScalingGroups(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } diff --git a/aws/ebs.go b/aws/ebs.go index d72b08ff..bbffbeb1 100644 --- a/aws/ebs.go +++ b/aws/ebs.go @@ -21,7 +21,7 @@ func getAllEbsVolumes(session *session.Session, region string, excludeSince time var volumeIds []*string for _, volume := range result.Volumes { - if excludeSince.Before(*volume.CreateTime) { + if excludeSince.After(*volume.CreateTime) { volumeIds = append(volumeIds, volume.VolumeId) } } diff --git a/aws/ebs_test.go b/aws/ebs_test.go index 1dc17262..5f311e78 100644 --- a/aws/ebs_test.go +++ b/aws/ebs_test.go @@ -80,7 +80,7 @@ func TestListEBSVolumes(t *testing.T) { // clean up after this test defer nukeAllEbsVolumes(session, []*string{volume.VolumeId}) - volumeIds, err := getAllEbsVolumes(session, region, time.Now()) + volumeIds, err := getAllEbsVolumes(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EBS Volumes") } @@ -113,7 +113,7 @@ func TestNukeEBSVolumes(t *testing.T) { if err := nukeAllEbsVolumes(session, volumeIds); err != nil { assert.Fail(t, errors.WithStackTrace(err).Error()) } - volumes, err := getAllEbsVolumes(session, region, time.Now()) + volumes, err := getAllEbsVolumes(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") diff --git a/aws/ec2.go b/aws/ec2.go index 4884a1cb..72f97527 100644 --- a/aws/ec2.go +++ b/aws/ec2.go @@ -28,7 +28,7 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp protected := *attr.DisableApiTermination.Value // Exclude protected EC2 instances - if !protected && excludeSince.Before(*instance.LaunchTime) { + if !protected && excludeSince.After(*instance.LaunchTime) { filteredIds = append(filteredIds, &instanceID) } } diff --git a/aws/ec2_test.go b/aws/ec2_test.go index e5b9125c..b26d1bda 100644 --- a/aws/ec2_test.go +++ b/aws/ec2_test.go @@ -130,7 +130,7 @@ func TestListInstances(t *testing.T) { // clean up after this test defer nukeAllEc2Instances(session, []*string{instance.InstanceId}) - instanceIds, err := getAllEc2Instances(session, region, time.Now()) + instanceIds, err := getAllEc2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") @@ -164,7 +164,7 @@ func TestNukeInstances(t *testing.T) { if err := nukeAllEc2Instances(session, instanceIds); err != nil { assert.Fail(t, errors.WithStackTrace(err).Error()) } - instances, err := getAllEc2Instances(session, region, time.Now()) + instances, err := getAllEc2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") diff --git a/aws/elb.go b/aws/elb.go index 8f09fbd8..ce493957 100644 --- a/aws/elb.go +++ b/aws/elb.go @@ -38,7 +38,7 @@ func getAllElbInstances(session *session.Session, region string, excludeSince ti var names []*string for _, balancer := range result.LoadBalancerDescriptions { - if excludeSince.Before(*balancer.CreatedTime) { + if excludeSince.After(*balancer.CreatedTime) { names = append(names, balancer.LoadBalancerName) } } diff --git a/aws/elb_test.go b/aws/elb_test.go index 700ece9b..56e7def1 100644 --- a/aws/elb_test.go +++ b/aws/elb_test.go @@ -52,7 +52,7 @@ func TestListELBs(t *testing.T) { // clean up after this test defer nukeAllElbInstances(session, []*string{&elbName}) - elbNames, err := getAllElbInstances(session, region, time.Now()) + elbNames, err := getAllElbInstances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } @@ -90,7 +90,7 @@ func TestNukeELBs(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - elbNames, err := getAllElbInstances(session, region, time.Now()) + elbNames, err := getAllElbInstances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of ELBs") } diff --git a/aws/elbv2.go b/aws/elbv2.go index 1b44976d..e71e94d5 100644 --- a/aws/elbv2.go +++ b/aws/elbv2.go @@ -19,7 +19,7 @@ func getAllElbv2Instances(session *session.Session, region string, excludeSince var arns []*string for _, balancer := range result.LoadBalancers { - if excludeSince.Before(*balancer.CreatedTime) { + if excludeSince.After(*balancer.CreatedTime) { arns = append(arns, balancer.LoadBalancerArn) } } diff --git a/aws/elbv2_test.go b/aws/elbv2_test.go index 04a21b52..5910f1e3 100644 --- a/aws/elbv2_test.go +++ b/aws/elbv2_test.go @@ -76,7 +76,7 @@ func TestListELBv2(t *testing.T) { // clean up after this test defer nukeAllElbv2Instances(session, []*string{balancer.LoadBalancerArn}) - arns, err := getAllElbv2Instances(session, region, time.Now()) + arns, err := getAllElbv2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of v2 ELBs") } @@ -122,7 +122,7 @@ func TestNukeELBv2(t *testing.T) { assert.Fail(t, errors.WithStackTrace(err).Error()) } - arns, err := getAllElbv2Instances(session, region, time.Now()) + arns, err := getAllElbv2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of v2 ELBs") } From 2ac52a258698106d9d48ce0ef6568ad0c1374516 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Wed, 14 Feb 2018 14:05:29 +0100 Subject: [PATCH 05/13] update README.md to include info about exclude-since flag --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index cce00436..86d3e7f4 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ You can use the `--exclude-region` flag to exclude resources in certain regions aws-nuke --exclude-region ap-south-1 --exclude-region ap-south-2 ``` +### Excluding Resources by Age + +You can use the `--exclude-since` flag to exclude resources created after a certain time, any resources older than that time will be deleted. For example the following command does not nuke resources created after the midnight on 1st Jan, 2017: + +```shell +aws-nuke --exclude-since '01-01-2017 12:00AM' +``` + Happy Nuking!!! ## Credentials From 1a8aa93621d6be8216224b6e2213f59e1e392d8b Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 00:51:24 +0100 Subject: [PATCH 06/13] rename exclude-since to exclude-after --- aws/asg.go | 4 ++-- aws/aws.go | 12 ++++++------ aws/ebs.go | 4 ++-- aws/ec2.go | 8 ++++---- aws/elb.go | 4 ++-- aws/elbv2.go | 4 ++-- commands/cli.go | 12 ++++++------ 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/aws/asg.go b/aws/asg.go index f9eef2ce..bc5e7cb0 100644 --- a/aws/asg.go +++ b/aws/asg.go @@ -11,7 +11,7 @@ import ( ) // Returns a formatted string of ASG Names -func getAllAutoScalingGroups(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { +func getAllAutoScalingGroups(session *session.Session, region string, excludeAfter time.Time) ([]*string, error) { svc := autoscaling.New(session) result, err := svc.DescribeAutoScalingGroups(&autoscaling.DescribeAutoScalingGroupsInput{}) if err != nil { @@ -20,7 +20,7 @@ func getAllAutoScalingGroups(session *session.Session, region string, excludeSin var groupNames []*string for _, group := range result.AutoScalingGroups { - if excludeSince.After(*group.CreatedTime) { + if excludeAfter.After(*group.CreatedTime) { groupNames = append(groupNames, group.AutoScalingGroupName) } } diff --git a/aws/aws.go b/aws/aws.go index 34690c54..33bcb690 100644 --- a/aws/aws.go +++ b/aws/aws.go @@ -42,7 +42,7 @@ func getRandomRegion() string { } // GetAllResources - Lists all aws resources -func GetAllResources(regions []string, excludedRegions []string, excludeSince time.Time) (*AwsAccountResources, error) { +func GetAllResources(regions []string, excludedRegions []string, excludeAfter time.Time) (*AwsAccountResources, error) { account := AwsAccountResources{ Resources: make(map[string]AwsRegionResource), } @@ -68,7 +68,7 @@ func GetAllResources(regions []string, excludedRegions []string, excludeSince ti // because of dependencies between resources // ASG Names - groupNames, err := getAllAutoScalingGroups(session, region, excludeSince) + groupNames, err := getAllAutoScalingGroups(session, region, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } @@ -81,7 +81,7 @@ func GetAllResources(regions []string, excludedRegions []string, excludeSince ti // End ASG Names // LoadBalancer Names - elbNames, err := getAllElbInstances(session, region, excludeSince) + elbNames, err := getAllElbInstances(session, region, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } @@ -94,7 +94,7 @@ func GetAllResources(regions []string, excludedRegions []string, excludeSince ti // End LoadBalancer Names // LoadBalancerV2 Arns - elbv2Arns, err := getAllElbv2Instances(session, region, excludeSince) + elbv2Arns, err := getAllElbv2Instances(session, region, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } @@ -107,7 +107,7 @@ func GetAllResources(regions []string, excludedRegions []string, excludeSince ti // End LoadBalancerV2 Arns // EC2 Instances - instanceIds, err := getAllEc2Instances(session, region, excludeSince) + instanceIds, err := getAllEc2Instances(session, region, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } @@ -120,7 +120,7 @@ func GetAllResources(regions []string, excludedRegions []string, excludeSince ti // End EC2 Instances // EBS Volumes - volumeIds, err := getAllEbsVolumes(session, region, excludeSince) + volumeIds, err := getAllEbsVolumes(session, region, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } diff --git a/aws/ebs.go b/aws/ebs.go index bbffbeb1..8f701933 100644 --- a/aws/ebs.go +++ b/aws/ebs.go @@ -11,7 +11,7 @@ import ( ) // Returns a formatted string of EBS volume ids -func getAllEbsVolumes(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { +func getAllEbsVolumes(session *session.Session, region string, excludeAfter time.Time) ([]*string, error) { svc := ec2.New(session) result, err := svc.DescribeVolumes(&ec2.DescribeVolumesInput{}) @@ -21,7 +21,7 @@ func getAllEbsVolumes(session *session.Session, region string, excludeSince time var volumeIds []*string for _, volume := range result.Volumes { - if excludeSince.After(*volume.CreateTime) { + if excludeAfter.After(*volume.CreateTime) { volumeIds = append(volumeIds, volume.VolumeId) } } diff --git a/aws/ec2.go b/aws/ec2.go index 72f97527..87dd8a77 100644 --- a/aws/ec2.go +++ b/aws/ec2.go @@ -11,7 +11,7 @@ import ( ) // returns only instance Ids of unprotected ec2 instances -func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutput, excludeSince time.Time) ([]*string, error) { +func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutput, excludeAfter time.Time) ([]*string, error) { var filteredIds []*string for _, reservation := range output.Reservations { for _, instance := range reservation.Instances { @@ -28,7 +28,7 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp protected := *attr.DisableApiTermination.Value // Exclude protected EC2 instances - if !protected && excludeSince.After(*instance.LaunchTime) { + if !protected && excludeAfter.After(*instance.LaunchTime) { filteredIds = append(filteredIds, &instanceID) } } @@ -38,7 +38,7 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp } // Returns a formatted string of EC2 instance ids -func getAllEc2Instances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { +func getAllEc2Instances(session *session.Session, region string, excludeAfter time.Time) ([]*string, error) { svc := ec2.New(session) params := &ec2.DescribeInstancesInput{ @@ -58,7 +58,7 @@ func getAllEc2Instances(session *session.Session, region string, excludeSince ti return nil, errors.WithStackTrace(err) } - instanceIds, err := filterOutProtectedInstances(svc, output, excludeSince) + instanceIds, err := filterOutProtectedInstances(svc, output, excludeAfter) if err != nil { return nil, errors.WithStackTrace(err) } diff --git a/aws/elb.go b/aws/elb.go index ce493957..258715f7 100644 --- a/aws/elb.go +++ b/aws/elb.go @@ -29,7 +29,7 @@ func waitUntilElbDeleted(svc *elb.ELB, input *elb.DescribeLoadBalancersInput) er } // Returns a formatted string of ELB names -func getAllElbInstances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { +func getAllElbInstances(session *session.Session, region string, excludeAfter time.Time) ([]*string, error) { svc := elb.New(session) result, err := svc.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{}) if err != nil { @@ -38,7 +38,7 @@ func getAllElbInstances(session *session.Session, region string, excludeSince ti var names []*string for _, balancer := range result.LoadBalancerDescriptions { - if excludeSince.After(*balancer.CreatedTime) { + if excludeAfter.After(*balancer.CreatedTime) { names = append(names, balancer.LoadBalancerName) } } diff --git a/aws/elbv2.go b/aws/elbv2.go index e71e94d5..6f6d4a97 100644 --- a/aws/elbv2.go +++ b/aws/elbv2.go @@ -10,7 +10,7 @@ import ( ) // Returns a formatted string of ELBv2 Arns -func getAllElbv2Instances(session *session.Session, region string, excludeSince time.Time) ([]*string, error) { +func getAllElbv2Instances(session *session.Session, region string, excludeAfter time.Time) ([]*string, error) { svc := elbv2.New(session) result, err := svc.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{}) if err != nil { @@ -19,7 +19,7 @@ func getAllElbv2Instances(session *session.Session, region string, excludeSince var arns []*string for _, balancer := range result.LoadBalancers { - if excludeSince.After(*balancer.CreatedTime) { + if excludeAfter.After(*balancer.CreatedTime) { arns = append(arns, balancer.LoadBalancerArn) } } diff --git a/commands/cli.go b/commands/cli.go index 5fcaa9eb..5155b8ea 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -29,7 +29,7 @@ func CreateCli(version string) *cli.App { Usage: "regions to exclude", }, cli.StringFlag{ - Name: "exclude-since", + Name: "exclude-after", Usage: "timestamp (MM-DD-YY hh:mmAM) of resources creation date to exclude from", }, } @@ -52,20 +52,20 @@ func awsNuke(c *cli.Context) error { } } - var excludeSince time.Time + var excludeAfter time.Time var err error - if c.String("exclude-since") != "" { - excludeSince, err = time.Parse("01-02-2006 03:04AM", c.String("exclude-since")) + if c.String("exclude-after") != "" { + excludeAfter, err = time.Parse("01-02-2006 03:04AM", c.String("exclude-after")) if err != nil { return errors.WithStackTrace(err) } } else { - excludeSince = time.Now() + excludeAfter = time.Now() } logging.Logger.Infoln("Retrieving all active AWS resources") - account, err := aws.GetAllResources(regions, excludedRegions, excludeSince) + account, err := aws.GetAllResources(regions, excludedRegions, excludeAfter) if err != nil { return errors.WithStackTrace(err) From c03a1d6e1c1fe001cf07e33ff6e4e9b872a3dac2 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 00:58:21 +0100 Subject: [PATCH 07/13] update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 86d3e7f4..8653986a 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,10 @@ aws-nuke --exclude-region ap-south-1 --exclude-region ap-south-2 ### Excluding Resources by Age -You can use the `--exclude-since` flag to exclude resources created after a certain time, any resources older than that time will be deleted. For example the following command does not nuke resources created after the midnight on 1st Jan, 2017: +You can use the `--exclude-after` flag to exclude resources created after a certain time, any resources older than that time will be deleted. For example the following command does not nuke resources created after the midnight on 1st Jan, 2017: ```shell -aws-nuke --exclude-since '01-01-2017 12:00AM' +aws-nuke --exclude-after '01-01-2017 12:00AM' ``` Happy Nuking!!! From ced4033843db1712f1f32e85a815cf933f5cb988 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 16:07:31 +0100 Subject: [PATCH 08/13] separate time parsing code into separate function and write tests --- commands/cli.go | 27 +++++++++++++++------------ commands/cli_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 commands/cli_test.go diff --git a/commands/cli.go b/commands/cli.go index 5155b8ea..c8e64754 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -31,13 +31,23 @@ func CreateCli(version string) *cli.App { cli.StringFlag{ Name: "exclude-after", Usage: "timestamp (MM-DD-YY hh:mmAM) of resources creation date to exclude from", + Value: time.Now().Format("01-02-2006 03:04AM"), }, } - app.Action = errors.WithPanicHandling(awsNuke) + app.Action = errors.WithPanicHandling(awsNuke) return app } +func parseTimeParam(paramValue string) (*time.Time, error) { + excludeAfter, err := time.Parse("01-02-2006 03:04AM", paramValue) + if err != nil { + return nil, errors.WithStackTrace(err) + } + + return &excludeAfter, nil +} + // Nuke it all!!! func awsNuke(c *cli.Context) error { regions := aws.GetAllRegions() @@ -52,20 +62,13 @@ func awsNuke(c *cli.Context) error { } } - var excludeAfter time.Time - var err error - - if c.String("exclude-after") != "" { - excludeAfter, err = time.Parse("01-02-2006 03:04AM", c.String("exclude-after")) - if err != nil { - return errors.WithStackTrace(err) - } - } else { - excludeAfter = time.Now() + excludeAfter, err := parseTimeParam(c.String("exclude-after")) + if err != nil { + return errors.WithStackTrace(err) } logging.Logger.Infoln("Retrieving all active AWS resources") - account, err := aws.GetAllResources(regions, excludedRegions, excludeAfter) + account, err := aws.GetAllResources(regions, excludedRegions, *excludeAfter) if err != nil { return errors.WithStackTrace(err) diff --git a/commands/cli_test.go b/commands/cli_test.go new file mode 100644 index 00000000..48352c57 --- /dev/null +++ b/commands/cli_test.go @@ -0,0 +1,29 @@ +package commands + +import ( + "testing" + "time" + + "github.com/gruntwork-io/gruntwork-cli/errors" + "github.com/stretchr/testify/assert" +) + +func TestParseTime(t *testing.T) { + dateString := "01-01-2018 00:00AM" + parsedTime, err := parseTimeParam(dateString) + if err != nil { + assert.Fail(t, errors.WithStackTrace(err).Error()) + } + + assert.Equal(t, parsedTime.Month(), time.Month(1)) + assert.Equal(t, parsedTime.Day(), 1) + assert.Equal(t, parsedTime.Year(), 2018) +} + +func TestParseTimeInvalidFormat(t *testing.T) { + _, err := parseTimeParam("") + assert.Error(t, err) + + _, err = parseTimeParam("01/01/2018") + assert.Error(t, err) +} From c3e668f5cb63bde177ae1e6870df6a8ab62430c2 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 16:28:48 +0100 Subject: [PATCH 09/13] ensure protected instances are filtered out before exclude timestamp check --- aws/ec2.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aws/ec2.go b/aws/ec2.go index 87dd8a77..cc9e8da4 100644 --- a/aws/ec2.go +++ b/aws/ec2.go @@ -28,8 +28,10 @@ func filterOutProtectedInstances(svc *ec2.EC2, output *ec2.DescribeInstancesOutp protected := *attr.DisableApiTermination.Value // Exclude protected EC2 instances - if !protected && excludeAfter.After(*instance.LaunchTime) { - filteredIds = append(filteredIds, &instanceID) + if !protected { + if excludeAfter.After(*instance.LaunchTime) { + filteredIds = append(filteredIds, &instanceID) + } } } } From dd35a5cce02e3de0ba9017a920a7483fe68b27a2 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 21:50:31 +0100 Subject: [PATCH 10/13] change exclude-after time flag to older-than duration --- README.md | 4 ++-- commands/cli.go | 16 ++++++++++------ commands/cli_test.go | 20 +++++++++----------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 8653986a..76b32cfc 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,10 @@ aws-nuke --exclude-region ap-south-1 --exclude-region ap-south-2 ### Excluding Resources by Age -You can use the `--exclude-after` flag to exclude resources created after a certain time, any resources older than that time will be deleted. For example the following command does not nuke resources created after the midnight on 1st Jan, 2017: +You can use the `--older-than` flag to nuke resources that were created before a certain period, the possible values are all valid values for [ParseDuration](https://golang.org/pkg/time/#ParseDuration) For example the following command nukes resources that are at least one day old: ```shell -aws-nuke --exclude-after '01-01-2017 12:00AM' +aws-nuke --older-than 24h ``` Happy Nuking!!! diff --git a/commands/cli.go b/commands/cli.go index c8e64754..4d8dc821 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -29,9 +29,9 @@ func CreateCli(version string) *cli.App { Usage: "regions to exclude", }, cli.StringFlag{ - Name: "exclude-after", - Usage: "timestamp (MM-DD-YY hh:mmAM) of resources creation date to exclude from", - Value: time.Now().Format("01-02-2006 03:04AM"), + Name: "older-than", + Usage: "duration of resources' creation date to delete from", + Value: "0s", }, } @@ -39,12 +39,16 @@ func CreateCli(version string) *cli.App { return app } -func parseTimeParam(paramValue string) (*time.Time, error) { - excludeAfter, err := time.Parse("01-02-2006 03:04AM", paramValue) +func parseDurationParam(paramValue string) (*time.Time, error) { + duration, err := time.ParseDuration(paramValue) if err != nil { return nil, errors.WithStackTrace(err) } + // make it negative so it goes back in time + duration = -1 * duration + + excludeAfter := time.Now().Add(duration) return &excludeAfter, nil } @@ -62,7 +66,7 @@ func awsNuke(c *cli.Context) error { } } - excludeAfter, err := parseTimeParam(c.String("exclude-after")) + excludeAfter, err := parseDurationParam(c.String("older-than")) if err != nil { return errors.WithStackTrace(err) } diff --git a/commands/cli_test.go b/commands/cli_test.go index 48352c57..0bf3da13 100644 --- a/commands/cli_test.go +++ b/commands/cli_test.go @@ -8,22 +8,20 @@ import ( "github.com/stretchr/testify/assert" ) -func TestParseTime(t *testing.T) { - dateString := "01-01-2018 00:00AM" - parsedTime, err := parseTimeParam(dateString) +func TestParseDuration(t *testing.T) { + now := time.Now() + then, err := parseDurationParam("1h") if err != nil { assert.Fail(t, errors.WithStackTrace(err).Error()) } - assert.Equal(t, parsedTime.Month(), time.Month(1)) - assert.Equal(t, parsedTime.Day(), 1) - assert.Equal(t, parsedTime.Year(), 2018) + assert.Equal(t, now.Hour()-1, then.Hour()) + assert.Equal(t, now.Month(), then.Month()) + assert.Equal(t, now.Day(), then.Day()) + assert.Equal(t, now.Year(), then.Year()) } -func TestParseTimeInvalidFormat(t *testing.T) { - _, err := parseTimeParam("") - assert.Error(t, err) - - _, err = parseTimeParam("01/01/2018") +func TestParseDurationInvalidFormat(t *testing.T) { + _, err := parseDurationParam("") assert.Error(t, err) } From e242ce09a7118689e3021376e418f41aa2ee5c77 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Thu, 15 Feb 2018 22:14:06 +0100 Subject: [PATCH 11/13] explicitly test for exclude since constraint --- aws/asg_test.go | 9 ++++++++- aws/ebs_test.go | 9 ++++++++- aws/ec2_test.go | 8 +++++++- aws/elb_test.go | 9 ++++++++- aws/elbv2_test.go | 9 ++++++++- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/aws/asg_test.go b/aws/asg_test.go index 18e2ad9d..b2da914d 100644 --- a/aws/asg_test.go +++ b/aws/asg_test.go @@ -54,7 +54,14 @@ func TestListAutoScalingGroups(t *testing.T) { // clean up after this test defer nukeAllAutoScalingGroups(session, []*string{&groupName}) - groupNames, err := getAllAutoScalingGroups(session, region, time.Now().Add(1*time.Hour)) + groupNames, err := getAllAutoScalingGroups(session, region, time.Now().Add(1*time.Hour*-1)) + if err != nil { + assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") + } + + assert.NotContains(t, awsgo.StringValueSlice(groupNames), groupName) + + groupNames, err = getAllAutoScalingGroups(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } diff --git a/aws/ebs_test.go b/aws/ebs_test.go index 5f311e78..b8f95fc1 100644 --- a/aws/ebs_test.go +++ b/aws/ebs_test.go @@ -80,7 +80,14 @@ func TestListEBSVolumes(t *testing.T) { // clean up after this test defer nukeAllEbsVolumes(session, []*string{volume.VolumeId}) - volumeIds, err := getAllEbsVolumes(session, region, time.Now().Add(1*time.Hour)) + volumeIds, err := getAllEbsVolumes(session, region, time.Now().Add(1*time.Hour*-1)) + if err != nil { + assert.Fail(t, "Unable to fetch list of EBS Volumes") + } + + assert.NotContains(t, awsgo.StringValueSlice(volumeIds), awsgo.StringValue(volume.VolumeId)) + + volumeIds, err = getAllEbsVolumes(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EBS Volumes") } diff --git a/aws/ec2_test.go b/aws/ec2_test.go index b26d1bda..93d59aa5 100644 --- a/aws/ec2_test.go +++ b/aws/ec2_test.go @@ -130,8 +130,14 @@ func TestListInstances(t *testing.T) { // clean up after this test defer nukeAllEc2Instances(session, []*string{instance.InstanceId}) - instanceIds, err := getAllEc2Instances(session, region, time.Now().Add(1*time.Hour)) + instanceIds, err := getAllEc2Instances(session, region, time.Now().Add(1*time.Hour*-1)) + if err != nil { + assert.Fail(t, "Unable to fetch list of EC2 Instances") + } + + assert.NotContains(t, instanceIds, instance.InstanceId) + instanceIds, err = getAllEc2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of EC2 Instances") } diff --git a/aws/elb_test.go b/aws/elb_test.go index 56e7def1..95aa8023 100644 --- a/aws/elb_test.go +++ b/aws/elb_test.go @@ -52,7 +52,14 @@ func TestListELBs(t *testing.T) { // clean up after this test defer nukeAllElbInstances(session, []*string{&elbName}) - elbNames, err := getAllElbInstances(session, region, time.Now().Add(1*time.Hour)) + elbNames, err := getAllElbInstances(session, region, time.Now().Add(1*time.Hour*-1)) + if err != nil { + assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") + } + + assert.NotContains(t, awsgo.StringValueSlice(elbNames), elbName) + + elbNames, err = getAllElbInstances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of Auto Scaling Groups") } diff --git a/aws/elbv2_test.go b/aws/elbv2_test.go index 5910f1e3..957c9cf2 100644 --- a/aws/elbv2_test.go +++ b/aws/elbv2_test.go @@ -76,7 +76,14 @@ func TestListELBv2(t *testing.T) { // clean up after this test defer nukeAllElbv2Instances(session, []*string{balancer.LoadBalancerArn}) - arns, err := getAllElbv2Instances(session, region, time.Now().Add(1*time.Hour)) + arns, err := getAllElbv2Instances(session, region, time.Now().Add(1*time.Hour*-1)) + if err != nil { + assert.Fail(t, "Unable to fetch list of v2 ELBs") + } + + assert.NotContains(t, awsgo.StringValueSlice(arns), awsgo.StringValue(balancer.LoadBalancerArn)) + + arns, err = getAllElbv2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { assert.Fail(t, "Unable to fetch list of v2 ELBs") } From dcef2eeeef223ee5dd372dad73bdc1d530261cc0 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Fri, 16 Feb 2018 16:07:34 +0100 Subject: [PATCH 12/13] update description of older-than flag --- README.md | 2 +- commands/cli.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76b32cfc..ca96373c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ aws-nuke --exclude-region ap-south-1 --exclude-region ap-south-2 ### Excluding Resources by Age -You can use the `--older-than` flag to nuke resources that were created before a certain period, the possible values are all valid values for [ParseDuration](https://golang.org/pkg/time/#ParseDuration) For example the following command nukes resources that are at least one day old: +You can use the `--older-than` flag to only nuke resources that were created before a certain period, the possible values are all valid values for [ParseDuration](https://golang.org/pkg/time/#ParseDuration) For example the following command nukes resources that are at least one day old: ```shell aws-nuke --older-than 24h diff --git a/commands/cli.go b/commands/cli.go index 4d8dc821..c1d8757f 100644 --- a/commands/cli.go +++ b/commands/cli.go @@ -30,7 +30,7 @@ func CreateCli(version string) *cli.App { }, cli.StringFlag{ Name: "older-than", - Usage: "duration of resources' creation date to delete from", + Usage: "Only delete resources older than this specified value. Can be any valid Go duration, such as 10m or 8h.", Value: "0s", }, } From 1d249e3d3dbabe434e57cbe2e128e23cd81fd03e Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Fri, 16 Feb 2018 18:46:42 +0100 Subject: [PATCH 13/13] test that protected instances are never returned --- aws/asg_test.go | 2 +- aws/ebs_test.go | 2 +- aws/ec2_test.go | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/aws/asg_test.go b/aws/asg_test.go index b2da914d..2563e7cb 100644 --- a/aws/asg_test.go +++ b/aws/asg_test.go @@ -14,7 +14,7 @@ import ( func createTestAutoScalingGroup(t *testing.T, session *session.Session, name string) { svc := autoscaling.New(session) - instance := createTestEC2Instance(t, session, name) + instance := createTestEC2Instance(t, session, name, false) param := &autoscaling.CreateAutoScalingGroupInput{ AutoScalingGroupName: &name, diff --git a/aws/ebs_test.go b/aws/ebs_test.go index b8f95fc1..88faaa16 100644 --- a/aws/ebs_test.go +++ b/aws/ebs_test.go @@ -108,7 +108,7 @@ func TestNukeEBSVolumes(t *testing.T) { } uniqueTestID := "aws-nuke-test-" + util.UniqueID() - createTestEC2Instance(t, session, uniqueTestID) + createTestEC2Instance(t, session, uniqueTestID, false) output, err := ec2.New(session).DescribeVolumes(&ec2.DescribeVolumesInput{}) if err != nil { diff --git a/aws/ec2_test.go b/aws/ec2_test.go index 93d59aa5..5c33346d 100644 --- a/aws/ec2_test.go +++ b/aws/ec2_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" ) -func createTestEC2Instance(t *testing.T, session *session.Session, name string) ec2.Instance { +func createTestEC2Instance(t *testing.T, session *session.Session, name string, protected bool) ec2.Instance { svc := ec2.New(session) imagesResult, err := svc.DescribeImages(&ec2.DescribeImagesInput{ @@ -32,10 +32,11 @@ func createTestEC2Instance(t *testing.T, session *session.Session, name string) imageID := *imagesResult.Images[0].ImageId params := &ec2.RunInstancesInput{ - ImageId: awsgo.String(imageID), - InstanceType: awsgo.String("t2.micro"), - MinCount: awsgo.Int64(1), - MaxCount: awsgo.Int64(1), + ImageId: awsgo.String(imageID), + InstanceType: awsgo.String("t2.micro"), + MinCount: awsgo.Int64(1), + MaxCount: awsgo.Int64(1), + DisableApiTermination: awsgo.Bool(protected), } runResult, err := svc.RunInstances(params) @@ -126,9 +127,10 @@ func TestListInstances(t *testing.T) { } uniqueTestID := "aws-nuke-test-" + util.UniqueID() - instance := createTestEC2Instance(t, session, uniqueTestID) + instance := createTestEC2Instance(t, session, uniqueTestID, false) + protectedInstance := createTestEC2Instance(t, session, uniqueTestID, true) // clean up after this test - defer nukeAllEc2Instances(session, []*string{instance.InstanceId}) + defer nukeAllEc2Instances(session, []*string{instance.InstanceId, protectedInstance.InstanceId}) instanceIds, err := getAllEc2Instances(session, region, time.Now().Add(1*time.Hour*-1)) if err != nil { @@ -136,6 +138,7 @@ func TestListInstances(t *testing.T) { } assert.NotContains(t, instanceIds, instance.InstanceId) + assert.NotContains(t, instanceIds, protectedInstance.InstanceId) instanceIds, err = getAllEc2Instances(session, region, time.Now().Add(1*time.Hour)) if err != nil { @@ -143,6 +146,7 @@ func TestListInstances(t *testing.T) { } assert.Contains(t, instanceIds, instance.InstanceId) + assert.NotContains(t, instanceIds, protectedInstance.InstanceId) } func TestNukeInstances(t *testing.T) { @@ -158,7 +162,7 @@ func TestNukeInstances(t *testing.T) { } uniqueTestID := "aws-nuke-test-" + util.UniqueID() - createTestEC2Instance(t, session, uniqueTestID) + createTestEC2Instance(t, session, uniqueTestID, false) output, err := ec2.New(session).DescribeInstances(&ec2.DescribeInstancesInput{}) if err != nil {