diff --git a/changelogs/fragments/623-cloudwatchevents_rule-support_input_transformer.yml b/changelogs/fragments/623-cloudwatchevents_rule-support_input_transformer.yml new file mode 100644 index 00000000000..adfc768f278 --- /dev/null +++ b/changelogs/fragments/623-cloudwatchevents_rule-support_input_transformer.yml @@ -0,0 +1,2 @@ +minor_changes: + - cloudwatchevent_rule - Added ``input_paths_map`` and ``input_template`` parameters to support ``input_transformer`` on CloudWatch event rule (https://github.com/ansible-collections/community.aws/pull/623). diff --git a/plugins/modules/cloudwatchevent_rule.py b/plugins/modules/cloudwatchevent_rule.py index d38db416864..820e6c38543 100644 --- a/plugins/modules/cloudwatchevent_rule.py +++ b/plugins/modules/cloudwatchevent_rule.py @@ -3,8 +3,8 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type DOCUMENTATION = r''' --- @@ -22,8 +22,8 @@ - A rule must contain at least an I(event_pattern) or I(schedule_expression). A rule can have both an I(event_pattern) and a I(schedule_expression), in which case the rule will trigger on matching events as well as on a schedule. - - When specifying targets, I(input) and I(input_path) are mutually-exclusive - and optional parameters. + - When specifying targets, I(input), I(input_path), I(input_paths_map) and I(input_template) + are mutually-exclusive and optional parameters. options: name: description: @@ -81,15 +81,31 @@ type: str description: - A JSON object that will override the event data when passed to the target. - - If neither I(input) nor I(input_path) is specified, then the entire - event is passed to the target in JSON form. + - If neither I(input) nor I(input_path) nor I(input_paths_map) nor I(input_template) + is specified, then the entire event is passed to the target in JSON form. input_path: type: str description: - A JSONPath string (e.g. C($.detail)) that specifies the part of the event data to be passed to the target. - - If neither I(input) nor I(input_path) is specified, then the entire - event is passed to the target in JSON form. + - If neither I(input) nor I(input_path) nor I(input_paths_map) nor I(input_template) + is specified, then the entire event is passed to the target in JSON form. + input_paths_map: + type: dict + version_added: 4.1.0 + description: + - A dict that specifies the transformation of the event data to + custom input parameters. + - If neither I(input) nor I(input_path) nor I(input_paths_map) nor I(input_template) + is specified, then the entire event is passed to the target in JSON form. + input_template: + type: str + version_added: 4.1.0 + description: + - A string that templates the values input_paths_map extracted from the event data. + It is used to produce the output you want to be sent to the target. + - If neither I(input) nor I(input_path) nor I(input_paths_map) nor I(input_template) + is specified, then the entire event is passed to the target in JSON form. ecs_parameters: type: dict description: @@ -123,6 +139,19 @@ arn: arn:aws:lambda:us-east-1:123456789012:function:MyFunction input: '{"foo": "bar"}' +- community.aws.cloudwatchevent_rule: + name: MyInstanceLaunchEvent + description: "Rule for EC2 instance launch" + state: present + event_pattern: '{"source":["aws.ec2"],"detail-type":["EC2 Instance State-change Notification"],"detail":{"state":["pending"]}}' + targets: + - id: MyTargetSnsTopic + arn: arn:aws:sns:us-east-1:123456789012:MySNSTopic + input_paths_map: + instance: "$.detail.instance-id" + state: "$.detail.state" + input_template: " is in state " + - community.aws.cloudwatchevent_rule: name: MyCronTask state: absent @@ -286,6 +315,12 @@ def _targets_request(self, targets): target_request['Input'] = target['input'] if 'input_path' in target: target_request['InputPath'] = target['input_path'] + if 'input_paths_map' in target or 'input_template' in target: + target_request['InputTransformer'] = {} + target_request['InputTransformer']['InputPathsMap'] = target['input_paths_map'] + target_request['InputTransformer']['InputTemplate'] = '"{0}"'.format( + target['input_template'] + ) if 'role_arn' in target: target_request['RoleArn'] = target['role_arn'] if 'ecs_parameters' in target: diff --git a/tests/integration/targets/cloudwatchevent_rule/aliases b/tests/integration/targets/cloudwatchevent_rule/aliases new file mode 100644 index 00000000000..4ef4b2067d0 --- /dev/null +++ b/tests/integration/targets/cloudwatchevent_rule/aliases @@ -0,0 +1 @@ +cloud/aws diff --git a/tests/integration/targets/cloudwatchevent_rule/defaults/main.yml b/tests/integration/targets/cloudwatchevent_rule/defaults/main.yml new file mode 100644 index 00000000000..04941aeb039 --- /dev/null +++ b/tests/integration/targets/cloudwatchevent_rule/defaults/main.yml @@ -0,0 +1,9 @@ +--- +name_pattern: "cloudwatch_event_rule" +unique_id: "{{ tiny_prefix }}" + +test_event_names: + - "{{ name_pattern }}-{{ unique_id }}-1" + - "{{ name_pattern }}-{{ unique_id }}-2" + +input_transformer_event_name: "{{ name_pattern }}-{{ unique_id }}-3" diff --git a/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml b/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml new file mode 100644 index 00000000000..5106c4fd91e --- /dev/null +++ b/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml @@ -0,0 +1,70 @@ +- module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + + block: + - name: Create SNS topic + sns_topic: + name: "TestSNSTopic" + state: present + display_name: "Test SNS Topic" + register: sns_topic_output + + - name: Create classic cloudwatch event rules + cloudwatchevent_rule: + name: "{{ item }}" + description: "Rule for {{ item }}" + state: present + schedule_expression: "cron(0 20 * * ? *)" + targets: + - id: "{{ sns_topic_output.sns_topic.name }}" + arn: "{{ sns_topic_output.sns_topic.topic_arn }}" + register: event_rules_classic_output + loop: "{{ test_event_names }}" + + - name: Create cloudwatch event rule with input transformer + cloudwatchevent_rule: + name: "{{ input_transformer_event_name }}" + description: "Event rule with input transformer configuration" + state: present + event_pattern: '{"source":["aws.ec2"],"detail-type":["EC2 Instance State-change Notification"],"detail":{"state":["pending"]}}' + targets: + - id: "{{ sns_topic_output.sns_topic.name }}" + arn: "{{ sns_topic_output.sns_topic.topic_arn }}" + input_paths_map: + instance: "$.detail.instance-id" + state: "$.detail.state" + input_template: " is in state " + register: event_rule_input_transformer_output + + - name: Assert that classic event rules were created + assert: + that: + - event_rules_classic_output.changed + - event_rules_classic_output.msg == "All items completed" + + - name: Assert that input transformer event rule was created + assert: + that: + - event_rule_input_transformer_output.changed + + always: + + - name: Delete classic CloudWatch event rules + cloudwatchevent_rule: + name: "{{ item }}" + state: absent + loop: "{{ test_event_names }}" + + - name: Delete input transformer CloudWatch event rules + cloudwatchevent_rule: + name: "{{ input_transformer_event_name }}" + state: absent + + - name: Delete SNS topic + sns_topic: + name: "TestSNSTopic" + state: absent