5

When using json_query in Ansible, I got the below error when running my code.

The Python used in Ansible is 3.6.8, where I installed jmespath with the command: 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 Answer 1

5

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
Sign up to request clarification or add additional context in comments.

1 Comment

You solved the puzzle. Thanks a lot! The reason I wanted to get json_query done is because I thought it could provide me the solution for a task I am working on. I will open up another question to explain the task.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.