provider/aws: Change of aws_subnet ipv6 causing update failure (#14545)

Fixes: #14530

When we found an update of IPv6 cidr block, we first tried to
disassociate the old cidr block association. This caused errors if there
was none, it threw an error, as we passed an empty associationId:

```
* aws_subnet.public_subnet.0: InvalidSubnetCidrBlockAssociationId.Malformed: The subnet CIDR block with association ID  is malformed
    status code: 400, request id: f438f468-9ca4-4000-ba78-63a0f25d390a
* aws_subnet.public_subnet[1]: 1 error(s) occurred:
```

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSubnet_'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/05/16 18:28:45 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSubnet_ -timeout 120m
=== RUN   TestAccAWSSubnet_importBasic
--- PASS: TestAccAWSSubnet_importBasic (55.40s)
=== RUN   TestAccAWSSubnet_basic
--- PASS: TestAccAWSSubnet_basic (53.62s)
=== RUN   TestAccAWSSubnet_ipv6
--- PASS: TestAccAWSSubnet_ipv6 (125.87s)
=== RUN   TestAccAWSSubnet_enableIpv6
--- PASS: TestAccAWSSubnet_enableIpv6 (88.88s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	323.787s
```
This commit is contained in:
Paul Stack 2017-05-16 23:06:28 +03:00 committed by GitHub
parent e2a37c1a51
commit 8b7f17c039
2 changed files with 88 additions and 42 deletions

View File

@ -170,25 +170,6 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("tags")
}
if d.HasChange("assign_ipv6_address_on_creation") {
modifyOpts := &ec2.ModifySubnetAttributeInput{
SubnetId: aws.String(d.Id()),
AssignIpv6AddressOnCreation: &ec2.AttributeBooleanValue{
Value: aws.Bool(d.Get("assign_ipv6_address_on_creation").(bool)),
},
}
log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
_, err := conn.ModifySubnetAttribute(modifyOpts)
if err != nil {
return err
} else {
d.SetPartial("assign_ipv6_address_on_creation")
}
}
if d.HasChange("map_public_ip_on_launch") {
modifyOpts := &ec2.ModifySubnetAttributeInput{
SubnetId: aws.String(d.Id()),
@ -217,30 +198,33 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
_, new := d.GetChange("ipv6_cidr_block")
//Firstly we have to disassociate the old IPv6 CIDR Block
disassociateOps := &ec2.DisassociateSubnetCidrBlockInput{
AssociationId: aws.String(d.Get("ipv6_cidr_block_association_id").(string)),
}
if v, ok := d.GetOk("ipv6_cidr_block_association_id"); ok {
_, err := conn.DisassociateSubnetCidrBlock(disassociateOps)
if err != nil {
return err
}
//Firstly we have to disassociate the old IPv6 CIDR Block
disassociateOps := &ec2.DisassociateSubnetCidrBlockInput{
AssociationId: aws.String(v.(string)),
}
// Wait for the CIDR to become disassociated
log.Printf(
"[DEBUG] Waiting for IPv6 CIDR (%s) to become disassociated",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"disassociating", "associated"},
Target: []string{"disassociated"},
Refresh: SubnetIpv6CidrStateRefreshFunc(conn, d.Id(), d.Get("ipv6_cidr_block_association_id").(string)),
Timeout: 3 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf(
"Error waiting for IPv6 CIDR (%s) to become disassociated: %s",
d.Id(), err)
_, err := conn.DisassociateSubnetCidrBlock(disassociateOps)
if err != nil {
return err
}
// Wait for the CIDR to become disassociated
log.Printf(
"[DEBUG] Waiting for IPv6 CIDR (%s) to become disassociated",
d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{"disassociating", "associated"},
Target: []string{"disassociated"},
Refresh: SubnetIpv6CidrStateRefreshFunc(conn, d.Id(), d.Get("ipv6_cidr_block_association_id").(string)),
Timeout: 3 * time.Minute,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf(
"Error waiting for IPv6 CIDR (%s) to become disassociated: %s",
d.Id(), err)
}
}
//Now we need to try and associate the new CIDR block
@ -260,7 +244,7 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
log.Printf(
"[DEBUG] Waiting for IPv6 CIDR (%s) to become associated",
d.Id())
stateConf = &resource.StateChangeConf{
stateConf := &resource.StateChangeConf{
Pending: []string{"associating", "disassociated"},
Target: []string{"associated"},
Refresh: SubnetIpv6CidrStateRefreshFunc(conn, d.Id(), *resp.Ipv6CidrBlockAssociation.AssociationId),
@ -275,6 +259,25 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("ipv6_cidr_block")
}
if d.HasChange("assign_ipv6_address_on_creation") {
modifyOpts := &ec2.ModifySubnetAttributeInput{
SubnetId: aws.String(d.Id()),
AssignIpv6AddressOnCreation: &ec2.AttributeBooleanValue{
Value: aws.Bool(d.Get("assign_ipv6_address_on_creation").(bool)),
},
}
log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
_, err := conn.ModifySubnetAttribute(modifyOpts)
if err != nil {
return err
} else {
d.SetPartial("assign_ipv6_address_on_creation")
}
}
d.Partial(false)
return resourceAwsSubnetRead(d, meta)

View File

@ -82,6 +82,33 @@ func TestAccAWSSubnet_ipv6(t *testing.T) {
})
}
func TestAccAWSSubnet_enableIpv6(t *testing.T) {
var subnet ec2.Subnet
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_subnet.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckSubnetDestroy,
Steps: []resource.TestStep{
{
Config: testAccSubnetConfigPreIpv6,
Check: resource.ComposeTestCheckFunc(
testAccCheckSubnetExists(
"aws_subnet.foo", &subnet),
),
},
{
Config: testAccSubnetConfigIpv6,
Check: resource.ComposeTestCheckFunc(
testAccCheckSubnetExists(
"aws_subnet.foo", &subnet),
),
},
},
})
}
func testAccCheckAwsSubnetIpv6BeforeUpdate(t *testing.T, subnet *ec2.Subnet) resource.TestCheckFunc {
return func(s *terraform.State) error {
if subnet.Ipv6CidrBlockAssociationSet == nil {
@ -192,6 +219,22 @@ resource "aws_subnet" "foo" {
}
`
const testAccSubnetConfigPreIpv6 = `
resource "aws_vpc" "foo" {
cidr_block = "10.10.0.0/16"
assign_generated_ipv6_cidr_block = true
}
resource "aws_subnet" "foo" {
cidr_block = "10.10.1.0/24"
vpc_id = "${aws_vpc.foo.id}"
map_public_ip_on_launch = true
tags {
Name = "tf-subnet-acc-test"
}
}
`
const testAccSubnetConfigIpv6 = `
resource "aws_vpc" "foo" {
cidr_block = "10.10.0.0/16"