Reputation: 16287
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 }}\" }"
?
Upvotes: 7
Views: 33272
Reputation: 131
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
Upvotes: 6
Reputation: 68469
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.
Upvotes: 13