Skip to content

Commit

Permalink
Merge pull request #20256 from hashicorp/f-redshift_event_target
Browse files Browse the repository at this point in the history
Add support for Redshift Event Target
  • Loading branch information
bill-rich authored Jul 22, 2021
2 parents 64e415d + 6f17e04 commit 15fa2e0
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/20256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_cloudwatch_event_target: Add support for Redshift event target.
```
1 change: 1 addition & 0 deletions aws/resource_aws_cloudwatch_event_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func testSweepCloudWatchEventRules(region string) error {
func testAccErrorCheckSkipEvents(t *testing.T) resource.ErrorCheckFunc {
return testAccErrorCheckSkipMessagesContaining(t,
"Operation is disabled in this region",
"not a supported service for a target",
)
}

Expand Down
90 changes: 90 additions & 0 deletions aws/resource_aws_cloudwatch_event_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,40 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
},
},

"redshift_target": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"database": {
Type: schema.TypeString,
Required: true,
},
"db_user": {
Type: schema.TypeString,
Optional: true,
},
"secrets_manager_arn": {
Type: schema.TypeString,
Optional: true,
},
"sql": {
Type: schema.TypeString,
Optional: true,
},
"statement_name": {
Type: schema.TypeString,
Optional: true,
},
"with_event": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},

"sqs_target": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -426,6 +460,12 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface
d.Set("http_target", nil)
}

if t.RedshiftDataParameters != nil {
if err := d.Set("redshift_target", flattenAwsCloudWatchEventTargetRedshiftParameters(t.RedshiftDataParameters)); err != nil {
return fmt.Errorf("Error setting ecs_target error: %w", err)
}
}

if t.EcsParameters != nil {
if err := d.Set("ecs_target", flattenAwsCloudWatchEventTargetEcsParameters(t.EcsParameters)); err != nil {
return fmt.Errorf("Error setting ecs_target error: %w", err)
Expand Down Expand Up @@ -538,6 +578,10 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
e.EcsParameters = expandAwsCloudWatchEventTargetEcsParameters(v.([]interface{}))
}

if v, ok := d.GetOk("redshift_target"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
e.RedshiftDataParameters = expandAwsCloudWatchEventTargetRedshiftParameters(v.([]interface{}))
}

if v, ok := d.GetOk("http_target"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
e.HttpParameters = expandAwsCloudWatchEventTargetHttpParameters(v.([]interface{})[0].(map[string]interface{}))
}
Expand Down Expand Up @@ -595,6 +639,34 @@ func expandAwsCloudWatchEventTargetRunParameters(config []interface{}) *events.R
return command
}

func expandAwsCloudWatchEventTargetRedshiftParameters(config []interface{}) *events.RedshiftDataParameters {
redshiftParameters := &events.RedshiftDataParameters{}
for _, c := range config {
param := c.(map[string]interface{})

redshiftParameters.Database = aws.String(param["database"].(string))
redshiftParameters.Sql = aws.String(param["sql"].(string))

if val, ok := param["with_event"].(bool); ok {
redshiftParameters.WithEvent = aws.Bool(val)
}

if val, ok := param["statement_name"].(string); ok && val != "" {
redshiftParameters.StatementName = aws.String(val)
}

if val, ok := param["secrets_manager_arn"].(string); ok && val != "" {
redshiftParameters.SecretManagerArn = aws.String(val)
}

if val, ok := param["db_user"].(string); ok && val != "" {
redshiftParameters.DbUser = aws.String(val)
}
}

return redshiftParameters
}

func expandAwsCloudWatchEventTargetEcsParameters(config []interface{}) *events.EcsParameters {
ecsParameters := &events.EcsParameters{}
for _, c := range config {
Expand Down Expand Up @@ -823,6 +895,24 @@ func flattenAwsCloudWatchEventTargetEcsParameters(ecsParameters *events.EcsParam
return result
}

func flattenAwsCloudWatchEventTargetRedshiftParameters(redshiftParameters *events.RedshiftDataParameters) []map[string]interface{} {
config := make(map[string]interface{})

if redshiftParameters == nil {
return []map[string]interface{}{config}
}

config["database"] = aws.StringValue(redshiftParameters.Database)
config["db_user"] = aws.StringValue(redshiftParameters.DbUser)
config["secrets_manager_arn"] = aws.StringValue(redshiftParameters.SecretManagerArn)
config["sql"] = aws.StringValue(redshiftParameters.Sql)
config["statement_name"] = aws.StringValue(redshiftParameters.StatementName)
config["with_event"] = aws.BoolValue(redshiftParameters.WithEvent)

result := []map[string]interface{}{config}
return result
}

func flattenAwsCloudWatchEventTargetEcsParametersNetworkConfiguration(nc *events.NetworkConfiguration) []interface{} {
if nc == nil {
return nil
Expand Down
62 changes: 62 additions & 0 deletions aws/resource_aws_cloudwatch_event_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,39 @@ func TestAccAWSCloudWatchEventTarget_ecs(t *testing.T) {
})
}

func TestAccAWSCloudWatchEventTarget_redshift(t *testing.T) {
resourceName := "aws_cloudwatch_event_target.test"
iamRoleResourceName := "aws_iam_role.test"
var v events.Target
rName := acctest.RandomWithPrefix("tf_ecs_target")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, events.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfigRedshift(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists(resourceName, &v),
resource.TestCheckResourceAttrPair(resourceName, "role_arn", iamRoleResourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "redshift_target.#", "1"),
resource.TestCheckResourceAttr(resourceName, "redshift_target.0.database", "redshiftdb"),
resource.TestCheckResourceAttr(resourceName, "redshift_target.0.sql", "SELECT * FROM table"),
resource.TestCheckResourceAttr(resourceName, "redshift_target.0.statement_name", "NewStatement"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}

func TestAccAWSCloudWatchEventTarget_ecsWithBlankLaunchType(t *testing.T) {
resourceName := "aws_cloudwatch_event_target.test"
iamRoleResourceName := "aws_iam_role.test"
Expand Down Expand Up @@ -1357,6 +1390,35 @@ resource "aws_cloudwatch_event_target" "test" {
`
}

func testAccAWSCloudWatchEventTargetConfigRedshift(rName string) string {
return composeConfig(testAccAWSCloudWatchEventTargetConfigEcsBase(rName),
testAccAvailableAZsNoOptInConfig(),
fmt.Sprintf(`
resource "aws_cloudwatch_event_target" "test" {
arn = aws_redshift_cluster.default.arn
rule = aws_cloudwatch_event_rule.test.id
role_arn = aws_iam_role.test.arn
redshift_target {
database = "redshiftdb"
sql = "SELECT * FROM table"
statement_name = "NewStatement"
db_user = "someUser"
}
}
resource "aws_redshift_cluster" "default" {
cluster_identifier = "tf-redshift-cluster-%d"
database_name = "mydb"
master_username = "foo_test"
master_password = "Mustbe8characters"
node_type = "dc1.large"
automated_snapshot_retention_period = 0
allow_version_upgrade = false
skip_final_snapshot = true
}
`, 123))
}

func testAccAWSCloudWatchEventTargetConfigEcsWithBlankLaunchType(rName string) string {
return testAccAWSCloudWatchEventTargetConfigEcsBase(rName) + `
resource "aws_cloudwatch_event_target" "test" {
Expand Down
10 changes: 10 additions & 0 deletions website/docs/r/cloudwatch_event_target.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ The following arguments are supported:
* `ecs_target` - (Optional) Parameters used when you are using the rule to invoke Amazon ECS Task. Documented below. A maximum of 1 are allowed.
* `batch_target` - (Optional) Parameters used when you are using the rule to invoke an Amazon Batch Job. Documented below. A maximum of 1 are allowed.
* `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.
* `redshift_target` - (Optional) Parameters used when you are using the rule to invoke an Amazon Redshift Statement. 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.
* `http_target` - (Optional) Parameters used when you are using the rule to invoke an API Gateway REST endpoint. Documented below. A maximum of 1 is 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`.
Expand Down Expand Up @@ -387,6 +388,15 @@ For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonEC

* `partition_key_path` - (Optional) The JSON path to be extracted from the event and used as the partition key.

### redshift_target

* `database` - (Required) The name of the database.
* `db_user` - (Optional) The database user name.
* `secrets_manager_arn` - (Optional) The name or ARN of the secret that enables access to the database.
* `sql` - (Optional) The SQL statement text to run.
* `statement_name` - (Optional) The name of the SQL statement.
* `with_event` - (Optional) Indicates whether to send an event back to EventBridge after the SQL statement runs.

### sqs_target

* `message_group_id` - (Optional) The FIFO message group ID to use as the target.
Expand Down

0 comments on commit 15fa2e0

Please sign in to comment.