From ecf1eaf3322e0633d2714128fd45bce1eb1d4cb2 Mon Sep 17 00:00:00 2001 From: Joel Verezhak Date: Mon, 22 Nov 2021 22:47:09 +0100 Subject: [PATCH 1/4] Added dns_ptr_record_set resource --- internal/provider/provider.go | 2 +- ...cord.go => resource_dns_ptr_record_set.go} | 77 +++++++++++-------- ...go => resource_dns_ptr_record_set_test.go} | 0 3 files changed, 48 insertions(+), 31 deletions(-) rename internal/provider/{resource_dns_ptr_record.go => resource_dns_ptr_record_set.go} (50%) rename internal/provider/{resource_dns_ptr_record_test.go => resource_dns_ptr_record_set_test.go} (100%) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index f1faf094..89588ded 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -153,7 +153,7 @@ func New() *schema.Provider { "dns_cname_record": resourceDnsCnameRecord(), "dns_mx_record_set": resourceDnsMXRecordSet(), "dns_ns_record_set": resourceDnsNSRecordSet(), - "dns_ptr_record": resourceDnsPtrRecord(), + "dns_ptr_record_set": resourceDnsPtrRecordSet(), "dns_srv_record_set": resourceDnsSRVRecordSet(), "dns_txt_record_set": resourceDnsTXTRecordSet(), }, diff --git a/internal/provider/resource_dns_ptr_record.go b/internal/provider/resource_dns_ptr_record_set.go similarity index 50% rename from internal/provider/resource_dns_ptr_record.go rename to internal/provider/resource_dns_ptr_record_set.go index c4cdbe55..cfe929dc 100644 --- a/internal/provider/resource_dns_ptr_record.go +++ b/internal/provider/resource_dns_ptr_record_set.go @@ -2,17 +2,18 @@ package provider import ( "fmt" + "sort" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/miekg/dns" ) -func resourceDnsPtrRecord() *schema.Resource { +func resourceDnsPtrRecordSet() *schema.Resource { return &schema.Resource{ - Create: resourceDnsPtrRecordCreate, - Read: resourceDnsPtrRecordRead, - Update: resourceDnsPtrRecordUpdate, - Delete: resourceDnsPtrRecordDelete, + Create: resourceDnsPtrRecordSetCreate, + Read: resourceDnsPtrRecordSetRead, + Update: resourceDnsPtrRecordSetUpdate, + Delete: resourceDnsPtrRecordSetDelete, Importer: &schema.ResourceImporter{ State: resourceDnsImport, }, @@ -30,10 +31,14 @@ func resourceDnsPtrRecord() *schema.Resource { ForceNew: true, ValidateFunc: validateName, }, - "ptr": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validateZone, + "ptrs": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validateZone, + }, + Set: schema.HashString, }, "ttl": { Type: schema.TypeInt, @@ -45,14 +50,14 @@ func resourceDnsPtrRecord() *schema.Resource { } } -func resourceDnsPtrRecordCreate(d *schema.ResourceData, meta interface{}) error { +func resourceDnsPtrRecordSetCreate(d *schema.ResourceData, meta interface{}) error { d.SetId(resourceFQDN(d)) - return resourceDnsPtrRecordUpdate(d, meta) + return resourceDnsPtrRecordSetUpdate(d, meta) } -func resourceDnsPtrRecordRead(d *schema.ResourceData, meta interface{}) error { +func resourceDnsPtrRecordSetRead(d *schema.ResourceData, meta interface{}) error { answers, err := resourceDnsRead(d, meta, dns.TypePTR) if err != nil { @@ -61,24 +66,30 @@ func resourceDnsPtrRecordRead(d *schema.ResourceData, meta interface{}) error { if len(answers) > 0 { - if len(answers) > 1 { - return fmt.Errorf("Error querying DNS record: multiple responses received") - } - record := answers[0] - ptr, ttl, err := getPtrVal(record) - if err != nil { - return fmt.Errorf("Error querying DNS record: %s", err) + var ttl sort.IntSlice + + ptrs := schema.NewSet(schema.HashString, nil) + for _, record := range answers { + ptr, t, err := getPtrVal(record) + if err != nil { + return fmt.Errorf("Error querying DNS record: %s", err) + } + ptrs.Add(ptr) + ttl = append(ttl, t) } - d.Set("ptr", ptr) - d.Set("ttl", ttl) + sort.Sort(ttl) + + d.Set("ptrs", ptrs) + d.Set("ttl", ttl[0]) } else { d.SetId("") } return nil + } -func resourceDnsPtrRecordUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceDnsPtrRecordSetUpdate(d *schema.ResourceData, meta interface{}) error { if meta != nil { @@ -90,15 +101,21 @@ func resourceDnsPtrRecordUpdate(d *schema.ResourceData, meta interface{}) error msg.SetUpdate(d.Get("zone").(string)) - if d.HasChange("ptr") { - o, n := d.GetChange("ptr") + if d.HasChange("ptrs") { + o, n := d.GetChange("ptrs") + os := o.(*schema.Set) + ns := n.(*schema.Set) + remove := os.Difference(ns).List() + add := ns.Difference(os).List() - if o != "" { - rr_remove, _ := dns.NewRR(fmt.Sprintf("%s %d PTR %s", rec_fqdn, ttl, o)) + // Loop through all the old ptrs and remove them + for _, ptr := range remove { + rr_remove, _ := dns.NewRR(fmt.Sprintf("%s %d PTR %s", rec_fqdn, ttl, ptr.(string))) msg.Remove([]dns.RR{rr_remove}) } - if n != "" { - rr_insert, _ := dns.NewRR(fmt.Sprintf("%s %d PTR %s", rec_fqdn, ttl, n)) + // Loop through all the new ptrs and insert them + for _, ptr := range add { + rr_insert, _ := dns.NewRR(fmt.Sprintf("%s %d PTR %s", rec_fqdn, ttl, ptr.(string))) msg.Insert([]dns.RR{rr_insert}) } @@ -113,13 +130,13 @@ func resourceDnsPtrRecordUpdate(d *schema.ResourceData, meta interface{}) error } } - return resourceDnsPtrRecordRead(d, meta) + return resourceDnsPtrRecordSetRead(d, meta) } else { return fmt.Errorf("update server is not set") } } -func resourceDnsPtrRecordDelete(d *schema.ResourceData, meta interface{}) error { +func resourceDnsPtrRecordSetDelete(d *schema.ResourceData, meta interface{}) error { return resourceDnsDelete(d, meta, dns.TypePTR) } diff --git a/internal/provider/resource_dns_ptr_record_test.go b/internal/provider/resource_dns_ptr_record_set_test.go similarity index 100% rename from internal/provider/resource_dns_ptr_record_test.go rename to internal/provider/resource_dns_ptr_record_set_test.go From be9cbba94409c04378f23b7f3a871a34969f2c79 Mon Sep 17 00:00:00 2001 From: Joel Verezhak Date: Mon, 22 Nov 2021 23:42:45 +0100 Subject: [PATCH 2/4] dns_ptr_record_set tests --- .../resource_dns_ptr_record_set_test.go | 86 +++++++++++-------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/internal/provider/resource_dns_ptr_record_set_test.go b/internal/provider/resource_dns_ptr_record_set_test.go index 580cadd9..6af86e00 100644 --- a/internal/provider/resource_dns_ptr_record_set_test.go +++ b/internal/provider/resource_dns_ptr_record_set_test.go @@ -5,17 +5,18 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/miekg/dns" ) -func TestAccDnsPtrRecord_basic(t *testing.T) { +func TestAccDnsPtrRecordSet_basic(t *testing.T) { var rec_name, rec_zone string - resourceName := "dns_ptr_record.foo" - resourceRoot := "dns_ptr_record.root" + resourceName := "dns_ptr_record_set.foo" + resourceRoot := "dns_ptr_record_set.root" - deletePtrRecord := func() { + deletePtrRecordSet := func() { meta := testAccProvider.Meta() msg := new(dns.Msg) @@ -39,25 +40,28 @@ func TestAccDnsPtrRecord_basic(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckDnsPtrRecordDestroy, + CheckDestroy: testAccCheckDnsPtrRecordSetDestroy, Steps: []resource.TestStep{ { - Config: testAccDnsPtrRecord_basic, + Config: testAccDnsPtrRecordSet_basic, Check: resource.ComposeTestCheckFunc( - testAccCheckDnsPtrRecordExists(t, resourceName, "bar.example.com.", &rec_name, &rec_zone), + resource.TestCheckResourceAttr(resourceName, "ptrs.#", "1"), + testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com."}, &rec_name, &rec_zone), ), }, { - Config: testAccDnsPtrRecord_update, + Config: testAccDnsPtrRecordSet_update, Check: resource.ComposeTestCheckFunc( - testAccCheckDnsPtrRecordExists(t, resourceName, "baz.example.com.", &rec_name, &rec_zone), + resource.TestCheckResourceAttr(resourceName, "ptrs.#", "2"), + testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com.", "baz.example.com."}, &rec_name, &rec_zone), ), }, { - PreConfig: deletePtrRecord, - Config: testAccDnsPtrRecord_update, + PreConfig: deletePtrRecordSet, + Config: testAccDnsPtrRecordSet_update, Check: resource.ComposeTestCheckFunc( - testAccCheckDnsPtrRecordExists(t, resourceName, "baz.example.com.", &rec_name, &rec_zone), + resource.TestCheckResourceAttr(resourceName, "addresses.#", "2"), + testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com.", "baz.example.com"}, &rec_name, &rec_zone), ), }, { @@ -66,9 +70,10 @@ func TestAccDnsPtrRecord_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccDnsPtrRecord_root, + Config: testAccDnsPtrRecordSet_root, Check: resource.ComposeTestCheckFunc( - testAccCheckDnsPtrRecordExists(t, resourceRoot, "baz.example.com.", &rec_name, &rec_zone), + resource.TestCheckResourceAttr(resourceRoot, "addresses.#", "3"), + testAccCheckDnsPtrRecordSetExists(t, resourceRoot, []interface{}{"machine1.example.com.", "machine2.example.com.", "machine3.example.com."}, &rec_name, &rec_zone), ), }, { @@ -80,11 +85,11 @@ func TestAccDnsPtrRecord_basic(t *testing.T) { }) } -func testAccCheckDnsPtrRecordDestroy(s *terraform.State) error { - return testAccCheckDnsDestroy(s, "dns_ptr_record", dns.TypePTR) +func testAccCheckDnsPtrRecordSetDestroy(s *terraform.State) error { + return testAccCheckDnsDestroy(s, "dns_ptr_record_set", dns.TypePTR) } -func testAccCheckDnsPtrRecordExists(t *testing.T, n string, expected string, rec_name, rec_zone *string) resource.TestCheckFunc { +func testAccCheckDnsPtrRecordSetExists(t *testing.T, n string, pointers []interface{}, rec_name, rec_zone *string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -103,6 +108,7 @@ func testAccCheckDnsPtrRecordExists(t *testing.T, n string, expected string, rec msg := new(dns.Msg) msg.SetQuestion(rec_fqdn, dns.TypePTR) + r, err := exchange(msg, false, meta) if err != nil { return fmt.Errorf("Error querying DNS record: %s", err) @@ -111,40 +117,50 @@ func testAccCheckDnsPtrRecordExists(t *testing.T, n string, expected string, rec return fmt.Errorf("Error querying DNS record") } - if len(r.Answer) > 1 { - return fmt.Errorf("Error querying DNS record: multiple responses received") - } - record := r.Answer[0] - ptr, _, err := getPtrVal(record) - if err != nil { - return fmt.Errorf("Error querying DNS record: %s", err) + ptrs := schema.NewSet(schema.HashString, nil) + expected := schema.NewSet(schema.HashString, pointers) + for _, record := range r.Answer { + ptr, _, err := getPtrVal(record) + if err != nil { + return fmt.Errorf("Error querying DNS record: %s", err) + } + ptrs.Add(ptr) } - if expected != ptr { - return fmt.Errorf("DNS record differs: expected %v, found %v", expected, ptr) + if !ptrs.Equal(expected) { + return fmt.Errorf("DNS record differs: expected %v, found %v", expected, addresses) } return nil } } -var testAccDnsPtrRecord_basic = fmt.Sprintf(` - resource "dns_ptr_record" "foo" { +var testAccDnsPtrRecordSet_basic = fmt.Sprintf(` + resource "dns_ptr_record_set" "foo" { zone = "example.com." name = "r._dns-sd._udp" - ptr = "bar.example.com." + ptrs = [ + "bar.example.com.", + ] ttl = 300 }`) -var testAccDnsPtrRecord_update = fmt.Sprintf(` - resource "dns_ptr_record" "foo" { +var testAccDnsPtrRecordSet_update = fmt.Sprintf(` + resource "dns_ptr_record_set" "foo" { zone = "example.com." name = "r._dns-sd._udp" - ptr = "baz.example.com." + ptrs = [ + "bar.example.com.", + "baz.example.com.", + ] ttl = 300 }`) -var testAccDnsPtrRecord_root = fmt.Sprintf(` - resource "dns_ptr_record" "root" { +var testAccDnsPtrRecordSet_root = fmt.Sprintf(` + resource "dns_ptr_record_set" "root" { zone = "example.com." - ptr = "baz.example.com." + ptrs = [ + "machine1.example.com.", + "machine2.example.com.", + "machine3.example.com.", + ] ttl = 300 }`) From 7fa72be839662fa1309e1051588808c6b400c1a1 Mon Sep 17 00:00:00 2001 From: Joel Verezhak Date: Tue, 23 Nov 2021 00:12:08 +0100 Subject: [PATCH 3/4] Updated docs --- .../resource_dns_ptr_record_set_test.go | 6 +++--- website/dns.erb | 4 ++-- ...rkdown => dns_ptr_record_set.html.markdown} | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) rename website/docs/r/{dns_ptr_record.html.markdown => dns_ptr_record_set.html.markdown} (69%) diff --git a/internal/provider/resource_dns_ptr_record_set_test.go b/internal/provider/resource_dns_ptr_record_set_test.go index 6af86e00..b8f31beb 100644 --- a/internal/provider/resource_dns_ptr_record_set_test.go +++ b/internal/provider/resource_dns_ptr_record_set_test.go @@ -60,7 +60,7 @@ func TestAccDnsPtrRecordSet_basic(t *testing.T) { PreConfig: deletePtrRecordSet, Config: testAccDnsPtrRecordSet_update, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "addresses.#", "2"), + resource.TestCheckResourceAttr(resourceName, "ptrs.#", "2"), testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com.", "baz.example.com"}, &rec_name, &rec_zone), ), }, @@ -72,7 +72,7 @@ func TestAccDnsPtrRecordSet_basic(t *testing.T) { { Config: testAccDnsPtrRecordSet_root, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceRoot, "addresses.#", "3"), + resource.TestCheckResourceAttr(resourceRoot, "ptrs.#", "3"), testAccCheckDnsPtrRecordSetExists(t, resourceRoot, []interface{}{"machine1.example.com.", "machine2.example.com.", "machine3.example.com."}, &rec_name, &rec_zone), ), }, @@ -127,7 +127,7 @@ func testAccCheckDnsPtrRecordSetExists(t *testing.T, n string, pointers []interf ptrs.Add(ptr) } if !ptrs.Equal(expected) { - return fmt.Errorf("DNS record differs: expected %v, found %v", expected, addresses) + return fmt.Errorf("DNS record differs: expected %v, found %v", expected, ptrs) } return nil } diff --git a/website/dns.erb b/website/dns.erb index 7598714f..50b009f4 100644 --- a/website/dns.erb +++ b/website/dns.erb @@ -59,8 +59,8 @@ > dns_ns_record_set - > - dns_ptr_record + > + dns_ptr_record_set > dns_srv_record_set diff --git a/website/docs/r/dns_ptr_record.html.markdown b/website/docs/r/dns_ptr_record_set.html.markdown similarity index 69% rename from website/docs/r/dns_ptr_record.html.markdown rename to website/docs/r/dns_ptr_record_set.html.markdown index 700a65a2..80f5ddad 100644 --- a/website/docs/r/dns_ptr_record.html.markdown +++ b/website/docs/r/dns_ptr_record_set.html.markdown @@ -1,22 +1,22 @@ --- layout: "dns" -page_title: "DNS: dns_ptr_record" -sidebar_current: "docs-dns-ptr-record" +page_title: "DNS: dns_ptr_record_set" +sidebar_current: "docs-dns-ptr-record-set" description: |- - Creates a PTR type DNS record. + Creates a PTR type DNS record set. --- -# dns_ptr_record +# dns_ptr_record_set -Creates a PTR type DNS record. +Creates a PTR type DNS record set. ## Example Usage ```hcl -resource "dns_ptr_record" "dns-sd" { +resource "dns_ptr_record_set" "dns-sd" { zone = "example.com." name = "r._dns-sd" - ptr = "example.com." + ptrs = ["example.com."] ttl = 300 } ``` @@ -27,7 +27,7 @@ The following arguments are supported: * `zone` - (Required) DNS zone the record belongs to. It must be an FQDN, that is, include the trailing dot. * `name` - (Optional) The name of the record. The `zone` argument will be appended to this value to create the full record path. -* `ptr` - (Required) The canonical name this record will point to. +* `ptrs` - (Required) A list of names that this record will point to. * `ttl` - (Optional) The TTL of the record set. Defaults to `3600`. ## Attributes Reference @@ -36,7 +36,7 @@ The following attributes are exported: * `zone` - See Argument Reference above. * `name` - See Argument Reference above. -* `ptr` - See Argument Reference above. +* `ptrs` - See Argument Reference above. * `ttl` - See Argument Reference above. ## Import From a7637c6f95745baffe3aaeb237a1d1eeac31376b Mon Sep 17 00:00:00 2001 From: Joel Verezhak Date: Tue, 23 Nov 2021 09:46:05 +0100 Subject: [PATCH 4/4] Fixed unit test FQDN --- internal/provider/resource_dns_ptr_record_set_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/provider/resource_dns_ptr_record_set_test.go b/internal/provider/resource_dns_ptr_record_set_test.go index b8f31beb..3fb5b47d 100644 --- a/internal/provider/resource_dns_ptr_record_set_test.go +++ b/internal/provider/resource_dns_ptr_record_set_test.go @@ -61,7 +61,7 @@ func TestAccDnsPtrRecordSet_basic(t *testing.T) { Config: testAccDnsPtrRecordSet_update, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "ptrs.#", "2"), - testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com.", "baz.example.com"}, &rec_name, &rec_zone), + testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com.", "baz.example.com."}, &rec_name, &rec_zone), ), }, {