From 1be0b9b3fc57122e5a3d8c200944febc34748efc Mon Sep 17 00:00:00 2001 From: Alexander Kalach Date: Sat, 18 Apr 2020 21:29:44 +0200 Subject: [PATCH] Add event_bus_name attribute to aws_cloudwatch_event_target --- aws/resource_aws_cloudwatch_event_target.go | 90 +++++++++++++++---- ...source_aws_cloudwatch_event_target_test.go | 12 +-- .../r/cloudwatch_event_target.html.markdown | 3 +- 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/aws/resource_aws_cloudwatch_event_target.go b/aws/resource_aws_cloudwatch_event_target.go index 9e559012e15..e6579c19ea9 100644 --- a/aws/resource_aws_cloudwatch_event_target.go +++ b/aws/resource_aws_cloudwatch_event_target.go @@ -2,14 +2,13 @@ package aws import ( "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "log" "math" "regexp" "strings" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" events "github.com/aws/aws-sdk-go/service/cloudwatchevents" @@ -28,6 +27,21 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { }, Schema: map[string]*schema.Schema{ + "event_bus_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 256), + StateFunc: func(v interface{}) string { + if v.(string) == "default" { + // "default" event bus name is not stored in the state to support the case when event_bus_name is omitted + return "" + } + + return v.(string) + }, + }, + "rule": { Type: schema.TypeString, Required: true, @@ -240,6 +254,10 @@ func resourceAwsCloudWatchEventTargetCreate(d *schema.ResourceData, meta interfa targetId = resource.UniqueId() d.Set("target_id", targetId) } + var busName string + if v, ok := d.GetOk("event_bus_name"); ok { + busName = v.(string) + } input := buildPutTargetInputStruct(d) @@ -254,7 +272,7 @@ func resourceAwsCloudWatchEventTargetCreate(d *schema.ResourceData, meta interfa out.FailedEntries) } - id := rule + "-" + targetId + id := prepareAwsCloudWatchEventTargetResourceId(busName, rule, targetId) d.SetId(id) log.Printf("[INFO] CloudWatch Event Target %q created", d.Id()) @@ -264,10 +282,14 @@ func resourceAwsCloudWatchEventTargetCreate(d *schema.ResourceData, meta interfa func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).cloudwatcheventsconn - + var busName string + if v, ok := d.GetOk("event_bus_name"); ok { + busName = v.(string) + } t, err := findEventTargetById( d.Get("target_id").(string), d.Get("rule").(string), + busName, nil, conn) if err != nil { if regexp.MustCompile(" not found$").MatchString(err.Error()) { @@ -340,12 +362,15 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface return nil } -func findEventTargetById(id, rule string, nextToken *string, conn *events.CloudWatchEvents) (*events.Target, error) { +func findEventTargetById(id, rule string, busName string, nextToken *string, conn *events.CloudWatchEvents) (*events.Target, error) { input := events.ListTargetsByRuleInput{ Rule: aws.String(rule), NextToken: nextToken, Limit: aws.Int64(100), // Set limit to allowed maximum to prevent API throttling } + if len(busName) > 0 { + input.EventBusName = aws.String(busName) + } log.Printf("[DEBUG] Reading CloudWatch Event Target: %s", input) out, err := conn.ListTargetsByRule(&input) if err != nil { @@ -359,7 +384,7 @@ func findEventTargetById(id, rule string, nextToken *string, conn *events.CloudW } if out.NextToken != nil { - return findEventTargetById(id, rule, nextToken, conn) + return findEventTargetById(id, rule, busName, nextToken, conn) } return nil, fmt.Errorf("CloudWatch Event Target %q (%q) not found", id, rule) @@ -382,9 +407,11 @@ func resourceAwsCloudWatchEventTargetUpdate(d *schema.ResourceData, meta interfa func resourceAwsCloudWatchEventTargetDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).cloudwatcheventsconn + busName := determineCloudWatchEventBusNameFromEventTargetResourceId(d.Id()) input := &events.RemoveTargetsInput{ - Ids: []*string{aws.String(d.Get("target_id").(string))}, - Rule: aws.String(d.Get("rule").(string)), + Ids: []*string{aws.String(d.Get("target_id").(string))}, + Rule: aws.String(d.Get("rule").(string)), + EventBusName: aws.String(busName), } output, err := conn.RemoveTargets(input) @@ -444,6 +471,9 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput { Rule: aws.String(d.Get("rule").(string)), Targets: []*events.Target{e}, } + if v, ok := d.GetOk("event_bus_name"); ok { + input.EventBusName = aws.String(v.(string)) + } return &input } @@ -663,18 +693,46 @@ func flattenAwsCloudWatchInputTransformer(inputTransformer *events.InputTransfor return result } -func resourceAwsCloudWatchEventTargetImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - idParts := strings.SplitN(d.Id(), "/", 2) - if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { - return nil, fmt.Errorf("unexpected format (%q), expected /", d.Id()) +func prepareAwsCloudWatchEventTargetResourceId(busName string, ruleName string, targetName string) string { + id := ruleName + "-" + targetName + if busName != "" && busName != "default" { + id = busName + "/" + id } - ruleName := idParts[0] - targetName := idParts[1] + return id +} +func determineCloudWatchEventBusNameFromEventTargetResourceId(id string) string { + idParts := strings.Split(id, "/") + if len(idParts) == 2 { + return idParts[0] + } + return "default" +} + +func resourceAwsCloudWatchEventTargetImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + idParts := strings.SplitN(d.Id(), "/", 3) + if len(idParts) < 2 || len(idParts) > 3 || idParts[0] == "" || idParts[1] == "" || (len(idParts) == 3 && idParts[2] == "") { + return nil, fmt.Errorf("unexpected format (%q), expected / or //", d.Id()) + } + busName := "default" + var ruleName string + var targetName string + if len(idParts) == 2 { + ruleName = idParts[0] + targetName = idParts[1] + } else { + busName = idParts[0] + ruleName = idParts[1] + targetName = idParts[2] + } d.Set("target_id", targetName) d.Set("rule", ruleName) - d.SetId(ruleName + "-" + targetName) + if busName != "default" { + d.Set("event_bus_name", busName) + } + id := prepareAwsCloudWatchEventTargetResourceId(busName, ruleName, targetName) + d.SetId(id) return []*schema.ResourceData{d}, nil } diff --git a/aws/resource_aws_cloudwatch_event_target_test.go b/aws/resource_aws_cloudwatch_event_target_test.go index 9fcef6210bb..8c202fd6046 100644 --- a/aws/resource_aws_cloudwatch_event_target_test.go +++ b/aws/resource_aws_cloudwatch_event_target_test.go @@ -108,6 +108,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) { Config: testAccAWSCloudWatchEventTargetConfig(ruleName, snsTopicName1, targetID1), Check: resource.ComposeTestCheckFunc( testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target), + resource.TestCheckNoResourceAttr("aws_cloudwatch_event_target.moobar", "event_bus_name"), resource.TestCheckResourceAttr("aws_cloudwatch_event_target.moobar", "rule", ruleName), resource.TestCheckResourceAttr("aws_cloudwatch_event_target.moobar", "target_id", targetID1), resource.TestMatchResourceAttr("aws_cloudwatch_event_target.moobar", "arn", @@ -383,7 +384,7 @@ func testAccCheckCloudWatchEventTargetExists(n string, rule *events.Target) reso conn := testAccProvider.Meta().(*AWSClient).cloudwatcheventsconn t, err := findEventTargetById(rs.Primary.Attributes["target_id"], - rs.Primary.Attributes["rule"], nil, conn) + rs.Primary.Attributes["rule"], "", nil, conn) if err != nil { return fmt.Errorf("Event Target not found: %s", err) } @@ -403,7 +404,7 @@ func testAccCheckAWSCloudWatchEventTargetDestroy(s *terraform.State) error { } t, err := findEventTargetById(rs.Primary.Attributes["target_id"], - rs.Primary.Attributes["rule"], nil, conn) + rs.Primary.Attributes["rule"], "", nil, conn) if err == nil { return fmt.Errorf("CloudWatch Event Target %q still exists: %s", rs.Primary.ID, t) @@ -432,9 +433,10 @@ resource "aws_cloudwatch_event_rule" "foo" { } resource "aws_cloudwatch_event_target" "moobar" { - rule = "${aws_cloudwatch_event_rule.foo.name}" - target_id = "%s" - arn = "${aws_sns_topic.moon.arn}" + rule = "${aws_cloudwatch_event_rule.foo.name}" + event_bus_name = "default" + target_id = "%s" + arn = "${aws_sns_topic.moon.arn}" } resource "aws_sns_topic" "moon" { diff --git a/website/docs/r/cloudwatch_event_target.html.markdown b/website/docs/r/cloudwatch_event_target.html.markdown index 43822e309b1..b68d9eb4823 100644 --- a/website/docs/r/cloudwatch_event_target.html.markdown +++ b/website/docs/r/cloudwatch_event_target.html.markdown @@ -248,6 +248,7 @@ DOC The following arguments are supported: * `rule` - (Required) The name of the rule you want to add targets to. +* `event_bus_name` - (Optional) The event bus to associate with the rule. If you omit this, the `default` event bus is used. * `target_id` - (Optional) The unique target assignment ID. If missing, will generate a random, unique id. * `arn` - (Required) The Amazon Resource Name (ARN) associated of the target. * `input` - (Optional) Valid JSON text passed to the target. @@ -305,7 +306,7 @@ For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonEC ## Import -Cloud Watch Event Target can be imported using the role event_rule and target_id separated by `/`. +Cloud Watch Event Target can be imported using `event_bus_name/rule-name/target-id` (if you omit `event_bus_name`, the `default` event bus will be used). ``` $ terraform import aws_cloudwatch_event_target.test-event-target rule-name/target-id