dns: Add special handling for ns records.

Cloud DNS requires every managed zone to have an NS record at all times.
This means if people want to manage their own NS records, we need to add
their new record and remove the old one in the same call. It also means
we can't delete NS records, as we wouldn't know what to replace it with.
So deleting of NS records short-circuits. For the case of `terraform
destroy`, this prevents the error. It does mean if the user explicitly
tries to remove their NS zone from their project, it silently does
nothing, but that's unavoidable unless we want to A) restore a default
value (and it looks like the default values change from zone to zone?
And that is arguably just as unexpected?) or B) let the (arguably more
reasonable) `terraform destroy` case be impossible.
This commit is contained in:
Paddy 2017-08-25 02:08:35 -07:00
parent a5b13bd6c6
commit b2ff683868
2 changed files with 61 additions and 0 deletions

View File

@ -77,6 +77,25 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
},
}
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 +154,13 @@ 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" {
return nil
}
config := meta.(*Config)
project, err := getProject(d, config)

View File

@ -84,6 +84,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)
@ -151,6 +169,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" {