github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/digitalocean/resource_digitalocean_record.go (about)

     1  package digitalocean
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/digitalocean/godo"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceDigitalOceanRecord() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceDigitalOceanRecordCreate,
    17  		Read:   resourceDigitalOceanRecordRead,
    18  		Update: resourceDigitalOceanRecordUpdate,
    19  		Delete: resourceDigitalOceanRecordDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"type": {
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"domain": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"name": {
    35  				Type:     schema.TypeString,
    36  				Optional: true,
    37  			},
    38  
    39  			"port": {
    40  				Type:     schema.TypeString,
    41  				Optional: true,
    42  				Computed: true,
    43  				ForceNew: true,
    44  			},
    45  
    46  			"priority": {
    47  				Type:     schema.TypeString,
    48  				Optional: true,
    49  				Computed: true,
    50  				ForceNew: true,
    51  			},
    52  
    53  			"weight": {
    54  				Type:     schema.TypeString,
    55  				Optional: true,
    56  				Computed: true,
    57  				ForceNew: true,
    58  			},
    59  
    60  			"ttl": {
    61  				Type:     schema.TypeString,
    62  				Optional: true,
    63  				Computed: true,
    64  			},
    65  
    66  			"value": {
    67  				Type:     schema.TypeString,
    68  				Optional: true,
    69  				Computed: true,
    70  				ForceNew: true,
    71  			},
    72  
    73  			"fqdn": {
    74  				Type:     schema.TypeString,
    75  				Computed: true,
    76  			},
    77  		},
    78  	}
    79  }
    80  
    81  func resourceDigitalOceanRecordCreate(d *schema.ResourceData, meta interface{}) error {
    82  	client := meta.(*godo.Client)
    83  
    84  	newRecord := godo.DomainRecordEditRequest{
    85  		Type: d.Get("type").(string),
    86  		Name: d.Get("name").(string),
    87  		Data: d.Get("value").(string),
    88  	}
    89  
    90  	var err error
    91  	if priority := d.Get("priority").(string); priority != "" {
    92  		newRecord.Priority, err = strconv.Atoi(priority)
    93  		if err != nil {
    94  			return fmt.Errorf("Failed to parse priority as an integer: %v", err)
    95  		}
    96  	}
    97  	if port := d.Get("port").(string); port != "" {
    98  		newRecord.Port, err = strconv.Atoi(port)
    99  		if err != nil {
   100  			return fmt.Errorf("Failed to parse port as an integer: %v", err)
   101  		}
   102  	}
   103  	if ttl := d.Get("ttl").(string); ttl != "" {
   104  		newRecord.TTL, err = strconv.Atoi(ttl)
   105  		if err != nil {
   106  			return fmt.Errorf("Failed to parse ttl as an integer: %v", err)
   107  		}
   108  	}
   109  	if weight := d.Get("weight").(string); weight != "" {
   110  		newRecord.Weight, err = strconv.Atoi(weight)
   111  		if err != nil {
   112  			return fmt.Errorf("Failed to parse weight as an integer: %v", err)
   113  		}
   114  	}
   115  
   116  	log.Printf("[DEBUG] record create configuration: %#v", newRecord)
   117  	rec, _, err := client.Domains.CreateRecord(context.Background(), d.Get("domain").(string), &newRecord)
   118  	if err != nil {
   119  		return fmt.Errorf("Failed to create record: %s", err)
   120  	}
   121  
   122  	d.SetId(strconv.Itoa(rec.ID))
   123  	log.Printf("[INFO] Record ID: %s", d.Id())
   124  
   125  	return resourceDigitalOceanRecordRead(d, meta)
   126  }
   127  
   128  func resourceDigitalOceanRecordRead(d *schema.ResourceData, meta interface{}) error {
   129  	client := meta.(*godo.Client)
   130  	domain := d.Get("domain").(string)
   131  	id, err := strconv.Atoi(d.Id())
   132  	if err != nil {
   133  		return fmt.Errorf("invalid record ID: %v", err)
   134  	}
   135  
   136  	rec, resp, err := client.Domains.Record(context.Background(), domain, id)
   137  	if err != nil {
   138  		// If the record is somehow already destroyed, mark as
   139  		// successfully gone
   140  		if resp.StatusCode == 404 {
   141  			d.SetId("")
   142  			return nil
   143  		}
   144  
   145  		return err
   146  	}
   147  
   148  	if t := rec.Type; t == "CNAME" || t == "MX" || t == "NS" || t == "SRV" {
   149  		if rec.Data == "@" {
   150  			rec.Data = domain
   151  		}
   152  		rec.Data += "."
   153  	}
   154  
   155  	d.Set("name", rec.Name)
   156  	d.Set("type", rec.Type)
   157  	d.Set("value", rec.Data)
   158  	d.Set("weight", strconv.Itoa(rec.Weight))
   159  	d.Set("priority", strconv.Itoa(rec.Priority))
   160  	d.Set("port", strconv.Itoa(rec.Port))
   161  	d.Set("ttl", strconv.Itoa(rec.TTL))
   162  
   163  	en := constructFqdn(rec.Name, d.Get("domain").(string))
   164  	log.Printf("[DEBUG] Constructed FQDN: %s", en)
   165  	d.Set("fqdn", en)
   166  
   167  	return nil
   168  }
   169  
   170  func resourceDigitalOceanRecordUpdate(d *schema.ResourceData, meta interface{}) error {
   171  	client := meta.(*godo.Client)
   172  
   173  	domain := d.Get("domain").(string)
   174  	id, err := strconv.Atoi(d.Id())
   175  	if err != nil {
   176  		return fmt.Errorf("invalid record ID: %v", err)
   177  	}
   178  
   179  	var editRecord godo.DomainRecordEditRequest
   180  	if v, ok := d.GetOk("name"); ok {
   181  		editRecord.Name = v.(string)
   182  	}
   183  
   184  	if d.HasChange("ttl") {
   185  		newTTL := d.Get("ttl").(string)
   186  		editRecord.TTL, err = strconv.Atoi(newTTL)
   187  		if err != nil {
   188  			return fmt.Errorf("Failed to parse ttl as an integer: %v", err)
   189  		}
   190  	}
   191  
   192  	log.Printf("[DEBUG] record update configuration: %#v", editRecord)
   193  	_, _, err = client.Domains.EditRecord(context.Background(), domain, id, &editRecord)
   194  	if err != nil {
   195  		return fmt.Errorf("Failed to update record: %s", err)
   196  	}
   197  
   198  	return resourceDigitalOceanRecordRead(d, meta)
   199  }
   200  
   201  func resourceDigitalOceanRecordDelete(d *schema.ResourceData, meta interface{}) error {
   202  	client := meta.(*godo.Client)
   203  
   204  	domain := d.Get("domain").(string)
   205  	id, err := strconv.Atoi(d.Id())
   206  	if err != nil {
   207  		return fmt.Errorf("invalid record ID: %v", err)
   208  	}
   209  
   210  	log.Printf("[INFO] Deleting record: %s, %d", domain, id)
   211  
   212  	resp, delErr := client.Domains.DeleteRecord(context.Background(), domain, id)
   213  	if delErr != nil {
   214  		// If the record is somehow already destroyed, mark as
   215  		// successfully gone
   216  		if resp.StatusCode == 404 {
   217  			return nil
   218  		}
   219  
   220  		return fmt.Errorf("Error deleting record: %s", delErr)
   221  	}
   222  
   223  	return nil
   224  }
   225  
   226  func constructFqdn(name, domain string) string {
   227  	rn := strings.ToLower(strings.TrimSuffix(name, "."))
   228  	domain = strings.TrimSuffix(domain, ".")
   229  	if !strings.HasSuffix(rn, domain) {
   230  		rn = strings.Join([]string{name, domain}, ".")
   231  	}
   232  	return rn
   233  }