Merge pull request #359 from terraform-providers/paddy_95_dns_ns

dns: Add special handling for ns records.
This commit is contained in:
Paddy 2017-11-07 16:46:38 -08:00 committed by GitHub
commit 8b2486cd15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 0 deletions

View File

@ -77,6 +77,33 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
},
}
// we need to replace NS record sets in the same call. That means
// we need to list all the current NS record sets attached to the
// zone and add them to the change as deletions. We can't just add
// new NS record sets, or we'll get an error about the NS record set
// already existing; see terraform-providers/terraform-provider-google#95.
// We also can't just remove the NS recordsets on creation, as at
// least one is required. So the solution is to "update in place" by
// putting the addition and the removal in the same API call.
if d.Get("type").(string) == "NS" {
log.Printf("[DEBUG] DNS record list request for %q", zone)
res, err := config.clientDns.ResourceRecordSets.List(project, zone).Do()
if err != nil {
return fmt.Errorf("Error retrieving record sets for %q: %s", zone, err)
}
var deletions []*dns.ResourceRecordSet
for _, record := range res.Rrsets {
if record.Type != "NS" {
continue
}
deletions = append(deletions, record)
}
if len(deletions) > 0 {
chg.Deletions = deletions
}
}
log.Printf("[DEBUG] DNS Record create request: %#v", chg)
chg, err = config.clientDns.Changes.Create(project, zone, chg).Do()
if err != nil {
@ -135,6 +162,14 @@ func resourceDnsRecordSetRead(d *schema.ResourceData, meta interface{}) error {
}
func resourceDnsRecordSetDelete(d *schema.ResourceData, meta interface{}) error {
// NS records must always have a value, so we short-circuit delete
// this allows terraform delete to work, but may have unexpected
// side-effects when deleting just that record set.
if d.Get("type").(string) == "NS" {
log.Println("[DEBUG] NS records can't be deleted due to API restrictions, so they're being left in place. See https://www.terraform.io/docs/providers/google/r/dns_record_set.html for more information.")
return nil
}
config := meta.(*Config)
project, err := getProject(d, config)

View File

@ -90,6 +90,24 @@ func TestAccDnsRecordSet_changeType(t *testing.T) {
})
}
func TestAccDnsRecordSet_ns(t *testing.T) {
zoneName := fmt.Sprintf("dnszone-test-ns-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckDnsRecordSetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDnsRecordSet_ns(zoneName, 300),
Check: resource.ComposeTestCheckFunc(
testAccCheckDnsRecordSetExists(
"google_dns_record_set.foobar", zoneName),
),
},
},
})
}
func testAccCheckDnsRecordSetDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
@ -157,6 +175,23 @@ func testAccDnsRecordSet_basic(zoneName string, addr2 string, ttl int) string {
`, zoneName, addr2, ttl)
}
func testAccDnsRecordSet_ns(name string, ttl int) string {
return fmt.Sprintf(`
resource "google_dns_managed_zone" "parent-zone" {
name = "%s"
dns_name = "hashicorptest.com."
description = "Test Description"
}
resource "google_dns_record_set" "foobar" {
managed_zone = "${google_dns_managed_zone.parent-zone.name}"
name = "hashicorptest.com."
type = "NS"
rrdatas = ["ns.hashicorp.services.", "ns2.hashicorp.services."]
ttl = %d
}
`, name, ttl)
}
func testAccDnsRecordSet_bigChange(zoneName string, ttl int) string {
return fmt.Sprintf(`
resource "google_dns_managed_zone" "parent-zone" {

View File

@ -10,6 +10,12 @@ description: |-
Manages a set of DNS records within Google Cloud DNS.
~> **Note:** The Google Cloud DNS API requires NS records be present at all
times. To accommodate this, when creating NS records, the default records
Google automatically creates will be silently overwritten. Also, when
destroying NS records, Terraform will not actually remove NS records, but will
report that it did.
## Example Usage
### Binding a DNS name to the ephemeral IP of a new instance: