Skip to content

Commit 2a0791a

Browse files
isumegiimre-sumegi
authored andcommitted
CB-29500 - Haunter cannot delete VPCs with dependencies correctly
1 parent c18a216 commit 2a0791a

3 files changed

Lines changed: 348 additions & 116 deletions

File tree

aws/aws.go

Lines changed: 111 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,11 @@ func (p awsProvider) GetResources() ([]*types.Resource, error) {
225225
if vpcsErr != nil {
226226
return nil, vpcsErr
227227
}
228-
subnets, subnetsErr := getSubnets(p.GetCloudType(), ec2Clients)
229-
if subnetsErr != nil {
230-
return nil, subnetsErr
231-
}
232228
lbs, lbsErr := getLoadBalancers(p.GetCloudType(), elbClients)
233229
if lbsErr != nil {
234230
return nil, lbsErr
235231
}
236-
resources := append(append(vpcs, subnets...), lbs...)
232+
resources := append(vpcs, lbs...)
237233
return resources, nil
238234
}
239235

@@ -294,62 +290,6 @@ func getVpcs(cloudType types.CloudType, ec2Clients map[string]ec2Client) ([]*typ
294290
return vpcs, nil
295291
}
296292

297-
func getSubnets(cloudType types.CloudType, ec2Clients map[string]ec2Client) ([]*types.Resource, error) {
298-
log.Debug("[AWS] Fetching subnets")
299-
subnetChan := make(chan *types.Resource, 5)
300-
wg := sync.WaitGroup{}
301-
wg.Add(len(ec2Clients))
302-
303-
for r, c := range ec2Clients {
304-
log.Debugf("[AWS] Fetching subnets from region: %s", r)
305-
go func(region string, client ec2Client) {
306-
defer wg.Done()
307-
ec2Request := &ec2.DescribeSubnetsInput{}
308-
for {
309-
subnetsOutput, subnetsErr := client.DescribeSubnets(ec2Request)
310-
if subnetsErr != nil {
311-
log.Errorf("[AWS] Failed to fetch subnets in region %s, err: %s", region, subnetsErr)
312-
return
313-
} else {
314-
for _, subnet := range subnetsOutput.Subnets {
315-
tags := make(map[string]string)
316-
for _, tag := range subnet.Tags {
317-
tags[*tag.Key] = *tag.Value
318-
}
319-
newSubnet := &types.Resource{
320-
ID: *subnet.SubnetId,
321-
Name: tags["Name"],
322-
CloudType: cloudType,
323-
Region: region,
324-
Tags: tags,
325-
Owner: tags[ctx.OwnerLabel],
326-
ResourceType: types.Subnet,
327-
}
328-
subnetChan <- newSubnet
329-
}
330-
}
331-
if subnetsOutput.NextToken != nil {
332-
ec2Request.SetNextToken(*subnetsOutput.NextToken)
333-
} else {
334-
break
335-
}
336-
}
337-
}(r, c)
338-
}
339-
340-
go func() {
341-
wg.Wait()
342-
close(subnetChan)
343-
}()
344-
345-
var subnets []*types.Resource
346-
for subnet := range subnetChan {
347-
subnets = append(subnets, subnet)
348-
}
349-
350-
return subnets, nil
351-
}
352-
353293
func getLoadBalancers(cloudType types.CloudType, elbClients map[string]elbClient) ([]*types.Resource, error) {
354294
log.Debug("[AWS] Fetching load balancers")
355295
lbChan := make(chan *types.Resource, 5)
@@ -596,9 +536,8 @@ func (p awsProvider) TerminateResources(resources *types.ResourceContainer) []er
596536
elbClients := p.getElbClientsByRegion()
597537
ec2Clients, _ := p.getEc2AndCTClientsByRegion()
598538
deleteVpcsErr := deleteVpcs(ec2Clients, resources.Get(p.GetCloudType()))
599-
deleteSubnetsErr := deleteSubnets(ec2Clients, resources.Get(p.GetCloudType()))
600539
deleteLoadBalancersErr := deleteLoadBalancers(elbClients, resources.Get(p.GetCloudType()))
601-
return append(append(deleteVpcsErr, deleteSubnetsErr...), deleteLoadBalancersErr...)
540+
return append(deleteVpcsErr, deleteLoadBalancersErr...)
602541
}
603542

604543
func deleteVpcs(ec2Clients map[string]ec2Client, resources []*types.Resource) []error {
@@ -620,13 +559,9 @@ func deleteVpcs(ec2Clients map[string]ec2Client, resources []*types.Resource) []
620559
if ctx.DryRun {
621560
log.Infof("[AWS] Dry-run set, VPC not deleted: %s in region: %s", vpc.ID, region)
622561
} else {
623-
_, err := ec2Client.DeleteVpc(&ec2.DeleteVpcInput{
624-
VpcId: &vpc.ID,
625-
})
562+
err := deleteVpcWithDependencies(ec2Client, "N/A", vpc.ID, region)
626563
if err != nil {
627564
errChan <- err
628-
} else {
629-
log.Infof("[AWS] Deleting VPC: %s, region: %s", vpc.ID, region)
630565
}
631566
}
632567
}
@@ -645,50 +580,6 @@ func deleteVpcs(ec2Clients map[string]ec2Client, resources []*types.Resource) []
645580
return errs
646581
}
647582

648-
func deleteSubnets(ec2Clients map[string]ec2Client, resources []*types.Resource) []error {
649-
regionSubnets := map[string][]*types.Resource{}
650-
for _, resource := range resources {
651-
if resource.ResourceType == types.Subnet {
652-
regionSubnets[resource.Region] = append(regionSubnets[resource.Region], resource)
653-
}
654-
}
655-
656-
wg := sync.WaitGroup{}
657-
errChan := make(chan error)
658-
wg.Add(len(regionSubnets))
659-
660-
for r, s := range regionSubnets {
661-
go func(region string, ec2Client ec2Client, subnets []*types.Resource) {
662-
defer wg.Done()
663-
for _, subnet := range subnets {
664-
if ctx.DryRun {
665-
log.Infof("[AWS] Dry-run set, subnet not deleted: %s in region: %s", subnet.ID, region)
666-
} else {
667-
_, deleteErr := ec2Client.DeleteSubnet(&ec2.DeleteSubnetInput{
668-
SubnetId: &subnet.ID,
669-
})
670-
if deleteErr != nil {
671-
errChan <- deleteErr
672-
} else {
673-
log.Infof("[AWS] Deleting subnet: %s, region: %s", subnet.ID, region)
674-
}
675-
}
676-
}
677-
}(r, ec2Clients[r], s)
678-
}
679-
680-
go func() {
681-
wg.Wait()
682-
close(errChan)
683-
}()
684-
685-
var errs []error
686-
for err := range errChan {
687-
errs = append(errs, err)
688-
}
689-
return errs
690-
}
691-
692583
func deleteLoadBalancers(elbClients map[string]elbClient, resources []*types.Resource) []error {
693584
regionLoadBalancers := map[string][]*types.Resource{}
694585
for _, resource := range resources {
@@ -1203,6 +1094,78 @@ func deleteVpcWithDependencies(ec2Client ec2Client, stackName string, vpcId stri
12031094
}
12041095
}
12051096

1097+
log.Infof("[AWS] Deleting internet gateways of VPC: %s in stack: %s, region: %s", vpcId, stackName, region)
1098+
1099+
attachmentVpcIdFilter := &ec2.Filter{}
1100+
attachmentVpcIdFilter.SetName("attachment.vpc-id")
1101+
attachmentVpcIdFilter.SetValues([]*string{&vpcId})
1102+
igws, err := ec2Client.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{
1103+
Filters: []*ec2.Filter{attachmentVpcIdFilter},
1104+
})
1105+
if err != nil {
1106+
log.Errorf("[AWS] Failed to list internet gateways of VPC: %s in stack: %s, err: %s", vpcId, stackName, err)
1107+
return err
1108+
}
1109+
1110+
for _, igw := range igws.InternetGateways {
1111+
_, err = ec2Client.DetachInternetGateway(&ec2.DetachInternetGatewayInput{
1112+
InternetGatewayId: igw.InternetGatewayId,
1113+
VpcId: &vpcId,
1114+
})
1115+
if err != nil {
1116+
log.Errorf("[AWS] Failed to detach internet gateway: %s in stack: %s, err: %s", *igw.InternetGatewayId, stackName, err)
1117+
return err
1118+
}
1119+
1120+
_, err = ec2Client.DeleteInternetGateway(&ec2.DeleteInternetGatewayInput{
1121+
InternetGatewayId: igw.InternetGatewayId,
1122+
})
1123+
if err != nil {
1124+
log.Errorf("[AWS] Failed to delete internet gateway: %s in stack: %s, err: %s", *igw.InternetGatewayId, stackName, err)
1125+
return err
1126+
}
1127+
}
1128+
1129+
log.Infof("[AWS] Deleting route tables of VPC: %s in stack: %s, region: %s", vpcId, stackName, region)
1130+
1131+
rts, err := ec2Client.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
1132+
Filters: []*ec2.Filter{vpcIdFilter},
1133+
})
1134+
if err != nil {
1135+
log.Errorf("[AWS] Failed to list route tables of VPC: %s in stack: %s, err: %s", vpcId, stackName, err)
1136+
return err
1137+
}
1138+
1139+
for _, rt := range rts.RouteTables {
1140+
isMain := false
1141+
for _, assoc := range rt.Associations {
1142+
if assoc.Main != nil && *assoc.Main {
1143+
isMain = true
1144+
break
1145+
}
1146+
}
1147+
if !isMain {
1148+
for _, assoc := range rt.Associations {
1149+
if assoc.RouteTableAssociationId != nil && (assoc.Main == nil || !*assoc.Main) {
1150+
_, err := ec2Client.DisassociateRouteTable(&ec2.DisassociateRouteTableInput{
1151+
AssociationId: assoc.RouteTableAssociationId,
1152+
})
1153+
if err != nil {
1154+
log.Errorf("[AWS] Failed to disassociate route table: %s in stack: %s, err: %s", *rt.RouteTableId, stackName, err)
1155+
return err
1156+
}
1157+
}
1158+
}
1159+
_, err := ec2Client.DeleteRouteTable(&ec2.DeleteRouteTableInput{
1160+
RouteTableId: rt.RouteTableId,
1161+
})
1162+
if err != nil {
1163+
log.Errorf("[AWS] Failed to delete route table: %s in stack: %s, err: %s", *rt.RouteTableId, stackName, err)
1164+
return err
1165+
}
1166+
}
1167+
}
1168+
12061169
log.Infof("[AWS] Deleting subnets of VPC: %s in stack: %s, region: %s", vpcId, stackName, region)
12071170

12081171
subnets, err := ec2Client.DescribeSubnets(&ec2.DescribeSubnetsInput{
@@ -1222,6 +1185,26 @@ func deleteVpcWithDependencies(ec2Client ec2Client, stackName string, vpcId stri
12221185
}
12231186
}
12241187

1188+
acls, err := ec2Client.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{
1189+
Filters: []*ec2.Filter{vpcIdFilter},
1190+
})
1191+
if err != nil {
1192+
log.Errorf("[AWS] Failed to list network ACLs of VPC: %s in stack: %s, err: %s", vpcId, stackName, err)
1193+
return err
1194+
}
1195+
1196+
for _, acl := range acls.NetworkAcls {
1197+
if !*acl.IsDefault {
1198+
_, err := ec2Client.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{
1199+
NetworkAclId: acl.NetworkAclId,
1200+
})
1201+
if err != nil {
1202+
log.Errorf("[AWS] Failed to delete network ACL: %s in stack: %s, err: %s", *acl.NetworkAclId, stackName, err)
1203+
return err
1204+
}
1205+
}
1206+
}
1207+
12251208
log.Infof("[AWS] Deleting security groups of VPC: %s in stack: %s, region: %s", vpcId, stackName, region)
12261209

12271210
securityGroups, err := ec2Client.DescribeSecurityGroups(&ec2.DescribeSecurityGroupsInput{
@@ -1601,8 +1584,16 @@ type ec2Client interface {
16011584
DeleteVpc(input *ec2.DeleteVpcInput) (*ec2.DeleteVpcOutput, error)
16021585
DescribeSubnets(input *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error)
16031586
DeleteSubnet(input *ec2.DeleteSubnetInput) (*ec2.DeleteSubnetOutput, error)
1587+
DescribeInternetGateways(input *ec2.DescribeInternetGatewaysInput) (*ec2.DescribeInternetGatewaysOutput, error)
1588+
DetachInternetGateway(input *ec2.DetachInternetGatewayInput) (*ec2.DetachInternetGatewayOutput, error)
1589+
DeleteInternetGateway(input *ec2.DeleteInternetGatewayInput) (*ec2.DeleteInternetGatewayOutput, error)
1590+
DescribeRouteTables(input *ec2.DescribeRouteTablesInput) (*ec2.DescribeRouteTablesOutput, error)
1591+
DeleteRouteTable(input *ec2.DeleteRouteTableInput) (*ec2.DeleteRouteTableOutput, error)
1592+
DescribeNetworkAcls(input *ec2.DescribeNetworkAclsInput) (*ec2.DescribeNetworkAclsOutput, error)
1593+
DeleteNetworkAcl(input *ec2.DeleteNetworkAclInput) (*ec2.DeleteNetworkAclOutput, error)
16041594
DescribeSecurityGroups(input *ec2.DescribeSecurityGroupsInput) (*ec2.DescribeSecurityGroupsOutput, error)
16051595
DeleteSecurityGroup(input *ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error)
1596+
DisassociateRouteTable(input *ec2.DisassociateRouteTableInput) (*ec2.DisassociateRouteTableOutput, error)
16061597
TerminateInstances(input *ec2.TerminateInstancesInput) (*ec2.TerminateInstancesOutput, error)
16071598
WaitUntilInstanceTerminated(input *ec2.DescribeInstancesInput) error
16081599
DescribeAddresses(input *ec2.DescribeAddressesInput) (*ec2.DescribeAddressesOutput, error)
@@ -2737,6 +2728,14 @@ func getEc2Tags(ec2Tags []*ec2.Tag) types.Tags {
27372728
return tags
27382729
}
27392730

2731+
func getElbTags(elbTags []*elb.Tag) types.Tags {
2732+
tags := make(types.Tags, 0)
2733+
for _, t := range elbTags {
2734+
tags[*t.Key] = *t.Value
2735+
}
2736+
return tags
2737+
}
2738+
27402739
func getCFTags(cfTags []*cloudformation.Tag) types.Tags {
27412740
tags := make(types.Tags, 0)
27422741
for _, t := range cfTags {

0 commit comments

Comments
 (0)