]> git.immae.eu Git - github/fretlink/terraform-provider-mailgun.git/blame - mailgun/resource_mailgun_domain.go
fix credentials and date
[github/fretlink/terraform-provider-mailgun.git] / mailgun / resource_mailgun_domain.go
CommitLineData
4457c936
AG
1package mailgun
2
3import (
4 "context"
5 "fmt"
6 "github.com/hashicorp/terraform/helper/schema"
1de838cb 7 "github.com/hashicorp/terraform/helper/resource"
7c735cfa 8 "github.com/mailgun/mailgun-go/v3"
4457c936
AG
9 "log"
10 "time"
11)
12
13func resourceMailgunDomain() *schema.Resource {
14 return &schema.Resource{
15 Create: CreateDomain,
16 Update: UpdateDomain,
17 Delete: DeleteDomain,
18 Read: ReadDomain,
19 Importer: &schema.ResourceImporter{
b8802d62 20 State: ImportStatePassthroughDomain,
4457c936
AG
21 },
22
23 Schema: map[string]*schema.Schema{
24 "name": &schema.Schema{
25 Type: schema.TypeString,
26 Required: true,
27 ForceNew: true,
28 },
29
30 "spam_action": &schema.Schema{
31 Type: schema.TypeString,
32 Default: "disabled",
33 ForceNew: true,
34 Optional: true,
35 },
36
37 "smtp_password": &schema.Schema{
38 Type: schema.TypeString,
39 ForceNew: true,
40 Optional: true,
41 },
42
43 "smtp_login": &schema.Schema{
44 Type: schema.TypeString,
45 Computed: true,
46 },
47
48 "wildcard": &schema.Schema{
49 Type: schema.TypeBool,
50 Default: false,
51 ForceNew: true,
52 Optional: true,
53 },
54
55 "created_at": &schema.Schema{
56 Type: schema.TypeString,
57 Computed: true,
58 ForceNew: true,
59 },
60
61 "state": &schema.Schema{
62 Type: schema.TypeString,
63 Computed: true,
64 },
65
66 "force_dkim_authority": &schema.Schema{
67 Type: schema.TypeBool,
68 Default: false,
69 Optional: true,
70 },
71
72 "dkim_key_size": &schema.Schema{
73 Type: schema.TypeInt,
74 Default: 1024,
75 ForceNew: true,
76 Optional: true,
77 },
78
79 "ips": &schema.Schema{
80 Type: schema.TypeList,
81 Computed: true,
82 ForceNew: true,
83 Optional: true,
84 Elem: &schema.Schema{Type: schema.TypeString},
85 },
86
87 "credentials": &schema.Schema{
88 Type: schema.TypeList,
89 Optional: true,
90 Elem: &schema.Resource{
91 Schema: map[string]*schema.Schema{
92 "created_at": &schema.Schema{
93 Type: schema.TypeString,
94 Computed: true,
95 },
96 "login": &schema.Schema{
97 Type: schema.TypeString,
98 Required: true,
99 },
100 "password": &schema.Schema{
101 Type: schema.TypeString,
05fbf613 102 Optional: true,
4457c936
AG
103 },
104 },
105 },
106 },
107
108 "open_tracking_settings_active": &schema.Schema{
109 Type: schema.TypeBool,
110 Optional: true,
40587421 111 Default: false,
4457c936
AG
112 },
113
114 "click_tracking_settings_active": &schema.Schema{
115 Type: schema.TypeBool,
116 Optional: true,
40587421 117 Default: false,
4457c936
AG
118 },
119
120 "unsubscribe_tracking_settings_active": &schema.Schema{
121 Type: schema.TypeBool,
122 Optional: true,
40587421 123 Default: false,
4457c936
AG
124 },
125 "unsubscribe_tracking_settings_html_footer": &schema.Schema{
126 Type: schema.TypeString,
127 Optional: true,
40587421 128 Default: "\n<br>\n<p><a href=\"%unsubscribe_url%\">unsubscribe</a></p>\n",
4457c936
AG
129 },
130 "unsubscribe_tracking_settings_text_footer": &schema.Schema{
131 Type: schema.TypeString,
132 Optional: true,
40587421 133 Default: "\n\nTo unsubscribe click: <%unsubscribe_url%>\n\n",
4457c936
AG
134 },
135
136 "require_tls": &schema.Schema{
137 Type: schema.TypeBool,
138 Default: false,
139 Optional: true,
140 },
141
142 "skip_verification": &schema.Schema{
143 Type: schema.TypeBool,
144 Default: false,
145 Optional: true,
146 },
147
148 "receiving_records": &schema.Schema{
149 Type: schema.TypeList,
150 Computed: true,
151 Elem: &schema.Resource{
152 Schema: map[string]*schema.Schema{
153 "name": &schema.Schema{
154 Type: schema.TypeString,
155 Computed: true,
156 },
157 "priority": &schema.Schema{
158 Type: schema.TypeString,
159 Computed: true,
160 },
161 "record_type": &schema.Schema{
162 Type: schema.TypeString,
163 Computed: true,
164 },
165 "valid": &schema.Schema{
166 Type: schema.TypeString,
167 Computed: true,
168 },
169 "value": &schema.Schema{
170 Type: schema.TypeString,
171 Computed: true,
172 },
173 },
174 },
175 },
176
177 "sending_records": &schema.Schema{
178 Type: schema.TypeList,
179 Computed: true,
180 Elem: &schema.Resource{
181 Schema: map[string]*schema.Schema{
182 "name": &schema.Schema{
183 Type: schema.TypeString,
184 Computed: true,
185 },
186 "priority": &schema.Schema{
187 Type: schema.TypeString,
188 Computed: true,
189 },
190 "record_type": &schema.Schema{
191 Type: schema.TypeString,
192 Computed: true,
193 },
194 "valid": &schema.Schema{
195 Type: schema.TypeString,
196 Computed: true,
197 },
198 "value": &schema.Schema{
199 Type: schema.TypeString,
200 Computed: true,
201 },
202 },
203 },
204 },
205 },
206 }
207}
208
61f3e553
AG
209func interfaceToStringTab(i interface{}) []string {
210 aInterface := i.([]interface{})
211 aString := make([]string, len(aInterface))
212 for i, v := range aInterface {
213 aString[i] = v.(string)
214 }
215 return aString
216}
4457c936
AG
217func CreateDomain(d *schema.ResourceData, meta interface{}) error {
218 mg := meta.(*mailgun.MailgunImpl)
219 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
220 defer cancel()
221
222 log.Printf("[DEBUG] creating mailgun domain: %s", d.Id())
223
224 creationResponse, err := mg.CreateDomain(ctx, d.Get("name").(string), &mailgun.CreateDomainOptions{
225 Password: d.Get("smtp_password").(string),
226 SpamAction: mailgun.SpamAction(d.Get("spam_action").(string)),
227 Wildcard: d.Get("wildcard").(bool),
228 ForceDKIMAuthority: d.Get("force_dkim_authority").(bool),
229 DKIMKeySize: d.Get("dkim_key_size").(int),
61f3e553 230 IPS: interfaceToStringTab(d.Get("ips")),
4457c936
AG
231 })
232
233 if err != nil {
234 return fmt.Errorf("Error creating mailgun domain: %s", err.Error())
235 }
236
237 mg = mailgun.NewMailgun(creationResponse.Domain.Name, mg.APIKey())
238
239 for _, i := range d.Get("credentials").([]interface{}) {
240 credential := i.(map[string]interface{})
241 err = mg.CreateCredential(ctx, credential["login"].(string), credential["password"].(string))
242 if err != nil {
243 return fmt.Errorf("Error creating mailgun credential: %s", err.Error())
244 }
245 }
246
247 err = mg.UpdateUnsubscribeTracking(ctx, creationResponse.Domain.Name, boolToString(d.Get("unsubscribe_tracking_settings_active").(bool)), d.Get("unsubscribe_tracking_settings_html_footer").(string), d.Get("unsubscribe_tracking_settings_text_footer").(string))
248 if err != nil {
249 return fmt.Errorf("Error updating mailgun unsubscribe tracking settings: %s", err.Error())
250 }
251
252 err = mg.UpdateOpenTracking(ctx, creationResponse.Domain.Name, boolToString(d.Get("open_tracking_settings_active").(bool)))
253 if err != nil {
254 return fmt.Errorf("Error updating mailgun open tracking settings: %s", err.Error())
255 }
256
257 err = mg.UpdateClickTracking(ctx, creationResponse.Domain.Name, boolToString(d.Get("click_tracking_settings_active").(bool)))
258 if err != nil {
259 return fmt.Errorf("Error updating mailgun click tracking settings: %s", err.Error())
260 }
261
262 err = mg.UpdateDomainConnection(ctx, creationResponse.Domain.Name, mailgun.DomainConnection{RequireTLS: d.Get("require_tls").(bool), SkipVerification: d.Get("skip_verification").(bool)})
263 if err != nil {
264 return fmt.Errorf("Error updating mailgun connexion settings: %s", err.Error())
265 }
266
267 d.SetId(creationResponse.Domain.Name)
268
269 return ReadDomain(d, meta)
270}
271
272func UpdateDomain(d *schema.ResourceData, meta interface{}) error {
273 mg := meta.(*mailgun.MailgunImpl)
274 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
275 defer cancel()
276 domainName := d.Get("name").(string)
277 mg = mailgun.NewMailgun(domainName, mg.APIKey())
278
279 log.Printf("[DEBUG] updating mailgun domain: %s", d.Id())
280
281 if d.HasChange("unsubscribe_tracking_settings_active") || d.HasChange("unsubscribe_tracking_settings_html_footer") || d.HasChange("unsubscribe_tracking_settings_text_footer") {
282 err := mg.UpdateUnsubscribeTracking(ctx, domainName, boolToString(d.Get("unsubscribe_tracking_settings_active").(bool)), d.Get("unsubscribe_tracking_settings_html_footer").(string), d.Get("unsubscribe_tracking_settings_text_footer").(string))
283 if err != nil {
284 return fmt.Errorf("Error updating mailgun unsubscribe tracking settings: %s", err.Error())
285 }
286 }
287 if d.HasChange("open_tracking_settings_active") {
288 err := mg.UpdateOpenTracking(ctx, domainName, boolToString(d.Get("open_tracking_settings_active").(bool)))
289 if err != nil {
290 return fmt.Errorf("Error updating mailgun open tracking settings: %s", err.Error())
291 }
292 }
293
294 if d.HasChange("click_tracking_settings_active") {
295 err := mg.UpdateClickTracking(ctx, domainName, boolToString(d.Get("click_tracking_settings_active").(bool)))
296 if err != nil {
297 return fmt.Errorf("Error updating mailgun click tracking settings: %s", err.Error())
298 }
299 }
300
301 if d.HasChange("require_tls") || d.HasChange("skip_verification") {
302 err := mg.UpdateDomainConnection(ctx, domainName, mailgun.DomainConnection{RequireTLS: d.Get("require_tls").(bool), SkipVerification: d.Get("skip_verification").(bool)})
303 if err != nil {
304 return fmt.Errorf("Error updating mailgun connexion settings: %s", err.Error())
305 }
306 }
307
308 if d.HasChange("credentials") {
309 old, new := d.GetChange("credentials")
310 for _, i := range old.([]interface{}) {
311 oldCredential := i.(map[string]interface{})
312 found := false
313 for _, j := range new.([]interface{}) {
314 newCredential := j.(map[string]interface{})
315 if oldCredential["login"] == newCredential["login"] {
316 found = true
05fbf613 317 if oldCredential["password"] != newCredential["password"] && newCredential["password"] != "" {
4457c936
AG
318 err := mg.ChangeCredentialPassword(ctx, oldCredential["login"].(string), newCredential["password"].(string))
319 if err != nil {
320 return fmt.Errorf("Error updating mailgun credential password: %s", err.Error())
321 }
322 }
323 break
324 }
325 }
326 if !found {
327 err := mg.DeleteCredential(ctx, oldCredential["login"].(string))
328 if err != nil {
329 return fmt.Errorf("Error deleting mailgun credential : %s", err.Error())
330 }
331 }
332 }
333
334 for _, i := range new.([]interface{}) {
335 newCredential := i.(map[string]interface{})
336 found := false
337 for _, j := range old.([]interface{}) {
338 oldCredential := j.(map[string]interface{})
339 if oldCredential["login"] == newCredential["login"] {
340 found = true
341 break
342 }
343 }
344 if !found {
345 err := mg.CreateCredential(ctx, newCredential["login"].(string), newCredential["password"].(string))
346 if err != nil {
347 return fmt.Errorf("Error creating mailgun credential : %s", err.Error())
348 }
349 }
350 }
351 }
352
353 return ReadDomain(d, meta)
354}
355
356func DeleteDomain(d *schema.ResourceData, meta interface{}) error {
357 mg := meta.(*mailgun.MailgunImpl)
358 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
359 defer cancel()
360
361 log.Printf("[DEBUG] Deleting mailgun domain: %s", d.Id())
362
363 err := mg.DeleteDomain(ctx, d.Get("name").(string))
364
365 return err
366}
367
368func ReadDomain(d *schema.ResourceData, meta interface{}) error {
369 mg := meta.(*mailgun.MailgunImpl)
5976bba0 370 ctx, cancel := context.WithTimeout(context.Background(), time.Second*120)
4457c936 371 defer cancel()
70ac6365 372 domainName := d.Id()
5c1feb2c 373 mg = mailgun.NewMailgun(domainName, mg.APIKey())
4457c936
AG
374
375 domainResponse, err := mg.GetDomain(ctx, domainName)
376 if err != nil {
377 return fmt.Errorf("Error Getting mailgun domain Details for %s: Error: %s", d.Id(), err)
378 }
379
05fbf613 380 d.Set("created_at", domainResponse.Domain.CreatedAt.String())
4457c936
AG
381 d.Set("smtd_login", domainResponse.Domain.SMTPLogin)
382 d.Set("name", domainResponse.Domain.Name)
383 d.Set("smtd_password", domainResponse.Domain.SMTPPassword)
384 d.Set("wildcard", domainResponse.Domain.Wildcard)
385 d.Set("spam_action", domainResponse.Domain.SpamAction)
386 d.Set("state", domainResponse.Domain.State)
387
388 simpleReceivingRecords := make([]map[string]interface{}, len(domainResponse.ReceivingDNSRecords))
389 for i, r := range domainResponse.ReceivingDNSRecords {
390 simpleReceivingRecords[i] = make(map[string]interface{})
391 simpleReceivingRecords[i]["priority"] = r.Priority
392 simpleReceivingRecords[i]["name"] = r.Name
393 simpleReceivingRecords[i]["valid"] = r.Valid
394 simpleReceivingRecords[i]["value"] = r.Value
395 simpleReceivingRecords[i]["record_type"] = r.RecordType
396 }
397 d.Set("receiving_records", simpleReceivingRecords)
398
399 simpleSendingRecords := make([]map[string]interface{}, len(domainResponse.SendingDNSRecords))
400 for i, r := range domainResponse.SendingDNSRecords {
401 simpleSendingRecords[i] = make(map[string]interface{})
402 simpleSendingRecords[i]["name"] = r.Name
403 simpleSendingRecords[i]["priority"] = r.Priority
404 simpleSendingRecords[i]["valid"] = r.Valid
405 simpleSendingRecords[i]["value"] = r.Value
406 simpleSendingRecords[i]["record_type"] = r.RecordType
407 }
408 d.Set("sending_records", simpleSendingRecords)
409
410 domainConnection, err := mg.GetDomainConnection(ctx, domainName)
411 if err != nil {
412 return fmt.Errorf("Error Getting mailgun domain connection Details for %s: Error: %s", d.Id(), err)
413 }
414 d.Set("require_tls", domainConnection.RequireTLS)
415 d.Set("skip_verification", domainConnection.SkipVerification)
416
417 domainTracking, err := mg.GetDomainTracking(ctx, domainName)
418 if err != nil {
419 return fmt.Errorf("Error Getting mailgun domain tracking Details for %s: Error: %s", d.Id(), err)
420 }
421
422 d.Set("open_tracking_settings_active", domainTracking.Open.Active)
423
424 d.Set("click_tracking_settings_active", domainTracking.Click.Active)
425 d.Set("unsubscribe_tracking_settings_active", domainTracking.Unsubscribe.Active)
426 d.Set("unsubscribe_tracking_settings_html_footer", domainTracking.Unsubscribe.HTMLFooter)
427 d.Set("unsubscribe_tracking_settings_text_footer", domainTracking.Unsubscribe.TextFooter)
428
5976bba0 429 ipAddress, err := getIps(ctx, mg)
40587421 430
4457c936 431 if err != nil {
40587421 432 return fmt.Errorf("Error Getting mailgun domain ips1 for %s: Error: %s", d.Id(), err)
4457c936
AG
433 }
434 ips := make([]string, len(ipAddress))
435 for i, r := range ipAddress {
436 ips[i] = r.IP
437
438 }
439 d.Set("ips", ips)
440
441 credentialsResponse, err := ListCredentials(domainName, mg.APIKey())
5c1feb2c
AG
442 if err != nil {
443 return fmt.Errorf("Error Getting mailgun credentials for %s: Error: %s", d.Id(), err)
444 }
61f3e553 445
4457c936 446 credentials := make([]map[string]interface{}, len(credentialsResponse))
05fbf613 447 credentialsConf := d.Get("credentials").([]interface{})
4457c936
AG
448 for i, r := range credentialsResponse {
449 credentials[i] = make(map[string]interface{})
05fbf613 450 credentials[i]["created_at"] = r.CreatedAt.String()
4457c936 451 credentials[i]["login"] = r.Login
05fbf613
AG
452 for _, c:= range credentialsConf {
453 conf:=c.(map[string]interface{})
454 if conf["login"] == credentials[i]["login"] {
455 credentials[i]["password"] = conf["password"]
456 }
457 }
4457c936 458 }
05fbf613 459
4457c936
AG
460 d.Set("credentials", credentials)
461
462 d.SetId(domainName)
463
464 return nil
465}
466
467func boolToString(b bool) string {
468 if b {
469 return "true"
470 }
471 return "false"
472}
473
474func ListCredentials(domain, apiKey string) ([]mailgun.Credential, error) {
475 mg := mailgun.NewMailgun(domain, apiKey)
476 it := mg.ListCredentials(nil)
477
478 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
479 defer cancel()
480
481 var page, result []mailgun.Credential
482 for it.Next(ctx, &page) {
483 result = append(result, page...)
484 }
485
486 if it.Err() != nil {
487 return nil, it.Err()
488 }
489 return result, nil
490}
b8802d62
AG
491
492func ImportStatePassthroughDomain(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
493 if _, ok := d.GetOk("dkim_key_size"); !ok {
494 d.Set("dkim_key_size", 1024)
495 }
496
497 if _, ok := d.GetOk("force_dkim_authority"); !ok {
498 d.Set("force_dkim_authority", false)
499 }
500 return []*schema.ResourceData{d}, nil
501}
5976bba0
AG
502
503func getIps(ctx context.Context,mg *mailgun.MailgunImpl) ([]mailgun.IPAddress, error){
1de838cb
AG
504 var ipAddress []mailgun.IPAddress
505 log.Printf("[DEBUG] begin to fetch ips for %s",mg.Domain())
506 err := resource.Retry(2*time.Minute, func() *resource.RetryError {
507 var err error
5976bba0 508 ipAddress, err = mg.ListDomainIPS(ctx)
1de838cb
AG
509 if err != nil {
510 log.Printf("[DEBUG] failed to fetch ips for %s",mg.Domain())
511 return resource.RetryableError(err)
512 }
513 log.Printf("[DEBUG] managed to fetch ips for %s",mg.Domain())
514
515 return nil
516 })
5976bba0
AG
517 return ipAddress, err
518}