Search code examples
jsonansiblejmespath

Filter a JSON document in Ansible


I have a JSON reply from a GitHub repository with a list of possible downloads for a certain release (the assets array in the document).

I want to get the browser download URL when the name of an asset ends with x64.AppImage.

In Ansible, the filters are built apon jmespath and using its terminal tool, I can query the url with the following expression:

assets[?ends_with(name, 'x64.AppImage')].browser_download_url

With the following playbook, the JSON document is queried and stored in the json_reply variable.

---
- hosts: local
  tasks:
    - name: Get list of Rambox releases
      uri:
        url: "https://api.github.com/repos/saenzramiro/rambox/releases/latest"
        body_format: json
      register: json_reply

    - name: Filter reply
      debug: URL -> "{{ item }}"
      with_items:
        - "{{ json_reply.json | json_query(json_filter) }}"
      vars:
        - json_filter: assets[?ends_with(name, 'x64.AppImage')].browser_download_url

However, executing this gives the following error:

fatal: [localhost]: FAILED! => {
    "msg": "JMESPathError in json_query filter plugin:\nIn function ends_with(), invalid type for value: latest-mac.json, expected one of: ['string'], received: \"unknown\""
}

Where latest-mac.json is the first object in the assets array.

How can I make Ansible to iterate over all the assets array and apply my filter?

PS:

If instead of querying if the name ends with a word I specify it directly, the filter works:

assets[?name == 'Rambox-0.5.13-x64.AppImage')].browser_download_url

JSON example:

{
  "url": "https://api.github.com/repos/saenzramiro/rambox/releases/8001922",
  "prerelease": false,
  "created_at": "2017-10-04T21:14:15Z",
  "published_at": "2017-10-05T01:10:55Z",
  "assets": [
    {
      "url": "https://api.github.com/repos/saenzramiro/rambox/releases/assets/4985942",
      "id": 4985942,
      "name": "latest-mac.json",
      "uploader": {
        "login": "saenzramiro",
        "id": 2694669
      },
      "browser_download_url": "https://github.com/saenzramiro/rambox/releases/download/0.5.13/latest-mac.json"
    },
    {
      "url": "https://api.github.com/repos/saenzramiro/rambox/releases/assets/4985640",
      "id": 4985640,
      "name": "Rambox-0.5.13-x64.AppImage",
      "uploader": {
        "login": "saenzramiro",
        "id": 2694669
       },
       "browser_download_url": "https://github.com/saenzramiro/rambox/releases/download/0.5.13/Rambox-0.5.13-x64.AppImage"
    }
  ],
  "tarball_url": "https://api.github.com/repos/saenzramiro/rambox/tarball/0.5.13"
}

Solution

  • The problem of type errors in JMESPath filters is discussed in issue 27299.

    You can use this patched json_query.py filter plugin.

    Or apply double conversion to your object as a workaround: | to_json | from_json |.
    This will convert object to JSON (thus plain strings) and back, so json_query will treat strings as supported type.