213 lines
5.1 KiB
Go
213 lines
5.1 KiB
Go
package dns
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func resourceDnsAAAARecordSet() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceDnsAAAARecordSetCreate,
|
|
Read: resourceDnsAAAARecordSetRead,
|
|
Update: resourceDnsAAAARecordSetUpdate,
|
|
Delete: resourceDnsAAAARecordSetDelete,
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"zone": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
"addresses": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Required: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
Set: schema.HashString,
|
|
},
|
|
"ttl": &schema.Schema{
|
|
Type: schema.TypeInt,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Default: 3600,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceDnsAAAARecordSetCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
rec_name := d.Get("name").(string)
|
|
rec_zone := d.Get("zone").(string)
|
|
|
|
if rec_zone != dns.Fqdn(rec_zone) {
|
|
return fmt.Errorf("Error creating DNS record: \"zone\" should be an FQDN")
|
|
}
|
|
|
|
rec_fqdn := fmt.Sprintf("%s.%s", rec_name, rec_zone)
|
|
|
|
d.SetId(rec_fqdn)
|
|
|
|
return resourceDnsAAAARecordSetUpdate(d, meta)
|
|
}
|
|
|
|
func resourceDnsAAAARecordSetRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
if meta != nil {
|
|
|
|
rec_name := d.Get("name").(string)
|
|
rec_zone := d.Get("zone").(string)
|
|
|
|
if rec_zone != dns.Fqdn(rec_zone) {
|
|
return fmt.Errorf("Error reading DNS record: \"zone\" should be an FQDN")
|
|
}
|
|
|
|
rec_fqdn := fmt.Sprintf("%s.%s", rec_name, rec_zone)
|
|
|
|
c := meta.(*DNSClient).c
|
|
srv_addr := meta.(*DNSClient).srv_addr
|
|
|
|
msg := new(dns.Msg)
|
|
msg.SetQuestion(rec_fqdn, dns.TypeAAAA)
|
|
|
|
r, _, err := c.Exchange(msg, srv_addr)
|
|
if err != nil {
|
|
return fmt.Errorf("Error querying DNS record: %s", err)
|
|
}
|
|
if r.Rcode != dns.RcodeSuccess {
|
|
return fmt.Errorf("Error querying DNS record: %v", r.Rcode)
|
|
}
|
|
|
|
addresses := schema.NewSet(schema.HashString, nil)
|
|
for _, record := range r.Answer {
|
|
addr, err := getAAAAVal(record)
|
|
if err != nil {
|
|
return fmt.Errorf("Error querying DNS record: %s", err)
|
|
}
|
|
addresses.Add(addr)
|
|
}
|
|
if !addresses.Equal(d.Get("addresses")) {
|
|
d.SetId("")
|
|
return fmt.Errorf("DNS record differs")
|
|
}
|
|
return nil
|
|
} else {
|
|
return fmt.Errorf("update server is not set")
|
|
}
|
|
}
|
|
|
|
func resourceDnsAAAARecordSetUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
if meta != nil {
|
|
|
|
rec_name := d.Get("name").(string)
|
|
rec_zone := d.Get("zone").(string)
|
|
ttl := d.Get("ttl").(int)
|
|
|
|
if rec_zone != dns.Fqdn(rec_zone) {
|
|
return fmt.Errorf("Error updating DNS record: \"zone\" should be an FQDN")
|
|
}
|
|
|
|
rec_fqdn := fmt.Sprintf("%s.%s", rec_name, rec_zone)
|
|
|
|
c := meta.(*DNSClient).c
|
|
srv_addr := meta.(*DNSClient).srv_addr
|
|
keyname := meta.(*DNSClient).keyname
|
|
keyalgo := meta.(*DNSClient).keyalgo
|
|
|
|
msg := new(dns.Msg)
|
|
|
|
msg.SetUpdate(rec_zone)
|
|
|
|
if d.HasChange("addresses") {
|
|
o, n := d.GetChange("addresses")
|
|
os := o.(*schema.Set)
|
|
ns := n.(*schema.Set)
|
|
remove := os.Difference(ns).List()
|
|
add := ns.Difference(os).List()
|
|
|
|
// Loop through all the old addresses and remove them
|
|
for _, addr := range remove {
|
|
rr_remove, _ := dns.NewRR(fmt.Sprintf("%s %d AAAA %s", rec_fqdn, ttl, addr.(string)))
|
|
msg.Remove([]dns.RR{rr_remove})
|
|
}
|
|
// Loop through all the new addresses and insert them
|
|
for _, addr := range add {
|
|
rr_insert, _ := dns.NewRR(fmt.Sprintf("%s %d AAAA %s", rec_fqdn, ttl, addr.(string)))
|
|
msg.Insert([]dns.RR{rr_insert})
|
|
}
|
|
|
|
if keyname != "" {
|
|
msg.SetTsig(keyname, keyalgo, 300, time.Now().Unix())
|
|
}
|
|
|
|
r, _, err := c.Exchange(msg, srv_addr)
|
|
if err != nil {
|
|
d.SetId("")
|
|
return fmt.Errorf("Error updating DNS record: %s", err)
|
|
}
|
|
if r.Rcode != dns.RcodeSuccess {
|
|
d.SetId("")
|
|
return fmt.Errorf("Error updating DNS record: %v", r.Rcode)
|
|
}
|
|
|
|
addresses := ns
|
|
d.Set("addresses", addresses)
|
|
}
|
|
|
|
return resourceDnsAAAARecordSetRead(d, meta)
|
|
} else {
|
|
return fmt.Errorf("update server is not set")
|
|
}
|
|
}
|
|
|
|
func resourceDnsAAAARecordSetDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
if meta != nil {
|
|
|
|
rec_name := d.Get("name").(string)
|
|
rec_zone := d.Get("zone").(string)
|
|
|
|
if rec_zone != dns.Fqdn(rec_zone) {
|
|
return fmt.Errorf("Error updating DNS record: \"zone\" should be an FQDN")
|
|
}
|
|
|
|
rec_fqdn := fmt.Sprintf("%s.%s", rec_name, rec_zone)
|
|
|
|
c := meta.(*DNSClient).c
|
|
srv_addr := meta.(*DNSClient).srv_addr
|
|
keyname := meta.(*DNSClient).keyname
|
|
keyalgo := meta.(*DNSClient).keyalgo
|
|
|
|
msg := new(dns.Msg)
|
|
|
|
msg.SetUpdate(rec_zone)
|
|
|
|
rr_remove, _ := dns.NewRR(fmt.Sprintf("%s 0 AAAA", rec_fqdn))
|
|
msg.RemoveRRset([]dns.RR{rr_remove})
|
|
|
|
if keyname != "" {
|
|
msg.SetTsig(keyname, keyalgo, 300, time.Now().Unix())
|
|
}
|
|
|
|
r, _, err := c.Exchange(msg, srv_addr)
|
|
if err != nil {
|
|
return fmt.Errorf("Error deleting DNS record: %s", err)
|
|
}
|
|
if r.Rcode != dns.RcodeSuccess {
|
|
return fmt.Errorf("Error deleting DNS record: %v", r.Rcode)
|
|
}
|
|
|
|
return nil
|
|
} else {
|
|
return fmt.Errorf("update server is not set")
|
|
}
|
|
}
|