2

I have a list of services defined in my Consul catalog, and I would like to remove the ones that have no label defined.

This list of services looks like this:

{
    "json": {
        "consul": [],
        "consul-exporter": [],
        "consul-8600": [
            "traefik.enable=false",
            "udp"
        ],
        "snmp-gateway": [],
    }
}

I would like to filter it using JMESPath to have the result containing only

{
    "json": {
        "consul-8600": [
            "traefik.enable=false",
            "udp"
        ],
    }
}

But the syntax of JMESPath filtering remains obscure to me.

I think I should use the length function to get the size of the attributes array, but how?

So far, I have a json.[length(*)>0] filter, but it shows no value.

What should I change to have a non-null result?

techraf
  • 64,883
  • 27
  • 193
  • 198
Riduidel
  • 22,052
  • 14
  • 85
  • 185

2 Answers2

1

I don't think this is possible with JMESPath (at least not in an easy way). See the other answer.

On the other hand, it is trivial to write your own filter in Python (filter_plugins/myfilters.py):

class FilterModule(object):
    def filters(self):
        return {
            'remove_keys_with_empty_values': self.remove_keys_with_empty_values
        }

    def remove_keys_with_empty_values(self, mydict):
        newdict = dict((key, value) for key, value in mydict.iteritems() if value)
        return newdict

and use it in the playbook:

- debug:
    msg: "{{ json | remove_keys_with_empty_values }}"
techraf
  • 64,883
  • 27
  • 193
  • 198
1

In Ansible 2.5 and later:

It is possible by combining JMESPath query with Ansible dict2items filter and Jinja2 dict function:

- debug:
    msg: "{{ dict(json | dict2items | json_query('@[?value].[key, value]')) }}"
techraf
  • 64,883
  • 27
  • 193
  • 198