-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
adds an event bus policy resource #16874
Changes from all commits
417fa7e
77d2d67
3223e42
86a43bf
770f2f2
037e046
d03d521
80a7465
42c3075
33b32a9
f768a0f
9b35502
d2a7bb3
d3e9ec0
31730bf
9800bb0
e05b408
37d6933
01f604c
77ce67f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,179 @@ | ||||
package aws | ||||
|
||||
import ( | ||||
"fmt" | ||||
"log" | ||||
|
||||
"github.com/aws/aws-sdk-go/aws" | ||||
events "github.com/aws/aws-sdk-go/service/cloudwatchevents" | ||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||||
tfevents "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/cloudwatchevents" | ||||
iamwaiter "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iam/waiter" | ||||
) | ||||
|
||||
func resourceAwsCloudWatchEventBusPolicy() *schema.Resource { | ||||
return &schema.Resource{ | ||||
Create: resourceAwsCloudWatchEventBusPolicyCreate, | ||||
Read: resourceAwsCloudWatchEventBusPolicyRead, | ||||
Update: resourceAwsCloudWatchEventBusPolicyUpdate, | ||||
Delete: resourceAwsCloudWatchEventBusPolicyDelete, | ||||
Importer: &schema.ResourceImporter{ | ||||
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { | ||||
d.Set("event_bus_name", d.Id()) | ||||
return []*schema.ResourceData{d}, nil | ||||
}, | ||||
}, | ||||
|
||||
Schema: map[string]*schema.Schema{ | ||||
"event_bus_name": { | ||||
Type: schema.TypeString, | ||||
Optional: true, | ||||
ForceNew: true, | ||||
ValidateFunc: validateCloudWatchEventBusNameOrARN, | ||||
Default: tfevents.DefaultEventBusName, | ||||
}, | ||||
"policy": { | ||||
Type: schema.TypeString, | ||||
Required: true, | ||||
ValidateFunc: validation.StringIsJSON, | ||||
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs, | ||||
}, | ||||
}, | ||||
} | ||||
} | ||||
|
||||
func resourceAwsCloudWatchEventBusPolicyCreate(d *schema.ResourceData, meta interface{}) error { | ||||
conn := meta.(*AWSClient).cloudwatcheventsconn | ||||
|
||||
eventBusName := d.Get("event_bus_name").(string) | ||||
policy := d.Get("policy").(string) | ||||
|
||||
input := events.PutPermissionInput{ | ||||
EventBusName: aws.String(eventBusName), | ||||
Policy: aws.String(policy), | ||||
} | ||||
|
||||
log.Printf("[DEBUG] Creating CloudWatch Events policy: %s", input) | ||||
_, err := conn.PutPermission(&input) | ||||
if err != nil { | ||||
return fmt.Errorf("Creating CloudWatch Events policy failed: %w", err) | ||||
} | ||||
|
||||
d.SetId(eventBusName) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm on the fence of this not being a combination of bus name + statement Id - I suspect it's okay given you can have a single resource policy per bus, so I'll defer to core maintainers on that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering the "aws_cloudwatch_event_bus_policy" resource supports multiple statements we think that making it unique for each event bus won't introduce limitations. Also this implementation appears to be consistent with the SDK/CLI, which don't model event bus permissions as independent resources. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't disagree. I don't just understand what the rationale was behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "aws_cloudwatch_event_permission" resource only defines one statement in the policy, and it's therefore identified by it. The resource "aws_cloudwatch_event_policy" defines the complete policy for the event bus (possibly with multiple statements) and it's intended to be unique for each event bus. |
||||
|
||||
return resourceAwsCloudWatchEventBusPolicyRead(d, meta) | ||||
} | ||||
|
||||
// See also: https://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_DescribeEventBus.html | ||||
func resourceAwsCloudWatchEventBusPolicyRead(d *schema.ResourceData, meta interface{}) error { | ||||
conn := meta.(*AWSClient).cloudwatcheventsconn | ||||
|
||||
eventBusName := d.Id() | ||||
|
||||
input := events.DescribeEventBusInput{ | ||||
Name: aws.String(eventBusName), | ||||
} | ||||
var output *events.DescribeEventBusOutput | ||||
var err error | ||||
var policy *string | ||||
|
||||
// Especially with concurrent PutPermission calls there can be a slight delay | ||||
err = resource.Retry(iamwaiter.PropagationTimeout, func() *resource.RetryError { | ||||
log.Printf("[DEBUG] Reading CloudWatch Events bus: %s", input) | ||||
output, err = conn.DescribeEventBus(&input) | ||||
if err != nil { | ||||
return resource.NonRetryableError(fmt.Errorf("reading CloudWatch Events permission (%s) failed: %w", d.Id(), err)) | ||||
} | ||||
|
||||
policy, err = getEventBusPolicy(output) | ||||
if err != nil { | ||||
return resource.RetryableError(err) | ||||
} | ||||
return nil | ||||
}) | ||||
|
||||
if isResourceTimeoutError(err) { | ||||
output, err = conn.DescribeEventBus(&input) | ||||
if output != nil { | ||||
policy, err = getEventBusPolicy(output) | ||||
} | ||||
} | ||||
|
||||
if isResourceNotFoundError(err) { | ||||
log.Printf("[WARN] Policy on {%s} EventBus not found, removing from state", d.Id()) | ||||
d.SetId("") | ||||
return nil | ||||
} | ||||
if err != nil { | ||||
return fmt.Errorf("error reading policy from CloudWatch EventBus (%s): %w", d.Id(), err) | ||||
} | ||||
|
||||
busName := aws.StringValue(output.Name) | ||||
if busName == "" { | ||||
busName = tfevents.DefaultEventBusName | ||||
} | ||||
d.Set("event_bus_name", busName) | ||||
|
||||
d.Set("policy", policy) | ||||
|
||||
return nil | ||||
} | ||||
|
||||
func getEventBusPolicy(output *events.DescribeEventBusOutput) (*string, error) { | ||||
if output == nil || output.Policy == nil { | ||||
return nil, &resource.NotFoundError{ | ||||
Message: fmt.Sprintf("Policy for CloudWatch EventBus %s not found", *output.Name), | ||||
LastResponse: output, | ||||
} | ||||
} | ||||
|
||||
return output.Policy, nil | ||||
} | ||||
|
||||
func resourceAwsCloudWatchEventBusPolicyUpdate(d *schema.ResourceData, meta interface{}) error { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you create a test updating a policy? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
conn := meta.(*AWSClient).cloudwatcheventsconn | ||||
|
||||
eventBusName := d.Id() | ||||
|
||||
input := events.PutPermissionInput{ | ||||
EventBusName: aws.String(eventBusName), | ||||
Policy: aws.String(d.Get("policy").(string)), | ||||
} | ||||
|
||||
log.Printf("[DEBUG] Update CloudWatch EventBus policy: %s", input) | ||||
_, err := conn.PutPermission(&input) | ||||
if isAWSErr(err, events.ErrCodeResourceNotFoundException, "") { | ||||
log.Printf("[WARN] CloudWatch EventBus %q not found, removing from state", d.Id()) | ||||
d.SetId("") | ||||
return nil | ||||
} | ||||
if err != nil { | ||||
return fmt.Errorf("error updating policy for CloudWatch EventBus (%s): %w", d.Id(), err) | ||||
} | ||||
|
||||
return resourceAwsCloudWatchEventBusPolicyRead(d, meta) | ||||
} | ||||
|
||||
func resourceAwsCloudWatchEventBusPolicyDelete(d *schema.ResourceData, meta interface{}) error { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you create a test for this? e.g.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you create a test for deletion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
conn := meta.(*AWSClient).cloudwatcheventsconn | ||||
|
||||
eventBusName := d.Id() | ||||
removeAllPermissions := true | ||||
|
||||
input := events.RemovePermissionInput{ | ||||
EventBusName: aws.String(eventBusName), | ||||
RemoveAllPermissions: &removeAllPermissions, | ||||
} | ||||
|
||||
log.Printf("[DEBUG] Delete CloudWatch EventBus Policy: %s", input) | ||||
_, err := conn.RemovePermission(&input) | ||||
if isAWSErr(err, events.ErrCodeResourceNotFoundException, "") { | ||||
return nil | ||||
} | ||||
if err != nil { | ||||
return fmt.Errorf("error deleting policy for CloudWatch EventBus (%s): %w", d.Id(), err) | ||||
} | ||||
return nil | ||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be wrong, but I'm on the fence about this not being a combination of eventBus + policy statement ID (unique), like in the
event_permission
resource.I'd defer to core maintainers on this one