github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_ses_receipt_rule.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "sort" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/ses" 12 "github.com/hashicorp/terraform/helper/hashcode" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceAwsSesReceiptRule() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsSesReceiptRuleCreate, 19 Update: resourceAwsSesReceiptRuleUpdate, 20 Read: resourceAwsSesReceiptRuleRead, 21 Delete: resourceAwsSesReceiptRuleDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "name": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 30 "rule_set_name": &schema.Schema{ 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 }, 35 36 "after": &schema.Schema{ 37 Type: schema.TypeString, 38 Optional: true, 39 }, 40 41 "enabled": &schema.Schema{ 42 Type: schema.TypeBool, 43 Optional: true, 44 Computed: true, 45 }, 46 47 "recipients": &schema.Schema{ 48 Type: schema.TypeSet, 49 Elem: &schema.Schema{Type: schema.TypeString}, 50 Optional: true, 51 Set: schema.HashString, 52 }, 53 54 "scan_enabled": &schema.Schema{ 55 Type: schema.TypeBool, 56 Optional: true, 57 Computed: true, 58 }, 59 60 "tls_policy": &schema.Schema{ 61 Type: schema.TypeString, 62 Optional: true, 63 Computed: true, 64 }, 65 66 "add_header_action": &schema.Schema{ 67 Type: schema.TypeSet, 68 Optional: true, 69 Elem: &schema.Resource{ 70 Schema: map[string]*schema.Schema{ 71 "header_name": &schema.Schema{ 72 Type: schema.TypeString, 73 Required: true, 74 }, 75 76 "header_value": &schema.Schema{ 77 Type: schema.TypeString, 78 Required: true, 79 }, 80 81 "position": &schema.Schema{ 82 Type: schema.TypeInt, 83 Required: true, 84 }, 85 }, 86 }, 87 Set: func(v interface{}) int { 88 var buf bytes.Buffer 89 m := v.(map[string]interface{}) 90 buf.WriteString(fmt.Sprintf("%s-", m["header_name"].(string))) 91 buf.WriteString(fmt.Sprintf("%s-", m["header_value"].(string))) 92 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 93 94 return hashcode.String(buf.String()) 95 }, 96 }, 97 98 "bounce_action": &schema.Schema{ 99 Type: schema.TypeSet, 100 Optional: true, 101 Elem: &schema.Resource{ 102 Schema: map[string]*schema.Schema{ 103 "message": &schema.Schema{ 104 Type: schema.TypeString, 105 Required: true, 106 }, 107 108 "sender": &schema.Schema{ 109 Type: schema.TypeString, 110 Required: true, 111 }, 112 113 "smtp_reply_code": &schema.Schema{ 114 Type: schema.TypeString, 115 Required: true, 116 }, 117 118 "status_code": &schema.Schema{ 119 Type: schema.TypeString, 120 Optional: true, 121 }, 122 123 "topic_arn": &schema.Schema{ 124 Type: schema.TypeString, 125 Optional: true, 126 }, 127 128 "position": &schema.Schema{ 129 Type: schema.TypeInt, 130 Required: true, 131 }, 132 }, 133 }, 134 Set: func(v interface{}) int { 135 var buf bytes.Buffer 136 m := v.(map[string]interface{}) 137 buf.WriteString(fmt.Sprintf("%s-", m["message"].(string))) 138 buf.WriteString(fmt.Sprintf("%s-", m["sender"].(string))) 139 buf.WriteString(fmt.Sprintf("%s-", m["smtp_reply_code"].(string))) 140 141 if _, ok := m["status_code"]; ok { 142 buf.WriteString(fmt.Sprintf("%s-", m["status_code"].(string))) 143 } 144 145 if _, ok := m["topic_arn"]; ok { 146 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 147 } 148 149 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 150 151 return hashcode.String(buf.String()) 152 }, 153 }, 154 155 "lambda_action": &schema.Schema{ 156 Type: schema.TypeSet, 157 Optional: true, 158 Elem: &schema.Resource{ 159 Schema: map[string]*schema.Schema{ 160 "function_arn": &schema.Schema{ 161 Type: schema.TypeString, 162 Required: true, 163 }, 164 165 "invocation_type": &schema.Schema{ 166 Type: schema.TypeString, 167 Optional: true, 168 Computed: true, 169 }, 170 171 "topic_arn": &schema.Schema{ 172 Type: schema.TypeString, 173 Optional: true, 174 }, 175 176 "position": &schema.Schema{ 177 Type: schema.TypeInt, 178 Required: true, 179 }, 180 }, 181 }, 182 Set: func(v interface{}) int { 183 var buf bytes.Buffer 184 m := v.(map[string]interface{}) 185 buf.WriteString(fmt.Sprintf("%s-", m["function_arn"].(string))) 186 187 if _, ok := m["invocation_type"]; ok { 188 buf.WriteString(fmt.Sprintf("%s-", m["invocation_type"].(string))) 189 } 190 191 if _, ok := m["topic_arn"]; ok { 192 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 193 } 194 195 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 196 197 return hashcode.String(buf.String()) 198 }, 199 }, 200 201 "s3_action": &schema.Schema{ 202 Type: schema.TypeSet, 203 Optional: true, 204 Elem: &schema.Resource{ 205 Schema: map[string]*schema.Schema{ 206 "bucket_name": &schema.Schema{ 207 Type: schema.TypeString, 208 Required: true, 209 }, 210 211 "kms_key_arn": &schema.Schema{ 212 Type: schema.TypeString, 213 Optional: true, 214 }, 215 216 "object_key_prefix": &schema.Schema{ 217 Type: schema.TypeString, 218 Optional: true, 219 }, 220 221 "topic_arn": &schema.Schema{ 222 Type: schema.TypeString, 223 Optional: true, 224 }, 225 226 "position": &schema.Schema{ 227 Type: schema.TypeInt, 228 Required: true, 229 }, 230 }, 231 }, 232 Set: func(v interface{}) int { 233 var buf bytes.Buffer 234 m := v.(map[string]interface{}) 235 buf.WriteString(fmt.Sprintf("%s-", m["bucket_name"].(string))) 236 237 if _, ok := m["kms_key_arn"]; ok { 238 buf.WriteString(fmt.Sprintf("%s-", m["kms_key_arn"].(string))) 239 } 240 241 if _, ok := m["object_key_prefix"]; ok { 242 buf.WriteString(fmt.Sprintf("%s-", m["object_key_prefix"].(string))) 243 } 244 245 if _, ok := m["topic_arn"]; ok { 246 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 247 } 248 249 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 250 251 return hashcode.String(buf.String()) 252 }, 253 }, 254 255 "sns_action": &schema.Schema{ 256 Type: schema.TypeSet, 257 Optional: true, 258 Elem: &schema.Resource{ 259 Schema: map[string]*schema.Schema{ 260 "topic_arn": &schema.Schema{ 261 Type: schema.TypeString, 262 Required: true, 263 }, 264 265 "position": &schema.Schema{ 266 Type: schema.TypeInt, 267 Required: true, 268 }, 269 }, 270 }, 271 Set: func(v interface{}) int { 272 var buf bytes.Buffer 273 m := v.(map[string]interface{}) 274 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 275 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 276 277 return hashcode.String(buf.String()) 278 }, 279 }, 280 281 "stop_action": &schema.Schema{ 282 Type: schema.TypeSet, 283 Optional: true, 284 Elem: &schema.Resource{ 285 Schema: map[string]*schema.Schema{ 286 "scope": &schema.Schema{ 287 Type: schema.TypeString, 288 Required: true, 289 }, 290 291 "topic_arn": &schema.Schema{ 292 Type: schema.TypeString, 293 Optional: true, 294 }, 295 296 "position": &schema.Schema{ 297 Type: schema.TypeInt, 298 Required: true, 299 }, 300 }, 301 }, 302 Set: func(v interface{}) int { 303 var buf bytes.Buffer 304 m := v.(map[string]interface{}) 305 buf.WriteString(fmt.Sprintf("%s-", m["scope"].(string))) 306 307 if _, ok := m["topic_arn"]; ok { 308 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 309 } 310 311 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 312 313 return hashcode.String(buf.String()) 314 }, 315 }, 316 317 "workmail_action": &schema.Schema{ 318 Type: schema.TypeSet, 319 Optional: true, 320 Elem: &schema.Resource{ 321 Schema: map[string]*schema.Schema{ 322 "organization_arn": &schema.Schema{ 323 Type: schema.TypeString, 324 Required: true, 325 }, 326 327 "topic_arn": &schema.Schema{ 328 Type: schema.TypeString, 329 Optional: true, 330 }, 331 332 "position": &schema.Schema{ 333 Type: schema.TypeInt, 334 Required: true, 335 }, 336 }, 337 }, 338 Set: func(v interface{}) int { 339 var buf bytes.Buffer 340 m := v.(map[string]interface{}) 341 buf.WriteString(fmt.Sprintf("%s-", m["organization_arn"].(string))) 342 343 if _, ok := m["topic_arn"]; ok { 344 buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string))) 345 } 346 347 buf.WriteString(fmt.Sprintf("%d-", m["position"].(int))) 348 349 return hashcode.String(buf.String()) 350 }, 351 }, 352 }, 353 } 354 } 355 356 func resourceAwsSesReceiptRuleCreate(d *schema.ResourceData, meta interface{}) error { 357 conn := meta.(*AWSClient).sesConn 358 359 createOpts := &ses.CreateReceiptRuleInput{ 360 Rule: buildReceiptRule(d, meta), 361 RuleSetName: aws.String(d.Get("rule_set_name").(string)), 362 } 363 364 if v, ok := d.GetOk("after"); ok { 365 createOpts.After = aws.String(v.(string)) 366 } 367 368 _, err := conn.CreateReceiptRule(createOpts) 369 if err != nil { 370 return fmt.Errorf("Error creating SES rule: %s", err) 371 } 372 373 d.SetId(d.Get("name").(string)) 374 375 return resourceAwsSesReceiptRuleUpdate(d, meta) 376 } 377 378 func resourceAwsSesReceiptRuleUpdate(d *schema.ResourceData, meta interface{}) error { 379 conn := meta.(*AWSClient).sesConn 380 381 updateOpts := &ses.UpdateReceiptRuleInput{ 382 Rule: buildReceiptRule(d, meta), 383 RuleSetName: aws.String(d.Get("rule_set_name").(string)), 384 } 385 386 _, err := conn.UpdateReceiptRule(updateOpts) 387 if err != nil { 388 return fmt.Errorf("Error updating SES rule: %s", err) 389 } 390 391 if d.HasChange("after") { 392 changePosOpts := &ses.SetReceiptRulePositionInput{ 393 After: aws.String(d.Get("after").(string)), 394 RuleName: aws.String(d.Get("name").(string)), 395 RuleSetName: aws.String(d.Get("rule_set_name").(string)), 396 } 397 398 _, err := conn.SetReceiptRulePosition(changePosOpts) 399 if err != nil { 400 return fmt.Errorf("Error updating SES rule: %s", err) 401 } 402 } 403 404 return resourceAwsSesReceiptRuleRead(d, meta) 405 } 406 407 func resourceAwsSesReceiptRuleRead(d *schema.ResourceData, meta interface{}) error { 408 conn := meta.(*AWSClient).sesConn 409 410 describeOpts := &ses.DescribeReceiptRuleInput{ 411 RuleName: aws.String(d.Id()), 412 RuleSetName: aws.String(d.Get("rule_set_name").(string)), 413 } 414 415 response, err := conn.DescribeReceiptRule(describeOpts) 416 if err != nil { 417 _, ok := err.(awserr.Error) 418 if ok && err.(awserr.Error).Code() == "RuleDoesNotExist" { 419 log.Printf("[WARN] SES Receipt Rule (%s) not found", d.Id()) 420 d.SetId("") 421 return nil 422 } else { 423 return err 424 } 425 } 426 427 d.Set("enabled", *response.Rule.Enabled) 428 d.Set("recipients", flattenStringList(response.Rule.Recipients)) 429 d.Set("scan_enabled", *response.Rule.ScanEnabled) 430 d.Set("tls_policy", *response.Rule.TlsPolicy) 431 432 addHeaderActionList := []map[string]interface{}{} 433 bounceActionList := []map[string]interface{}{} 434 lambdaActionList := []map[string]interface{}{} 435 s3ActionList := []map[string]interface{}{} 436 snsActionList := []map[string]interface{}{} 437 stopActionList := []map[string]interface{}{} 438 workmailActionList := []map[string]interface{}{} 439 440 for i, element := range response.Rule.Actions { 441 if element.AddHeaderAction != nil { 442 addHeaderAction := map[string]interface{}{ 443 "header_name": *element.AddHeaderAction.HeaderName, 444 "header_value": *element.AddHeaderAction.HeaderValue, 445 "position": i, 446 } 447 addHeaderActionList = append(addHeaderActionList, addHeaderAction) 448 } 449 450 if element.BounceAction != nil { 451 bounceAction := map[string]interface{}{ 452 "message": *element.BounceAction.Message, 453 "sender": *element.BounceAction.Sender, 454 "smtp_reply_code": *element.BounceAction.SmtpReplyCode, 455 "position": i, 456 } 457 458 if element.BounceAction.StatusCode != nil { 459 bounceAction["status_code"] = *element.BounceAction.StatusCode 460 } 461 462 if element.BounceAction.TopicArn != nil { 463 bounceAction["topic_arn"] = *element.BounceAction.TopicArn 464 } 465 466 bounceActionList = append(bounceActionList, bounceAction) 467 } 468 469 if element.LambdaAction != nil { 470 lambdaAction := map[string]interface{}{ 471 "function_arn": *element.LambdaAction.FunctionArn, 472 "position": i, 473 } 474 475 if element.LambdaAction.InvocationType != nil { 476 lambdaAction["invocation_type"] = *element.LambdaAction.InvocationType 477 } 478 479 if element.LambdaAction.TopicArn != nil { 480 lambdaAction["topic_arn"] = *element.LambdaAction.TopicArn 481 } 482 483 lambdaActionList = append(lambdaActionList, lambdaAction) 484 } 485 486 if element.S3Action != nil { 487 s3Action := map[string]interface{}{ 488 "bucket_name": *element.S3Action.BucketName, 489 "position": i, 490 } 491 492 if element.S3Action.KmsKeyArn != nil { 493 s3Action["kms_key_arn"] = *element.S3Action.KmsKeyArn 494 } 495 496 if element.S3Action.ObjectKeyPrefix != nil { 497 s3Action["object_key_prefix"] = *element.S3Action.ObjectKeyPrefix 498 } 499 500 if element.S3Action.TopicArn != nil { 501 s3Action["topic_arn"] = *element.S3Action.TopicArn 502 } 503 504 s3ActionList = append(s3ActionList, s3Action) 505 } 506 507 if element.SNSAction != nil { 508 snsAction := map[string]interface{}{ 509 "topic_arn": *element.SNSAction.TopicArn, 510 "position": i, 511 } 512 513 snsActionList = append(snsActionList, snsAction) 514 } 515 516 if element.StopAction != nil { 517 stopAction := map[string]interface{}{ 518 "scope": *element.StopAction.Scope, 519 "position": i, 520 } 521 522 if element.StopAction.TopicArn != nil { 523 stopAction["topic_arn"] = *element.StopAction.TopicArn 524 } 525 526 stopActionList = append(stopActionList, stopAction) 527 } 528 529 if element.WorkmailAction != nil { 530 workmailAction := map[string]interface{}{ 531 "organization_arn": *element.WorkmailAction.OrganizationArn, 532 "position": i, 533 } 534 535 if element.WorkmailAction.TopicArn != nil { 536 workmailAction["topic_arn"] = *element.WorkmailAction.TopicArn 537 } 538 539 workmailActionList = append(workmailActionList, workmailAction) 540 } 541 542 } 543 544 err = d.Set("add_header_action", addHeaderActionList) 545 if err != nil { 546 return err 547 } 548 549 err = d.Set("bounce_action", bounceActionList) 550 if err != nil { 551 return err 552 } 553 554 err = d.Set("lambda_action", lambdaActionList) 555 if err != nil { 556 return err 557 } 558 559 err = d.Set("s3_action", s3ActionList) 560 if err != nil { 561 return err 562 } 563 564 err = d.Set("sns_action", snsActionList) 565 if err != nil { 566 return err 567 } 568 569 err = d.Set("stop_action", stopActionList) 570 if err != nil { 571 return err 572 } 573 574 err = d.Set("workmail_action", workmailActionList) 575 if err != nil { 576 return err 577 } 578 579 return nil 580 } 581 582 func resourceAwsSesReceiptRuleDelete(d *schema.ResourceData, meta interface{}) error { 583 conn := meta.(*AWSClient).sesConn 584 585 deleteOpts := &ses.DeleteReceiptRuleInput{ 586 RuleName: aws.String(d.Id()), 587 RuleSetName: aws.String(d.Get("rule_set_name").(string)), 588 } 589 590 _, err := conn.DeleteReceiptRule(deleteOpts) 591 if err != nil { 592 return fmt.Errorf("Error deleting SES receipt rule: %s", err) 593 } 594 595 return nil 596 } 597 598 func buildReceiptRule(d *schema.ResourceData, meta interface{}) *ses.ReceiptRule { 599 receiptRule := &ses.ReceiptRule{ 600 Name: aws.String(d.Get("name").(string)), 601 } 602 603 if v, ok := d.GetOk("enabled"); ok { 604 receiptRule.Enabled = aws.Bool(v.(bool)) 605 } 606 607 if v, ok := d.GetOk("recipients"); ok { 608 receiptRule.Recipients = expandStringList(v.(*schema.Set).List()) 609 } 610 611 if v, ok := d.GetOk("scan_enabled"); ok { 612 receiptRule.ScanEnabled = aws.Bool(v.(bool)) 613 } 614 615 if v, ok := d.GetOk("tls_policy"); ok { 616 receiptRule.TlsPolicy = aws.String(v.(string)) 617 } 618 619 actions := make(map[int]*ses.ReceiptAction) 620 621 if v, ok := d.GetOk("add_header_action"); ok { 622 for _, element := range v.(*schema.Set).List() { 623 elem := element.(map[string]interface{}) 624 625 actions[elem["position"].(int)] = &ses.ReceiptAction{ 626 AddHeaderAction: &ses.AddHeaderAction{ 627 HeaderName: aws.String(elem["header_name"].(string)), 628 HeaderValue: aws.String(elem["header_value"].(string)), 629 }, 630 } 631 } 632 } 633 634 if v, ok := d.GetOk("bounce_action"); ok { 635 for _, element := range v.(*schema.Set).List() { 636 elem := element.(map[string]interface{}) 637 638 bounceAction := &ses.BounceAction{ 639 Message: aws.String(elem["message"].(string)), 640 Sender: aws.String(elem["sender"].(string)), 641 SmtpReplyCode: aws.String(elem["smtp_reply_code"].(string)), 642 } 643 644 if elem["status_code"] != "" { 645 bounceAction.StatusCode = aws.String(elem["status_code"].(string)) 646 } 647 648 if elem["topic_arn"] != "" { 649 bounceAction.TopicArn = aws.String(elem["topic_arn"].(string)) 650 } 651 652 actions[elem["position"].(int)] = &ses.ReceiptAction{ 653 BounceAction: bounceAction, 654 } 655 } 656 } 657 658 if v, ok := d.GetOk("lambda_action"); ok { 659 for _, element := range v.(*schema.Set).List() { 660 elem := element.(map[string]interface{}) 661 662 lambdaAction := &ses.LambdaAction{ 663 FunctionArn: aws.String(elem["function_arn"].(string)), 664 } 665 666 if elem["invocation_type"] != "" { 667 lambdaAction.InvocationType = aws.String(elem["invocation_type"].(string)) 668 } 669 670 if elem["topic_arn"] != "" { 671 lambdaAction.TopicArn = aws.String(elem["topic_arn"].(string)) 672 } 673 674 actions[elem["position"].(int)] = &ses.ReceiptAction{ 675 LambdaAction: lambdaAction, 676 } 677 } 678 } 679 680 if v, ok := d.GetOk("s3_action"); ok { 681 for _, element := range v.(*schema.Set).List() { 682 elem := element.(map[string]interface{}) 683 684 s3Action := &ses.S3Action{ 685 BucketName: aws.String(elem["bucket_name"].(string)), 686 KmsKeyArn: aws.String(elem["kms_key_arn"].(string)), 687 ObjectKeyPrefix: aws.String(elem["object_key_prefix"].(string)), 688 } 689 690 if elem["topic_arn"] != "" { 691 s3Action.TopicArn = aws.String(elem["topic_arn"].(string)) 692 } 693 694 actions[elem["position"].(int)] = &ses.ReceiptAction{ 695 S3Action: s3Action, 696 } 697 } 698 } 699 700 if v, ok := d.GetOk("sns_action"); ok { 701 for _, element := range v.(*schema.Set).List() { 702 elem := element.(map[string]interface{}) 703 704 snsAction := &ses.SNSAction{ 705 TopicArn: aws.String(elem["topic_arn"].(string)), 706 } 707 708 actions[elem["position"].(int)] = &ses.ReceiptAction{ 709 SNSAction: snsAction, 710 } 711 } 712 } 713 714 if v, ok := d.GetOk("stop_action"); ok { 715 for _, element := range v.(*schema.Set).List() { 716 elem := element.(map[string]interface{}) 717 718 stopAction := &ses.StopAction{ 719 Scope: aws.String(elem["scope"].(string)), 720 } 721 722 if elem["topic_arn"] != "" { 723 stopAction.TopicArn = aws.String(elem["topic_arn"].(string)) 724 } 725 726 actions[elem["position"].(int)] = &ses.ReceiptAction{ 727 StopAction: stopAction, 728 } 729 } 730 } 731 732 if v, ok := d.GetOk("workmail_action"); ok { 733 for _, element := range v.(*schema.Set).List() { 734 elem := element.(map[string]interface{}) 735 736 workmailAction := &ses.WorkmailAction{ 737 OrganizationArn: aws.String(elem["organization_arn"].(string)), 738 } 739 740 if elem["topic_arn"] != "" { 741 workmailAction.TopicArn = aws.String(elem["topic_arn"].(string)) 742 } 743 744 actions[elem["position"].(int)] = &ses.ReceiptAction{ 745 WorkmailAction: workmailAction, 746 } 747 } 748 } 749 750 var keys []int 751 for k := range actions { 752 keys = append(keys, k) 753 } 754 sort.Ints(keys) 755 756 sortedActions := []*ses.ReceiptAction{} 757 for _, k := range keys { 758 sortedActions = append(sortedActions, actions[k]) 759 } 760 761 receiptRule.Actions = sortedActions 762 763 return receiptRule 764 }