Repository: ansible/awx

Issue:
Tower Settings of type on/off idempotency not working
### Please confirm the following

- [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
- [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.
- [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.
- [X] I am **NOT** reporting a (potential) security vulnerability. (These should be emailed to `security@ansible.com` instead.)

### Bug Summary

When trying to set the setting named AWX_MOUNT_ISOLATED_PATHS_ON_K8S to true, no matter what I put in the playbook it is always marked as "changed: true", even if the setting is already true..

Sample Task:
```
    - name: SET AWX EXPOSE HOST PATHS
      awx.awx.settings:
        name: "AWX_MOUNT_ISOLATED_PATHS_ON_K8S"
        value: true

```

When I change the playbook value and register the results of the task to review the results I get this:

| Value In Playbook | Resulting Debug|
| ------- | ------- |
| true    | ok: [awxlab] => {<br>    "this_setting": {<br>        "changed": true,<br>        "failed": false,<br>        "new_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": "True"<br>        },<br>        "old_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": true<br>        },<br>        "value": true<br>    }<br>}|
| True    | ok: [awxlab] => {<br>    "this_setting": {<br>        "changed": true,<br>        "failed": false,<br>        "new_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": "True"<br>        },<br>        "old_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": true<br>        },<br>        "value": true<br>    }<br>}|
| "true"  | ok: [awxlab] => {<br>    "this_setting": {<br>        "changed": true,<br>        "failed": false,<br>        "new_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": "true"<br>        },<br>        "old_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": true<br>        },<br>        "value": true<br>    }<br>}|
| "True"  | ok: [awxlab] => {<br>    "this_setting": {<br>        "changed": true,<br>        "failed": false,<br>        "new_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": "True"<br>        },<br>        "old_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": true<br>        },<br>        "value": true<br>    }<br>}
| yes     | ok: [awxlab] => {<br>    "this_setting": {<br>        "changed": true,<br>        "failed": false,<br>        "new_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": "True"<br>        },<br>        "old_values": {<br>            "AWX_MOUNT_ISOLATED_PATHS_ON_K8S": true<br>        },<br>        "value": true<br>    }<br>}


The documentation says this:
```> AWX.AWX.SETTINGS    ([...]collections/ansible_collections/awx/awx/plugins/modules/settings.py)

        Modify Automation Platform Controller settings. See https://www.ansible.com/tower for an overview.

OPTIONS (= is mandatory):
- value
        Value to be modified for given setting.
        **If given a non-string type, will make best effort to cast it to type API expects.**
        For better control over types, use the `settings' param instead.
        default: null
        type: str
```

This leads me to believe that the logic used to sanitize the input might be doing a little extra or the conversion of 'settings' parameters to/from name/value parameters.

The documentation does show an example of how to use both the settings parameter and the name/value parameter.  So, this may be lower priority but I wanted to get this somewhere that could be search by others who may be running into this issue.

### AWX version

23.1.0

### Select the relevant components

- [ ] UI
- [ ] UI (tech preview)
- [ ] API
- [ ] Docs
- [X] Collection
- [ ] CLI
- [ ] Other

### Installation method

kubernetes

### Modifications

no

### Ansible version

2.15.4

### Operating system

CentOS Stream release 9

### Web browser

Firefox

### Steps to reproduce

Use a playbook that modifies a boolean setting.
Use the awx.awx.setting module.
Use the name/value parameters instead of the settings paremeter.
Sample:
```
    - name: SET AWX EXPOSE HOST PATHS
      awx.awx.settings:
        name: "AWX_MOUNT_ISOLATED_PATHS_ON_K8S"
        value: true
      register: this_setting
    
    - name: Debug this setting
      debug: var=this_setting
```

### Expected results

When the setting is already true, idempotency keeps the playbook from trying to update the setting again.

### Actual results

Regardless if the setting is true or not, the playbook always updates the setting.

### Additional information

_No response_


Discussion:
As documented, `settings` param is recommended for non-string types settings.

> For better control over types, use the `settings' param instead.

So try this out:

```yaml
    - name: SET AWX EXPOSE HOST PATHS
      awx.awx.settings:
        settings:
          AWX_MOUNT_ISOLATED_PATHS_ON_K8S: true
      register: this_setting
```

This is what I ended up doing and it works.

I realize this may not be the most important issue for an open source project of this size, and  I wasn't sure if this was intended behavior.  So, I reported it.

Thank you,

Dustin

Resolving patch:
diff --git a/awx_collection/plugins/modules/settings.py b/awx_collection/plugins/modules/settings.py
--- a/awx_collection/plugins/modules/settings.py
+++ b/awx_collection/plugins/modules/settings.py
@@ -89,7 +89,7 @@ def coerce_type(module, value):
         if not HAS_YAML:
             module.fail_json(msg="yaml is not installed, try 'pip install pyyaml'")
         return yaml.safe_load(value)
-    elif value.lower in ('true', 'false', 't', 'f'):
+    elif value.lower() in ('true', 'false', 't', 'f'):
         return {'t': True, 'f': False}[value[0].lower()]
     try:
         return int(value)


Test patch:
diff --git a/awx_collection/tests/integration/targets/settings/tasks/main.yml b/awx_collection/tests/integration/targets/settings/tasks/main.yml
--- a/awx_collection/tests/integration/targets/settings/tasks/main.yml
+++ b/awx_collection/tests/integration/targets/settings/tasks/main.yml
@@ -1,4 +1,42 @@
 ---
+- name: Initialize starting project vvv setting to false
+  awx.awx.settings:
+    name: "PROJECT_UPDATE_VVV"
+    value: false
+
+- name: Change project vvv setting to true
+  awx.awx.settings:
+    name: "PROJECT_UPDATE_VVV"
+    value: true
+  register: result
+
+- name: Changing setting to true should have changed the value
+  assert:
+    that:
+      - "result is changed"
+
+- name: Change project vvv setting to true
+  awx.awx.settings:
+    name: "PROJECT_UPDATE_VVV"
+    value: true
+  register: result
+
+- name: Changing setting to true again should not change the value
+  assert:
+    that:
+      - "result is not changed"
+
+- name: Change project vvv setting back to false
+  awx.awx.settings:
+    name: "PROJECT_UPDATE_VVV"
+    value: false
+  register: result
+
+- name: Changing setting back to false should have changed the value
+  assert:
+    that:
+      - "result is changed"
+
 - name: Set the value of AWX_ISOLATION_SHOW_PATHS to a baseline
   settings:
     name: AWX_ISOLATION_SHOW_PATHS