Add import support to google_dns_record_set (#895)

* Add import support to google_dns_record_set

* Add import test to NS record

* Minimize diff change

* Improve docs

* Make error message more helpful

* Add note about trailing dot at the end of the record name
This commit is contained in:
Vincent Roseberry 2018-01-17 11:19:55 -08:00 committed by GitHub
parent d0f5fec463
commit fc7c0ce74a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 6 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/dns/v1" "google.golang.org/api/dns/v1"
"strings"
) )
func resourceDnsRecordSet() *schema.Resource { func resourceDnsRecordSet() *schema.Resource {
@ -14,6 +15,9 @@ func resourceDnsRecordSet() *schema.Resource {
Read: resourceDnsRecordSetRead, Read: resourceDnsRecordSetRead,
Delete: resourceDnsRecordSetDelete, Delete: resourceDnsRecordSetDelete,
Update: resourceDnsRecordSetUpdate, Update: resourceDnsRecordSetUpdate,
Importer: &schema.ResourceImporter{
State: resourceDnsRecordSetImportState,
},
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"managed_zone": &schema.Schema{ "managed_zone": &schema.Schema{
@ -64,14 +68,16 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
return err return err
} }
name := d.Get("name").(string)
zone := d.Get("managed_zone").(string) zone := d.Get("managed_zone").(string)
rType := d.Get("type").(string)
// Build the change // Build the change
chg := &dns.Change{ chg := &dns.Change{
Additions: []*dns.ResourceRecordSet{ Additions: []*dns.ResourceRecordSet{
&dns.ResourceRecordSet{ &dns.ResourceRecordSet{
Name: d.Get("name").(string), Name: name,
Type: d.Get("type").(string), Type: rType,
Ttl: int64(d.Get("ttl").(int)), Ttl: int64(d.Get("ttl").(int)),
Rrdatas: rrdata(d), Rrdatas: rrdata(d),
}, },
@ -86,7 +92,7 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
// We also can't just remove the NS recordsets on creation, as at // 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 // least one is required. So the solution is to "update in place" by
// putting the addition and the removal in the same API call. // putting the addition and the removal in the same API call.
if d.Get("type").(string) == "NS" { if rType == "NS" {
log.Printf("[DEBUG] DNS record list request for %q", zone) log.Printf("[DEBUG] DNS record list request for %q", zone)
res, err := config.clientDns.ResourceRecordSets.List(project, zone).Do() res, err := config.clientDns.ResourceRecordSets.List(project, zone).Do()
if err != nil { if err != nil {
@ -95,7 +101,7 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
var deletions []*dns.ResourceRecordSet var deletions []*dns.ResourceRecordSet
for _, record := range res.Rrsets { for _, record := range res.Rrsets {
if record.Type != "NS" || record.Name != d.Get("name").(string) { if record.Type != "NS" || record.Name != name {
continue continue
} }
deletions = append(deletions, record) deletions = append(deletions, record)
@ -111,7 +117,7 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Error creating DNS RecordSet: %s", err) return fmt.Errorf("Error creating DNS RecordSet: %s", err)
} }
d.SetId(chg.Id) d.SetId(fmt.Sprintf("%s/%s/%s", zone, name, rType))
w := &DnsChangeWaiter{ w := &DnsChangeWaiter{
Service: config.clientDns, Service: config.clientDns,
@ -156,6 +162,7 @@ func resourceDnsRecordSetRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Only expected 1 record set, got %d", len(resp.Rrsets)) return fmt.Errorf("Only expected 1 record set, got %d", len(resp.Rrsets))
} }
d.Set("type", resp.Rrsets[0].Type)
d.Set("ttl", resp.Rrsets[0].Ttl) d.Set("ttl", resp.Rrsets[0].Ttl)
d.Set("rrdatas", resp.Rrsets[0].Rrdatas) d.Set("rrdatas", resp.Rrsets[0].Rrdatas)
d.Set("project", project) d.Set("project", project)
@ -286,6 +293,19 @@ func resourceDnsRecordSetUpdate(d *schema.ResourceData, meta interface{}) error
return resourceDnsRecordSetRead(d, meta) return resourceDnsRecordSetRead(d, meta)
} }
func resourceDnsRecordSetImportState(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 3 {
return nil, fmt.Errorf("Invalid dns record specifier. Expecting {zone-name}/{record-name}/{record-type}. The record name must include a trailing '.' at the end.")
}
d.Set("managed_zone", parts[0])
d.Set("name", parts[1])
d.Set("type", parts[2])
return []*schema.ResourceData{d}, nil
}
func rrdata( func rrdata(
d *schema.ResourceData, d *schema.ResourceData,
) []string { ) []string {

View File

@ -25,6 +25,12 @@ func TestAccDnsRecordSet_basic(t *testing.T) {
"google_dns_record_set.foobar", zoneName), "google_dns_record_set.foobar", zoneName),
), ),
}, },
resource.TestStep{
ResourceName: "google_dns_record_set.foobar",
ImportStateId: fmt.Sprintf("%s/test-record.hashicorptest.com./A", zoneName),
ImportState: true,
ImportStateVerify: true,
},
}, },
}) })
} }
@ -91,6 +97,8 @@ func TestAccDnsRecordSet_changeType(t *testing.T) {
} }
func TestAccDnsRecordSet_ns(t *testing.T) { func TestAccDnsRecordSet_ns(t *testing.T) {
t.Parallel()
zoneName := fmt.Sprintf("dnszone-test-ns-%s", acctest.RandString(10)) zoneName := fmt.Sprintf("dnszone-test-ns-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
@ -104,11 +112,19 @@ func TestAccDnsRecordSet_ns(t *testing.T) {
"google_dns_record_set.foobar", zoneName), "google_dns_record_set.foobar", zoneName),
), ),
}, },
resource.TestStep{
ResourceName: "google_dns_record_set.foobar",
ImportStateId: fmt.Sprintf("%s/hashicorptest.com./NS", zoneName),
ImportState: true,
ImportStateVerify: true,
},
}, },
}) })
} }
func TestAccDnsRecordSet_nestedNS(t *testing.T) { func TestAccDnsRecordSet_nestedNS(t *testing.T) {
t.Parallel()
zoneName := fmt.Sprintf("dnszone-test-ns-%s", acctest.RandString(10)) zoneName := fmt.Sprintf("dnszone-test-ns-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },

View File

@ -8,7 +8,8 @@ description: |-
# google\_dns\_record\_set # google\_dns\_record\_set
Manages a set of DNS records within Google Cloud DNS. Manages a set of DNS records within Google Cloud DNS. For more information see [the official documentation](https://cloud.google.com/dns/records/) and
[API](https://cloud.google.com/dns/api/v1/resourceRecordSets).
~> **Note:** The Google Cloud DNS API requires NS records be present at all ~> **Note:** The Google Cloud DNS API requires NS records be present at all
times. To accommodate this, when creating NS records, the default records times. To accommodate this, when creating NS records, the default records
@ -98,3 +99,13 @@ The following arguments are supported:
## Attributes Reference ## Attributes Reference
Only the arguments listed above are exposed as attributes. Only the arguments listed above are exposed as attributes.
## Import
DNS record set can be imported using the `zone name`, `record name` and record `type`, e.g.
```
$ terraform import google_dns_record_set.frontend prod-zone/frontend.prod.mydomain.com./A
```
Note: The record name must include the trailing dot at the end.