如何在此任务中使用“列表”变量

时间:2019-07-15 15:13:33

标签: ansible

我是Ansible的新手,目前正在努力编写一本剧本,以使用以下模块来部署某些Palo Alto配置:

https://github.com/PaloAltoNetworks/ansible-pan

我已经花了一个星期的时间试图解决这个问题,但我无法弄清楚为什么这个“列表”不起作用。总之,此代码连接到防火墙,创建一个新的地址对象,并且如果存在“ http”或“ https”的“服务”变量,则它将将该对象添加到现有的防火墙地址组中。

问题在于防火墙组的添加。完成此任务的任务似乎是覆盖组中的现有对象,而不是附加到该对象。

要尝试解决这个问题,我有一个任务是“查找”现有对象(结果在字典中,然后我找到一个列表变量。然后在“ static_value”作业中使用此变量和新的服务器变量来:更新地址组。这似乎不起作用,并且看起来超出了字符限制,就好像它是一个字符串一样。

我还尝试过自己重新添加现有对象,并且以下操作也失败了:

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

有一次我可以使它工作的方法是在“如果将80/443的EFW对象添加到地址组”任务中使用“ with_items”循环来填充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"

1 个答案:

答案 0 :(得分:0)

免责声明,这是一个完全盲目的调试,因为我无法复制您原始帖子中的任何内容。如果可能,请始终考虑制作minimal reproducible examples


inline documentation of your module for the static_value parameter明确声明它正在等待“地址对象”列表:

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