Ansible 带变量的模板有更好的方法吗?

Ansible 带变量的模板有更好的方法吗?,ansible,jinja2,ansible-template,Ansible,Jinja2,Ansible Template,我正在设置一组任务来管理大量的系统。用于构建和设置以及正在进行的更新 处理网络脚本任务并遇到问题 每个框上的接口数量是可变的 每个接口上的ip地址数是可变的 我为每台主机都有一个host_vars文件。在该文件中,我定义了接口的数量和名称以及ip地址。第一个任务获取接口的mac地址。第二个任务用数据模板接口配置文件 host_vars文件的示例 interfaces: - eth0 - eth1 eth0_ip: 10.135.61.213 eth0_subnet: 255.255.25

我正在设置一组任务来管理大量的系统。用于构建和设置以及正在进行的更新

处理网络脚本任务并遇到问题

  • 每个框上的接口数量是可变的
  • 每个接口上的ip地址数是可变的
  • 我为每台主机都有一个host_vars文件。在该文件中,我定义了接口的数量和名称以及ip地址。第一个任务获取接口的mac地址。第二个任务用数据模板接口配置文件

    host_vars文件的示例

    interfaces:
      - eth0
      - eth1
    eth0_ip: 10.135.61.213
    eth0_subnet: 255.255.255.0
    eth1_ip: 10.135.8.190
    eth1_subnet: 255.255.255.248
    eth1_ip_secondary: 10.135.8.191
    eth1_ip_secondary_subnet: 255.255.255.248
    
    任务

    - name: "get mac address from target system"
      shell: "{{ 'cat /sys/class/net/' + item + '/address' }}"
      register: macAddresses
      check_mode: no
      with_items: "{{interfaces}}"
    
    - name: check/update network interfaces
      template:
        src: template/etc/sysconfig/network-scripts/ifcfg-ethx
        dest: "{{ '/etc/sysconfig/network-scripts/ifcfg-' + item.item }}"
        group: root
        owner: root
        mode: 0644
      with_items: "{{macAddresses.results}}"
    
    模板接口文件

    DEVICE={{ item.item }}
    ONBOOT=yes
    HWADDR={{ item.stdout }}
    TYPE=Ethernet
    BOOTPROTO=none
    {{ 'IPADDR0=' + lookup('vars', item.item + '_ip')  }}
    {{ 'NETMASK0=' + lookup('vars', item.item + '_subnet') }}
    {%  if lookup('vars', item.item + '_ip_secondary') is defined %}
    {{ 'IPADDR1=' + lookup('vars', item.item + '_ip_secondary')  }}
    {{ 'NETMASK1=' + lookup('vars', item.item + '_ip_secondary_subnet') }}
    {% endif %}
    
    如果在host_vars文件中设置了变量,if语句就可以正常工作,但如果没有设置,则会失败

    TASK [network : check/update network interfaces] ***************************************************************************************************************************************
    failed: [localhost] (item={'_ansible_parsed': True, 'stderr_lines': [], u'changed': True, u'stdout': u'00:50:56:ba:af:b2', '_ansible_item_result': True, u'delta': u'0:00:00.102648', 'stdout_lines': [u'00:50:56:ba:af:b2'], '_ansible_item_label': u'eth0', u'end': u'2019-04-06 14:00:28.468507', '_ansible_no_log': False, 'failed': False, u'cmd': u'cat /sys/class/net/eth0/address', 'item': u'eth0', u'stderr': u'', u'rc': 0, u'invocation': {u'module_args': {u'warn': True, u'executable': None, u'_uses_shell': True, u'_raw_params': u'cat /sys/class/net/eth0/address', u'removes': None, u'argv': None, u'creates': None, u'chdir': None, u'stdin': None}}, u'start': u'2019-04-06 14:00:28.365859', '_ansible_ignore_errors': None}) => {"changed": false, "item": {"changed": true, "cmd": "cat /sys/class/net/eth0/address", "delta": "0:00:00.102648", "end": "2019-04-06 14:00:28.468507", "failed": false, "invocation": {"module_args": {"_raw_params": "cat /sys/class/net/eth0/address", "_uses_shell": true, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "warn": true}}, "item": "eth0", "rc": 0, "start": "2019-04-06 14:00:28.365859", "stderr": "", "stderr_lines": [], "stdout": "00:50:56:ba:af:b2", "stdout_lines": ["00:50:56:ba:af:b2"]}, "msg": "AnsibleUndefinedVariable: No variable found with this name: eth0_ip_secondary"}
    changed: [localhost] => (item={'_ansible_parsed': True, 'stderr_lines': [], u'changed': True, u'stdout': u'00:50:56:ba:ce:08', '_ansible_item_result': True, u'delta': u'0:00:00.095483', 'stdout_lines': [u'00:50:56:ba:ce:08'], '_ansible_item_label': u'eth1', u'end': u'2019-04-06 14:00:28.976139', '_ansible_no_log': False, 'failed': False, u'cmd': u'cat /sys/class/net/eth1/address', 'item': u'eth1', u'stderr': u'', u'rc': 0, u'invocation': {u'module_args': {u'warn': True, u'executable': None, u'_uses_shell': True, u'_raw_params': u'cat /sys/class/net/eth1/address', u'removes': None, u'argv': None, u'creates': None, u'chdir': None, u'stdin': None}}, u'start': u'2019-04-06 14:00:28.880656', '_ansible_ignore_errors': None})
    

    如有任何建议,将不胜感激。谢谢大家!

    我认为你可以通过多种方式简化剧本。首先,没有理由将“辅助”ip地址与主地址区别对待:您可以从第一个ip地址的
    IPADDR0
    NETMASK0
    开始,然后从那里增加索引(
    IPADDR1
    NETMASK1
    等等)。考虑到这一点,我们可以像这样重新构造接口数据:

    ---
    interfaces:
      eth0:
        addresses:
          - ipaddr: 10.135.61.213
            mask: 255.255.255.0
      eth1:
        addresses:
          - ipaddr: 10.235.8.190
            mask: 255.255.255.248
          - ipaddr: 10.135.8.191
            mask: 255.255.255.248
    
    由于
    interfaces
    现在是一本字典,我们需要修改剧本以匹配:

    ---
    - hosts: localhost
      gather_facts: false
      tasks:
        - debug:
            var: item
          loop: "{{ interfaces|dict2items }}"
    
        - name: "get mac address from target system"
          shell: "{{ 'cat /sys/class/net/' + item.key + '/address' }}"
          register: macAddresses
          check_mode: no
          loop: "{{interfaces|dict2items }}"
    
        - debug:
            var: macAddresses.results
    
        - name: check/update network interfaces
          template:
            src: ./ifcfg-ethx
            dest: "./conf/ifcfg-{{ item.item.key }}"
          loop: "{{macAddresses.results}}"
    
    最后,我们可以删除对模板中
    lookup
    的一系列不必要的调用,我们可以使用一个简单的
    for
    循环来迭代每个接口的地址:

    DEVICE={{ item.item.key }}
    ONBOOT=yes
    HWADDR={{ item.stdout }}
    TYPE=Ethernet
    BOOTPROTO=none
    {% for address in item.item.value.addresses|default([]) %}
    IPADDR{{ loop.index0 }}={{ address.ipaddr }}
    NETMASK{{ loop.index0 }}={{ address.mask }}
    {% endfor %}
    
    这将导致以下方面的输出:

    $ cat ifcfg-eth0
    DEVICE=eth0
    ONBOOT=yes
    HWADDR=52:54:00:7a:a2:a5
    TYPE=Ethernet
    BOOTPROTO=none
    IPADDR0=10.135.61.213
    NETMASK0=255.255.255.0
    
    $ cat ifcfg-eth1
    DEVICE=eth1
    ONBOOT=yes
    HWADDR=52:54:00:0e:72:1e
    TYPE=Ethernet
    BOOTPROTO=none
    IPADDR0=10.235.8.190
    NETMASK0=255.255.255.248
    IPADDR1=10.135.8.191
    NETMASK1=255.255.255.248
    

    哇,太棒了!!我想知道我的主机设置是否使我的解决方案过于复杂。这很好用。我还可以看到如何在其他方面使用它来更好地定义变量。非常感谢。很乐意帮忙!如果这回答了您的问题,您可以单击答案左侧的复选框。