(相关Ansible 角色中的回调或钩子以及可重复使用的任务系列):
在 Ansible 中,有没有比使用 jina2 模板表达式更好的方法将键附加到列表或向字典中添加键?
我知道你可以做类似的事情:
- name: this is a hack
shell: echo "{% originalvar.append('x') %}New value of originalvar is {{originalvar}}"
但真的没有任何元任务或助手可以做到这一点吗?
它感觉很脆弱,似乎没有记录,并且依赖于许多关于 Ansible 中变量如何工作的假设。
我的用例是多个角色(数据库服务器扩展),每个角色都需要向基本角色(数据库服务器)提供一些配置。这并不像在数据库服务器配置文件中添加一行那么简单;每个更改都适用于同一条线,例如扩展bdr
和pg_stat_statements
必须都出现在目标行上:
shared_preload_libaries = 'bdr, pg_stat_statements'
Ansible 的实现方式是使用正则表达式多次处理配置文件 (每个扩展一次),提取当前值,解析它,然后重写它?如果是这样,如何使它在多次运行中具有幂等性?
如果配置解析起来比这更困难,而且不像添加另一个逗号分隔的值那么简单,该怎么办?想想 XML 配置文件。
答案1
您可以使用 合并变量中的两个列表+
。假设您有一个group_vars
包含以下内容的文件:
---
# group_vars/all
pgsql_extensions:
- ext1
- ext2
- ext3
它在模板中的使用方式pgsql.conf.j2
如下:
# {{ ansible_managed }}
pgsql_extensions={% for item in pgsql_extensions %}{{ item }}, {% endfor %}
然后,您可以将扩展附加到测试数据库服务器,如下所示:
---
# group_vars/testing_db
append_exts:
- ext4
- ext5
pgsql_extensions: "{{ pgsql_extensions + append_exts }}"
当在任何测试服务器中运行该角色时,将添加附加扩展。
我不确定这是否也适用于字典,而且还要小心空格并在行尾留下悬垂逗号。
答案2
从 Ansible v2.x 开始你可以执行以下操作:
# use case I: appending to LIST variable:
- name: my appender
set_fact:
my_list_var: '{{my_list_myvar + new_items_list}}'
# use case II: appending to LIST variable one by one:
- name: my appender
set_fact:
my_list_var: '{{my_list_var + [item]}}'
with_items: '{{my_new_items|list}}'
# use case III: appending more keys DICT variable in a "batch":
- name: my appender
set_fact:
my_dict_var: '{{my_dict_var|combine(my_new_keys_in_a_dict)}}'
# use case IV: appending keys DICT variable one by one from tuples
- name: setup list of tuples (for 2.4.x and up
set_fact:
lot: >
[('key1', 'value1',), ('key2', 'value2',), ..., ('keyN', 'valueN',)],
- name: my appender
set_fact:
my_dict_var: '{{my_dict_var|combine({item[0]: item[1]})}}'
with_items: '{{lot}}'
# use case V: appending keys DICT variable one by one from list of dicts (thanks to @ssc)
- name: add new key / value pairs to dict
set_fact:
my_dict_var: "{{ my_dict_var | combine({item.key: item.value}) }}"
with_items:
- { key: 'key01', value: 'value 01' }
- { key: 'key02', value: 'value 03' }
- { key: 'key03', value: 'value 04' }
以上所有内容均记录在: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-hashes-dictionaries
答案3
你需要将循环拆分成 2 个
--- - 主机:本地主机 任务: - include_vars:堆栈 - 设置事实:角色={{stacks.Roles | 拆分(' ')}} - 包括:addhost.yml with_items:“{{roles}}”
和 addhost.yml
- set_facts:组名={{item}} - 设置事实:ips={{stacks[item]|split(' ')}} - local_action:add_host 主机名={{item}} 组名={{groupname}} with_items:{{ips}}
答案4
没有把握什么时候他们添加了这个,但至少对于字典/哈希(不是列表/数组),你可以设置变量hash_behaviour,就像这样:hash_behaviour = merge
在你的ansible.cfg
。
我花了好几个小时才偶然发现这个设置:S