0

我想过滤 ad-hoc ansible 命令的 JSON 输出 - 例如,为多个主机获取一长串“事实”,并只显示一个可能有几个级别的深度,例如ansible_lsb.description,这样我就可以快速比较哪些版本他们正在运行的软件,检查准确的时间或时区,无论如何。

这有效:

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
}

但是,正如设置模块文档所述,“过滤器选项仅过滤 ansible_facts 下的第一级子键”,因此失败:

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

(虽然作为参考,您可以在其他地方使用点符号,例如任务的when conditional

有没有办法在显示输出之前过滤 JSON 键?

4

1 回答 1

2

标准setup模块只能对“顶级”事实应用过滤器。

为了实现你想要的,你可以制作一个带有setup名称的动作插件来应用自定义过滤器。

工作示例./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

它调用原始setup模块剥离myfilter参数,然后如果任务没有失败并且设置了 myfilter,则使用简单的 reduce 实现过滤结果。查找函数非常简单,因此它不适用于列表,只能用于对象。

结果:

$ ansible myserver -m setup -a "myfilter=ansible_lsb.description"
myserver | SUCCESS => {
    "ansible_lsb.description": "Ubuntu 12.04.4 LTS",
    "changed": false
}
于 2016-10-21T17:50:52.607 回答