Skip to content

Commit

Permalink
nuke implementation rds-proxy (#720)
Browse files Browse the repository at this point in the history
  • Loading branch information
james03160927 authored Jun 11, 2024
1 parent a111ffb commit b2ce0a4
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS res
| RDS | Neptune |
| RDS | Document DB instances |
| RDS | RDS parameter group |
| RDS | RDS Proxy |
| Security Hub | Hubs |
| Security Hub | Members |
| Security Hub | Administrators |
Expand Down Expand Up @@ -604,6 +605,7 @@ of the file that are supported are listed here.
| rds | DBInstances | ✅ (DB Name) | ✅ (Creation Time) | ✅ | ✅ |
| rds-parameter-group | RdsParameterGroup | ✅ (Group Name) | ❌ | ❌ | ✅ |
| rds-subnet-group | DBSubnetGroups | ✅ (DB Subnet Group Name) | ❌ | ❌ | ✅ |
| rds-proxy | RDSProxy | ✅ (proxy Name) | ✅ (Creation Time) | ❌ | ✅ |
| s3 | s3 | ✅ (Bucket Name) | ✅ (Creation Time) | ✅ | ✅ |
| s3-ap | s3AccessPoint | ✅ (Access point Name) | ❌ | ❌ | ✅ |
| s3-olap | S3ObjectLambdaAccessPoint | ✅ (Object Lambda Access point Name) | ❌ | ❌ | ✅ |
Expand Down
1 change: 1 addition & 0 deletions aws/resource_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func getRegisteredRegionalResources() []AwsResource {
&resources.DBInstances{},
&resources.DBSubnetGroups{},
&resources.DBClusters{},
&resources.RdsProxy{},
&resources.RdsSnapshot{},
&resources.RdsParameterGroup{},
&resources.RedshiftClusters{},
Expand Down
73 changes: 73 additions & 0 deletions aws/resources/rds_proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"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 (rdp *RdsProxy) getAll(_ context.Context, configObj config.Config) ([]*string, error) {
var names []*string
err := rdp.Client.DescribeDBProxiesPagesWithContext(
rdp.Context,
&rds.DescribeDBProxiesInput{},
func(page *rds.DescribeDBProxiesOutput, lastPage bool) bool {
for _, proxy := range page.DBProxies {
if configObj.RdsProxy.ShouldInclude(config.ResourceValue{
Name: proxy.DBProxyName,
Time: proxy.CreatedDate,
}) {
names = append(names, proxy.DBProxyName)
}
}

return !lastPage
})
if err != nil {
return nil, errors.WithStackTrace(err)
}

return names, nil
}

func (rdp *RdsProxy) nukeAll(identifiers []*string) error {
if len(identifiers) == 0 {
logging.Debugf("No RDS proxy in region %s", rdp.Region)
return nil
}

logging.Debugf("Deleting all DB Proxies in region %s", rdp.Region)
var deleted []*string

for _, identifier := range identifiers {
logging.Debugf("[RDS Proxy] Deleting %s in region %s", *identifier, rdp.Region)

_, err := rdp.Client.DeleteDBProxyWithContext(
rdp.Context,
&rds.DeleteDBProxyInput{
DBProxyName: identifier,
})
if err != nil {
logging.Errorf("[RDS Proxy] Error deleting RDS Proxy %s: %s", *identifier, err)
} else {
deleted = append(deleted, identifier)
logging.Debugf("[RDS Proxy] Deleted RDS Proxy %s", *identifier)
}

// Record status of this resource
e := report.Entry{
Identifier: aws.StringValue(identifier),
ResourceType: rdp.ResourceName(),
Error: err,
}
report.Record(e)
}

logging.Debugf("[OK] %d RDS DB proxi(s) nuked in %s", len(deleted), rdp.Region)
return nil
}
106 changes: 106 additions & 0 deletions aws/resources/rds_proxy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package resources

import (
"context"
"regexp"
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"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/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type mockedRdsProxy struct {
rdsiface.RDSAPI
DescribeDBProxiesOutput rds.DescribeDBProxiesOutput
DeleteDBProxyOutput rds.DeleteDBProxyOutput
}

func (m mockedRdsProxy) DescribeDBProxiesPagesWithContext(_ aws.Context, _ *rds.DescribeDBProxiesInput, callback func(*rds.DescribeDBProxiesOutput, bool) bool, _ ...request.Option) error {
callback(&m.DescribeDBProxiesOutput, true)
return nil
}

func (m mockedRdsProxy) DeleteDBProxyWithContext(aws.Context, *rds.DeleteDBProxyInput, ...request.Option) (*rds.DeleteDBProxyOutput, error) {
return &m.DeleteDBProxyOutput, nil
}

func TestRdsProxy_GetAll(t *testing.T) {

t.Parallel()

testName1 := "test-name1"
testName2 := "test-name2"
now := time.Now()
snapshot := RdsProxy{
Client: mockedRdsProxy{
DescribeDBProxiesOutput: rds.DescribeDBProxiesOutput{
DBProxies: []*rds.DBProxy{
{
DBProxyName: &testName1,
CreatedDate: &now,
},
{
DBProxyName: &testName2,
CreatedDate: aws.Time(now.Add(1)),
},
},
},
},
}

tests := map[string]struct {
configObj config.ResourceType
expected []string
}{
"emptyFilter": {
configObj: config.ResourceType{},
expected: []string{testName1, testName2},
},
"nameExclusionFilter": {
configObj: config.ResourceType{
ExcludeRule: config.FilterRule{
NamesRegExp: []config.Expression{{
RE: *regexp.MustCompile(testName1),
}}},
},
expected: []string{testName2},
},
"timeAfterExclusionFilter": {
configObj: config.ResourceType{
ExcludeRule: config.FilterRule{
TimeAfter: aws.Time(now.Add(-1 * time.Hour)),
}},
expected: []string{},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
names, err := snapshot.getAll(context.Background(), config.Config{
RdsProxy: tc.configObj,
})
require.NoError(t, err)
require.Equal(t, tc.expected, aws.StringValueSlice(names))
})
}
}

func TestRdsProxy_NukeAll(t *testing.T) {

t.Parallel()

testName := "test-db-proxy"
snapshot := RdsProxy{
Client: mockedRdsProxy{
DeleteDBProxyOutput: rds.DeleteDBProxyOutput{},
},
}

err := snapshot.nukeAll([]*string{&testName})
assert.NoError(t, err)
}
60 changes: 60 additions & 0 deletions aws/resources/rds_proxy_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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/rds"
"github.com/aws/aws-sdk-go/service/rds/rdsiface"
"github.com/gruntwork-io/cloud-nuke/config"
"github.com/gruntwork-io/go-commons/errors"
)

type RdsProxy struct {
BaseAwsResource
Client rdsiface.RDSAPI
Region string
GroupNames []string
}

func (pg *RdsProxy) Init(session *session.Session) {
pg.Client = rds.New(session)
}

func (pg *RdsProxy) ResourceName() string {
return "rds-proxy"
}

// ResourceIdentifiers - The names of the rds parameter group
func (pg *RdsProxy) ResourceIdentifiers() []string {
return pg.GroupNames
}

func (pg *RdsProxy) MaxBatchSize() int {
// Tentative batch size to ensure AWS doesn't throttle
return 49
}

func (pg *RdsProxy) GetAndSetResourceConfig(configObj config.Config) config.ResourceType {
return configObj.RdsProxy
}

func (pg *RdsProxy) GetAndSetIdentifiers(c context.Context, configObj config.Config) ([]string, error) {
identifiers, err := pg.getAll(c, configObj)
if err != nil {
return nil, err
}

pg.GroupNames = awsgo.StringValueSlice(identifiers)
return pg.GroupNames, nil
}

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

return nil
}
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type Config struct {
Redshift ResourceType `yaml:"Redshift"`
RdsSnapshot ResourceType `yaml:"RdsSnapshot"`
RdsParameterGroup ResourceType `yaml:"RdsParameterGroup"`
RdsProxy ResourceType `yaml:"RdsProxy"`
S3 ResourceType `yaml:"s3"`
S3AccessPoint ResourceType `yaml:"S3AccessPoint"`
S3ObjectLambdaAccessPoint ResourceType `yaml:"S3ObjectLambdaAccessPoint"`
Expand Down

0 comments on commit b2ce0a4

Please sign in to comment.