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 event_bus_name to aws_cloudwatch_event_target #12887

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
90 changes: 74 additions & 16 deletions aws/resource_aws_cloudwatch_event_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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,
Expand Down Expand Up @@ -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)

Expand All @@ -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())
Expand All @@ -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()) {
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 <rule-name>/<target-id>", 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 <rule-name>/<target-id> or <bus-name>/<rule-name>/<target-id>", 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
}
12 changes: 7 additions & 5 deletions aws/resource_aws_cloudwatch_event_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
Expand Down Expand Up @@ -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" {
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/cloudwatch_event_target.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down