terraform/builtin/providers/aws/resource_aws_ses_receipt_ru...

765 lines
19 KiB
Go
Raw Normal View History

package aws
import (
"bytes"
"fmt"
"log"
"sort"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ses"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsSesReceiptRule() *schema.Resource {
return &schema.Resource{
Create: resourceAwsSesReceiptRuleCreate,
Update: resourceAwsSesReceiptRuleUpdate,
Read: resourceAwsSesReceiptRuleRead,
Delete: resourceAwsSesReceiptRuleDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"rule_set_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"after": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"enabled": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"recipients": &schema.Schema{
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Set: schema.HashString,
},
"scan_enabled": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"tls_policy": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"add_header_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"header_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"header_value": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["header_name"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["header_value"].(string)))
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"bounce_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"message": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"sender": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"smtp_reply_code": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"status_code": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["message"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["sender"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["smtp_reply_code"].(string)))
if _, ok := m["status_code"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["status_code"].(string)))
}
if _, ok := m["topic_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
}
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"lambda_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"function_arn": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"invocation_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["function_arn"].(string)))
if _, ok := m["invocation_type"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["invocation_type"].(string)))
}
if _, ok := m["topic_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
}
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"s3_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"bucket_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"kms_key_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"object_key_prefix": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["bucket_name"].(string)))
if _, ok := m["kms_key_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["kms_key_arn"].(string)))
}
if _, ok := m["object_key_prefix"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["object_key_prefix"].(string)))
}
if _, ok := m["topic_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
}
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"sns_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"stop_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"scope": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["scope"].(string)))
if _, ok := m["topic_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
}
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
"workmail_action": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organization_arn": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
},
},
Set: func(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["organization_arn"].(string)))
if _, ok := m["topic_arn"]; ok {
buf.WriteString(fmt.Sprintf("%s-", m["topic_arn"].(string)))
}
buf.WriteString(fmt.Sprintf("%d-", m["position"].(int)))
return hashcode.String(buf.String())
},
},
},
}
}
func resourceAwsSesReceiptRuleCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sesConn
createOpts := &ses.CreateReceiptRuleInput{
Rule: buildReceiptRule(d, meta),
RuleSetName: aws.String(d.Get("rule_set_name").(string)),
}
if v, ok := d.GetOk("after"); ok {
createOpts.After = aws.String(v.(string))
}
_, err := conn.CreateReceiptRule(createOpts)
if err != nil {
return fmt.Errorf("Error creating SES rule: %s", err)
}
d.SetId(d.Get("name").(string))
return resourceAwsSesReceiptRuleUpdate(d, meta)
}
func resourceAwsSesReceiptRuleUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sesConn
updateOpts := &ses.UpdateReceiptRuleInput{
Rule: buildReceiptRule(d, meta),
RuleSetName: aws.String(d.Get("rule_set_name").(string)),
}
_, err := conn.UpdateReceiptRule(updateOpts)
if err != nil {
return fmt.Errorf("Error updating SES rule: %s", err)
}
if d.HasChange("after") {
changePosOpts := &ses.SetReceiptRulePositionInput{
After: aws.String(d.Get("after").(string)),
RuleName: aws.String(d.Get("name").(string)),
RuleSetName: aws.String(d.Get("rule_set_name").(string)),
}
_, err := conn.SetReceiptRulePosition(changePosOpts)
if err != nil {
return fmt.Errorf("Error updating SES rule: %s", err)
}
}
return resourceAwsSesReceiptRuleRead(d, meta)
}
func resourceAwsSesReceiptRuleRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sesConn
describeOpts := &ses.DescribeReceiptRuleInput{
RuleName: aws.String(d.Id()),
RuleSetName: aws.String(d.Get("rule_set_name").(string)),
}
response, err := conn.DescribeReceiptRule(describeOpts)
if err != nil {
_, ok := err.(awserr.Error)
if ok && err.(awserr.Error).Code() == "RuleDoesNotExist" {
log.Printf("[WARN] SES Receipt Rule (%s) not found", d.Id())
d.SetId("")
return nil
} else {
return err
}
}
d.Set("enabled", *response.Rule.Enabled)
d.Set("recipients", flattenStringList(response.Rule.Recipients))
d.Set("scan_enabled", *response.Rule.ScanEnabled)
d.Set("tls_policy", *response.Rule.TlsPolicy)
addHeaderActionList := []map[string]interface{}{}
bounceActionList := []map[string]interface{}{}
lambdaActionList := []map[string]interface{}{}
s3ActionList := []map[string]interface{}{}
snsActionList := []map[string]interface{}{}
stopActionList := []map[string]interface{}{}
workmailActionList := []map[string]interface{}{}
for i, element := range response.Rule.Actions {
if element.AddHeaderAction != nil {
addHeaderAction := map[string]interface{}{
"header_name": *element.AddHeaderAction.HeaderName,
"header_value": *element.AddHeaderAction.HeaderValue,
"position": i,
}
addHeaderActionList = append(addHeaderActionList, addHeaderAction)
}
if element.BounceAction != nil {
bounceAction := map[string]interface{}{
"message": *element.BounceAction.Message,
"sender": *element.BounceAction.Sender,
"smtp_reply_code": *element.BounceAction.SmtpReplyCode,
"position": i,
}
if element.BounceAction.StatusCode != nil {
bounceAction["status_code"] = *element.BounceAction.StatusCode
}
if element.BounceAction.TopicArn != nil {
bounceAction["topic_arn"] = *element.BounceAction.TopicArn
}
bounceActionList = append(bounceActionList, bounceAction)
}
if element.LambdaAction != nil {
lambdaAction := map[string]interface{}{
"function_arn": *element.LambdaAction.FunctionArn,
"position": i,
}
if element.LambdaAction.InvocationType != nil {
lambdaAction["invocation_type"] = *element.LambdaAction.InvocationType
}
if element.LambdaAction.TopicArn != nil {
lambdaAction["topic_arn"] = *element.LambdaAction.TopicArn
}
lambdaActionList = append(lambdaActionList, lambdaAction)
}
if element.S3Action != nil {
s3Action := map[string]interface{}{
"bucket_name": *element.S3Action.BucketName,
"position": i,
}
if element.S3Action.KmsKeyArn != nil {
s3Action["kms_key_arn"] = *element.S3Action.KmsKeyArn
}
if element.S3Action.ObjectKeyPrefix != nil {
s3Action["object_key_prefix"] = *element.S3Action.ObjectKeyPrefix
}
if element.S3Action.TopicArn != nil {
s3Action["topic_arn"] = *element.S3Action.TopicArn
}
s3ActionList = append(s3ActionList, s3Action)
}
if element.SNSAction != nil {
snsAction := map[string]interface{}{
"topic_arn": *element.SNSAction.TopicArn,
"position": i,
}
snsActionList = append(snsActionList, snsAction)
}
if element.StopAction != nil {
stopAction := map[string]interface{}{
"scope": *element.StopAction.Scope,
"position": i,
}
if element.StopAction.TopicArn != nil {
stopAction["topic_arn"] = *element.StopAction.TopicArn
}
stopActionList = append(stopActionList, stopAction)
}
if element.WorkmailAction != nil {
workmailAction := map[string]interface{}{
"organization_arn": *element.WorkmailAction.OrganizationArn,
"position": i,
}
if element.WorkmailAction.TopicArn != nil {
workmailAction["topic_arn"] = *element.WorkmailAction.TopicArn
}
workmailActionList = append(workmailActionList, workmailAction)
}
}
err = d.Set("add_header_action", addHeaderActionList)
if err != nil {
return err
}
err = d.Set("bounce_action", bounceActionList)
if err != nil {
return err
}
err = d.Set("lambda_action", lambdaActionList)
if err != nil {
return err
}
err = d.Set("s3_action", s3ActionList)
if err != nil {
return err
}
err = d.Set("sns_action", snsActionList)
if err != nil {
return err
}
err = d.Set("stop_action", stopActionList)
if err != nil {
return err
}
err = d.Set("workmail_action", workmailActionList)
if err != nil {
return err
}
return nil
}
func resourceAwsSesReceiptRuleDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).sesConn
deleteOpts := &ses.DeleteReceiptRuleInput{
RuleName: aws.String(d.Id()),
RuleSetName: aws.String(d.Get("rule_set_name").(string)),
}
_, err := conn.DeleteReceiptRule(deleteOpts)
if err != nil {
return fmt.Errorf("Error deleting SES receipt rule: %s", err)
}
return nil
}
func buildReceiptRule(d *schema.ResourceData, meta interface{}) *ses.ReceiptRule {
receiptRule := &ses.ReceiptRule{
Name: aws.String(d.Get("name").(string)),
}
if v, ok := d.GetOk("enabled"); ok {
receiptRule.Enabled = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("recipients"); ok {
receiptRule.Recipients = expandStringList(v.(*schema.Set).List())
}
if v, ok := d.GetOk("scan_enabled"); ok {
receiptRule.ScanEnabled = aws.Bool(v.(bool))
}
if v, ok := d.GetOk("tls_policy"); ok {
receiptRule.TlsPolicy = aws.String(v.(string))
}
actions := make(map[int]*ses.ReceiptAction)
if v, ok := d.GetOk("add_header_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
actions[elem["position"].(int)] = &ses.ReceiptAction{
AddHeaderAction: &ses.AddHeaderAction{
HeaderName: aws.String(elem["header_name"].(string)),
HeaderValue: aws.String(elem["header_value"].(string)),
},
}
}
}
if v, ok := d.GetOk("bounce_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
bounceAction := &ses.BounceAction{
Message: aws.String(elem["message"].(string)),
Sender: aws.String(elem["sender"].(string)),
SmtpReplyCode: aws.String(elem["smtp_reply_code"].(string)),
}
if elem["status_code"] != "" {
bounceAction.StatusCode = aws.String(elem["status_code"].(string))
}
if elem["topic_arn"] != "" {
bounceAction.TopicArn = aws.String(elem["topic_arn"].(string))
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
BounceAction: bounceAction,
}
}
}
if v, ok := d.GetOk("lambda_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
lambdaAction := &ses.LambdaAction{
FunctionArn: aws.String(elem["function_arn"].(string)),
}
if elem["invocation_type"] != "" {
lambdaAction.InvocationType = aws.String(elem["invocation_type"].(string))
}
if elem["topic_arn"] != "" {
lambdaAction.TopicArn = aws.String(elem["topic_arn"].(string))
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
LambdaAction: lambdaAction,
}
}
}
if v, ok := d.GetOk("s3_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
s3Action := &ses.S3Action{
BucketName: aws.String(elem["bucket_name"].(string)),
KmsKeyArn: aws.String(elem["kms_key_arn"].(string)),
ObjectKeyPrefix: aws.String(elem["object_key_prefix"].(string)),
}
if elem["topic_arn"] != "" {
s3Action.TopicArn = aws.String(elem["topic_arn"].(string))
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
S3Action: s3Action,
}
}
}
if v, ok := d.GetOk("sns_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
snsAction := &ses.SNSAction{
TopicArn: aws.String(elem["topic_arn"].(string)),
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
SNSAction: snsAction,
}
}
}
if v, ok := d.GetOk("stop_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
stopAction := &ses.StopAction{
Scope: aws.String(elem["scope"].(string)),
}
if elem["topic_arn"] != "" {
stopAction.TopicArn = aws.String(elem["topic_arn"].(string))
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
StopAction: stopAction,
}
}
}
if v, ok := d.GetOk("workmail_action"); ok {
for _, element := range v.(*schema.Set).List() {
elem := element.(map[string]interface{})
workmailAction := &ses.WorkmailAction{
OrganizationArn: aws.String(elem["organization_arn"].(string)),
}
if elem["topic_arn"] != "" {
workmailAction.TopicArn = aws.String(elem["topic_arn"].(string))
}
actions[elem["position"].(int)] = &ses.ReceiptAction{
WorkmailAction: workmailAction,
}
}
}
var keys []int
for k := range actions {
keys = append(keys, k)
}
sort.Ints(keys)
sortedActions := []*ses.ReceiptAction{}
for _, k := range keys {
sortedActions = append(sortedActions, actions[k])
}
receiptRule.Actions = sortedActions
return receiptRule
}