Errors when use "json_query" in Ansible

Viewed 2512

When use json_query in Ansible, got the error along with my code as shown below.

The Python used in Ansible is 3.6.8, and used the same version installed jmespath: pip install jmespath, so, this should not be the issue. The Ansible code should be fine as well.

fatal: [localhost]: FAILED! => {"msg": "template error while templating string: no filter named 'json_query'. String: {{ jsondata | json_query(jmesquery) }}"

The following is the Ansible codes:

---
- name: ReadJsonfile
  hosts: localhost
  tasks:
    - name: Display the JSON file content
  shell: cat config.json
  register: result

- name: save the JSON data to a Variable as a Fact
  set_fact:
    jsondata: "{{ result.stdout | from_json }}"

- name: setDomainName
  set_fact:
    domain_name: "{{ jsondata | json_query(jmesquery) }}"

  vars:
    jmesquery: 'domain.name'

- name: setDomainUsername
  set_fact:
    domain_username: "{{ jsondata | json_query(jmesquery) }}"

  vars:
    jmesquery: 'domain.user'

- name: setDomainPassword
  set_fact:
    domain_password: "{{ jsondata | json_query(jmesquery) }}"

  vars:
    jmesquery: 'domain.password'

- name: setadmin_Listenport
  set_fact:
    admin_ListenPort: "{{ jsondata | json_query(jmesquery) }}"

  vars:
    jmesquery: 'domain.admin.listenport'

- name: Debug the values
  debug: msg=" Admin Listen Port => {{ admin_ListenPort }}, DomainName => {{ domain_name }}, DomainUserName => {{ domain_username }} , Domain Password => {{ domain_password }}"
1 Answers

From the error message, I suspect you are using ansible 2.10

The json_query filter is part of the community.general collection which needs to be installed separately starting from this version (this is clearly stated in the documentation)

ansible-galaxy collection install community.general

That being said:

  1. your actual jmespath queries will not return what you expect
  2. using shell to get a file content from remote is a bad practice
  3. that's lots of set_facts and json_query to simply get data that is readily available

Since yaml is a strict superset of json, any valid json is also a valid yaml. In your case, you only have to load the content of the file and you have the data.

One solution is to fetch the file locally and then use include_vars.

In this particular case, using slurp looks like the best option.

This is what (I believe, since you did not provide an example) your config file looks like. I pushed that file in /tmp/config.json for my example.

{
  "domain": {
    "name": "toto",
    "user": "doejohn",
    "password": "sosecret",
    "admin": {
      "listenport": 5501
    }
  }
}

This is the demo playbook

---
- name: Load remote json content demo
  hosts: localhost
  gather_facts: false

  vars:
    config_file: /tmp/config.json

    # Of course the below vars will fire errors
    # if you call them before slurping data from remote.
    # Note: loading `data` in a jinja expression on its own
    # forces to transform it back rom string to json data.
    # You can accomplish the same result in one go
    # using the `from_json` filter
    # i.e. => domain: "{{ (slurped_config.content | b64decode | from_json).domain }}"
    data: "{{ slurped_config.content | b64decode }}"
    domain: "{{ data.domain }}"
    # Note2: the above will work and adapt to N hosts in your play: you will get
    # the correct data for each host in every task.

  tasks:
    - name: Slurp config file content
      slurp:
        src: "{{ config_file }}"
      register: slurped_config

    - name: Show result
      vars:
        message: |-
          name is: {{ domain.name }}
          user is: {{ domain.user }}
          password is: {{ domain.password }}
          port is: {{ domain.admin.listenport }}
      debug:
        msg: "{{ message.split('\n') }}"

which gives:

PLAY [Load remote json content demo] ******************************************************

TASK [Slurp config file content] **********************************************************
Wednesday 21 April 2021  17:57:47 +0200 (0:00:00.010)       0:00:00.010 ******* 
ok: [localhost]

TASK [Show result] ************************************************************************
Wednesday 21 April 2021  17:57:48 +0200 (0:00:00.199)       0:00:00.209 ******* 
ok: [localhost] => {
    "msg": [
        "name is: toto",
        "user is: doejohn",
        "password is: sosecret",
        "port is: 5501"
    ]
}

PLAY RECAP ********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Wednesday 21 April 2021  17:57:48 +0200 (0:00:00.027)       0:00:00.237 ******* 
=============================================================================== 
Slurp config file content ---------------------------------------------------------- 0.20s
Show result ------------------------------------------------------------------------ 0.03s
Related