Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

platform/api/aws/networking: detect broken networking #930

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions platform/api/aws/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ func (a *API) getSecurityGroupID(name string) (string, error) {
return "", fmt.Errorf("unable to get security group named %v: %v", name, err)
}

// Validates that the required networking resources are present, if not attempts to
// delete the Security Group, VPC, and relevant networking resources
if valid, err := a.validateNetworkResources(sgIds.SecurityGroups[0]); err != nil {
return "", err
} else if !valid {
return a.createSecurityGroup(name)
}

return *sgIds.SecurityGroups[0].GroupId, nil
}

Expand Down Expand Up @@ -340,3 +348,115 @@ func (a *API) getVPCID(sgId string) (string, error) {
}
return "", fmt.Errorf("no vpc found for security group %v", sgId)
}

func (a *API) validateNetworkResources(sg *ec2.SecurityGroup) (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name doesn't make completely clear what the bool return value is, or that it can delete resources as a side effect.

if sg.VpcId == nil || *sg.VpcId == "" {
return false, nil
}

vpcs, err := a.ec2.DescribeVpcs(&ec2.DescribeVpcsInput{
VpcIds: []*string{
sg.VpcId,
},
})
if err != nil || len(vpcs.Vpcs) < 1 {
return false, nil
}

subnets, err := a.ec2.DescribeSubnets(&ec2.DescribeSubnetsInput{
Filters: []*ec2.Filter{
{
Name: aws.String("vpc-id"),
Values: []*string{
sg.VpcId,
},
},
},
})
if err != nil || len(subnets.Subnets) < 1 {
// Delete the VPC to remove all networking resources used by kola
// as they will be recreated after this check.
err = a.DeleteVPC(sg.GroupId, vpcs.Vpcs[0])
return false, err
}

return true, nil
}

func (a *API) DeleteVPC(sgId *string, vpc *ec2.Vpc) error {
_, err := a.ec2.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{
GroupId: sgId,
})
if err != nil {
return fmt.Errorf("deleting security group: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the resource IDs included in err? If not, they should be added to these error messages.

}

rts, err := a.ec2.DescribeRouteTables(&ec2.DescribeRouteTablesInput{
Filters: []*ec2.Filter{
{
Name: aws.String("vpc-id"),
Values: []*string{
vpc.VpcId,
},
},
{
Name: aws.String("tag:CreatedBy"),
Values: []*string{
aws.String("mantle"),
},
},
},
})
if err != nil {
return fmt.Errorf("retrieving route tables: %v", err)
}

for _, rt := range rts.RouteTables {
_, err = a.ec2.DeleteRouteTable(&ec2.DeleteRouteTableInput{
RouteTableId: rt.RouteTableId,
})
if err != nil {
return fmt.Errorf("deleting route table: %v", err)
}
}

igws, err := a.ec2.DescribeInternetGateways(&ec2.DescribeInternetGatewaysInput{
Filters: []*ec2.Filter{
{
Name: aws.String("attachment.vpc-id"),
Values: []*string{
vpc.VpcId,
},
},
},
})
if err != nil {
return fmt.Errorf("retrieving internet gateways: %v", err)
}

for _, igw := range igws.InternetGateways {
_, err = a.ec2.DetachInternetGateway(&ec2.DetachInternetGatewayInput{
InternetGatewayId: igw.InternetGatewayId,
VpcId: vpc.VpcId,
})
if err != nil {
return fmt.Errorf("detaching internet gateway: %v", err)
}

_, err = a.ec2.DeleteInternetGateway(&ec2.DeleteInternetGatewayInput{
InternetGatewayId: igw.InternetGatewayId,
})
if err != nil {
return fmt.Errorf("deleting internet gateway: %v", err)
}
}

_, err = a.ec2.DeleteVpc(&ec2.DeleteVpcInput{
VpcId: vpc.VpcId,
})
if err != nil {
return fmt.Errorf("deleting vpc: %v", err)
}

return nil
}