Я новичок в Ansible и в настоящее время работаю над составлением сценария для развертывания некоторой конфигурации Palo Alto с использованием следующих модулей:
https://github.com/PaloAltoNetworks/ansible-пан
Я занимаюсь этим уже неделю, пытаясь разобраться, и я не могу понять, почему этот «список» не работает. Таким образом, этот код подключается к брандмауэру, создает новый адресный объект, и если существует переменная «служба», которая говорит http или https, то он добавит этот объект в существующую адресную группу брандмауэра.
Проблема с добавлением в группу брандмауэра. Задача, которая выполняет это, кажется, перезаписывает существующие объекты в группе, а не добавляет к ней.
Чтобы попытаться бороться с этим, у меня есть задача, которая «находит» существующие объекты (результаты находятся в словаре, который я затем переношу в переменную списка. Эта переменная + новая серверная переменная затем используются в задании «static_value» для обновления адреса group. Это не работает и похоже, что превышен лимит символов, как если бы это была одна строка.
Я также попытался повторно добавить существующие объекты самостоятельно, и это также не удалось со следующим:
"msg": "Failed apply: DevUKST-Web-Servers -> static '['UKST1MXWEB002D-NAT-EFW-01', 'UKST1MXWEB003D-NAT-EFW-01']' is not a valid reference\n DevUKST-Web-Servers -> static is invalid"
}
Единственный раз, когда я могу заставить его работать, — это использовать цикл with_items в задаче «Добавить объекты EFW в адресную группу, если 80/443» для заполнения static_values. Он перебирает «результат» задачи поиска объектов и добавляет новый адресный объект «efwone» в конце. Проблема с этим заключается в том, что он перезаписывает каждый результат каждый раз, когда он зацикливается.
Это пьеса, которую я запускаю
---
- hosts: localhost
connection: local
gather_facts: false
roles:
- role: PaloAltoNetworks.paloaltonetworks
vars_prompt:
- name: "username"
prompt: "Enter Username"
- name: "password"
prompt: "Enter Password"
vars:
cli:
ip_address: x.x.x.x
username: "{{ username }}"
password: "{{ password }}"
port: 443
objects: []
efwone: "{{ hostname }}-NAT-EFW-01"
tasks:
- name: include variables (free-form)
tags: [dev, prod]
include_vars: vars.yml
no_log: 'false'
# Configure Address Objects
- name: Create object "NAT-EFW-01"
tags: [dev, prod]
panos_address_object:
provider: "{{ cli }}"
name: "{{ hostname }}-NAT-EFW-01"
value: "{{ efw01_serviceip }}"
description: "{{ service_name }} - Public LB Backend pool IP"
commit: false
- name: Create object "Server Object"
tags: [dev, prod]
panos_address_object:
provider: "{{ cli }}"
name: "{{ hostname }}"
value: "{{ serverip }}"
description: "{{ service_name }} - {{ service_type }}"
commit: false
# Find existing objects in webserver address group
- name: Find objects in address group
tags: dev
when: service == "http" or service == "https"
panos_object_facts:
provider: "{{ cli }}"
name: "{{ dgshort }}-Web-Servers"
object_type: "address-group"
register: output
- name: Display Output
tags: [dev, prod]
debug: msg = "{{ output.results.static_value }}"
- name: Display efwone
tags: [dev, prod]
debug: var=efwone
- name: Populate list with address objects
tags: [dev, prod]
set_fact:
objects: "{{ output.results.static_value + [ efwone ] }}"
- name: Display new object list
tags: [dev, prod]
debug: var=objects
# Add EFW objects to address group if 80/443
- name: Update Web-Servers group dev
tags: dev
when: service == "http" or service == "https"
panos_address_group:
provider: "{{ cli }}"
name: "{{ dgshort }}-Web-Servers"
static_value: [ "{{ objects }}" ]
commit: false
Module:
# Copyright 2018 Palo Alto Networks, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: panos_address_group
short_description: Create address group objects on PAN-OS devices.
description:
- Create address group objects on PAN-OS devices.
author:
- Michael Richardson (@mrichardson03)
- Garfield Lee Freeman (@shinmog)
version_added: "2.8"
requirements:
- pan-python can be obtained from PyPI U(https://pypi.python.org/pypi/pan-python)
- pandevice can be obtained from PyPI U(https://pypi.python.org/pypi/pandevice)
notes:
- Panorama is supported.
- Check mode is supported.
extends_documentation_fragment:
- panos.transitional_provider
- panos.vsys
- panos.device_group
- panos.state
options:
name:
description:
- Name of address group to create.
required: true
static_value:
description:
- List of address objects to be included in the group.
type: list
dynamic_value:
description:
- Registered IP tags for a dynamic address group.
type: string
description:
description:
- Descriptive name for this address group.
tag:
description:
- List of tags to add to this address group.
type: list
commit:
description:
- Commit changes after creating object. If I(ip_address) is a Panorama device, and I(device_group) is
also set, perform a commit to Panorama and a commit-all to the device group.
default: true
type: bool
'''
EXAMPLES = '''
- name: Create object group 'Prod'
panos_address_group:
provider: '{{ provider }}'
name: 'Prod'
static_value: ['Test-One', 'Test-Three']
tag: ['Prod']
- name: Create object group 'SI'
panos_address_group:
provider: '{{ provider }}'
name: 'SI'
dynamic_value: "'SI_Instances'"
tag: ['SI']
- name: Delete object group 'SI'
panos_address_group:
provider: '{{ provider }}'
name: 'SI'
state: 'absent'
'''
RETURN = '''
# Default return values
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.panos.panos import get_connection
try:
from pandevice.objects import AddressGroup
from pandevice.errors import PanDeviceError
except ImportError:
pass
def main():
helper = get_connection(
vsys=True,
device_group=True,
with_classic_provider_spec=True,
with_state=True,
required_one_of=[
['static_value', 'dynamic_value'],
],
argument_spec=dict(
name=dict(type='str', required=True),
static_value=dict(type='list'),
dynamic_value=dict(),
description=dict(),
tag=dict(type='list'),
commit=dict(type='bool', default=True),
),
)
mutually_exclusive = [
['static_value', 'dynamic_value']
]
module = AnsibleModule(
argument_spec=helper.argument_spec,
required_one_of=helper.required_one_of,
mutually_exclusive=mutually_exclusive,
supports_check_mode=True,
)
# Verify libs are present, get parent object.
parent = helper.get_pandevice_parent(module)
# Object params.
spec = {
'name': module.params['name'],
'static_value': module.params['static_value'],
'dynamic_value': module.params['dynamic_value'],
'description': module.params['description'],
'tag': module.params['tag'],
}
# Other info.
commit = module.params['commit']
# Retrieve current info.
try:
listing = AddressGroup.refreshall(parent, add=False)
except PanDeviceError as e:
module.fail_json(msg='Failed refresh: {0}'.format(e))
# Build the object based on the user spec.
obj = AddressGroup(**spec)
parent.add(obj)
# Apply the state.
changed = helper.apply_state(obj, listing, module)
# Commit.
if commit and changed:
helper.commit(module)
# Done.
module.exit_json(changed=changed)
if __name__ == '__main__':
main()
Это результаты
ok: [localhost] => {
"changed": false,
"invocation": {
"module_args": {
"api_key": null,
"device_group": "shared",
"ip_address": null,
"name": "DevUKST-Web-Servers",
"name_regex": null,
"object_type": "address-group",
"password": null,
"port": 443,
"provider": {
"api_key": null,
"ip_address": "x.x.x.x",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"serial_number": null,
"username": "xxxx"
},
"username": "admin",
"vsys": "vsys1"
}
},
"objects": [
{
"description": null,
"dynamic_value": null,
"name": "DevUKST-Web-Servers",
"static_value": [
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01"
],
"tag": null
}
],
"results": {
"description": null,
"dynamic_value": null,
"name": "DevUKST-Web-Servers",
"static_value": [
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01"
],
"tag": null
}
}
TASK [Display Output] **********************************************************************************************************************************************************
task path: /etc/ansible/playbooks/NETOPS/AZURE/PALO/deployserviceparams.yml:91
ok: [localhost] => {
"msg": [
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01"
]
}
TASK [Display efwone] **********************************************************************************************************************************************************
task path: /etc/ansible/playbooks/NETOPS/AZURE/PALO/deployserviceparams.yml:95
ok: [localhost] => {
"efwone": "Test-NAT-EFW-01"
}
TASK [Populate list with address objects] **************************************************************************************************************************************
task path: /etc/ansible/playbooks/NETOPS/AZURE/PALO/deployserviceparams.yml:100
ok: [localhost] => {
"ansible_facts": {
"objects": [
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01",
"Test-NAT-EFW-01"
]
},
"changed": false
}
TASK [Display new object list] *************************************************************************************************************************************************
task path: /etc/ansible/playbooks/NETOPS/AZURE/PALO/deployserviceparams.yml:105
ok: [localhost] => {
"objects": [
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01",
"Test-NAT-EFW-01"
]
}
fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"api_key": null,
"commit": false,
"description": null,
"device_group": "shared",
"dynamic_value": null,
"ip_address": null,
"name": "DevUKST-Web-Servers",
"password": null,
"port": 443,
"provider": {
"api_key": null,
"ip_address": "x.x.x.x",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"serial_number": null,
"username": "xxxxx"
},
"state": "present",
"static_value": [
[
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01",
"Test-NAT-EFW-01"
]
],
"tag": null,
"username": "admin",
"vsys": "vsys1"
}
},
"msg": "Failed apply: DevUKST-Web-Servers -> static Node can be at most 63 characters, but current length: 77 value: ['UKST1MXWEB002D-NAT-EFW-01', 'UKST1MXWEB003D-NAT-EFW-01', 'Test-NAT-EFW-01']...\n DevUKST-Web-Servers -> static is invalid"

Отказ от ответственности Это полностью слепая отладка, так как я не могу ничего воспроизвести из вашего исходного сообщения. Всегда рассматривайте вариант минимальные воспроизводимые примеры, если это возможно.
встроенная документация вашего модуля для параметра static_value четко указывает, что ожидает список «адресных объектов»:
static_value:
description:
- List of address objects to be included in the group.
type: list
Примечание: Из остальной части вашего поста я слепо предполагаю, что строка является допустимым адресным объектом.
В выводе вашего запуска мы видим, что вы отправляете не список адресных объектов но список списков адресных объектов
"static_value": [
[
"UKST1MXWEB002D-NAT-EFW-01",
"UKST1MXWEB003D-NAT-EFW-01",
"Test-NAT-EFW-01"
]
]
Проблемная строка вашей пьесы, которая приводит к этой ситуации, находится в вашей последней задаче:
static_value: [ "{{ objects }}" ]
Ваша последняя задача должна быть (обратите внимание на исчезнувшие скобки)
- name: Update Web-Servers group dev
tags: dev
when: service == "http" or service == "https"
panos_address_group:
provider: "{{ cli }}"
name: "{{ dgshort }}-Web-Servers"
static_value: "{{ objects }}"
commit: false
Если это решит вашу проблему, вы должны принять ответ, чтобы другие знали, что существует фактическое решение.
Не могу поверить, как это было просто! Спасибо большое. Я даже не заметил, что это был список в списке, пока вы не указали на это. Глядя на результаты сейчас, это на самом деле совершенно очевидно с двумя наборами [].