Skip to content

Commit

Permalink
resource/aws_vpc: Refactor to use keyvaluetags and call Read after Cr…
Browse files Browse the repository at this point in the history
…eate

Reference: #7926

In preparation for provider-wide ignore and default tag logic, here we refactor this resource to use the consistent keyvaluetags handling. The previous `setTags()` logic was always performing retries only necessary for resource creation and not following recommended practices to call the `Read` function after `Create`.

Output from acceptance testing:

```
--- PASS: TestAccAWSVpc_disappears (16.21s)
--- PASS: TestAccAWSVpc_coreMismatchedDiffs (23.55s)
--- PASS: TestAccAWSVpc_DisabledDnsSupport (28.46s)
--- PASS: TestAccAWSVpc_classiclinkOptionSet (28.64s)
--- PASS: TestAccAWSVpc_bothDnsOptionsSet (28.66s)
--- PASS: TestAccAWSVpc_classiclinkDnsSupportOptionSet (29.10s)
--- PASS: TestAccAWSVpc_basic (29.31s)
--- PASS: TestAccAWSVpc_update (40.02s)
--- PASS: TestAccAWSVpc_tags (45.37s)
--- PASS: TestAccAWSVpc_AssignGeneratedIpv6CidrBlock (62.90s)
--- PASS: TestAccAWSVpc_Tenancy (62.94s)
```
  • Loading branch information
bflad committed Oct 1, 2019
1 parent 8b88f68 commit a23d496
Showing 1 changed file with 103 additions and 9 deletions.
112 changes: 103 additions & 9 deletions aws/resource_aws_vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsVpc() *schema.Resource {
Expand Down Expand Up @@ -171,8 +172,96 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error {
}
}

// Update our attributes and return
return resourceAwsVpcUpdate(d, meta)
// You cannot modify the DNS resolution and DNS hostnames attributes in the same request. Use separate requests for each attribute.
// Reference: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyVpcAttribute.html

if d.Get("enable_dns_hostnames").(bool) {
input := &ec2.ModifyVpcAttributeInput{
EnableDnsHostnames: &ec2.AttributeBooleanValue{
Value: aws.Bool(true),
},
VpcId: aws.String(d.Id()),
}

if _, err := conn.ModifyVpcAttribute(input); err != nil {
return fmt.Errorf("error enabling VPC (%s) DNS hostnames: %s", d.Id(), err)
}

d.SetPartial("enable_dns_hostnames")
}

// By default, only the enableDnsSupport attribute is set to true in a VPC created any other way.
// Reference: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support

if !d.Get("enable_dns_support").(bool) {
input := &ec2.ModifyVpcAttributeInput{
EnableDnsSupport: &ec2.AttributeBooleanValue{
Value: aws.Bool(false),
},
VpcId: aws.String(d.Id()),
}

if _, err := conn.ModifyVpcAttribute(input); err != nil {
return fmt.Errorf("error disabling VPC (%s) DNS support: %s", d.Id(), err)
}

d.SetPartial("enable_dns_support")
}

if d.Get("enable_classiclink").(bool) {
input := &ec2.EnableVpcClassicLinkInput{
VpcId: aws.String(d.Id()),
}

if _, err := conn.EnableVpcClassicLink(input); err != nil {
return fmt.Errorf("error enabling VPC (%s) ClassicLink: %s", d.Id(), err)
}

d.SetPartial("enable_classiclink")
}

if d.Get("enable_classiclink_dns_support").(bool) {
input := &ec2.EnableVpcClassicLinkDnsSupportInput{
VpcId: aws.String(d.Id()),
}

if _, err := conn.EnableVpcClassicLinkDnsSupport(input); err != nil {
return fmt.Errorf("error enabling VPC (%s) ClassicLink DNS support: %s", d.Id(), err)
}

d.SetPartial("enable_classiclink_dns_support")
}

if v := d.Get("tags").(map[string]interface{}); len(v) > 0 {
// Handle EC2 eventual consistency on creation
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
err := keyvaluetags.Ec2UpdateTags(conn, d.Id(), nil, v)

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

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if isResourceTimeoutError(err) {
err = keyvaluetags.Ec2UpdateTags(conn, d.Id(), nil, v)
}

if err != nil {
return fmt.Errorf("error adding tags: %s", err)
}

d.SetPartial("tags")
}

d.Partial(false)

return resourceAwsVpcRead(d, meta)
}

func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -205,8 +294,9 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
}.String()
d.Set("arn", arn)

// Tags
d.Set("tags", tagsToMap(vpc.Tags))
if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(vpc.Tags).IgnoreAws().Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

d.Set("owner_id", vpc.OwnerId)

Expand Down Expand Up @@ -404,7 +494,7 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("enable_classiclink_dns_support")
}

if d.HasChange("assign_generated_ipv6_cidr_block") && !d.IsNewResource() {
if d.HasChange("assign_generated_ipv6_cidr_block") {
toAssign := d.Get("assign_generated_ipv6_cidr_block").(bool)

log.Printf("[INFO] Modifying assign_generated_ipv6_cidr_block to %#v", toAssign)
Expand Down Expand Up @@ -445,7 +535,7 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("assign_generated_ipv6_cidr_block")
}

if d.HasChange("instance_tenancy") && !d.IsNewResource() {
if d.HasChange("instance_tenancy") {
modifyOpts := &ec2.ModifyVpcTenancyInput{
VpcId: aws.String(vpcid),
InstanceTenancy: aws.String(d.Get("instance_tenancy").(string)),
Expand All @@ -460,9 +550,13 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("instance_tenancy")
}

if err := setTags(conn, d); err != nil {
return err
} else {
if d.HasChange("tags") {
o, n := d.GetChange("tags")

if err := keyvaluetags.Ec2UpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating tags: %s", err)
}

d.SetPartial("tags")
}

Expand Down

0 comments on commit a23d496

Please sign in to comment.