0

I'd like to filter the JSON output of ad-hoc ansible commands - e.g. grab the long list of "facts" for multiple hosts, and show only one that could be several levels deep, such as ansible_lsb.description, so I can quickly compare what versions of software they're running, check accurate times or timezones, whatever.

This works:

ansible myserver -m setup -a 'filter=ansible_lsb'
myserver | SUCCESS => {
    "ansible_facts": {
        "ansible_lsb": {
            "codename": "wheezy",
            "description": "Debian GNU/Linux 7.11 (wheezy)",
            "id": "Debian",
            "major_release": "7",
            "release": "7.11"
        }
    },
    "changed": false
}

However, as the setup module docs state, "the filter option filters only the first level subkey below ansible_facts", so this fails:

ansible myserver -m setup -a 'filter=ansible_lsb.description'
myserver | SUCCESS => {
    "ansible_facts": {},
    "changed": false
}

(though for reference, you can use dot notation in other places such as a task's when conditional)

Is there a way to filter the JSON keys before the output is displayed?

1 Answer 1

2

Standard setup module can apply filter only on "top-level" facts.

To achieve what you want, you can make an action plugin with setup name to apply custom filters.

Working example ./action_plugins/setup.py:

from ansible.plugins.action import ActionBase

class ActionModule(ActionBase):

    def run(self, tmp=None, task_vars=None):

        def lookup(obj, path):
            return reduce(dict.get, path.split('.'), obj)

        result = super(ActionModule, self).run(tmp, task_vars)

        myfilter = self._task.args.get('myfilter', None)

        module_args = self._task.args.copy()
        if myfilter:
            module_args.pop('myfilter')

        module_return = self._execute_module(module_name='setup', module_args=module_args, task_vars=task_vars, tmp=tmp)

        if not module_return.get('failed') and myfilter:
            return {"changed":False, myfilter:lookup(module_return['ansible_facts'], myfilter)}
        else:
            return module_return

It calls original setup module stripping myfilter parameter, then filters result with simple reduce implementation if task is not failed and myfilter is set. Lookup function is very simple, so it will not work with lists, only with objects.

Result:

$ ansible myserver -m setup -a "myfilter=ansible_lsb.description"
myserver | SUCCESS => {
    "ansible_lsb.description": "Ubuntu 12.04.4 LTS",
    "changed": false
}
Sign up to request clarification or add additional context in comments.

Comments

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.