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

eventbridge: ISO-friendly tagging #22550

Merged
merged 3 commits into from
Jan 12, 2022
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
7 changes: 7 additions & 0 deletions .changelog/22550.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_cloudwatch_event_rule: Attempt `tags`-on-create, fallback to tag after create, and allow some `tags` errors to be non-fatal to support non-standard AWS partitions (i.e., ISO)
```

```release-note:enhancement
resource/aws_cloudwatch_event_bus: Attempt `tags`-on-create, fallback to tag after create, and allow some `tags` errors to be non-fatal to support non-standard AWS partitions (i.e., ISO)
```
41 changes: 39 additions & 2 deletions internal/service/events/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ func resourceBusCreate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Creating EventBridge event bus: %v", input)

_, err := conn.CreateEventBus(input)

// Some partitions may not support tag-on-create
if input.Tags != nil && (tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException)) {
log.Printf("[WARN] EventBridge Bus (%s) create failed (%s) with tags. Trying create without tags.", d.Id(), err)
input.Tags = nil
_, err = conn.CreateEventBus(input)
}

if err != nil {
return fmt.Errorf("Creating EventBridge event bus (%s) failed: %w", eventBusName, err)
}
Expand All @@ -77,6 +85,20 @@ func resourceBusCreate(d *schema.ResourceData, meta interface{}) error {

log.Printf("[INFO] EventBridge event bus (%s) created", d.Id())

// Post-create tagging supported in some partitions
if input.Tags == nil && len(tags) > 0 {
err := UpdateTags(conn, d.Id(), nil, tags)

if v, ok := d.GetOk("tags"); (!ok || len(v.(map[string]interface{})) == 0) && (tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException)) {
log.Printf("[WARN] error adding tags after create for EventBridge Bus (%s): %s", d.Id(), err)
return resourceBusRead(d, meta)
}

if err != nil {
return fmt.Errorf("error creating EventBridge Bus (%s) tags: %w", d.Id(), err)
}
}

return resourceBusRead(d, meta)
}

Expand Down Expand Up @@ -106,9 +128,17 @@ func resourceBusRead(d *schema.ResourceData, meta interface{}) error {
d.Set("name", output.Name)

tags, err := ListTags(conn, aws.StringValue(output.Arn))

// ISO partitions may not support tagging, giving error
if tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException) {
log.Printf("[WARN] Unable to list tags for EventBridge Bus %s: %s", d.Id(), err)
return nil
}

if err != nil {
return fmt.Errorf("error listing tags for EventBridge event bus (%s): %w", d.Id(), err)
}

tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
Expand All @@ -130,8 +160,15 @@ func resourceBusUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := UpdateTags(conn, arn, o, n); err != nil {
return fmt.Errorf("error updating CloudwWatch Events event bus (%s) tags: %w", arn, err)
err := UpdateTags(conn, arn, o, n)

if tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException) {
log.Printf("[WARN] Unable to update tags for EventBridge Bus %s: %s", d.Id(), err)
return resourceBusRead(d, meta)
}

if err != nil {
return fmt.Errorf("error updating EventBridge Bus tags: %w", err)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package events

const (
ErrCodeAccessDenied = "AccessDenied"
)

const (
DefaultEventBusName = "default"
)
74 changes: 57 additions & 17 deletions internal/service/events/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,14 @@ func resourceRuleCreate(d *schema.ResourceData, meta interface{}) error {
}

log.Printf("[DEBUG] Creating EventBridge Rule: %s", input)
// IAM Roles take some time to propagate
err = resource.Retry(tfiam.PropagationTimeout, func() *resource.RetryError {
_, err = conn.PutRule(input)

if tfawserr.ErrMessageContains(err, "ValidationException", "cannot be assumed by principal") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})
err = retryPutRule(conn, input)

if tfresource.TimedOut(err) {
_, err = conn.PutRule(input)
// Some partitions may not support tag-on-create
if input.Tags != nil && (tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException)) {
log.Printf("[WARN] EventBridge Rule (%s) create failed (%s) with tags. Trying create without tags.", d.Id(), err)
input.Tags = nil
err = retryPutRule(conn, input)
}

if err != nil {
Expand All @@ -145,6 +136,20 @@ func resourceRuleCreate(d *schema.ResourceData, meta interface{}) error {

d.SetId(RuleCreateResourceID(aws.StringValue(input.EventBusName), aws.StringValue(input.Name)))

// Post-create tagging supported in some partitions
if input.Tags == nil && len(tags) > 0 {
err := UpdateTags(conn, d.Id(), nil, tags)

if v, ok := d.GetOk("tags"); (!ok || len(v.(map[string]interface{})) == 0) && (tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException)) {
log.Printf("[WARN] error adding tags after create for EventBridge Rule (%s): %s", d.Id(), err)
return resourceRuleRead(d, meta)
}

if err != nil {
return fmt.Errorf("error creating EventBridge Rule (%s) tags: %w", name, err)
}
}

return resourceRuleRead(d, meta)
}

Expand Down Expand Up @@ -197,6 +202,12 @@ func resourceRuleRead(d *schema.ResourceData, meta interface{}) error {

tags, err := ListTags(conn, arn)

// ISO partitions may not support tagging, giving error
if tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException) {
log.Printf("[WARN] Unable to list tags for EventBridge Rule %s: %s", d.Id(), err)
return nil
}

if err != nil {
return fmt.Errorf("error listing tags for EventBridge Rule (%s): %w", arn, err)
}
Expand Down Expand Up @@ -257,8 +268,15 @@ func resourceRuleUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := UpdateTags(conn, arn, o, n); err != nil {
return fmt.Errorf("error updating CloudwWatch Event Rule (%s) tags: %w", arn, err)
err := UpdateTags(conn, arn, o, n)

if tfawserr.ErrCodeContains(err, ErrCodeAccessDenied) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeInternalException) || tfawserr.ErrCodeContains(err, eventbridge.ErrCodeOperationDisabledException) {
log.Printf("[WARN] Unable to update tags for EventBridge Rule %s: %s", d.Id(), err)
return resourceRuleRead(d, meta)
}

if err != nil {
return fmt.Errorf("error updating EventBridge Rule tags: %w", err)
}
}

Expand Down Expand Up @@ -311,6 +329,28 @@ func resourceRuleDelete(d *schema.ResourceData, meta interface{}) error {
return nil
}

func retryPutRule(conn *eventbridge.EventBridge, input *eventbridge.PutRuleInput) error {
err := resource.Retry(tfiam.PropagationTimeout, func() *resource.RetryError {
_, err := conn.PutRule(input)

if tfawserr.ErrMessageContains(err, "ValidationException", "cannot be assumed by principal") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if tfresource.TimedOut(err) {
_, err = conn.PutRule(input)
}

return err
}

func buildPutRuleInputStruct(d *schema.ResourceData, name string) (*eventbridge.PutRuleInput, error) {
input := eventbridge.PutRuleInput{
Name: aws.String(name),
Expand Down