From 4358e46b02ba60e435df6f908ae1afe6516c16c5 Mon Sep 17 00:00:00 2001 From: Johann Wagner Date: Mon, 4 Jul 2022 14:59:46 +0200 Subject: [PATCH] Introducing data source for PTR record generation --- powerdns/provider.go | 4 +- powerdns/resource_powerdns_ptr.go | 79 ++++++++++++++++++++++++++ powerdns/resource_powerdns_ptr_test.go | 43 ++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 powerdns/resource_powerdns_ptr.go create mode 100644 powerdns/resource_powerdns_ptr_test.go diff --git a/powerdns/provider.go b/powerdns/provider.go index d8d2040..d400754 100644 --- a/powerdns/provider.go +++ b/powerdns/provider.go @@ -52,7 +52,9 @@ func Provider() terraform.ResourceProvider { Description: "Set cache TTL in seconds", }, }, - + DataSourcesMap: map[string]*schema.Resource{ + "powerdns_ptr": resourcePDNSPTR(), + }, ResourcesMap: map[string]*schema.Resource{ "powerdns_zone": resourcePDNSZone(), "powerdns_record": resourcePDNSRecord(), diff --git a/powerdns/resource_powerdns_ptr.go b/powerdns/resource_powerdns_ptr.go new file mode 100644 index 0000000..34d302d --- /dev/null +++ b/powerdns/resource_powerdns_ptr.go @@ -0,0 +1,79 @@ +package powerdns + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "net" + "strings" +) + +func expandIPv6Address(ip net.IP) string { + b := make([]byte, 0, len(ip)) + + // Print with possible :: in place of run of zeros + for i := 0; i < len(ip); i += 2 { + if i > 0 { + b = append(b, ':') + } + s := (uint32(ip[i]) << 8) | uint32(ip[i+1]) + bHex := fmt.Sprintf("%04x", s) + b = append(b, bHex...) + } + return string(b) +} + +func resourcePDNSPTR() *schema.Resource { + return &schema.Resource{ + Read: resourcePDNSPTRRead, + Schema: map[string]*schema.Schema{ + "ip_address": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "ptr_address": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourcePDNSPTRRead(d *schema.ResourceData, meta interface{}) error { + ipAddressStr := d.Get("ip_address").(string) + + ipAddress := net.ParseIP(ipAddressStr) + if ipAddress == nil { + return fmt.Errorf("%v is not a valid IP address", ipAddressStr) + } + + d.SetId(ipAddressStr) + + ipAddress4 := ipAddress.To4() + + if ipAddress4 != nil { + // IPv4 + addressStringSplitted := strings.Split(ipAddress4.String(), ".") + reverseAddressParts := make([]string, 0) + for i := len(addressStringSplitted) - 1; i >= 0; i-- { + reverseAddressParts = append(reverseAddressParts, addressStringSplitted[i]) + } + reverseAddress := strings.Join(reverseAddressParts, ".") + + ptrRecord := fmt.Sprintf("%v.in-addr.arpa.", reverseAddress) + return d.Set("ptr_address", ptrRecord) + } + + expandedAddress := expandIPv6Address(ipAddress) + + addressStringSplitted := strings.Split(strings.ReplaceAll(expandedAddress, ":", ""), "") + reverseAddressParts := []string{} + for i := len(addressStringSplitted) - 1; i >= 0; i-- { + reverseAddressParts = append(reverseAddressParts, addressStringSplitted[i]) + } + reverseAddress := strings.Join(reverseAddressParts, ".") + + ptrRecord := fmt.Sprintf("%v.ip6.arpa.", reverseAddress) + return d.Set("ptr_address", ptrRecord) + +} diff --git a/powerdns/resource_powerdns_ptr_test.go b/powerdns/resource_powerdns_ptr_test.go new file mode 100644 index 0000000..f4c8c44 --- /dev/null +++ b/powerdns/resource_powerdns_ptr_test.go @@ -0,0 +1,43 @@ +package powerdns + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccPDNSPTR_v4(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testPDNSPtrConfig4, + Check: resource.TestCheckResourceAttr("data.powerdns_ptr.test4", "ptr_address", "4.3.2.1.in-addr.arpa."), + }, + }, + }) +} + +func TestAccPDNSPTR_v6(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testPDNSPtrConfig6, + Check: resource.TestCheckResourceAttr("data.powerdns_ptr.test6", "ptr_address", "1.1.b.6.f.a.d.1.5.e.6.7.c.0.6.d.5.9.2.0.0.c.a.8.8.0.1.8.2.0.a.2.ip6.arpa."), + }, + }, + }) +} + +const testPDNSPtrConfig4 = ` +data "powerdns_ptr" "test4" { + ip_address = "1.2.3.4" +}` + +const testPDNSPtrConfig6 = ` +data "powerdns_ptr" "test6" { + ip_address = "2a02:8108:8ac0:295:d60c:76e5:1daf:6b11" +}`