Шаблон с переменными переменными есть ли лучший способ?

Я настраиваю набор задач для управления большим объемом системы. как для сборки и настройки, так и для текущих обновлений.

работая над задачами сетевого сценария и сталкиваясь с проблемами.

  1. количество интерфейсов на каждом блоке является переменным.
  2. количество 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 %}

оператор if отлично работает, если переменная установлена ​​в файле host_vars, но терпит неудачу, если это не так.

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})

Любые предложения будут ценны. Спасибо!

Введение в Ansible Roles
Введение в Ansible Roles
Ansible - это отличный инструмент управления конфигурацией, который можно использовать для автоматизации настройки или развертывания на большом...
0
0
312
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что вы можете упростить свою пьесу несколькими способами. Во-первых, нет причин рассматривать «вторичные» 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 теперь является словарем, нам нужно изменить playbook, чтобы он соответствовал:

---
- 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

ВАУ это потрясающе!! мне было интересно, делает ли моя установка host_vars мое решение слишком сложным. это работает отлично. я также вижу, как использовать это в других вещах, чтобы лучше определить переменные. Спасибо!!!!

Jesse Smith 07.04.2019 04:59

Рад помочь! Если это ответило на ваш вопрос, вы можете установить флажок слева от ответа.

larsks 07.04.2019 14:29

Другие вопросы по теме