Templating JSON to send with uri

890 views
Skip to first unread message

David Resnick

unread,
Feb 10, 2016, 9:27:45 AM2/10/16
to Ansible Project
I'm trying to POST some JSON that I have in a file. 

This is the code I have:

task.yml:

---

- name: grafana | add graphite as data source
  uri:
    url: http://{{ ansible_host }}:3000/api/datasources
    method: POST
    user: "{{ grafana_admin_user }}"
    password: "{{ grafana_admin_password }}"
    body: "{{ lookup('template','add-datasource.json') }}"
    force_basic_auth: yes
    status_code: 200
    body_format: json
  delegate_to: localhost
  become: no

add-datasource.json:

{  "name":"grafite",  "type":"graphite",  "access":"proxy",  "url":"http://{{ ansible_host }}/",  "password":"",  "user":"",  "database":"",  "basicAuth":true,  "basicAuthUser":"",  "basicAuthPassword":"",  "withCredentials":false,  "isDefault":true,  "jsonData":null}

When I run that I get this error:

fatal: [mats -> localhost]: FAILED! => {"changed": false, "content": "[{\"classification\":\"DeserializationError\",\"message\":\"json: cannot unmarshal string into Go value of type models.AddDataSourceCommand\"},{\"fieldNames\":[\"Name\"],\"classification\":\"RequiredError\",\"message\":\"Required\"},{\"fieldNames\":[\"Type\"],\"classification\":\"RequiredError\",\"message\":\"Required\"},{\"fieldNames\":[\"Access\"],\"classification\":\"RequiredError\",\"message\":\"Required\"}]", "content_length": "371", "content_type": "application/json; charset=utf-8", "date": "Wed, 10 Feb 2016 06:56:29 GMT", "failed": true, "invocation": {"module_args": {"backup": null, "body": "{  \"name\":\"grafite\",  \"type\":\"graphite\",  \"access\":\"proxy\",  \"url\":\"http://10.225.39.185/\",  \"password\":\"\",  \"user\":\"\",  \"database\":\"\",  \"basicAuth\":true,  \"basicAuthUser\":\"\",  \"basicAuthPassword\":\"\",  \"withCredentials\":false,  \"isDefault\":true,  \"jsonData\":null}\n", "body_format": "json", "content": null, "creates": null, "delimiter": null, "dest": null, "directory_mode": null, "follow": false, "follow_redirects": "safe", "force": null, "force_basic_auth": true, "group": null, "method": "POST", "mode": null, "owner": null, "password": "W6v^tfVgv", "regexp": null, "remote_src": null, "removes": null, "return_content": false, "selevel": null, "serole": null, "setype": null, "seuser": null, "src": null, "status_code": ["200"], "timeout": 30, "url": "http://10.225.39.185:3000/api/datasources", "user": "admin", "validate_certs": true}, "module_name": "uri"}, "json": [{"classification": "DeserializationError", "message": "json: cannot unmarshal string into Go value of type models.AddDataSourceCommand"}, {"classification": "RequiredError", "fieldNames": ["Name"], "message": "Required"}, {"classification": "RequiredError", "fieldNames": ["Type"], "message": "Required"}, {"classification": "RequiredError", "fieldNames": ["Access"], "message": "Required"}], "msg": "Status code was not [200]", "redirected": false, "status": 400}

When I use the json file inline as the body, then it succeeds:

task.yml:

---

- name: grafana | add graphite as data source
  uri:
    url: http://{{ ansible_host }}:3000/api/datasources
    method: POST
    user: "{{ grafana_admin_user }}"
    password: "{{ grafana_admin_password }}"
    body: { "name":"grafite",  "type":"graphite",  "access":"proxy",  "url":"http://{{ ansible_host }}/",  "password":"",  "user":"",  "database":"",  "basicAuth":true,  "basicAuthUser":"",  "basicAuthPassword":"",  "withCredentials":false,  "isDefault":true,  "jsonData":null }
    force_basic_auth: yes
    status_code: 200
    body_format: json
  delegate_to: localhost
  become: no

The problem might be related to issue https://github.com/ansible/ansible/issues/7005

Though I am using the same format as the uri example for creating a JIRA issue.

Ansible version 2.0.0.2.

What am I missing?

- David

Matt Martz

unread,
Feb 10, 2016, 9:41:17 AM2/10/16
to ansible...@googlegroups.com
When specifying body_format: json, the uri module will JSON encode the body.  Your body is already JSON encoded, so it is being double encoded.

Try using from_json on your lookup such as:

"{{ lookup('template', ...)|from_json }}"

Or remove body_format from your uri task, which may require you to set the content type header explicitly.
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/08e6a989-246c-4932-9868-b03577c4ed92%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Matt Martz
@sivel
sivel.net

Brian Coca

unread,
Feb 10, 2016, 10:35:21 AM2/10/16
to ansible...@googlegroups.com
actually you want |to_json filter.

Matt Martz

unread,
Feb 10, 2016, 10:38:52 AM2/10/16
to ansible...@googlegroups.com
I think that would end up triple json encoding it.  The uri module is basically expecting a dict when you supply body_format=json.

On Wednesday, February 10, 2016, Brian Coca <bc...@ansible.com> wrote:
actually you want |to_json filter.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CACVha7fQgi%2BRhUeHW2cL2CjUKUt63UvJ0zASZRdEfgs4Cwg10A%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

Brian Coca

unread,
Feb 10, 2016, 10:52:34 AM2/10/16
to ansible...@googlegroups.com
The JSON from the template (w/o filters) will be 'typed' by Ansible into a Python data structure, but if it has to_json it will be kept as string bypassing the typing. The from_json will convert it to a Python data structure before Ansible attempts to type it.


David Resnick

unread,
Feb 17, 2016, 11:16:49 AM2/17/16
to Ansible Project
"{{ lookup('template','add-datasource.json') | from_json }}" worked.

Thanks for responding so quickly; I didn't notice the replies because notifications weren't enabled.

- David

Giri Chintala

unread,
Feb 17, 2016, 9:05:14 PM2/17/16
to Ansible Project
try adding "_hack":null

example 

body: '{"pattern":"^{{item.0.queue}}$", "definition":{"ha-mode":"all", "ha-sync-mode":"automatic", "federation-upstream-set": "all"}, "priority": 100000, "apply-to": "queues", "_hack":null}'  
Reply all
Reply to author
Forward
0 new messages