Using ansible 2.5.3 on ubuntu 16.10.
I need to include a variable in a JSON string for the body tag of the Ansible uri module. I have tried various things. My latest try looks like this in the below task in a role:
- name: REST POST Example
uri:
url: "{{ webapp_url }}/api/orgs"
method: POST
return_content: yes
body: "{ \"name\": \"{{ project_name }}\" }"
validate_certs: no
user: "{{ user }}"
password: "{{ password }}"
force_basic_auth: yes
headers:
Content-Type: "application/json"
In my playbook I define the project_name variable:
---
- hosts: all
gather_facts: no
vars:
project_name: "SAMPLE_PROJECT"
But when I run the playbook the project_name variable does not seem to get expanded correctly:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TypeError: unhashable type
fatal: [localhost]: FAILED! => {"changed": false, "content": "", "msg": "Status code was -1 and not [200]: An unknown error occurred: unhashable type", "redirected": false, "status": -1, "url": "https://webapp/api/orgs"}
In the above role/task. If I hardcode the body like:
body: "{\"name\": \"SAMPLE_PROJECT\"}"
it works fine. But I cannot do that I need the variable in there. Any suggestions on how to fix:
body: "{ \"name\": \"{{ project_name }}\" }"
?
Set json as the body type inside body_format parameter:
- name: REST POST Example
uri:
url: "{{ webapp_url }}/api/orgs"
method: POST
return_content: yes
body: "{ \"name\": \"{{ project_name }}\" }"
body_format: json
validate_certs: no
user: "{{ user }}"
password: "{{ password }}"
force_basic_auth: yes
When you use body: "{\"name\": \"SAMPLE_PROJECT\"}", the value is represented internally as a string (AnsibleUnicode).
When you use body: "{ \"name\": \"{{ project_name }}\" }", the value becomes a dictionary (dict), because it goes through the templating engine, after which the output is mapped into a Python object (it doesn't happen with plain strings).
Trivia: you can still trick Ansible to think it is a string by adding a space before first {. See the answers here.
uri module uses body_format: raw by default and it expects a string, if it finds an object it fails; refer to this issue.
Ansible ca interpret YAML as json automatically, I recommand the method below :
- name: REST POST Example
uri:
url: "{{ webapp_url }}/api/orgs"
method: POST
return_content: yes
body:
name: "{{ projectname }}"
body_format: json
validate_certs: no
user: "{{ user }}"
password: "{{ password }}"
force_basic_auth: yes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With