-
-
Notifications
You must be signed in to change notification settings - Fork 358
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support for nuking dataSync Task(s) & dataSync Location(s). (#729)
- Loading branch information
Showing
10 changed files
with
551 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/datasync" | ||
"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 (dsl *DataSyncLocation) nukeAll(identifiers []*string) error { | ||
if len(identifiers) == 0 { | ||
logging.Debugf("[Data Sync Location] No Data Sync Locations found in region %s", dsl.Region) | ||
return nil | ||
} | ||
|
||
logging.Debugf("[Data Sync Location] Deleting all Data Sync Locations in region %s", dsl.Region) | ||
var deleted []*string | ||
|
||
for _, identifier := range identifiers { | ||
logging.Debugf("[Data Sync Location] Deleting Data Sync Location %s in region %s", *identifier, dsl.Region) | ||
_, err := dsl.Client.DeleteLocationWithContext(dsl.Context, &datasync.DeleteLocationInput{ | ||
LocationArn: identifier, | ||
}) | ||
if err != nil { | ||
logging.Debugf("[Data Sync Location] Error deleting Data Sync Location %s in region %s", *identifier, dsl.Region) | ||
return err | ||
} else { | ||
deleted = append(deleted, identifier) | ||
logging.Debugf("[Data Sync Location] Deleted Data Sync Location %s in region %s", *identifier, dsl.Region) | ||
} | ||
|
||
e := report.Entry{ | ||
Identifier: aws.StringValue(identifier), | ||
ResourceType: dsl.ResourceName(), | ||
Error: err, | ||
} | ||
report.Record(e) | ||
} | ||
|
||
logging.Debugf("[OK] %d Data Sync Location(s) nuked in %s", len(deleted), dsl.Region) | ||
return nil | ||
} | ||
|
||
func (dsl *DataSyncLocation) getAll(c context.Context, _ config.Config) ([]*string, error) { | ||
var identifiers []*string | ||
paginator := func(output *datasync.ListLocationsOutput, lastPage bool) bool { | ||
for _, location := range output.Locations { | ||
identifiers = append(identifiers, location.LocationArn) | ||
} | ||
|
||
return !lastPage | ||
} | ||
|
||
param := &datasync.ListLocationsInput{ | ||
MaxResults: aws.Int64(100), | ||
} | ||
|
||
if err := dsl.Client.ListLocationsPagesWithContext(c, param, paginator); err != nil { | ||
logging.Debugf("[Data Sync Location] Failed to list Data Sync Locations: %s", err) | ||
return nil, errors.WithStackTrace(err) | ||
} | ||
|
||
return identifiers, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/request" | ||
"github.com/aws/aws-sdk-go/service/datasync" | ||
"github.com/aws/aws-sdk-go/service/datasync/datasynciface" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
type mockDatasyncLocation struct { | ||
datasynciface.DataSyncAPI | ||
ListLocationsOutput datasync.ListLocationsOutput | ||
DeleteLocationOutput datasync.DeleteLocationOutput | ||
} | ||
|
||
func (m mockDatasyncLocation) ListLocationsPagesWithContext(_ aws.Context, _ *datasync.ListLocationsInput, callback func(*datasync.ListLocationsOutput, bool) bool, _ ...request.Option) error { | ||
callback(&m.ListLocationsOutput, true) | ||
return nil | ||
} | ||
|
||
func (m mockDatasyncLocation) DeleteLocationWithContext(aws.Context, *datasync.DeleteLocationInput, ...request.Option) (*datasync.DeleteLocationOutput, error) { | ||
return &m.DeleteLocationOutput, nil | ||
} | ||
|
||
func TestDataSyncLocation_NukeAll(t *testing.T) { | ||
|
||
t.Parallel() | ||
|
||
testName := "test-datasync-location" | ||
service := DataSyncLocation{ | ||
Client: mockDatasyncLocation{ | ||
DeleteLocationOutput: datasync.DeleteLocationOutput{}, | ||
}, | ||
} | ||
|
||
err := service.nukeAll([]*string{&testName}) | ||
assert.NoError(t, err) | ||
} | ||
|
||
func TestDataSyncLocation_GetAll(t *testing.T) { | ||
|
||
t.Parallel() | ||
|
||
testName1 := "test-datasync-location-1" | ||
testName2 := "test-datasync-location-2" | ||
location := DataSyncLocation{ | ||
Client: mockDatasyncLocation{ | ||
ListLocationsOutput: datasync.ListLocationsOutput{ | ||
Locations: []*datasync.LocationListEntry{ | ||
{ | ||
LocationArn: aws.String(fmt.Sprintf("arn::location/%s", testName1)), | ||
}, | ||
{ | ||
LocationArn: aws.String(fmt.Sprintf("arn::location/%s", testName2)), | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
tests := map[string]struct { | ||
configObj config.ResourceType | ||
expected []string | ||
}{ | ||
"emptyFilter": { | ||
configObj: config.ResourceType{}, | ||
expected: []string{fmt.Sprintf("arn::location/%s", testName1), fmt.Sprintf("arn::location/%s", testName2)}, | ||
}, | ||
} | ||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
names, err := location.getAll(context.Background(), config.Config{ | ||
DataSyncLocation: tc.configObj, | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expected, aws.StringValueSlice(names)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/session" | ||
"github.com/aws/aws-sdk-go/service/datasync" | ||
"github.com/aws/aws-sdk-go/service/datasync/datasynciface" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/gruntwork-io/go-commons/errors" | ||
) | ||
|
||
type DataSyncLocation struct { | ||
BaseAwsResource | ||
Client datasynciface.DataSyncAPI | ||
Region string | ||
DataSyncLocations []string | ||
} | ||
|
||
func (dsl *DataSyncLocation) GetAndSetResourceConfig(configObj config.Config) config.ResourceType { | ||
return configObj.DataSyncLocation | ||
} | ||
|
||
func (dsl *DataSyncLocation) Init(session *session.Session) { | ||
dsl.Client = datasync.New(session) | ||
} | ||
|
||
func (dsl *DataSyncLocation) ResourceName() string { return "data-sync-location" } | ||
|
||
func (dsl *DataSyncLocation) ResourceIdentifiers() []string { return dsl.DataSyncLocations } | ||
|
||
func (dsl *DataSyncLocation) MaxBatchSize() int { return 19 } | ||
|
||
func (dsl *DataSyncLocation) Nuke(identifiers []string) error { | ||
if err := dsl.nukeAll(aws.StringSlice(identifiers)); err != nil { | ||
return errors.WithStackTrace(err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (dsl *DataSyncLocation) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) { | ||
identifiers, err := dsl.getAll(c, configObj) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
dsl.DataSyncLocations = aws.StringValueSlice(identifiers) | ||
return dsl.DataSyncLocations, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/datasync" | ||
"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 (dst *DataSyncTask) nukeAll(identifiers []*string) error { | ||
if len(identifiers) == 0 { | ||
logging.Debugf("[Data Sync Task] No Data Sync Tasks found in region %s", dst.Region) | ||
return nil | ||
} | ||
|
||
logging.Debugf("[Data Sync Task] Deleting all Data Sync Tasks in region %s", dst.Region) | ||
var deleted []*string | ||
|
||
for _, identifier := range identifiers { | ||
logging.Debugf("[Data Sync Task] Deleting Data Sync Task %s in region %s", *identifier, dst.Region) | ||
_, err := dst.Client.DeleteTaskWithContext(dst.Context, &datasync.DeleteTaskInput{ | ||
TaskArn: identifier, | ||
}) | ||
if err != nil { | ||
logging.Debugf("[Data Sync Task] Error deleting Data Sync Task %s in region %s", *identifier, dst.Region) | ||
return err | ||
} else { | ||
deleted = append(deleted, identifier) | ||
logging.Debugf("[Data Sync Task] Deleted Data Sync Task %s in region %s", *identifier, dst.Region) | ||
} | ||
|
||
e := report.Entry{ | ||
Identifier: aws.StringValue(identifier), | ||
ResourceType: dst.ResourceName(), | ||
Error: err, | ||
} | ||
report.Record(e) | ||
} | ||
|
||
logging.Debugf("[OK] %d Data Sync Task(s) nuked in %s", len(deleted), dst.Region) | ||
return nil | ||
} | ||
|
||
func (dst *DataSyncTask) getAll(c context.Context, configObj config.Config) ([]*string, error) { | ||
var identifiers []*string | ||
paginator := func(output *datasync.ListTasksOutput, lastPage bool) bool { | ||
for _, task := range output.Tasks { | ||
if configObj.DataSyncTask.ShouldInclude(config.ResourceValue{ | ||
Name: task.Name, | ||
}) { | ||
identifiers = append(identifiers, task.TaskArn) | ||
} | ||
} | ||
|
||
return !lastPage | ||
} | ||
|
||
param := &datasync.ListTasksInput{ | ||
MaxResults: aws.Int64(100), | ||
} | ||
|
||
if err := dst.Client.ListTasksPagesWithContext(c, param, paginator); err != nil { | ||
logging.Debugf("[Data Sync Task] Failed to list data sync tasks: %s", err) | ||
return nil, errors.WithStackTrace(err) | ||
} | ||
|
||
return identifiers, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package resources | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/request" | ||
"github.com/aws/aws-sdk-go/service/datasync" | ||
"github.com/aws/aws-sdk-go/service/datasync/datasynciface" | ||
"github.com/gruntwork-io/cloud-nuke/config" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
type mockDataSyncTask struct { | ||
datasynciface.DataSyncAPI | ||
ListTasksOutput datasync.ListTasksOutput | ||
DeleteTaskOutput datasync.DeleteTaskOutput | ||
} | ||
|
||
func (m mockDataSyncTask) ListTasksPagesWithContext(_ aws.Context, _ *datasync.ListTasksInput, callback func(*datasync.ListTasksOutput, bool) bool, _ ...request.Option) error { | ||
callback(&m.ListTasksOutput, true) | ||
return nil | ||
} | ||
|
||
func (m mockDataSyncTask) DeleteTaskWithContext(aws.Context, *datasync.DeleteTaskInput, ...request.Option) (*datasync.DeleteTaskOutput, error) { | ||
return &m.DeleteTaskOutput, nil | ||
} | ||
|
||
func TestDataSyncTask_NukeAll(t *testing.T) { | ||
|
||
t.Parallel() | ||
|
||
testName := "test-datasync-task" | ||
task := DataSyncTask{ | ||
Client: mockDataSyncTask{ | ||
DeleteTaskOutput: datasync.DeleteTaskOutput{}, | ||
}, | ||
} | ||
|
||
err := task.nukeAll([]*string{&testName}) | ||
assert.NoError(t, err) | ||
} | ||
|
||
func TestDataSyncTask_GetAll(t *testing.T) { | ||
|
||
t.Parallel() | ||
|
||
testName1 := "test-task-1" | ||
testName2 := "test-task-2" | ||
|
||
task := DataSyncTask{Client: mockDataSyncTask{ | ||
ListTasksOutput: datasync.ListTasksOutput{ | ||
Tasks: []*datasync.TaskListEntry{ | ||
{ | ||
Name: &testName1, | ||
TaskArn: aws.String(fmt.Sprintf("arn::%s", testName1)), | ||
}, | ||
{ | ||
Name: &testName2, | ||
TaskArn: aws.String(fmt.Sprintf("arn::%s", testName2)), | ||
}, | ||
}, | ||
}, | ||
}} | ||
|
||
tests := map[string]struct { | ||
configObj config.ResourceType | ||
expected []string | ||
}{ | ||
"emptyFilter": { | ||
configObj: config.ResourceType{}, | ||
expected: []string{fmt.Sprintf("arn::%s", testName1), fmt.Sprintf("arn::%s", testName2)}, | ||
}, | ||
"nameExclusionFilter": { | ||
configObj: config.ResourceType{ | ||
ExcludeRule: config.FilterRule{ | ||
NamesRegExp: []config.Expression{{ | ||
RE: *regexp.MustCompile(testName1), | ||
}}, | ||
}}, | ||
expected: []string{fmt.Sprintf("arn::%s", testName2)}, | ||
}, | ||
} | ||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
names, err := task.getAll(context.Background(), config.Config{ | ||
DataSyncTask: tc.configObj, | ||
}) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expected, aws.StringValueSlice(names)) | ||
}) | ||
} | ||
} |
Oops, something went wrong.