由于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脚本来解决此问题。
如果我知道如何正确地做的话,那将是一个很大的帮助/步骤。 预先感谢!
答案 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 行为。