Repository: ansible-collections/community.aws

Issue:
sqs_queue is not idempotent when any queue attribute parameter passed in playbook
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Explain the problem briefly below -->
sqs-queue is not idempotent if we pass any parameter (sqs attributes)

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.10.4
  config file = None
  configured module search path = ['/Users/spathak3/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/ansible
  executable location = /Library/Frameworks/Python.framework/Versions/3.8/bin/ansible
  python version = 3.8.0 (v3.8.0:fa919fdf25, Oct 14 2019, 10:23:27) [Clang 6.0 (clang-600.0.57)]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below
No change
```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
Darwin Darwin Kernel Version 20.3.0: Thu Jan 21 00:07:06 PST 2021; root:xnu-7195.81.3~1/RELEASE_X86_64 i386

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
# This playbook is idempotent running multiple time
---
- name: sqs idempotency check
  hosts: localhost
  tasks:
  - name: Idempotence check
    community.aws.sqs_queue:
      name: sqs-idempotency-issue
      region: eu-west-1
      state: present

# This playbook is NOT idempotent on multiple run, only happen when we pass any attribute params here e.g. default_visibility_timeout
---
- name: sqs idempotency check
  hosts: localhost
  tasks:
  - name: Idempotence check
    community.aws.sqs_queue:
      name: sqs-idempotency-issue
      region: eu-west-1
      state: present
      default_visibility_timeout: 120
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->

setting parameter (sqs attributes) in playbook shouldn't prevent the idempotency.

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

Adding parameter `default_visibility_timeout: 120` prevents idempotency on multiple run.

<!--- Paste verbatim command output between quotes -->
```paste below
spathak3@macbook ~/infra/aws-operator
> $ (⎈ |minikube:aws-operator-system) ansible-playbook roles/sqs-queue/tasks/demo.yaml -v
No config file found; using defaults
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [sqs idempotency check] *************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [Idempotence check] *****************************************************************************************************************************************************************************
changed: [localhost] => {"approximate_number_of_messages": 0, "approximate_number_of_messages_delayed": 0, "approximate_number_of_messages_not_visible": 0, "changed": true, "created_timestamp": 1620915962, "default_visibility_timeout": 120, "delay_seconds": 0, "delivery_delay": 0, "last_modified_timestamp": 1620916213, "maximum_message_size": 262144, "message_retention_period": 345600, "name": "sqs-idempotency-issue", "policy": null, "queue_arn": "arn:aws:sqs:eu-west-1:822436023150:sqs-idempotency-issue", "queue_url": "https://eu-west-1.queue.amazonaws.com/822436023150/sqs-idempotency-issue", "receive_message_wait_time": 0, "receive_message_wait_time_seconds": 0, "redrive_policy": null, "region": "eu-west-1", "tags": {}, "visibility_timeout": 120}

PLAY RECAP *******************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0




spathak3@macbook ~/infra/aws-operator
> $ (⎈ |minikube:aws-operator-system) ansible-playbook roles/sqs-queue/tasks/demo.yaml -v
No config file found; using defaults
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [sqs idempotency check] *************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [Idempotence check] *****************************************************************************************************************************************************************************
changed: [localhost] => {"approximate_number_of_messages": 0, "approximate_number_of_messages_delayed": 0, "approximate_number_of_messages_not_visible": 0, "changed": true, "created_timestamp": 1620915962, "default_visibility_timeout": 120, "delay_seconds": 0, "delivery_delay": 0, "last_modified_timestamp": 1620916213, "maximum_message_size": 262144, "message_retention_period": 345600, "name": "sqs-idempotency-issue", "policy": null, "queue_arn": "arn:aws:sqs:eu-west-1:822436023150:sqs-idempotency-issue", "queue_url": "https://eu-west-1.queue.amazonaws.com/822436023150/sqs-idempotency-issue", "receive_message_wait_time": 0, "receive_message_wait_time_seconds": 0, "redrive_policy": null, "region": "eu-west-1", "tags": {}, "visibility_timeout": 120}

PLAY RECAP *******************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0



spathak3@macbook~/infra/aws-operator
> $ (⎈ |minikube:aws-operator-system) ansible-playbook roles/sqs-queue/tasks/demo.yaml -v
No config file found; using defaults
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [sqs idempotency check] *************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [Idempotence check] *****************************************************************************************************************************************************************************
changed: [localhost] => {"approximate_number_of_messages": 0, "approximate_number_of_messages_delayed": 0, "approximate_number_of_messages_not_visible": 0, "changed": true, "created_timestamp": 1620915962, "default_visibility_timeout": 120, "delay_seconds": 0, "delivery_delay": 0, "last_modified_timestamp": 1620916213, "maximum_message_size": 262144, "message_retention_period": 345600, "name": "sqs-idempotency-issue", "policy": null, "queue_arn": "arn:aws:sqs:eu-west-1:822436023150:sqs-idempotency-issue", "queue_url": "https://eu-west-1.queue.amazonaws.com/822436023150/sqs-idempotency-issue", "receive_message_wait_time": 0, "receive_message_wait_time_seconds": 0, "redrive_policy": null, "region": "eu-west-1", "tags": {}, "visibility_timeout": 120}

PLAY RECAP *******************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


```



Discussion:

Resolving patch:
diff --git a/plugins/modules/sqs_queue.py b/plugins/modules/sqs_queue.py
--- a/plugins/modules/sqs_queue.py
+++ b/plugins/modules/sqs_queue.py
@@ -377,7 +377,7 @@ def update_sqs_queue(module, client, queue_url):
             new_value = str(new_value).lower()
             value = str(value).lower()
 
-        if new_value == value:
+        if str(new_value) == str(value):
             continue
 
         # Boto3 expects strings


Test patch:
diff --git a/tests/integration/targets/sqs_queue/tasks/main.yml b/tests/integration/targets/sqs_queue/tasks/main.yml
--- a/tests/integration/targets/sqs_queue/tasks/main.yml
+++ b/tests/integration/targets/sqs_queue/tasks/main.yml
@@ -67,6 +67,50 @@
             - create_result.policy.Version == "2012-10-17"
             - create_result.policy.Statement[0].Effect == "Allow"
             - create_result.policy.Statement[0].Action == "*"
+      - name: Test idempotentcy
+        sqs_queue:
+          name: "{{ create_result.name }}"
+          default_visibility_timeout: 900
+          delivery_delay: 900
+          maximum_message_size: 9009
+          message_retention_period: 900
+          receive_message_wait_time: 10
+          policy:
+            Version: "2012-10-17"
+            Statement:
+              Effect: Allow
+              Action: "*"
+        register: create_result
+      - name: Assert nothing changed
+        assert:
+          that:
+            - not create_result.changed
+      - name: Test update
+        sqs_queue:
+          name: "{{ create_result.name }}"
+          default_visibility_timeout: 899
+          delivery_delay: 899
+          maximum_message_size: 9008
+          message_retention_period: 899
+          receive_message_wait_time: 9
+          policy:
+            Version: "2012-10-17"
+            Statement:
+              Effect: Allow
+              Action: "*"
+        register: create_result
+      - name: Assert queue updated with configuration
+        assert:
+          that:
+            - create_result.changed
+            - create_result.default_visibility_timeout == 899
+            - create_result.delivery_delay == 899
+            - create_result.maximum_message_size == 9008
+            - create_result.message_retention_period == 899
+            - create_result.receive_message_wait_time == 9
+            - create_result.policy.Version == "2012-10-17"
+            - create_result.policy.Statement[0].Effect == "Allow"
+            - create_result.policy.Statement[0].Action == "*"
     always:
       - name: Cleaning up queue
         sqs_queue: