Ansible package_facts:通过与另一个简单列表进行比较来设置事实

时间:2018-09-11 11:08:36

标签: ansible ansible-facts

由于ansible-cmdb,我目前正在为每个清单主机生成报告。这个工具很棒,但是我在修改某些事实时遇到问题:

我使用package_facts 模块注册已安装的软件包。它们会自动在hostvars中注册为像这样的字典列表( ansible_facts.packages ):

"packages": {
    "accountsservice": [
        {
            "arch": "amd64",
            "name": "accountsservice",
            "source": "apt",
            "version": "0.6.40-2ubuntu11.3"
        }
    ],
    "acl": [
        {
            "arch": "amd64",
            "name": "acl",
            "source": "apt",
            "version": "2.2.52-3"
        }
    ],
    "acpid": [
        {
            "arch": "amd64",
            "name": "acpid",
            "source": "apt",
            "version": "1:2.0.26-1ubuntu2"
        }
    ]}

另一方面,我有一个远程bash 脚本,它输出一个手动在主机上安装的软件包名称的简单列表。对于每个主机,我想比较两个列表(如果有软件包)名称也位于 ansible_facts.packages 中,然后在所需的包“ manual”:true 的包事实中添加密钥。否则,如果可能,添加“ manual”:false 。因此,经过比较后,事实应该像这样设置:

"packages": {
    "accountsservice": [
        {
            "arch": "amd64",
            "name": "accountsservice",
            "source": "apt",
            "version": "0.6.40-2ubuntu11.3",
            "manual": true
        }
    ],
    "acl": [
        {
            "arch": "amd64",
            "name": "acl",
            "source": "apt",
            "version": "2.2.52-3",
            "manual": false
        }
    ],
...}

您认为以适当的方式可行吗?我是一个关于使用Ansible处理JSON数据结构的新手,这就是为什么我将以某种正确的方式工作(没有成功)的原因,所以我将使用Python脚本来解决此问题。

如果我知道如何正确地做的话,那将是一个很大的帮助/步骤。 预先感谢!

1 个答案:

答案 0 :(得分:0)

是的,Jinja是一种功能强大的模板语言,您可以使用set_facts模块声明新的事实,从而得到如下结果:

  vars:
    the_list: |
      [
       {"name": "alpha"},
       {"name": "beta"}
      ]
    the_names: |
      ["alpha", "charlie"]
  tasks:
  - set_fact:
     new_list: |
      [
      {% set names_list = (the_names|from_json) %}
      {% for item in (the_list|from_json) %}
      {{ '' if loop.first else ',' }}
      {% set _ = item.update({"manual": item.name in names_list}) %}
      {{ item | to_json }}
      {% endfor %}
      ]
  - debug: var=item.manual verbosity=0
    with_items: '{{ new_list }}'

其中set _ =部分是因为jinja仅具有set语句会引起副作用,而其余只是从文本到实际dict的强制,然后是{ {1}}以with_items和朋友为您这样做的相同方式将文本强制转换为丰富的对象:如果看起来 json-y,他们会这样对待。我们必须手动执行--extra-vars,因为强制是一种 ansible 行为,而不是 jinja 行为。