由于ansible-cmdb,我目前正在为每个库存主机生成报告。这个工具很棒,但我有一个问题需要修改一些事实:
我使用package_facts模块来注册已安装的软件包。它们会自动在hostvars中注册为这样的dicts列表(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脚本做一个解决方法的原因,因为我工作了几天以正确的方式(没有成功)。
如果我知道如何正确地做这件事,那将是一个很大的帮助/步骤。提前致谢 !
是的,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
,因为强制行为是一种安全行为,而不是一种恶行为。