From 9545f26fa01c67d2339cb80163a9a0392c7e1e2a Mon Sep 17 00:00:00 2001 From: Phil Frost Date: Fri, 20 Mar 2015 13:29:11 -0400 Subject: [PATCH 1/2] Correct AWS VPC or route table read functions If the state file contained a VPC or a route table which no longer exists, Terraform would fail to create the correct plan, which is to recreate them. In the case of VPCs, this was due to incorrect error handling. The AWS SDK returns a aws.APIError, not a *aws.APIError on error. When the VPC no longer exists, upon attempting to refresh state Terraform would simply exit with an error. For route tables, the provider would recognize that the route table no longer existed, but would not make the appropriate call to update the state as such. Thus there'd be no crash, but also no plan to re-create the route table. --- builtin/providers/aws/resource_aws_route_table.go | 1 + builtin/providers/aws/resource_aws_vpc.go | 4 ++-- builtin/providers/aws/resource_aws_vpc_test.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route_table.go b/builtin/providers/aws/resource_aws_route_table.go index 6a4b1d3ca..5574e93b2 100644 --- a/builtin/providers/aws/resource_aws_route_table.go +++ b/builtin/providers/aws/resource_aws_route_table.go @@ -107,6 +107,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { return err } if rtRaw == nil { + d.SetId("") return nil } diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 0ef8aa570..727287039 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -238,7 +238,7 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { } log.Printf("[INFO] Deleting VPC: %s", d.Id()) if err := ec2conn.DeleteVPC(DeleteVpcOpts); err != nil { - ec2err, ok := err.(*aws.APIError) + ec2err, ok := err.(aws.APIError) if ok && ec2err.Code == "InvalidVpcID.NotFound" { return nil } @@ -258,7 +258,7 @@ func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { } resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { - if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { + if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { resp = nil } else { log.Printf("Error on VPCStateRefresh: %s", err) diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index 092f47806..ab97249a2 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -132,7 +132,7 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*aws.APIError) + ec2err, ok := err.(aws.APIError) if !ok { return err } From b49fba6b61886a4226738325ddd86d939f9351ff Mon Sep 17 00:00:00 2001 From: Phil Frost Date: Fri, 20 Mar 2015 14:44:42 -0400 Subject: [PATCH 2/2] Don't error when enabling DNS hostnames in a VPC The AWS API call ModifyVpcAttribute will allow only one attribute to be modified at a time. Modifying both results in the error: Fields for multiple attribute types specified: enableDnsHostnames, enableDnsSupport Retructure the provider to honor this restriction. Also, enable DNS support before attempting to enable DNS hostnames, since the former is a prerequisite of the latter. Additionally, fix what must have been a copy&paste error, setting enable_dns_support to the value of enable_dns_hostnames. --- builtin/providers/aws/resource_aws_vpc.go | 46 ++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 727287039..7b27f3b6e 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -185,29 +185,14 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { // Turn on partial mode d.Partial(true) vpcid := d.Id() - modifyOpts := &ec2.ModifyVPCAttributeRequest{ - VPCID: &vpcid, - } - if d.HasChange("enable_dns_hostnames") { - val := d.Get("enable_dns_hostnames").(bool) - modifyOpts.EnableDNSHostnames = &ec2.AttributeBooleanValue{ - Value: &val, - } - - log.Printf( - "[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", - d.Id(), modifyOpts) - if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { - return err - } - - d.SetPartial("enable_dns_hostnames") - } if d.HasChange("enable_dns_support") { - val := d.Get("enable_dns_hostnames").(bool) - modifyOpts.EnableDNSSupport = &ec2.AttributeBooleanValue{ - Value: &val, + val := d.Get("enable_dns_support").(bool) + modifyOpts := &ec2.ModifyVPCAttributeRequest{ + VPCID: &vpcid, + EnableDNSSupport: &ec2.AttributeBooleanValue{ + Value: &val, + }, } log.Printf( @@ -220,6 +205,25 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { d.SetPartial("enable_dns_support") } + if d.HasChange("enable_dns_hostnames") { + val := d.Get("enable_dns_hostnames").(bool) + modifyOpts := &ec2.ModifyVPCAttributeRequest{ + VPCID: &vpcid, + EnableDNSHostnames: &ec2.AttributeBooleanValue{ + Value: &val, + }, + } + + log.Printf( + "[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", + d.Id(), modifyOpts) + if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { + return err + } + + d.SetPartial("enable_dns_hostnames") + } + if err := setTags(ec2conn, d); err != nil { return err } else {