Lubo
Lubo

Reputation: 185

extract multiple values from json using json query ansible

I have following output(snippet):

ok: [localhost] => {
    "output": {
        "ansible_facts": {
            "openstack_servers": [
                {
                    "az": "xxx",
                    "cloud": "xxx",
                    "created": "2019-10-14T09:42:42Z",
                    "created_at": "2019-10-14T09:42:42Z",
                    "disk_config": "MANUAL",
                    "flavor": {
                        "id": "s2.medium.4"
                    },
                    "has_config_drive": false,
                    "hostId": "78336513777de579fd80a528b9ace4a84bca0a725dd1dde5e7827309",
                    "host_id": "78336513777de579fd80a528b9ace4a84bca0a725dd1dde5e7827309",
                    "id": "d2fe3a68-44ec-4965-89bd-c792389bc7f7",
                    "image": {
                        "id": "ef7bf265-c69e-407d-8812-692f4a6ff6ab"
                    },
                    "interface_ip": "",
                    "key_name": "xxx",
                    "launched_at": "2019-10-14T09:42:59.000000",
                    "metadata": {},
                    "name": "QDETWR",
                    "networks": {},
                    "power_state": 1,
                    "progress": 0,
                    "project_id": "54026885c74446c2b833f4dc7cb77bd2",
                    "status": "ACTIVE",

When I try to get status value:

      msg: "{{ output.ansible_facts.openstack_servers | json_query('[].status')}}"

It works fine.

I want to extract several values, but following doesn`t work:

      msg: "{{ output.ansible_facts.openstack_servers | json_query('[status, flavor, az]')}}"

or

      msg: "{{ item }}"
    with_items: "{{ output.ansible_facts.openstack_servers.content | from_json | json_query('[status, flavor]') }}"

What is wrong with my syntax?

Upvotes: 1

Views: 5337

Answers (1)

baggagescreen
baggagescreen

Reputation: 136

Perusing the documentation for the json_query Ansible filter they do have an example that might be relevant to you.

Given a data structure:

domain_definition:
    domain:
        cluster:
            - name: "cluster1"
            - name: "cluster2"
        server:
            - name: "server11"
              cluster: "cluster1"
              port: "8080"
            - name: "server12"
              cluster: "cluster1"
              port: "8090"
            - name: "server21"
              cluster: "cluster2"
              port: "9080"
            - name: "server22"
              cluster: "cluster2"
              port: "9090"
        library:
            - name: "lib1"
              target: "cluster1"
            - name: "lib2"
              target: "cluster2"

They provide an example to query it for multiple values, mapped as hashes to the resultant output.

In this example, we get a hash map with all ports and names of a cluster:

 - name: "Display all server ports and names from cluster1"
   debug:
     var: item   loop: "{{ domain_definition | json_query(server_name_cluster1_query) }}"
   vars:
     server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"

Note that they are only using vars: to define the query, ostensibly for readability, but the important bit is right there:

domain.server[?cluster=='cluster2'].{name: name, port: port}

So they're querying the domain.server (Which is a list of dictionaries, each with the same attributes), selecting only the ones with a cluster value of cluster2, and then for each of those returning the name as name and the port as port.

In your case, you want to return multiple attributes, but you don't want to select items with specific values. So you might use something more like:

msg: "{{ my_var | json_query('domain.server[*].{name: name, cluster: cluster}') }}"

The output I get back is:

    "msg": [
        {
            "cluster": "cluster1",
            "name": "server11"
        },
        {
            "cluster": "cluster1",
            "name": "server12"
        },
        {
            "cluster": "cluster2",
            "name": "server21"
        },
        {
            "cluster": "cluster2",
            "name": "server22"
        }
    ]

TLDR: Adapted to your specific question and use case, I believe what you want is:

      msg: "{{ output.ansible_facts.openstack_servers | json_query('[*].{status: status, flavor: flavor, az: az}') }}"

Thanks, hope that helps!

Upvotes: 3

Related Questions