Skip to content

Commit

Permalink
Fixing dhcp nuke failing (gruntwork-io#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
james03160927 authored Jun 20, 2024
1 parent 238a784 commit cff6e67
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 5 deletions.
78 changes: 73 additions & 5 deletions aws/resources/ec2_dhcp_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,44 @@ func (v *EC2DhcpOption) getAll(_ context.Context, configObj config.Config) ([]*s
var dhcpOptionIds []*string
err := v.Client.DescribeDhcpOptionsPagesWithContext(v.Context, &ec2.DescribeDhcpOptionsInput{}, func(page *ec2.DescribeDhcpOptionsOutput, lastPage bool) bool {
for _, dhcpOption := range page.DhcpOptions {
// No specific filters to apply at this point, we can think about introducing
// filtering with name tag in the future. In the initial version, we just getAll
// without filtering.
dhcpOptionIds = append(dhcpOptionIds, dhcpOption.DhcpOptionsId)
var isEligibleForNuke = true

// check the dhcp is attached with any vpc
// if the vpc is default one, then omit the dhcp option id from result
vpcs, err := v.Client.DescribeVpcsWithContext(v.Context, &ec2.DescribeVpcsInput{
Filters: []*ec2.Filter{
{
Name: awsgo.String("dhcp-options-id"),
Values: []*string{dhcpOption.DhcpOptionsId},
},
},
})
if err != nil {
logging.Debugf("[Failed] %s", err)
continue
}

for _, vpc := range vpcs.Vpcs {
// check the vpc is the default one then set isEligible false as we dont need to remove the dhcp option of default vpc
if awsgo.BoolValue(vpc.IsDefault) {
logging.Debugf("[Skipping] %s is attached with a default vpc %s", awsgo.StringValue(dhcpOption.DhcpOptionsId), awsgo.StringValue(vpc.VpcId))
isEligibleForNuke = false
}

v.DhcpOptions[awsgo.StringValue(dhcpOption.DhcpOptionsId)] = DHCPOption{
Id: dhcpOption.DhcpOptionsId,
VpcId: vpc.VpcId,
}

}

if isEligibleForNuke {
// No specific filters to apply at this point, we can think about introducing
// filtering with name tag in the future. In the initial version, we just getAll
// without filtering.
dhcpOptionIds = append(dhcpOptionIds, dhcpOption.DhcpOptionsId)

}
}

return !lastPage
Expand All @@ -42,14 +76,48 @@ func (v *EC2DhcpOption) getAll(_ context.Context, configObj config.Config) ([]*s
return dhcpOptionIds, nil
}

func (v *EC2DhcpOption) disAssociatedAttachedVpcs(identifier *string) error {
if option, ok := v.DhcpOptions[awsgo.StringValue(identifier)]; ok {
logging.Debugf("[disAssociatedAttachedVpcs] detaching the dhcp option %s from %v", awsgo.StringValue(identifier), awsgo.StringValue(option.VpcId))

_, err := v.Client.AssociateDhcpOptionsWithContext(v.Context, &ec2.AssociateDhcpOptionsInput{
VpcId: option.VpcId,
DhcpOptionsId: awsgo.String("default"), // The ID of the DHCP options set, or default to associate no DHCP options with the VPC.
})
if err != nil {
logging.Debugf("[Failed] %s", err)
return errors.WithStackTrace(err)
}
logging.Debugf("[disAssociatedAttachedVpcs] Success dhcp option %s detached from %v", awsgo.StringValue(identifier), awsgo.StringValue(option.VpcId))
}

return nil
}

func (v *EC2DhcpOption) nuke(identifier *string) error {

err := v.disAssociatedAttachedVpcs(identifier)
if err != nil {
logging.Debugf("[disAssociatedAttachedVpcs] Failed %s", err)
return errors.WithStackTrace(err)
}

err = nukeDhcpOption(v.Client, identifier)
if err != nil {
logging.Debugf("[nukeDhcpOption] Failed %s", err)
return errors.WithStackTrace(err)
}
return nil
}

func (v *EC2DhcpOption) nukeAll(identifiers []*string) error {
for _, identifier := range identifiers {
if nukable, reason := v.IsNukable(awsgo.StringValue(identifier)); !nukable {
logging.Debugf("[Skipping] %s nuke because %v", awsgo.StringValue(identifier), reason)
continue
}

err := nukeDhcpOption(v.Client, identifier)
err := v.nuke(identifier)
if err != nil {
logging.Debugf("Failed to delete DHCP option w/ err: %s.", err)
} else {
Expand Down
9 changes: 9 additions & 0 deletions aws/resources/ec2_dhcp_option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type mockedEC2DhcpOption struct {
ec2iface.EC2API
DescribeDhcpOptionsOutput ec2.DescribeDhcpOptionsOutput
DeleteDhcpOptionsOutput ec2.DeleteDhcpOptionsOutput
DescribeVpcsOutput ec2.DescribeVpcsOutput
AssociateDhcpOptionsOutput ec2.AssociateDhcpOptionsOutput
}

func (m mockedEC2DhcpOption) DescribeDhcpOptionsPagesWithContext(_ awsgo.Context, _ *ec2.DescribeDhcpOptionsInput, fn func(*ec2.DescribeDhcpOptionsOutput, bool) bool, _ ...request.Option) error {
Expand All @@ -31,6 +33,13 @@ func (m mockedEC2DhcpOption) DeleteDhcpOptionsWithContext(_ awsgo.Context, _ *ec
return &m.DeleteDhcpOptionsOutput, nil
}

func (m mockedEC2DhcpOption) DescribeVpcsWithContext(awsgo.Context, *ec2.DescribeVpcsInput, ...request.Option) (*ec2.DescribeVpcsOutput, error) {
return &m.DescribeVpcsOutput, nil
}
func (m mockedEC2DhcpOption) AssociateDhcpOptionsWithContext(awsgo.Context, *ec2.AssociateDhcpOptionsInput, ...request.Option) (*ec2.AssociateDhcpOptionsOutput, error){
return &m.AssociateDhcpOptionsOutput, nil
}

func TestEC2DhcpOption_GetAll(t *testing.T) {

t.Parallel()
Expand Down
7 changes: 7 additions & 0 deletions aws/resources/ec2_dhcp_option_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@ import (
"github.com/gruntwork-io/go-commons/errors"
)

type DHCPOption struct {
Id *string
VpcId *string
}

type EC2DhcpOption struct {
BaseAwsResource
Client ec2iface.EC2API
Region string
VPCIds []string
DhcpOptions map[string]DHCPOption
}

func (v *EC2DhcpOption) Init(session *session.Session) {
v.Client = ec2.New(session)
v.DhcpOptions = make(map[string]DHCPOption)
}

// ResourceName - the simple name of the aws resource
Expand Down

0 comments on commit cff6e67

Please sign in to comment.