Ansible package_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中,则在软件包事实中添加一个键,用于所需的软件包"手动":true。否则,如果可能,添加"手动":假。所以,经过比较,事实应该这样设定:

"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 脚本做一个解决方法,因为我几天来一直在以正确的方式工作(没有成功(。

如果我知道如何正确地做到这一点,这将是一个很大的帮助/步骤。 提前感谢!

是的,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的胁迫,然后with_items--extra-vars和朋友为你这样做一样,将文本强制回丰富的对象: 如果它看起来像json-y,他们会这样对待它。我们必须手动from_json,因为胁迫是一种可言的行为,而不是一种忍者行为。

最新更新