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