2014-07-24 19:47:22 +02:00
|
|
|
package digitalocean
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
2015-09-27 06:06:51 +02:00
|
|
|
"strconv"
|
2014-09-05 17:09:52 +02:00
|
|
|
"strings"
|
2014-07-24 19:47:22 +02:00
|
|
|
|
2015-09-27 06:06:51 +02:00
|
|
|
"github.com/digitalocean/godo"
|
2014-09-09 22:29:36 +02:00
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
2014-07-24 19:47:22 +02:00
|
|
|
)
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
func resourceDigitalOceanRecord() *schema.Resource {
|
2014-09-09 22:29:36 +02:00
|
|
|
return &schema.Resource{
|
2014-11-17 18:55:45 +01:00
|
|
|
Create: resourceDigitalOceanRecordCreate,
|
|
|
|
Read: resourceDigitalOceanRecordRead,
|
|
|
|
Update: resourceDigitalOceanRecordUpdate,
|
|
|
|
Delete: resourceDigitalOceanRecordDelete,
|
2014-09-09 22:29:36 +02:00
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"type": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"domain": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"port": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"priority": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"weight": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"value": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
2016-02-09 17:57:42 +01:00
|
|
|
|
|
|
|
"fqdn": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2014-09-09 22:29:36 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
func resourceDigitalOceanRecordCreate(d *schema.ResourceData, meta interface{}) error {
|
2015-09-27 06:06:51 +02:00
|
|
|
client := meta.(*godo.Client)
|
|
|
|
|
|
|
|
newRecord := godo.DomainRecordEditRequest{
|
|
|
|
Type: d.Get("type").(string),
|
|
|
|
Name: d.Get("name").(string),
|
|
|
|
Data: d.Get("value").(string),
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if priority := d.Get("priority").(string); priority != "" {
|
|
|
|
newRecord.Priority, err = strconv.Atoi(priority)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to parse priority as an integer: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if port := d.Get("port").(string); port != "" {
|
|
|
|
newRecord.Port, err = strconv.Atoi(port)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to parse port as an integer: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if weight := d.Get("weight").(string); weight != "" {
|
|
|
|
newRecord.Weight, err = strconv.Atoi(weight)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to parse weight as an integer: %v", err)
|
|
|
|
}
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] record create configuration: %#v", newRecord)
|
2015-09-27 06:06:51 +02:00
|
|
|
rec, _, err := client.Domains.CreateRecord(d.Get("domain").(string), &newRecord)
|
2014-07-24 19:47:22 +02:00
|
|
|
if err != nil {
|
2014-09-09 22:29:36 +02:00
|
|
|
return fmt.Errorf("Failed to create record: %s", err)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
2015-09-27 06:06:51 +02:00
|
|
|
d.SetId(strconv.Itoa(rec.ID))
|
2014-09-09 22:29:36 +02:00
|
|
|
log.Printf("[INFO] Record ID: %s", d.Id())
|
2014-07-24 19:47:22 +02:00
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
return resourceDigitalOceanRecordRead(d, meta)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
func resourceDigitalOceanRecordRead(d *schema.ResourceData, meta interface{}) error {
|
2015-09-27 06:06:51 +02:00
|
|
|
client := meta.(*godo.Client)
|
2015-02-28 11:55:10 +01:00
|
|
|
domain := d.Get("domain").(string)
|
2015-09-27 06:06:51 +02:00
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("invalid record ID: %v", err)
|
|
|
|
}
|
2014-11-17 18:55:45 +01:00
|
|
|
|
2015-12-06 12:52:35 +01:00
|
|
|
rec, resp, err := client.Domains.Record(domain, id)
|
2014-11-17 18:55:45 +01:00
|
|
|
if err != nil {
|
|
|
|
// If the record is somehow already destroyed, mark as
|
2015-09-11 20:56:20 +02:00
|
|
|
// successfully gone
|
2015-12-06 12:52:35 +01:00
|
|
|
if resp.StatusCode == 404 {
|
2014-11-17 18:55:45 +01:00
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-02-28 11:55:10 +01:00
|
|
|
// Update response data for records with domain value
|
|
|
|
if t := rec.Type; t == "CNAME" || t == "MX" || t == "NS" || t == "SRV" {
|
|
|
|
// Append dot to response if resource value is absolute
|
|
|
|
if value := d.Get("value").(string); strings.HasSuffix(value, ".") {
|
|
|
|
rec.Data += "."
|
|
|
|
// If resource value ends with current domain, make response data absolute
|
|
|
|
if strings.HasSuffix(value, domain+".") {
|
|
|
|
rec.Data += domain + "."
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
d.Set("name", rec.Name)
|
|
|
|
d.Set("type", rec.Type)
|
|
|
|
d.Set("value", rec.Data)
|
2015-09-27 06:06:51 +02:00
|
|
|
d.Set("weight", strconv.Itoa(rec.Weight))
|
|
|
|
d.Set("priority", strconv.Itoa(rec.Priority))
|
|
|
|
d.Set("port", strconv.Itoa(rec.Port))
|
2014-11-17 18:55:45 +01:00
|
|
|
|
2016-02-09 17:57:42 +01:00
|
|
|
en := constructFqdn(rec.Name, d.Get("domain").(string))
|
2016-02-22 19:31:59 +01:00
|
|
|
log.Printf("[DEBUG] Constructed FQDN: %s", en)
|
2016-02-09 17:57:42 +01:00
|
|
|
d.Set("fqdn", en)
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceDigitalOceanRecordUpdate(d *schema.ResourceData, meta interface{}) error {
|
2015-09-27 06:06:51 +02:00
|
|
|
client := meta.(*godo.Client)
|
2014-07-24 19:47:22 +02:00
|
|
|
|
2015-09-27 06:06:51 +02:00
|
|
|
domain := d.Get("domain").(string)
|
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("invalid record ID: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var editRecord godo.DomainRecordEditRequest
|
2014-09-09 22:29:36 +02:00
|
|
|
if v, ok := d.GetOk("name"); ok {
|
2015-09-27 06:06:51 +02:00
|
|
|
editRecord.Name = v.(string)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
2015-09-27 06:06:51 +02:00
|
|
|
log.Printf("[DEBUG] record update configuration: %#v", editRecord)
|
|
|
|
_, _, err = client.Domains.EditRecord(domain, id, &editRecord)
|
2014-07-24 19:47:22 +02:00
|
|
|
if err != nil {
|
2014-09-09 22:29:36 +02:00
|
|
|
return fmt.Errorf("Failed to update record: %s", err)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
return resourceDigitalOceanRecordRead(d, meta)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
2014-11-17 18:55:45 +01:00
|
|
|
func resourceDigitalOceanRecordDelete(d *schema.ResourceData, meta interface{}) error {
|
2015-09-27 06:06:51 +02:00
|
|
|
client := meta.(*godo.Client)
|
|
|
|
|
|
|
|
domain := d.Get("domain").(string)
|
|
|
|
id, err := strconv.Atoi(d.Id())
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("invalid record ID: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[INFO] Deleting record: %s, %d", domain, id)
|
2014-07-24 19:47:22 +02:00
|
|
|
|
2015-12-17 18:24:24 +01:00
|
|
|
resp, delErr := client.Domains.DeleteRecord(domain, id)
|
2015-12-06 12:52:35 +01:00
|
|
|
if delErr != nil {
|
2014-09-05 17:09:52 +02:00
|
|
|
// If the record is somehow already destroyed, mark as
|
2015-09-11 20:56:20 +02:00
|
|
|
// successfully gone
|
2015-12-06 12:52:35 +01:00
|
|
|
if resp.StatusCode == 404 {
|
2014-09-05 17:09:52 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-12-06 12:52:35 +01:00
|
|
|
return fmt.Errorf("Error deleting record: %s", delErr)
|
2014-07-24 19:47:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2016-02-09 17:57:42 +01:00
|
|
|
|
|
|
|
func constructFqdn(name, domain string) string {
|
|
|
|
rn := strings.ToLower(strings.TrimSuffix(name, "."))
|
|
|
|
domain = strings.TrimSuffix(domain, ".")
|
|
|
|
if !strings.HasSuffix(rn, domain) {
|
|
|
|
rn = strings.Join([]string{name, domain}, ".")
|
|
|
|
}
|
|
|
|
return rn
|
|
|
|
}
|