0

All

I am using Ansible to POST data on a website. I have taken a very simple example of the JSON content

{
  "test2":"{{test}}"
}

Below is snippet for ansible task responsible to POST data:

  vars:
    test: "somerandomtest"
  
  tasks:

  - name: Test
    register: json_output
    uri:
      url: "http://localhost:3000"
      validate_certs: no
      follow_redirects: none
      headers:
       Authorization: Bearer 12344
       Content-Type: application/json
      method: POST
      body_format: json
      body: " {{ lookup('file','test.json') | from_json }} "
      #body: '{"test2":" {{test}} "}'
      timeout: 600

But on the web service I see the below data, where "test" is not replaced with "somerandomtest".

{'test2': '{{test}}'}

Not sure what I am doing wrong, or maybe I am using lookup the wrong way. If I replace the body with the content everything is fine, but the real JSON I work with is 400 lines, and I want to keep it separate.

Can anyone please let me know what can I do to change the JSON data using Ansible?

Geebee
  • 113
  • 3
  • 9

2 Answers2

1

The file lookup doesn't evaluate file content for Jinja template markers (which would lead to unexpected behavior if a document just happened to contain {{).

If you want to read in a template, use the template lookup instead:

- hosts: localhost
  gather_facts: false
  tasks:
  vars:
    test: "somerandomtest"
  
  tasks:

    - name: Test
      register: json_output
      uri:
        url: "https://httpbin.org/post"
        validate_certs: no
        follow_redirects: none
        headers:
          Content-Type: application/json
        method: POST
        body_format: json
        body: " {{ lookup('template','test.json') }} "
        return_content: true
        timeout: 600

    - debug:
        var: json_output

This shows that the content sent to the remote server is:

{'test2': 'somerandomtest'}
larsks
  • 277,717
  • 41
  • 399
  • 399
  • if it literally sent those characters, then this answer is incorrect, as that's python dict literal syntax and not JSON – mdaniel Jan 24 '21 at 02:47
  • This one helped me and on the server I can see the text transformed. I just changed the lookup type from file to a template. Thank you for your help. – Geebee Jan 24 '21 at 09:41
  • @mdaniel in fact, this actually sends the JSON serialization, but if you were to run this example (go ahead, you can just copy and paste it), you'll note that the `debug` tasks prints the de-serialized version of the data returned from the server. – larsks Jan 24 '21 at 13:24
1

Put the hash into a dictionary and format it to_json. For example

- hosts: localhost
  vars:
    test: somerandomtest
    body:
      test2: "{{ test }}"
  tasks:
    - debug:
        msg: "{{ body|to_json }}"

gives the JSON

msg: '{"test2": "somerandomtest"}'

The template gives the same result

shell> cat test.json
{
  "test2": "{{ test }}"
}
    - debug:
        msg: "{{ lookup('template','test.json')|to_json }}"
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • With text in the body I do not see any issue, the issue was only when I use an external JSON file – Geebee Jan 24 '21 at 09:45
  • There is no difference in the evaluation of the dictionary and the template. – Vladimir Botka Jan 24 '21 at 10:01
  • I thought that too, that a file vs data should be the same. However, suggestion by larsks helped where lookup were pointed to use template instead of file. – Geebee Jan 24 '21 at 10:34
  • See [Single vs double quotes in JSON](https://stackoverflow.com/questions/4162642/single-vs-double-quotes-in-json/). The point is the filter *to_json*. – Vladimir Botka Jan 24 '21 at 10:51