Skip to content

Commit

Permalink
Merge pull request #968 from convox/existing-private-fix
Browse files Browse the repository at this point in the history
Fix upgrade for existing private-mode Racks
  • Loading branch information
ddollar authored Aug 2, 2016
2 parents c3207c0 + 6c94127 commit 6d670a9
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 33 deletions.
100 changes: 100 additions & 0 deletions api/cmd/formation/handler/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"regexp"
"strconv"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
)

Expand All @@ -31,6 +33,42 @@ func HandleEC2AvailabilityZones(req Request) (string, map[string]string, error)
return "", nil, fmt.Errorf("unknown RequestType: %s", req.RequestType)
}

// HandleEC2NatGateway handles the lifecycle of a Custom::EC2NatGateway
func HandleEC2NatGateway(req Request) (string, map[string]string, error) {
defer recoverFailure(req)

switch req.RequestType {
case "Create":
return "invalid", nil, fmt.Errorf("Custom::EC2NatGateway is no longer available")
case "Update":
return "invalid", nil, fmt.Errorf("Custom::EC2NatGateway is no longer available")
case "Delete":
fmt.Println("DELETING NATGATEWAY")
fmt.Printf("req %+v\n", req)
return EC2NatGatewayDelete(req)
}

return "", nil, fmt.Errorf("unknown RequestType: %s", req.RequestType)
}

// HandleEC2Route handles the lifecycle of a Custom::EC2Route
func HandleEC2Route(req Request) (string, map[string]string, error) {
defer recoverFailure(req)

switch req.RequestType {
case "Create":
return "invalid", nil, fmt.Errorf("Custom::EC2Route is no longer available")
case "Update":
return "invalid", nil, fmt.Errorf("Custom::EC2Route is no longer available")
case "Delete":
fmt.Println("DELETING ROUTE")
fmt.Printf("req %+v\n", req)
return EC2RouteDelete(req)
}

return "", nil, fmt.Errorf("unknown RequestType: %s", req.RequestType)
}

var regexMatchAvailabilityZones = regexp.MustCompile(`following availability zones: ([^.]+)`)

func EC2AvailabilityZonesCreate(req Request) (string, map[string]string, error) {
Expand Down Expand Up @@ -72,3 +110,65 @@ func EC2AvailabilityZonesDelete(req Request) (string, map[string]string, error)
// nop
return req.PhysicalResourceId, nil, nil
}

// EC2NatGatewayDelete deletes a Custom::EC2route
// TODO: delete
func EC2NatGatewayDelete(req Request) (string, map[string]string, error) {
_, err := EC2(req).DeleteNatGateway(&ec2.DeleteNatGatewayInput{
NatGatewayId: aws.String(req.PhysicalResourceId),
})

// block for 2 minutes until it's deleted
// Fixes subsequent CF error on deleting Elastic IP:
// API: ec2:disassociateAddress You do not have permission to access the specified resource.
for i := 0; i < 12; i++ {
resp, derr := EC2(req).DescribeNatGateways(&ec2.DescribeNatGatewaysInput{
NatGatewayIds: []*string{aws.String(req.PhysicalResourceId)},
})

if derr != nil {
fmt.Printf("EC2NatGatewayDelete error: %s\n", derr)

// if nat gateway not found, break
if ae, ok := derr.(awserr.Error); ok {
if ae.Code() == "InvalidParameterException" {
break
}
}
}

// if NAT gateway is deleted, break
if len(resp.NatGateways) == 1 {
n := resp.NatGateways[0]

if *n.State == "deleted" {
break
}
}

// sleep and retry
time.Sleep(10 * time.Second)
}

// return original DeleteNatGateway success / failure
return req.PhysicalResourceId, nil, err
}

// EC2RouteDelete deletes a Custom::EC2route
// TODO: delete
func EC2RouteDelete(req Request) (string, map[string]string, error) {
parts := strings.SplitN(req.PhysicalResourceId, "/", 2)

_, err := EC2(req).DeleteRoute(&ec2.DeleteRouteInput{
DestinationCidrBlock: aws.String(parts[1]),
RouteTableId: aws.String(parts[0]),
})

if ae, ok := err.(awserr.Error); ok {
if ae.Code() == "InvalidRoute.NotFound" {
return req.PhysicalResourceId, nil, nil
}
}

return req.PhysicalResourceId, nil, err
}
4 changes: 4 additions & 0 deletions api/cmd/formation/handler/formation.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ func HandleRequest(freq Request) error {
switch freq.ResourceType {
case "Custom::EC2AvailabilityZones":
physical, outputs, err = HandleEC2AvailabilityZones(freq)
case "Custom::EC2NatGateway":
physical, outputs, err = HandleEC2NatGateway(freq)
case "Custom::EC2Route":
physical, outputs, err = HandleEC2Route(freq)
case "Custom::ECRRepository":
physical, outputs, err = HandleECRRepository(freq)
case "Custom::ECSService":
Expand Down
66 changes: 33 additions & 33 deletions api/dist/kernel.json
Original file line number Diff line number Diff line change
Expand Up @@ -538,45 +538,45 @@
"VpcId": { "Ref": "Vpc" }
}
},
"NatGateway0": {
"Nat0": {
"Condition": "Private",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "NatIp0", "AllocationId" ] },
"AllocationId": { "Fn::GetAtt": [ "NatAddress0", "AllocationId" ] },
"SubnetId": { "Ref": "Subnet0" }
}
},
"NatGateway1": {
"Nat1": {
"Condition": "Private",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "NatIp1", "AllocationId" ] },
"AllocationId": { "Fn::GetAtt": [ "NatAddress1", "AllocationId" ] },
"SubnetId": { "Ref": "Subnet1" }
}
},
"NatGateway2": {
"Nat2": {
"Condition": "Private",
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "NatIp2", "AllocationId" ] },
"AllocationId": { "Fn::GetAtt": [ "NatAddress2", "AllocationId" ] },
"SubnetId": { "Ref": "Subnet2" }
}
},
"NatIp0": {
"NatAddress0": {
"Condition": "Private",
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatIp1": {
"NatAddress1": {
"Condition": "Private",
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatIp2": {
"NatAddress2": {
"Condition": "Private",
"Type": "AWS::EC2::EIP",
"Properties": {
Expand Down Expand Up @@ -694,9 +694,9 @@
"RouteTableId": { "Ref": "Routes" }
}
},
"RoutesPrivate0": {
"RouteTablePrivate0": {
"Condition": "Private",
"DependsOn": [ "NatGateway0" ],
"DependsOn": [ "Nat0" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Fn::If": [ "BlankExistingVpc",
Expand All @@ -705,9 +705,9 @@
] }
}
},
"RoutesPrivate1": {
"RouteTablePrivate1": {
"Condition": "Private",
"DependsOn": [ "NatGateway1" ],
"DependsOn": [ "Nat1" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Fn::If": [ "BlankExistingVpc",
Expand All @@ -716,9 +716,9 @@
] }
}
},
"RoutesPrivate2": {
"RouteTablePrivate2": {
"Condition": "Private",
"DependsOn": [ "NatGateway2" ],
"DependsOn": [ "Nat2" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Fn::If": [ "BlankExistingVpc",
Expand All @@ -727,34 +727,34 @@
] }
}
},
"RoutePrivateDefault0": {
"RouteDefaultPrivate0": {
"Condition": "Private",
"DependsOn": [ "NatGateway0", "RoutesPrivate0" ],
"DependsOn": [ "Nat0", "RouteTablePrivate0" ],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway0" },
"RouteTableId": { "Ref": "RoutesPrivate0" }
"NatGatewayId": { "Ref": "Nat0" },
"RouteTableId": { "Ref": "RouteTablePrivate0" }
}
},
"RoutePrivateDefault1": {
"RouteDefaultPrivate1": {
"Condition": "Private",
"DependsOn": [ "NatGateway1", "RoutesPrivate1" ],
"DependsOn": [ "Nat1", "RouteTablePrivate1" ],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway1" },
"RouteTableId": { "Ref": "RoutesPrivate1" }
"NatGatewayId": { "Ref": "Nat1" },
"RouteTableId": { "Ref": "RouteTablePrivate1" }
}
},
"RoutePrivateDefault2": {
"RouteDefaultPrivate2": {
"Condition": "Private",
"DependsOn": [ "NatGateway2", "RoutesPrivate2" ],
"DependsOn": [ "Nat2", "RouteTablePrivate2" ],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway2" },
"RouteTableId": { "Ref": "RoutesPrivate2" }
"NatGatewayId": { "Ref": "Nat2" },
"RouteTableId": { "Ref": "RouteTablePrivate2" }
}
},
"Subnet0Routes": {
Expand Down Expand Up @@ -786,29 +786,29 @@
},
"SubnetPrivate0Routes": {
"Condition": "Private",
"DependsOn": [ "SubnetPrivate0", "RoutesPrivate0" ],
"DependsOn": [ "SubnetPrivate0", "RouteTablePrivate0" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetPrivate0" },
"RouteTableId": { "Ref": "RoutesPrivate0" }
"RouteTableId": { "Ref": "RouteTablePrivate0" }
}
},
"SubnetPrivate1Routes": {
"Condition": "Private",
"DependsOn": [ "SubnetPrivate1", "RoutesPrivate1" ],
"DependsOn": [ "SubnetPrivate1", "RouteTablePrivate1" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetPrivate1" },
"RouteTableId": { "Ref": "RoutesPrivate1" }
"RouteTableId": { "Ref": "RouteTablePrivate1" }
}
},
"SubnetPrivate2Routes": {
"Condition": "Private",
"DependsOn": [ "SubnetPrivate2", "RoutesPrivate2" ],
"DependsOn": [ "SubnetPrivate2", "RouteTablePrivate2" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetPrivate2" },
"RouteTableId": { "Ref": "RoutesPrivate2" }
"RouteTableId": { "Ref": "RouteTablePrivate2" }
}
},
"SecurityGroup": {
Expand Down

0 comments on commit 6d670a9

Please sign in to comment.