diff --git a/aws/resource_aws_route53_record.go b/aws/resource_aws_route53_record.go index 7884b8a9fb3..f8dd02a7abe 100644 --- a/aws/resource_aws_route53_record.go +++ b/aws/resource_aws_route53_record.go @@ -235,6 +235,12 @@ func resourceAwsRoute53Record() *schema.Resource { Optional: true, Set: schema.HashString, }, + + "allow_overwrite": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, }, } } @@ -382,6 +388,16 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er return err } + // Protect existing DNS records which might be managed in another way + // Use UPSERT only if the overwrite flag is true or if the current action is an update + // Else CREATE is used and fail if the same record exists + var action string + if d.Get("allow_overwrite").(bool) || !d.IsNewResource() { + action = "UPSERT" + } else { + action = "CREATE" + } + // Create the new records. We abuse StateChangeConf for this to // retry for us since Route53 sometimes returns errors about another // operation happening at the same time. @@ -389,7 +405,7 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er Comment: aws.String("Managed by Terraform"), Changes: []*route53.Change{ { - Action: aws.String("UPSERT"), + Action: aws.String(action), ResourceRecordSet: rec, }, }, diff --git a/aws/resource_aws_route53_record_test.go b/aws/resource_aws_route53_record_test.go index cb54d39b437..714c72eab5a 100644 --- a/aws/resource_aws_route53_record_test.go +++ b/aws/resource_aws_route53_record_test.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + "regexp" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/route53" @@ -527,6 +529,24 @@ func TestAccAWSRoute53Record_multivalue_answer_basic(t *testing.T) { }) } +func TestAccAWSRoute53Record_allowOverwrite(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRoute53RecordDestroy, + Steps: []resource.TestStep{ + { + Config: testAccRoute53RecordConfig_allowOverwrite(false), + ExpectError: regexp.MustCompile("Tried to create resource record set \\[name='www.notexample.com.', type='A'] but it already exists"), + }, + { + Config: testAccRoute53RecordConfig_allowOverwrite(true), + Check: resource.ComposeTestCheckFunc(testAccCheckRoute53RecordExists("aws_route53_record.overwriting")), + }, + }, + }) +} + func testAccCheckRoute53RecordDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).r53conn for _, rs := range s.RootModule().Resources { @@ -612,6 +632,33 @@ func testAccCheckRoute53RecordExists(n string) resource.TestCheckFunc { } } +func testAccRoute53RecordConfig_allowOverwrite(allowOverwrite bool) string { + return fmt.Sprintf(` +resource "aws_route53_zone" "main" { + name = "notexample.com." +} + +resource "aws_route53_record" "default" { + zone_id = "${aws_route53_zone.main.zone_id}" + name = "www.notexample.com" + type = "A" + ttl = "30" + records = ["127.0.0.1"] +} + +resource "aws_route53_record" "overwriting" { + depends_on = ["aws_route53_record.default"] + + allow_overwrite = %v + zone_id = "${aws_route53_zone.main.zone_id}" + name = "www.notexample.com" + type = "A" + ttl = "30" + records = ["127.0.0.1"] +} +`, allowOverwrite) +} + const testAccRoute53RecordConfig = ` resource "aws_route53_zone" "main" { name = "notexample.com" diff --git a/website/docs/r/route53_record.html.markdown b/website/docs/r/route53_record.html.markdown index 46406071fa4..cb2a6e40b52 100644 --- a/website/docs/r/route53_record.html.markdown +++ b/website/docs/r/route53_record.html.markdown @@ -108,6 +108,7 @@ The following arguments are supported: * `latency_routing_policy` - (Optional) A block indicating a routing policy based on the latency between the requestor and an AWS region. Conflicts with any other routing policy. Documented below. * `weighted_routing_policy` - (Optional) A block indicating a weighted routing policy. Conflicts with any other routing policy. Documented below. * `multivalue_answer_routing_policy` - (Optional) A block indicating a multivalue answer routing policy. Conflicts with any other routing policy. +* `allow_overwrite` - (Optional) Allow creation of this record in Terraform to overwrite an existing record, if any. This does not prevent other resources within Terraform or manual Route53 changes from overwriting this record. `true` by default. Exactly one of `records` or `alias` must be specified: this determines whether it's an alias record.