#ansible #jinja2 #ansible-template #fortigate
Вопрос:
Я новичок в Ansible и пытаюсь автоматизировать настройку Fortigate с помощью модулей fortinet.fortios.
У меня возникла проблема с fortios_firewall_addrgrp
тем, что конкретно не поддерживает добавление адреса брандмауэра в группу.
У меня есть этот набор в моих переменных:
addresses:
host_0:
subnet: 192.168.1.10/24
group: group_0
host_1:
subnet: 192.168.1.11/24
group: group_0
host_2:
subnet: 192.168.10.10/24
group: group_1
host_3:
subnet: 192.168.10.11/24
group: group_1
И я выполняю эту задачу для создания группы адресов.
- name: Configure IPv4 address groups.
fortios_firewall_addrgrp:
vdom: '{{ vdom }}'
state: present
firewall_addrgrp:
name: '{{ item.value.group }}'
member:
- name: '{{ item.key }}'
loop: '{{ addresses | dict2items }}'
Он проходит по каждому хосту и генерирует группу адресов, но в результате получается 2 группы, содержащие только последнее имя хоста в списке.
В идеале модуль должен поддерживать добавление имени хоста к существующей группе, но это не так, поэтому я пытаюсь обойти его, чтобы сделать следующее:
member:
- name: host_0
- name: host_1
Приведенный выше пример будет работать, но я не могу заранее знать группы и имена хостов в переменной.
Я мог бы сгенерировать или отфильтровать входную переменную в словарь хоста и групп и передать ее участникам. Тем не менее, я не могу понять, как динамически перебирать его.
Комментарии:
1. Я думаю, что, вероятно, было бы лучше открыть проблему .
Ответ №1:
Проблема, с которой вы столкнулись, связана со структурой данных, которую вы используете для цикла. Как вы упомянули, fortios_firewall_addrgrp
модуль ожидает список словарей для members
ключа, представляющих каждый хост.
Итак, вам нужно создать новую структуру данных, которая соответствует входным fortios_firewall_addrgrp
данным модуля. Вот пример того, как это сделать:
---
- hosts: localhost
gather_facts: 'no'
vars:
addresses:
host_0:
subnet: 192.168.1.10/24
group: group_0
host_1:
subnet: 192.168.1.11/24
group: group_0
host_2:
subnet: 192.168.10.10/24
group: group_1
host_3:
subnet: 192.168.10.11/24
group: group_1
tasks:
- set_fact:
addresses_by_group: |
{{
addresses_by_group | default({}) | combine({
item.value.group: (addresses_by_group[item.value.group] | default([])) [{"name": item.key}]
})
}}
loop: '{{ addresses | dict2items }}'
- name: Configure IPv4 address groups.
fortios_firewall_addrgrp:
vdom: '{{ vdom }}'
state: present
firewall_addrgrp:
name: '{{ item.key }}'
member: '{{ item.value }}'
loop: '{{ addresses_by_group | dict2items }}'
Мы создаем новую переменную с именем addresses_by_group
, в которой будет храниться список хостов для каждой группы. combine
Фильтр позволяет объединить два разных словаря, в то время default
как фильтр устанавливает значение по умолчанию для неопределенной переменной. Мы используем
оператор для объединения двух списков. Если вы отладите значение переменной addresses_by_group
, вы увидите следующее:
TASK [debug] *******************************************************************
ok: [localhost] =>
addresses_by_group:
group_0:
- name: host_0
- name: host_1
group_1:
- name: host_2
- name: host_3
А это как раз то, что нам нужно. Имейте в виду, что мы не касались addresses
переменных, чтобы вы могли использовать их позже.
Комментарии:
1. Отличный ответ, спасибо. Я пытался преобразовать логику для генерации addresses_by_group из Python в Ansible, но как это сделать на самом деле, было выше моего понимания. Фильтры-это ответ!