Skip to content

Commit

Permalink
change port ebs, ecr, ecs cluster, ecs service, efs, eip, eks, elasti…
Browse files Browse the repository at this point in the history
…c beanstalk, elasticache, elb, elbv2, guardduty to awsSDKv2 #770 (#777)
  • Loading branch information
wakeful authored Nov 2, 2024
1 parent 849ee20 commit 334b2bc
Show file tree
Hide file tree
Showing 39 changed files with 975 additions and 854 deletions.
59 changes: 33 additions & 26 deletions aws/resources/ebs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package resources

import (
"context"
goerr "errors"
"time"

"github.com/aws/aws-sdk-go/aws"
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-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/aws/smithy-go"
"github.com/gruntwork-io/cloud-nuke/config"
"github.com/gruntwork-io/cloud-nuke/logging"
"github.com/gruntwork-io/cloud-nuke/report"
Expand All @@ -20,9 +22,9 @@ func (ev *EBSVolumes) getAll(c context.Context, configObj config.Config) ([]*str
// Since the output of this function is used to delete the returned volumes
// We want to only list EBS volumes with a status of "available" or "creating"
// Since those are the only statuses that are eligible for deletion
statusFilter := ec2.Filter{Name: aws.String("status"), Values: aws.StringSlice([]string{"available", "creating", "error"})}
result, err := ev.Client.DescribeVolumesWithContext(ev.Context, &ec2.DescribeVolumesInput{
Filters: []*ec2.Filter{&statusFilter},
statusFilter := types.Filter{Name: aws.String("status"), Values: []string{"available", "creating", "error"}}
result, err := ev.Client.DescribeVolumes(ev.Context, &ec2.DescribeVolumesInput{
Filters: []types.Filter{statusFilter},
})

if err != nil {
Expand All @@ -38,28 +40,28 @@ func (ev *EBSVolumes) getAll(c context.Context, configObj config.Config) ([]*str

// checking the nukable permissions
ev.VerifyNukablePermissions(volumeIds, func(id *string) error {
_, err := ev.Client.DeleteVolumeWithContext(ev.Context, &ec2.DeleteVolumeInput{
_, err := ev.Client.DeleteVolume(ev.Context, &ec2.DeleteVolumeInput{
VolumeId: id,
DryRun: awsgo.Bool(true),
DryRun: aws.Bool(true),
})
return err
})

return volumeIds, nil
}

func shouldIncludeEBSVolume(volume *ec2.Volume, configObj config.Config) bool {
func shouldIncludeEBSVolume(volume types.Volume, configObj config.Config) bool {
name := ""
for _, tag := range volume.Tags {
if tag != nil && aws.StringValue(tag.Key) == "Name" {
name = aws.StringValue(tag.Value)
if aws.ToString(tag.Key) == "Name" {
name = aws.ToString(tag.Value)
}
}

return configObj.EBSVolume.ShouldInclude(config.ResourceValue{
Name: &name,
Time: volume.CreateTime,
Tags: util.ConvertEC2TagsToMap(volume.Tags),
Tags: util.ConvertTypesTagsToMap(volume.Tags),
})
}

Expand All @@ -75,32 +77,36 @@ func (ev *EBSVolumes) nukeAll(volumeIds []*string) error {

for _, volumeID := range volumeIds {

if nukable, reason := ev.IsNukable(awsgo.StringValue(volumeID)); !nukable {
logging.Debugf("[Skipping] %s nuke because %v", awsgo.StringValue(volumeID), reason)
if nukable, reason := ev.IsNukable(aws.ToString(volumeID)); !nukable {
logging.Debugf("[Skipping] %s nuke because %v", aws.ToString(volumeID), reason)
continue
}

params := &ec2.DeleteVolumeInput{
VolumeId: volumeID,
}

_, err := ev.Client.DeleteVolumeWithContext(ev.Context, params)
_, err := ev.Client.DeleteVolume(ev.Context, params)

// Record status of this resource
e := report.Entry{
Identifier: aws.StringValue(volumeID),
Identifier: aws.ToString(volumeID),
ResourceType: "EBS Volume",
Error: err,
}
report.Record(e)

if err != nil {
if awsErr, isAwsErr := err.(awserr.Error); isAwsErr && awsErr.Code() == "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" {
logging.Debugf("EBS volume %s has already been deleted", *volumeID)
} else {
logging.Debugf("[Failed] %s", err)
var apiErr smithy.APIError
if goerr.As(err, &apiErr) {
switch apiErr.ErrorCode() {
case "VolumeInUse":
logging.Debugf("EBS volume %s can't be deleted, it is still attached to an active resource", *volumeID)
case "InvalidVolume.NotFound":
logging.Debugf("EBS volume %s has already been deleted", *volumeID)
default:
logging.Debugf("[Failed] %s", err)
}
}
} else {
deletedVolumeIDs = append(deletedVolumeIDs, volumeID)
Expand All @@ -109,9 +115,10 @@ func (ev *EBSVolumes) nukeAll(volumeIds []*string) error {
}

if len(deletedVolumeIDs) > 0 {
err := ev.Client.WaitUntilVolumeDeletedWithContext(ev.Context, &ec2.DescribeVolumesInput{
VolumeIds: deletedVolumeIDs,
})
waiter := ec2.NewVolumeDeletedWaiter(ev.Client)
err := waiter.Wait(ev.Context, &ec2.DescribeVolumesInput{
VolumeIds: aws.ToStringSlice(deletedVolumeIDs),
}, 5*time.Minute)
if err != nil {
logging.Debugf("[Failed] %s", err)
return errors.WithStackTrace(err)
Expand Down
52 changes: 21 additions & 31 deletions aws/resources/ebs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,28 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"

"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-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/gruntwork-io/cloud-nuke/config"
"github.com/stretchr/testify/require"
)

type mockedEBS struct {
ec2iface.EC2API
DeleteVolumeOutput ec2.DeleteVolumeOutput
EBSVolumesAPI
DescribeVolumesOutput ec2.DescribeVolumesOutput
DeleteVolumeOutput ec2.DeleteVolumeOutput
}

func (m mockedEBS) DeleteVolumeWithContext(_ awsgo.Context, input *ec2.DeleteVolumeInput, _ ...request.Option) (*ec2.DeleteVolumeOutput, error) {
return &m.DeleteVolumeOutput, nil
}

func (m mockedEBS) DescribeVolumesWithContext(_ awsgo.Context, input *ec2.DescribeVolumesInput, _ ...request.Option) (*ec2.DescribeVolumesOutput, error) {
func (m mockedEBS) DescribeVolumes(ctx context.Context, params *ec2.DescribeVolumesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVolumesOutput, error) {
return &m.DescribeVolumesOutput, nil
}

func (m mockedEBS) WaitUntilVolumeDeletedWithContext(_ awsgo.Context, input *ec2.DescribeVolumesInput, _ ...request.WaiterOption) error {
return nil
func (m mockedEBS) DeleteVolume(ctx context.Context, params *ec2.DeleteVolumeInput, optFns ...func(*ec2.Options)) (*ec2.DeleteVolumeOutput, error) {
return &m.DeleteVolumeOutput, nil
}

func TestEBSVolume_GetAll(t *testing.T) {

t.Parallel()

testName1 := "test-name1"
Expand All @@ -46,21 +38,21 @@ func TestEBSVolume_GetAll(t *testing.T) {
ev := EBSVolumes{
Client: mockedEBS{
DescribeVolumesOutput: ec2.DescribeVolumesOutput{
Volumes: []*ec2.Volume{
Volumes: []types.Volume{
{
VolumeId: awsgo.String(testVolume1),
CreateTime: awsgo.Time(now),
Tags: []*ec2.Tag{{
Key: awsgo.String("Name"),
Value: awsgo.String(testName1),
VolumeId: aws.String(testVolume1),
CreateTime: aws.Time(now),
Tags: []types.Tag{{
Key: aws.String("Name"),
Value: aws.String(testName1),
}},
},
{
VolumeId: awsgo.String(testVolume2),
CreateTime: awsgo.Time(now.Add(1)),
Tags: []*ec2.Tag{{
Key: awsgo.String("Name"),
Value: awsgo.String(testName2),
VolumeId: aws.String(testVolume2),
CreateTime: aws.Time(now.Add(1)),
Tags: []types.Tag{{
Key: aws.String("Name"),
Value: aws.String(testName2),
}},
},
}}}}
Expand Down Expand Up @@ -97,13 +89,12 @@ func TestEBSVolume_GetAll(t *testing.T) {
EBSVolume: tc.configObj,
})
require.NoError(t, err)
require.Equal(t, tc.expected, aws.StringValueSlice(names))
require.Equal(t, tc.expected, aws.ToStringSlice(names))
})
}
}

func TestEBSVolumne_NukeAll(t *testing.T) {

func TestEBSVolume_NukeAll(t *testing.T) {
t.Parallel()

ev := EBSVolumes{
Expand All @@ -114,5 +105,4 @@ func TestEBSVolumne_NukeAll(t *testing.T) {

err := ev.nukeAll([]*string{aws.String("test-volume")})
require.NoError(t, err)

}
23 changes: 14 additions & 9 deletions aws/resources/ebs_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@ package resources
import (
"context"

awsgo "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/gruntwork-io/cloud-nuke/config"
"github.com/gruntwork-io/go-commons/errors"
)

type EBSVolumesAPI interface {
DescribeVolumes(ctx context.Context, params *ec2.DescribeVolumesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVolumesOutput, error)
DeleteVolume(ctx context.Context, params *ec2.DeleteVolumeInput, optFns ...func(*ec2.Options)) (*ec2.DeleteVolumeOutput, error)
}

// EBSVolumes - represents all ebs volumes
type EBSVolumes struct {
BaseAwsResource
Client ec2iface.EC2API
Client EBSVolumesAPI
Region string
VolumeIds []string
}

func (ev *EBSVolumes) Init(session *session.Session) {
ev.Client = ec2.New(session)
func (ev *EBSVolumes) InitV2(cfg aws.Config) {
ev.Client = ec2.NewFromConfig(cfg)
}

func (ev *EBSVolumes) IsUsingV2() bool { return true }

// ResourceName - the simple name of the aws resource
func (ev *EBSVolumes) ResourceName() string {
return "ebs"
Expand All @@ -48,13 +53,13 @@ func (ev *EBSVolumes) GetAndSetIdentifiers(c context.Context, configObj config.C
return nil, err
}

ev.VolumeIds = awsgo.StringValueSlice(identifiers)
ev.VolumeIds = aws.ToStringSlice(identifiers)
return ev.VolumeIds, nil
}

// Nuke - nuke 'em all!!!
func (ev *EBSVolumes) Nuke(identifiers []string) error {
if err := ev.nukeAll(awsgo.StringSlice(identifiers)); err != nil {
if err := ev.nukeAll(aws.StringSlice(identifiers)); err != nil {
return errors.WithStackTrace(err)
}

Expand Down
25 changes: 12 additions & 13 deletions aws/resources/ecr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@ package resources
import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"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 (registry *ECR) getAll(c context.Context, configObj config.Config) ([]*string, error) {
repositoryNames := []*string{}
var repositoryNames []*string

paginator := ecr.NewDescribeRepositoriesPaginator(registry.Client, &ecr.DescribeRepositoriesInput{})
for paginator.HasMorePages() {
output, err := paginator.NextPage(c)
if err != nil {
return nil, errors.WithStackTrace(err)
}

paginator := func(output *ecr.DescribeRepositoriesOutput, lastPage bool) bool {
for _, repository := range output.Repositories {
if configObj.ECRRepository.ShouldInclude(config.ResourceValue{
Time: repository.CreatedAt,
Expand All @@ -23,13 +29,6 @@ func (registry *ECR) getAll(c context.Context, configObj config.Config) ([]*stri
repositoryNames = append(repositoryNames, repository.RepositoryName)
}
}
return !lastPage
}

param := &ecr.DescribeRepositoriesInput{}
err := registry.Client.DescribeRepositoriesPagesWithContext(registry.Context, param, paginator)
if err != nil {
return nil, errors.WithStackTrace(err)
}

return repositoryNames, nil
Expand All @@ -45,11 +44,11 @@ func (registry *ECR) nukeAll(repositoryNames []string) error {

for _, repositoryName := range repositoryNames {
params := &ecr.DeleteRepositoryInput{
Force: aws.Bool(true),
Force: true,
RepositoryName: aws.String(repositoryName),
}

_, err := registry.Client.DeleteRepositoryWithContext(registry.Context, params)
_, err := registry.Client.DeleteRepository(registry.Context, params)

// Record status of this resource
e := report.Entry{
Expand Down
Loading

0 comments on commit 334b2bc

Please sign in to comment.