Skip to content

Commit

Permalink
Merge pull request #6394 from terraform-providers/b-aws_vpc-ipv6-on-c…
Browse files Browse the repository at this point in the history
…reate

resource/aws_vpc: Wait for IPv6 association on Create
  • Loading branch information
bflad authored Nov 8, 2018
2 parents 3dfa533 + 2b41d36 commit d5c454c
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 192 deletions.
99 changes: 56 additions & 43 deletions aws/resource_aws_vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error {
d.Id(), err)
}

if len(vpc.Ipv6CidrBlockAssociationSet) > 0 && vpc.Ipv6CidrBlockAssociationSet[0] != nil {
log.Printf("[DEBUG] Waiting for EC2 VPC (%s) IPv6 CIDR to become associated", d.Id())
if err := waitForEc2VpcIpv6CidrBlockAssociationCreate(conn, d.Id(), aws.StringValue(vpcResp.Vpc.Ipv6CidrBlockAssociationSet[0].AssociationId)); err != nil {
return fmt.Errorf("error waiting for EC2 VPC (%s) IPv6 CIDR to become associated: %s", d.Id(), err)
}
}

// Update our attributes and return
return resourceAwsVpcUpdate(d, meta)
}
Expand Down Expand Up @@ -202,7 +209,7 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
d.Set("ipv6_cidr_block", "")

for _, a := range vpc.Ipv6CidrBlockAssociationSet {
if *a.Ipv6CidrBlockState.State == "associated" { //we can only ever have 1 IPv6 block associated at once
if aws.StringValue(a.Ipv6CidrBlockState.State) == ec2.VpcCidrBlockStateCodeAssociated { //we can only ever have 1 IPv6 block associated at once
d.Set("assign_generated_ipv6_cidr_block", true)
d.Set("ipv6_association_id", a.AssociationId)
d.Set("ipv6_cidr_block", a.Ipv6CidrBlock)
Expand Down Expand Up @@ -407,45 +414,24 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error {
return err
}

// Wait for the CIDR to become available
log.Printf(
"[DEBUG] Waiting for IPv6 CIDR (%s) to become associated",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"associating", "disassociated"},
Target: []string{"associated"},
Refresh: Ipv6CidrStateRefreshFunc(conn, d.Id(), *resp.Ipv6CidrBlockAssociation.AssociationId),
Timeout: 1 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf(
"Error waiting for IPv6 CIDR (%s) to become associated: %s",
d.Id(), err)
log.Printf("[DEBUG] Waiting for EC2 VPC (%s) IPv6 CIDR to become associated", d.Id())
if err := waitForEc2VpcIpv6CidrBlockAssociationCreate(conn, d.Id(), aws.StringValue(resp.Ipv6CidrBlockAssociation.AssociationId)); err != nil {
return fmt.Errorf("error waiting for EC2 VPC (%s) IPv6 CIDR to become associated: %s", d.Id(), err)
}
} else {
associationID := d.Get("ipv6_association_id").(string)
modifyOpts := &ec2.DisassociateVpcCidrBlockInput{
AssociationId: aws.String(d.Get("ipv6_association_id").(string)),
AssociationId: aws.String(associationID),
}
log.Printf("[INFO] Disabling assign_generated_ipv6_cidr_block vpc attribute for %s: %#v",
d.Id(), modifyOpts)
if _, err := conn.DisassociateVpcCidrBlock(modifyOpts); err != nil {
return err
}

// Wait for the CIDR to become available
log.Printf(
"[DEBUG] Waiting for IPv6 CIDR (%s) to become disassociated",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"disassociating", "associated"},
Target: []string{"disassociated"},
Refresh: Ipv6CidrStateRefreshFunc(conn, d.Id(), d.Get("ipv6_association_id").(string)),
Timeout: 1 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf(
"Error waiting for IPv6 CIDR (%s) to become disassociated: %s",
d.Id(), err)
log.Printf("[DEBUG] Waiting for EC2 VPC (%s) IPv6 CIDR to become disassociated", d.Id())
if err := waitForEc2VpcIpv6CidrBlockAssociationDelete(conn, d.Id(), associationID); err != nil {
return fmt.Errorf("error waiting for EC2 VPC (%s) IPv6 CIDR to become disassociated: %s", d.Id(), err)
}
}

Expand Down Expand Up @@ -552,28 +538,24 @@ func Ipv6CidrStateRefreshFunc(conn *ec2.EC2, id string, associationId string) re
VpcIds: []*string{aws.String(id)},
}
resp, err := conn.DescribeVpcs(describeVpcOpts)

if isAWSErr(err, "InvalidVpcID.NotFound", "") {
return nil, "", nil
}

if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcID.NotFound" {
resp = nil
} else {
log.Printf("Error on VPCStateRefresh: %s", err)
return nil, "", err
}
return nil, "", err
}

if resp == nil {
if resp == nil || len(resp.Vpcs) == 0 || resp.Vpcs[0] == nil || resp.Vpcs[0].Ipv6CidrBlockAssociationSet == nil {
// Sometimes AWS just has consistency issues and doesn't see
// our instance yet. Return an empty state.
return nil, "", nil
}

if resp.Vpcs[0].Ipv6CidrBlockAssociationSet == nil {
return nil, "", nil
}

for _, association := range resp.Vpcs[0].Ipv6CidrBlockAssociationSet {
if *association.AssociationId == associationId {
return association, *association.Ipv6CidrBlockState.State, nil
if aws.StringValue(association.AssociationId) == associationId {
return association, aws.StringValue(association.Ipv6CidrBlockState.State), nil
}
}

Expand Down Expand Up @@ -733,3 +715,34 @@ func vpcDescribe(conn *ec2.EC2, vpcId string) (*ec2.Vpc, error) {
return nil, fmt.Errorf("Found %d VPCs for %s, expected 1", n, vpcId)
}
}

func waitForEc2VpcIpv6CidrBlockAssociationCreate(conn *ec2.EC2, vpcID, associationID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.VpcCidrBlockStateCodeAssociating,
ec2.VpcCidrBlockStateCodeDisassociated,
},
Target: []string{ec2.VpcCidrBlockStateCodeAssociated},
Refresh: Ipv6CidrStateRefreshFunc(conn, vpcID, associationID),
Timeout: 1 * time.Minute,
}
_, err := stateConf.WaitForState()

return err
}

func waitForEc2VpcIpv6CidrBlockAssociationDelete(conn *ec2.EC2, vpcID, associationID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.VpcCidrBlockStateCodeAssociated,
ec2.VpcCidrBlockStateCodeDisassociating,
},
Target: []string{ec2.VpcCidrBlockStateCodeDisassociated},
Refresh: Ipv6CidrStateRefreshFunc(conn, vpcID, associationID),
Timeout: 1 * time.Minute,
NotFoundChecks: 1,
}
_, err := stateConf.WaitForState()

return err
}
Loading

0 comments on commit d5c454c

Please sign in to comment.