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 }