Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_cloudwatch_event_target - add support for dead letter queue #16366

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions aws/resource_aws_cloudwatch_event_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,41 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
},
},
},

"dead_letter_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"retry_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"maximum_retry_attempts": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 185),
Default: 185,
},
"maximum_event_age_in_seconds": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(60, 86400),
Default: 86400,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -350,6 +385,18 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface
}
}

if t.RetryPolicy != nil {
if err := d.Set("retry_policy", flattenAwsCloudWatchEventTargetRetryPolicyParameters(t.RetryPolicy)); err != nil {
return fmt.Errorf("Error setting retry_policy error: %#v", err)
}
}

if t.DeadLetterConfig != nil {
if err := d.Set("dead_letter_config", flattenAwsCloudWatchEventTargetDeadLetterConfigParameters(t.DeadLetterConfig)); err != nil {
return fmt.Errorf("Error setting dead_letter_config error: %#v", err)
}
}

return nil
}

Expand Down Expand Up @@ -434,6 +481,14 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
e.InputTransformer = expandAwsCloudWatchEventTransformerParameters(v.([]interface{}))
}

if v, ok := d.GetOk("retry_policy"); ok {
e.RetryPolicy = expandAwsCloudWatchEventRetryPolicyParameters(v.([]interface{}))
}

if v, ok := d.GetOk("dead_letter_config"); ok {
e.DeadLetterConfig = expandAwsCloudWatchEventDeadLetterConfigParameters(v.([]interface{}))
}

input := events.PutTargetsInput{
Rule: aws.String(d.Get("rule").(string)),
Targets: []*events.Target{e},
Expand Down Expand Up @@ -550,6 +605,31 @@ func expandAwsCloudWatchEventTargetSqsParameters(config []interface{}) *events.S
return sqsParameters
}

func expandAwsCloudWatchEventRetryPolicyParameters(config []interface{}) *events.RetryPolicy {
retryPolicyParameters := &events.RetryPolicy{}
for _, c := range config {
param := c.(map[string]interface{})
if v, ok := param["maximum_event_age_in_seconds"].(int); ok {
retryPolicyParameters.MaximumEventAgeInSeconds = aws.Int64(int64(v))
}
if v, ok := param["maximum_retry_attempts"].(int); ok {
retryPolicyParameters.MaximumRetryAttempts = aws.Int64(int64(v))
}
}
return retryPolicyParameters
}

func expandAwsCloudWatchEventDeadLetterConfigParameters(config []interface{}) *events.DeadLetterConfig {
deadLetterConfigParameters := &events.DeadLetterConfig{}
for _, c := range config {
param := c.(map[string]interface{})
if v, ok := param["arn"].(string); ok && v != "" {
deadLetterConfigParameters.Arn = aws.String(v)
}
}
return deadLetterConfigParameters
}

func expandAwsCloudWatchEventTransformerParameters(config []interface{}) *events.InputTransformer {
transformerParameters := &events.InputTransformer{}

Expand Down Expand Up @@ -638,6 +718,21 @@ func flattenAwsCloudWatchEventTargetKinesisParameters(kinesisParameters *events.
return result
}

func flattenAwsCloudWatchEventTargetRetryPolicyParameters(retryPolicy *events.RetryPolicy) []map[string]interface{} {
config := make(map[string]interface{})
config["maximum_event_age_in_seconds"] = int(aws.Int64Value(retryPolicy.MaximumEventAgeInSeconds))
config["maximum_retry_attempts"] = int(aws.Int64Value(retryPolicy.MaximumRetryAttempts))
result := []map[string]interface{}{config}
return result
}

func flattenAwsCloudWatchEventTargetDeadLetterConfigParameters(deadLetterConfig *events.DeadLetterConfig) []map[string]interface{} {
config := make(map[string]interface{})
config["arn"] = aws.StringValue(deadLetterConfig.Arn)
result := []map[string]interface{}{config}
return result
}

func flattenAwsCloudWatchEventTargetSqsParameters(sqsParameters *events.SqsParameters) []map[string]interface{} {
config := make(map[string]interface{})
config["message_group_id"] = aws.StringValue(sqsParameters.MessageGroupId)
Expand Down
28 changes: 24 additions & 4 deletions aws/resource_aws_cloudwatch_event_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "kinesis_target.#", "0"),
resource.TestCheckResourceAttr(resourceName, "sqs_target.#", "0"),
resource.TestCheckResourceAttr(resourceName, "input_transformer.#", "0"),
resource.TestCheckResourceAttr(resourceName, "retry_policy.#", "0"),
resource.TestCheckResourceAttr(resourceName, "dead_letter_config.#", "0"),
),
},
{
Expand Down Expand Up @@ -250,26 +252,34 @@ func TestAccAWSCloudWatchEventTarget_GeneratedTargetId(t *testing.T) {
func TestAccAWSCloudWatchEventTarget_full(t *testing.T) {
resourceName := "aws_cloudwatch_event_target.test"
kinesisStreamResourceName := "aws_kinesis_stream.test"
deadLetterSQSResourceName := "aws_sqs_queue.test"

var v events.Target

ruleName := acctest.RandomWithPrefix("tf-acc-cw-event-rule-full")
ssmDocumentName := acctest.RandomWithPrefix("tf_ssm_Document")
targetID := acctest.RandomWithPrefix("tf-acc-cw-target-full")

maximumRetryAttempts := acctest.RandIntRange(1, 10)
maximumEventAgeInSeconds := acctest.RandIntRange(60, 360)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfig_full(ruleName, targetID, ssmDocumentName),
Config: testAccAWSCloudWatchEventTargetConfig_full(ruleName, targetID, ssmDocumentName, maximumRetryAttempts, maximumEventAgeInSeconds),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists(resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "rule", ruleName),
resource.TestCheckResourceAttr(resourceName, "target_id", targetID),
resource.TestCheckResourceAttrPair(resourceName, "arn", kinesisStreamResourceName, "arn"),
testAccCheckResourceAttrEquivalentJSON(resourceName, "input", `{"source": ["aws.cloudtrail"]}`),
resource.TestCheckResourceAttr(resourceName, "input_path", ""),
resource.TestCheckResourceAttrPair(resourceName, "dead_letter_config.0.arn", deadLetterSQSResourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "retry_policy.0.maximum_retry_attempts", fmt.Sprint(maximumRetryAttempts)),
resource.TestCheckResourceAttr(resourceName, "retry_policy.0.maximum_event_age_in_seconds", fmt.Sprint(maximumEventAgeInSeconds)),
),
},
{
Expand Down Expand Up @@ -730,7 +740,7 @@ resource "aws_sns_topic" "test" {
`, ruleName, snsTopicName)
}

func testAccAWSCloudWatchEventTargetConfig_full(ruleName, targetName, rName string) string {
func testAccAWSCloudWatchEventTargetConfig_full(ruleName, targetName, rName string, maximumRetryAttempts int, maximumEventAgeInSeconds int) string {
return fmt.Sprintf(`
resource "aws_cloudwatch_event_rule" "test" {
name = %[1]q
Expand Down Expand Up @@ -784,7 +794,13 @@ EOF
resource "aws_cloudwatch_event_target" "test" {
rule = aws_cloudwatch_event_rule.test.name
target_id = %[3]q

dead_letter_config {
arn = aws_sqs_queue.test.arn
}
retry_policy {
maximum_retry_attempts = %[4]d
maximum_event_age_in_seconds= %[5]d
}
input = <<INPUT
{ "source": ["aws.cloudtrail"] }
INPUT
Expand All @@ -797,8 +813,12 @@ resource "aws_kinesis_stream" "test" {
shard_count = 1
}

resource "aws_sqs_queue" "test" {
name = "%[2]s_sqs_test"
}

data "aws_partition" "current" {}
`, ruleName, rName, targetName)
`, ruleName, rName, targetName, maximumRetryAttempts, maximumEventAgeInSeconds)
}

func testAccAWSCloudWatchEventTargetConfigSsmDocument(rName string) string {
Expand Down
8 changes: 8 additions & 0 deletions website/docs/r/cloudwatch_event_target.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ The following arguments are supported:
* `kinesis_target` - (Optional) Parameters used when you are using the rule to invoke an Amazon Kinesis Stream. Documented below. A maximum of 1 are allowed.
* `sqs_target` - (Optional) Parameters used when you are using the rule to invoke an Amazon SQS Queue. Documented below. A maximum of 1 are allowed.
* `input_transformer` - (Optional) Parameters used when you are providing a custom input to a target based on certain event data. Conflicts with `input` and `input_path`.
* `dead_letter_config` - (Optional) The target queue to send dead-letter queue events to.
* `retry_policy` - (Optional) The retry policy configuration to use for the dead-letter queue.

`run_command_targets` support the following:

Expand Down Expand Up @@ -354,6 +356,12 @@ For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonEC

* `input_template` - (Required) Template to customize data sent to the target. Must be valid JSON. To send a string value, the string value must include double quotes. Values must be escaped for both JSON and Terraform, e.g. `"\"Your string goes here.\\nA new line.\""`

`dead_letter_config` support the following:
* `arn` - (Required) The ARN of the SQS queue specified as the target for the dead-letter queue.

`retry_policy` support the following:
* `maximum_retry_attempts` - (Optional) The maximum amount of time, in seconds, to continue to make retry attempts.
* `maximum_event_age_in_seconds` - (Optional) The maximum number of retry attempts to make before the request fails.
## Import

EventBridge Targets can be imported using `event_bus_name/rule-name/target-id` (if you omit `event_bus_name`, the `default` event bus will be used).
Expand Down