在 Ansible 中附加到列表或向字典添加键

在 Ansible 中附加到列表或向字典添加键

(相关Ansible 角色中的回调或钩子以及可重复使用的任务系列):

在 Ansible 中,有没有比使用 jina2 模板表达式更好的方法将键附加到列表或向字典中添加键?

我知道你可以做类似的事情:

- name: this is a hack
  shell: echo "{% originalvar.append('x') %}New value of originalvar is {{originalvar}}"

但真的没有任何元任务或助手可以做到这一点吗?

它感觉很脆弱,似乎没有记录,并且依赖于许多关于 Ansible 中变量如何工作的假设。

我的用例是多个角色(数据库服务器扩展),每个角色都需要向基本角色(数据库服务器)提供一些配置。这并不像在数据库服务器配置文件中添加一行那么简单;每个更改都适用于同一条线,例如扩展bdrpg_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

相关内容