【问题标题】:How to assign an array to a variable in an Ansible-Playbook如何将数组分配给 Ansible-Playbook 中的变量
【发布时间】:2023-03-11 06:15:02
【问题描述】:

在剧本中我得到了以下代码:

---
- hosts: db
  vars:
    postgresql_ext_install_contrib: yes
    postgresql_pg_hba_passwd_hosts: ['10.129.181.241/32']
...

我想将postgresql_pg_hba_passwd_hosts 的值替换为我所有的网络服务器私有ip。我知道我可以在 模板 中获得像 this 这样的值:

{% for host in groups['web'] %}
   {{ hostvars[host]['ansible_eth1']['ipv4']['address'] }}
{% endfor %}

将此循环的结果分配给剧本中的变量的最简单/最简单的方法是什么?还是有更好的方法来收集这些信息?我应该把这个循环放在模板中吗?

其他挑战:我必须在每个条目中添加/32

【问题讨论】:

    标签: ansible ansible-playbook


    【解决方案1】:

    您可以通过 set_fact 和 ansible filter plugin 将列表分配给变量。

    将自定义过滤器插件放入 filter_plugins 目录,如下所示:

    (ansible top directory)
    site.yml
    hosts
    filter_plugins/
        to_group_vars.py
    

    to_group_vars.py 将主机变量转换为按组选择的列表。

    from ansible import errors, runner
    import json
    
    def to_group_vars(host_vars, groups, target = 'all'):
        if type(host_vars) != runner.HostVars:
            raise errors.AnsibleFilterError("|failed expects a HostVars")
    
        if type(groups) != dict:
            raise errors.AnsibleFilterError("|failed expects a Dictionary")
    
        data = []
        for host in groups[target]:
            data.append(host_vars[host])
        return data
    
    class FilterModule (object):
        def filters(self):
            return {"to_group_vars": to_group_vars}
    

    这样使用:

    ---
    - hosts: all
      tasks:
      - set_fact:
          web_ips: "{{hostvars|to_group_vars(groups, 'web')|map(attribute='ansible_eth0.ipv4.address')|list }}"
      - debug:
          msg: "web ip is {{item}}/32"
        with_items: web_ips
    

    【讨论】:

    • 这个例子效果很好。谢谢!现在我唯一缺少的步骤是如何将web_ips 的值分配给postgresql_pg_hba_passwd_hosts,就像问题中一样?
    • 在 Ansible 2.0 中,HostVars 可以在 ansible.vars.hostvars 中找到。
    • 注意:from ansible import runner 已在 Ansible >v2.x 中更改,请参阅 github.com/ansible/ansible/issues/14018
    • 对于 Ansible 2.0,将 from ansible import runner 替换为 from ansible.vars.hostvars import HostVars。相应地更新类型检查。这很漂亮。我希望我能再次对此表示赞同。你为我节省了几个小时的工作时间!
    【解决方案2】:

    在剧本中:

    vars:
         - arrayname:
            - name: itemname
              value1: itemvalue1
              value2: itemvalue2
            - name: otheritem
              value1: itemvalue3
              value2: itemvalue4
    

    在模板中:(示例是 ini 类型的文件,包含部分、键和值):

    {% for item in arrayname %}
    [{{ item.name }}]
    key1 = {{ item.value1 }}
    key2 = {{ item.value2 }}
    {% endfor %}
    

    这应该将模板呈现为:

    [itemname]
    key1 = itemvalue1
    key2 = itemvalue2
    [otheritem]
    key1 = itemvalue3
    key2 = itemvalue4
    

    【讨论】:

    • 谢谢。这正是我需要看到的例子。我想写一些配置文件,我需要为模板文件使用 2-3 个变量。
    【解决方案3】:

    变量可以表示为标准 YAML 结构,因此您可以将列表值分配给键,如下所示:

    ---
    - hosts: db
      vars:
        postgresql_ext_install_contrib: yes
        postgresql_pg_hba_passwd_hosts:
          - '10.129.181.241/32'
          - '1.2.3.0/8'
    

    【讨论】:

    • 您能否提供一个完整的解决方案,即如何从收集的事实中动态获取值?
    • KISS,这很好用,可以这样使用{%for ntpserver in ntpservers %} server {{ ntpserver }} iburst {% endfor %}
    • 或者如果你只需要数组的第一个元素,{{ ntpservers[0] }}
    • 哈哈,太感谢你了,Tima,我专门找postgresql_pg_hba_passwd_hosts。您使用相同的变量真是个奇迹!
    【解决方案4】:

    您可以使用 jinja2 过滤器:

    {{ groups['nodes']|map('extract', hostvars, ['ansible_eth1','ipv4', 'address']) |list }}
    

    将返回一个 IP 地址列表。即

    ---
    - hosts: db
      vars:
        postgresql_ext_install_contrib: yes
        postgresql_pg_hba_passwd_hosts: {{ groups['nodes']|map('extract', hostvars, ['ansible_eth1','ipv4', 'address']) |list }}
    ...
    

    不包括挑战(附加/32)。但它也应该可以通过 jinja2 过滤器实现。

    需要 ansible 版本 >= 2.1

    【讨论】:

      【解决方案5】:

      要将“/32”添加到地址,您可以使用 Ansible ipaddr 过滤器 (converting to CIDR notation)。

      {{ ip_addresses|ipaddr('host') }}
      

      【讨论】:

        猜你喜欢
        • 2020-06-17
        • 1970-01-01
        • 2015-08-20
        • 1970-01-01
        • 1970-01-01
        • 2023-01-11
        • 1970-01-01
        • 2016-12-12
        • 2020-02-04
        相关资源
        最近更新 更多