Repository: ansible-collections/amazon.aws

Issue:
cloudwatchevent_rule always reports Changed = True
### Summary

`cloudwatchevent_rule` module always reports `Changed` = `True`.

I believe this is caused to ansible-collections/community.aws#1355.

Output of boto3 `describe_rule` method only includes previously specified parameters. Therefore AWS `_rule_matches_aws` method ends up comparing something like this:

```
[{'id': 'my-target-id', 'arn': 'arn:aws:lambda:us-east-1:123412341234:function:my-function', 'role_arn': None, 'input': None, 'input_path': None, 'input_transformer': None, 'ecs_parameters': None}]
```

with `describe_rule` output that looks like this:

```
[{'id': 'my-target-id', 'arn': 'arn:aws:lambda:us-east-1:123412341234:function:my-function'}]
```

### Issue Type

Bug Report

### Component Name

cloudwatchevent_rule

### Ansible Version

```console (paste below)
ansible [core 2.12.7]
  configured module search path = ['/usr/share/ansible/plugins/modules']
  python version = 3.8.13 (default, May  8 2022, 17:48:02) [Clang 13.1.6 (clang-1316.0.21.2)]
  jinja version = 3.1.2
  libyaml = False
```


### Collection Versions

```console (paste below)
amazon.aws            4.1.0  
community.aws         4.1.1  
```


### AWS SDK versions

```console (paste below)
Name: boto3
Version: 1.24.43
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email: 
License: Apache License 2.0
Requires: botocore, jmespath, s3transfer
Required-by: 
---
Name: botocore
Version: 1.27.43
Summary: Low-level, data-driven core of boto 3.
Home-page: https://github.com/boto/botocore
Author: Amazon Web Services
Author-email: 
License: Apache License 2.0
Requires: jmespath, python-dateutil, urllib3
Required-by: boto3, s3transfer
```

### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

_No response_

### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- community.aws.cloudwatchevent_rule:
    name: my-rule
    schedule_expression: "rate(1 day)"
    targets:
      - id: my-target
        arn: "arn:aws:lambda:us-east-1:123412341234:function:my-function"
    state: present
```


### Expected Results

Module should return `Changed` = `True` on the first execution, and `Changed` = `False` on all subsequent executions.

### Actual Results

Module always returns `Changed` = `True`.

### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/modules/cloudwatchevent_rule.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/cloudwatchevent_rule.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @jillr @jsdalton @markuman @s-hertel @tremble
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/plugins/modules/cloudwatchevent_rule.py b/plugins/modules/cloudwatchevent_rule.py
--- a/plugins/modules/cloudwatchevent_rule.py
+++ b/plugins/modules/cloudwatchevent_rule.py
@@ -433,6 +433,18 @@ def _rule_matches_aws(self):
     def _targets_to_put(self):
         """Returns a list of targets that need to be updated or added remotely"""
         remote_targets = self.rule.list_targets()
+
+        # keys with none values must be scrubbed off of self.targets
+        temp = []
+        for t in self.targets:
+            if t["input_transformer"] is not None and t["input_transformer"]["input_template"] is not None:
+                # The remote_targets contain quotes, so add
+                # quotes to temp
+                val = t["input_transformer"]["input_template"]
+                t["input_transformer"]["input_template"] = '"' + val + '"'
+            temp.append(scrub_none_parameters(t))
+        self.targets = temp
+
         return [t for t in self.targets if t not in remote_targets]
 
     def _remote_target_ids_to_remove(self):


Test patch:
diff --git a/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml b/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml
--- a/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml
+++ b/tests/integration/targets/cloudwatchevent_rule/tasks/main.yml
@@ -52,6 +52,27 @@
         that:
           - event_rule_input_transformer_output.changed
 
+    - name: Create cloudwatch event rule with input transformer (idempotent)
+      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_transformer:
+              input_paths_map:
+                instance: "$.detail.instance-id"
+                state: "$.detail.state"
+              input_template: "<instance> is in state <state>"
+      register: event_rule_input_transformer_output
+
+    - name: Assert that no changes were made to the rule
+      assert:
+        that:
+          - event_rule_input_transformer_output is not changed
+
     - name: Create cloudwatch event rule with inputs
       cloudwatchevent_rule:
         name: "{{ input_event_name }}"