Ansible - passing JSON string in environment to sh

2019-01-25 23:08发布

问题:

I am trying to pass JSON string in environment.

- name: Start {{service_name}}
  shell: "<<starting springboot jar>> --server.port={{service_port}}\""
  environment:
    - SPRING_APPLICATION_JSON: '{"test-host.1":"{{test_host_1}}","test-host.2":"{{test_host_2}}"}'

test_host_1 is 172.31.00.00

test_host_2 is 172.31.00.00

But in spring logs, I get JSON parse exception where it prints

Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character (''' (code 39)): was expecting double-quote to start field name
 at [Source: {'test-host.1': '172.31.00.00', 'test-host.2': '172.31.00.00'}; line: 1, column: 3]

As seen, double quotes are converted to single quotes !!!

I tried escaping double quotes but with no luck.

Any idea why it happens, or any work around?

回答1:

There is a thing about Ansible template engine.
If a string seems like an object (starts with { or [) Ansible converts it into object. See code.

To prevent this, you may use one of STRING_TYPE_FILTERS:

- SPRING_APPLICATION_JSON: "{{ {'test-host.1':test_host_1,'test-host.2':test_host_2} | to_json }}"

P.S. this is why hack with space character from @techraf's answer works: Ansible misses startswith("{") comparison and don't convert string to object.



回答2:

Quick hack: add a space to the variable definition (after the first single quote) - a single space doesn't influence the actual variable value (space will be ignored):

- name: Start {{service_name}}
  shell: "<<starting springboot jar>> --server.port={{service_port}}\""
  environment:
    - SPRING_APPLICATION_JSON: ' {"test-host.1":"{{test_host_1}}","test-host.2":"{{test_host_2}}"}'

With the space Ansible passes to shell (test1, test2 are values I set):

SPRING_APPLICATION_JSON='"'"' {"test-host.1":"test1","test-host.2":"test2"}'"'"'

Without the space:

SPRING_APPLICATION_JSON='"'"'{'"'"'"'"'"'"'"'"'test-host.2'"'"'"'"'"'"'"'"': '"'"'"'"'"'"'"'"'test2'"'"'"'"'"'"'"'"', '"'"'"'"'"'"'"'"'test-host.1'"'"'"'"'"'"'"'"': '"'"'"'"'"'"'"'"'test1'"'"'"'"'"'"'"'"'}'"'"'

Order is reversed too. Seems like without a space it interprets the JSON, with the space as string.

I don't really get why it happens so...



标签: json ansible