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

Add support for Redshift Event Target #20256

Merged
merged 6 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return fmt.Errorf("Error setting ecs_target error: %w", err)
return fmt.Errorf("error setting redshift_target: %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