Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand All @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {

Expand All @@ -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})
}

Expand All @@ -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)
}
166 changes: 166 additions & 0 deletions internal/provider/resource_dns_ptr_record_set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package provider

import (
"fmt"
"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 TestAccDnsPtrRecordSet_basic(t *testing.T) {

var rec_name, rec_zone string
resourceName := "dns_ptr_record_set.foo"
resourceRoot := "dns_ptr_record_set.root"

deletePtrRecordSet := func() {
meta := testAccProvider.Meta()

msg := new(dns.Msg)

msg.SetUpdate(rec_zone)

rec_fqdn := testResourceFQDN(rec_name, rec_zone)

rr_remove, _ := dns.NewRR(fmt.Sprintf("%s 0 PTR", rec_fqdn))
msg.RemoveRRset([]dns.RR{rr_remove})

r, err := exchange(msg, true, meta)
if err != nil {
t.Fatalf("Error deleting DNS record: %s", err)
}
if r.Rcode != dns.RcodeSuccess {
t.Fatalf("Error deleting DNS record: %v", r.Rcode)
}
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckDnsPtrRecordSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccDnsPtrRecordSet_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "ptrs.#", "1"),
testAccCheckDnsPtrRecordSetExists(t, resourceName, []interface{}{"bar.example.com."}, &rec_name, &rec_zone),
),
},
{
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),
),
},
{
PreConfig: deletePtrRecordSet,
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),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccDnsPtrRecordSet_root,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceRoot, "ptrs.#", "3"),
testAccCheckDnsPtrRecordSetExists(t, resourceRoot, []interface{}{"machine1.example.com.", "machine2.example.com.", "machine3.example.com."}, &rec_name, &rec_zone),
),
},
{
ResourceName: resourceRoot,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckDnsPtrRecordSetDestroy(s *terraform.State) error {
return testAccCheckDnsDestroy(s, "dns_ptr_record_set", dns.TypePTR)
}

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 {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

*rec_name = rs.Primary.Attributes["name"]
*rec_zone = rs.Primary.Attributes["zone"]

rec_fqdn := testResourceFQDN(*rec_name, *rec_zone)

meta := testAccProvider.Meta()

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)
}
if r.Rcode != dns.RcodeSuccess {
return fmt.Errorf("Error querying DNS record")
}

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 !ptrs.Equal(expected) {
return fmt.Errorf("DNS record differs: expected %v, found %v", expected, ptrs)
}
return nil
}
}

var testAccDnsPtrRecordSet_basic = fmt.Sprintf(`
resource "dns_ptr_record_set" "foo" {
zone = "example.com."
name = "r._dns-sd._udp"
ptrs = [
"bar.example.com.",
]
ttl = 300
}`)

var testAccDnsPtrRecordSet_update = fmt.Sprintf(`
resource "dns_ptr_record_set" "foo" {
zone = "example.com."
name = "r._dns-sd._udp"
ptrs = [
"bar.example.com.",
"baz.example.com.",
]
ttl = 300
}`)

var testAccDnsPtrRecordSet_root = fmt.Sprintf(`
resource "dns_ptr_record_set" "root" {
zone = "example.com."
ptrs = [
"machine1.example.com.",
"machine2.example.com.",
"machine3.example.com.",
]
ttl = 300
}`)
Loading