From e7eca550341461ce12d18583608fd708480341b0 Mon Sep 17 00:00:00 2001 From: Adam Baumeister <32481037+adambaumeister@users.noreply.github.com> Date: Fri, 16 Feb 2024 11:02:39 +1100 Subject: [PATCH 01/23] chore: Update SUPPORT.md --- SUPPORT.md | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/SUPPORT.md b/SUPPORT.md index ed66cfb78..45aee05dc 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,20 +1,8 @@ -Community Supported +# Community Supported -The software and templates in the repo are released under an as-is, best effort, -support policy. This software should be seen as community supported and Palo -Alto Networks will contribute our expertise as and when possible. We do not -provide technical support or help in using or troubleshooting the components of -the project through our normal support options such as Palo Alto Networks -support teams, or ASC (Authorized Support Centers) partners and backline support -options. The underlying product used (the VM-Series firewall) by the scripts or -templates are still supported, but the support is only for the product -functionality and not for help in deploying or using the template or script -itself. Unless explicitly tagged, all projects or work posted in our GitHub -repository (at https://github.com/PaloAltoNetworks) or sites other than our -official Downloads page on https://support.paloaltonetworks.com are provided -under the best effort policy. +This template/script/solution is released “as-is”, with no warranty and no support. These should be seen as community supported and Palo Alto Networks may contribute its expertise at its discretion. Palo Alto Networks, including through its Authorized Support Centers (ASC) partners and backline support options, will not provide technical support or help in using or troubleshooting this template/script/solution. The underlying product used by this template/script/solution will still be supported in accordance with the product’s applicable support policy and the customer’s entitlements. As of version 2.12.2, this Collection of Ansible Modules for PAN-OS is [certified on Ansible Automation Hub](https://console.redhat.com/ansible/automation-hub/repo/published/paloaltonetworks/panos) and officially supported for Ansible subscribers. Ansible subscribers can engage -for support through their usual route towards Red Hat. \ No newline at end of file +for support through their usual route towards Red Hat. From 2d45ade33e14888571d5132d1d14bdd610e8f33c Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 19 Feb 2024 14:44:03 +0300 Subject: [PATCH 02/23] docs: fix qoutes for sanity checks --- SUPPORT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SUPPORT.md b/SUPPORT.md index 45aee05dc..874c2abf1 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,6 +1,6 @@ # Community Supported -This template/script/solution is released “as-is”, with no warranty and no support. These should be seen as community supported and Palo Alto Networks may contribute its expertise at its discretion. Palo Alto Networks, including through its Authorized Support Centers (ASC) partners and backline support options, will not provide technical support or help in using or troubleshooting this template/script/solution. The underlying product used by this template/script/solution will still be supported in accordance with the product’s applicable support policy and the customer’s entitlements. +This template/script/solution is released "as-is", with no warranty and no support. These should be seen as community supported and Palo Alto Networks may contribute its expertise at its discretion. Palo Alto Networks, including through its Authorized Support Centers (ASC) partners and backline support options, will not provide technical support or help in using or troubleshooting this template/script/solution. The underlying product used by this template/script/solution will still be supported in accordance with the product's applicable support policy and the customer's entitlements. As of version 2.12.2, this Collection of Ansible Modules for PAN-OS is [certified on Ansible Automation Hub](https://console.redhat.com/ansible/automation-hub/repo/published/paloaltonetworks/panos) From 666ca6bc2a8f4b415f3d857634a833cba2c7608d Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 19 Feb 2024 18:35:08 +0300 Subject: [PATCH 03/23] docs: fix eda ruff docs linting --- extensions/eda/plugins/event_source/logs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/eda/plugins/event_source/logs.py b/extensions/eda/plugins/event_source/logs.py index 42b475e8e..c5cbd6eea 100644 --- a/extensions/eda/plugins/event_source/logs.py +++ b/extensions/eda/plugins/event_source/logs.py @@ -59,6 +59,7 @@ async def status() -> web.Response: Returns ------- A web.Response object with status 200 and the text "up" returned by the function. + """ return web.Response(status=200, text="up") @@ -78,6 +79,7 @@ async def webhook(request: web.Request) -> web.Response: Returns ------- A web.Response object with status 200 and the status. + """ try: payload = await request.json() From 8ef4e277826ee6ad99662c159feb3241d84c5f58 Mon Sep 17 00:00:00 2001 From: michalbil <92343355+michalbil@users.noreply.github.com> Date: Fri, 29 Mar 2024 01:12:46 +0100 Subject: [PATCH 04/23] docs: fix custom url category "name" parameter description (#554) --- plugins/modules/panos_custom_url_category.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/panos_custom_url_category.py b/plugins/modules/panos_custom_url_category.py index 45096fa61..bc092ef4f 100644 --- a/plugins/modules/panos_custom_url_category.py +++ b/plugins/modules/panos_custom_url_category.py @@ -42,7 +42,7 @@ options: name: description: - - Name of the tag. + - Name of the url category. type: str description: description: From 0d0fd6d11d3bfd55a3795f32f69f9201fd54f554 Mon Sep 17 00:00:00 2001 From: Horia Gunica <43091730+horiagunica@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:55:03 +0200 Subject: [PATCH 05/23] fix(panos_facts.py): Fixed virtual systems fact name (#558) --- plugins/modules/panos_facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/panos_facts.py b/plugins/modules/panos_facts.py index 88c71307a..09511707d 100644 --- a/plugins/modules/panos_facts.py +++ b/plugins/modules/panos_facts.py @@ -483,7 +483,7 @@ def populate_facts(self): } ) - self.facts.update({"virtual-systems": virtual_systems}) + self.facts.update({"virtual_systems": virtual_systems}) class Config(Factbase): From 73c28a890ab35784a40ee14a47c11b31f4ffac6d Mon Sep 17 00:00:00 2001 From: michalbil <92343355+michalbil@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:08:16 +0200 Subject: [PATCH 06/23] fix: Add 'parent_interface' parameter for l2/l3 subinterface modules (#552) --- plugins/modules/panos_l2_subinterface.py | 39 ++++++- plugins/modules/panos_l3_subinterface.py | 39 ++++++- .../firewall/test_panos_l2_subinterface.yml | 105 ++++++++++++++++++ .../firewall/test_panos_l3_subinterface.yml | 105 ++++++++++++++++++ 4 files changed, 281 insertions(+), 7 deletions(-) create mode 100644 tests/integration/firewall/test_panos_l2_subinterface.yml create mode 100644 tests/integration/firewall/test_panos_l3_subinterface.yml diff --git a/plugins/modules/panos_l2_subinterface.py b/plugins/modules/panos_l2_subinterface.py index f38696c98..965fb996b 100644 --- a/plugins/modules/panos_l2_subinterface.py +++ b/plugins/modules/panos_l2_subinterface.py @@ -46,6 +46,10 @@ description: - Name of the interface to configure. type: str + parent_interface: + description: + - Name of the parent interface + type: str tag: description: - Tag (vlan id) for the interface @@ -103,8 +107,31 @@ class Helper(ConnectionHelper): def initial_handling(self, module): - if "." not in module.params["name"]: - module.fail_json(msg='interface name does not have "." in it') + # Sanity check. + name_set = True if module.params["name"] is not None else False + parent_set = True if module.params["parent_interface"] is not None else False + + if module.params["state"] == "gathered" and not parent_set: + module.fail_json( + msg="'parent_interface' is required when state is 'gathered'." + ) + + if name_set: + if "." not in module.params["name"]: + module.fail_json( + msg="Subinterface name does not have '.' in it: {0}".format( + module.params["name"] + ) + ) + if ( + parent_set + and module.params["parent_interface"] not in module.params["name"] + ): + module.fail_json( + msg="Parent and subinterface names do not match: {0} - {1}".format( + module.params["parent_interface"], module.params["name"] + ) + ) if module.params["state"] not in ("present", "replaced"): return @@ -113,7 +140,10 @@ def initial_handling(self, module): module.params["vsys"] = "vsys1" def parent_handling(self, parent, module): - iname = module.params["name"].split(".")[0] + if module.params["parent_interface"] is not None: + iname = module.params["parent_interface"] + else: + iname = module.params["name"].split(".")[0] if iname.startswith("ae"): eth = to_sdk_cls("network", "AggregateInterface")(iname) @@ -147,6 +177,9 @@ def main(): netflow_profile=dict(sdk_param="netflow_profile_l2"), comment=dict(), ), + extra_params=dict( + parent_interface=dict(type="str"), + ), ) module = AnsibleModule( diff --git a/plugins/modules/panos_l3_subinterface.py b/plugins/modules/panos_l3_subinterface.py index cada05cd5..b8afb08ae 100644 --- a/plugins/modules/panos_l3_subinterface.py +++ b/plugins/modules/panos_l3_subinterface.py @@ -48,6 +48,10 @@ description: - Name of the interface to configure. type: str + parent_interface: + description: + - Name of the parent interface + type: str tag: description: - Tag (vlan id) for the interface @@ -151,8 +155,30 @@ class Helper(ConnectionHelper): def initial_handling(self, module): # Sanity check. - if "." not in module.params["name"]: - module.fail_json(msg='Interface name does not have "." in it') + name_set = True if module.params["name"] is not None else False + parent_set = True if module.params["parent_interface"] is not None else False + + if module.params["state"] == "gathered" and not parent_set: + module.fail_json( + msg="'parent_interface' is required when state is 'gathered'." + ) + + if name_set: + if "." not in module.params["name"]: + module.fail_json( + msg="Subinterface name does not have '.' in it: {0}".format( + module.params["name"] + ) + ) + if ( + parent_set + and module.params["parent_interface"] not in module.params["name"] + ): + module.fail_json( + msg="Parent and subinterface names do not match: {0} - {1}".format( + module.params["parent_interface"], module.params["name"] + ) + ) if module.params["state"] not in ("present", "replaced"): return @@ -161,9 +187,11 @@ def initial_handling(self, module): module.params["vsys"] = "vsys1" def parent_handling(self, parent, module): - iname = module.params["name"].split(".")[0] + if module.params["parent_interface"] is not None: + iname = module.params["parent_interface"] + else: + iname = module.params["name"].split(".")[0] - eth = None if iname.startswith("ae"): eth = to_sdk_cls("network", "AggregateInterface")(iname) else: @@ -215,6 +243,9 @@ def main(): ), dhcp_default_route_metric=dict(type="int"), ), + extra_params=dict( + parent_interface=dict(type="str"), + ), ) module = AnsibleModule( diff --git a/tests/integration/firewall/test_panos_l2_subinterface.yml b/tests/integration/firewall/test_panos_l2_subinterface.yml new file mode 100644 index 000000000..7ece31808 --- /dev/null +++ b/tests/integration/firewall/test_panos_l2_subinterface.yml @@ -0,0 +1,105 @@ +--- +- name: test_panos_l2_subinterface - Create + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + register: result + +- name: test_panos_l2_subinterface - Assert create was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l2_subinterface - Create (idempotence) + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + register: result + +- name: test_panos_l2_subinterface - Assert create (idempotence) was successful + assert: + that: + - result is success + - result is not changed + +- name: test_panos_l2_subinterface - Modify + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 1 + register: result + +- name: test_panos_l2_subinterface - Assert modify was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l2_subinterface - Gather all + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: '*' + register: result + +- name: test_panos_l2_subinterface - Assert gather all returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 1 }}" + +- name: test_panos_l2_subinterface - Gather by parameter with one match + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: 'name ends-with 1' + register: result + +- name: test_panos_l2_subinterface - Assert gather by parameter with one match returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 1 }}" + +- name: test_panos_l2_subinterface - Gather by parameter with no match + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: 'name ends-with 2' + register: result + +- name: test_panos_l2_subinterface - Assert gather by parameter with no match returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 0 }}" + +- name: test_panos_l2_subinterface - Delete + paloaltonetworks.panos.panos_l2_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + state: 'absent' + register: result + +- name: test_panos_l2_subinterface - Assert delete was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l2_subinterface - Make sure changes commit cleanly + paloaltonetworks.panos.panos_commit_firewall: + provider: '{{ device }}' + register: result + +- name: test_panos_l2_subinterface - Assert commit was successful + assert: + that: + - result is success diff --git a/tests/integration/firewall/test_panos_l3_subinterface.yml b/tests/integration/firewall/test_panos_l3_subinterface.yml new file mode 100644 index 000000000..7f63a6d32 --- /dev/null +++ b/tests/integration/firewall/test_panos_l3_subinterface.yml @@ -0,0 +1,105 @@ +--- +- name: test_panos_l3_subinterface - Create + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + register: result + +- name: test_panos_l3_subinterface - Assert create was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l3_subinterface - Create (idempotence) + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + register: result + +- name: test_panos_l3_subinterface - Assert create (idempotence) was successful + assert: + that: + - result is success + - result is not changed + +- name: test_panos_l3_subinterface - Modify + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 1 + register: result + +- name: test_panos_l3_subinterface - Assert modify was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l3_subinterface - Gather all + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: '*' + register: result + +- name: test_panos_l3_subinterface - Assert gather all returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 1 }}" + +- name: test_panos_l3_subinterface - Gather by parameter with one match + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: 'name ends-with 1' + register: result + +- name: test_panos_l3_subinterface - Assert gather by parameter with one match returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 1 }}" + +- name: test_panos_l3_subinterface - Gather by parameter with no match + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + parent_interface: 'ethernet1/1' + state: 'gathered' + gathered_filter: 'name ends-with 2' + register: result + +- name: test_panos_l3_subinterface - Assert gather by parameter with no match returned result + assert: + that: + - result is success + - "{{ result.gathered | length == 0 }}" + +- name: test_panos_l3_subinterface - Delete + paloaltonetworks.panos.panos_l3_subinterface: + provider: '{{ device }}' + name: 'ethernet1/1.1' + tag: 2 + state: 'absent' + register: result + +- name: test_panos_l3_subinterface - Assert delete was successful + assert: + that: + - result is success + - result is changed + +- name: test_panos_l3_subinterface - Make sure changes commit cleanly + paloaltonetworks.panos.panos_commit_firewall: + provider: '{{ device }}' + register: result + +- name: test_panos_l3_subinterface - Assert commit was successful + assert: + that: + - result is success From a2870f5d742a6d6dd2e759e101ba1b6fcc9e6ee9 Mon Sep 17 00:00:00 2001 From: Adrian Celebanski <135693994+acelebanski@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:10:33 +0200 Subject: [PATCH 07/23] feat: Add new option to panos_active_in_ha module (#560) --- plugins/modules/panos_active_in_ha.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/modules/panos_active_in_ha.py b/plugins/modules/panos_active_in_ha.py index 3a7e42aa9..5d10c1d7d 100644 --- a/plugins/modules/panos_active_in_ha.py +++ b/plugins/modules/panos_active_in_ha.py @@ -53,6 +53,12 @@ node's current state in an HA pair. Can be useful when working with partially upgraded nodes. Use with caution. type: bool default: false + ignore_non_functional: + description: + - Use with caution, when set to `True` will ignore if device state is `non-functional` on one of the nodes. Helpful + when verifying a state of a partially upgraded HA pair with vmseries plugin version mismatch. + type: bool + default: false # """ EXAMPLES = """ @@ -112,6 +118,7 @@ def main(): argument_spec=dict( force_fail=dict(type="bool", default=False), skip_config_sync=dict(type="bool", default=False), + ignore_non_functional=dict(type="bool", default=False), ), panorama_error="This is a firewall only module", ) @@ -123,7 +130,8 @@ def main(): firewall = FirewallProxy(firewall=helper.get_pandevice_parent(module)) is_active = CheckFirewall(firewall).check_is_ha_active( - skip_config_sync=module.params["skip_config_sync"] + skip_config_sync=module.params["skip_config_sync"], + ignore_non_functional=module.params["ignore_non_functional"], ) if module.params["force_fail"]: From 8e6e2509a9d88a60890f21a9205e3f38ec81512d Mon Sep 17 00:00:00 2001 From: itsamemarkus <34944988+itsamemarkus@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:51:16 +0200 Subject: [PATCH 08/23] docs: replaced pan-os-upgrade-assurance with panos-upgrade-assurance (#557) --- plugins/modules/panos_active_in_ha.py | 2 +- plugins/modules/panos_readiness_checks.py | 2 +- plugins/modules/panos_snapshot_report.py | 2 +- plugins/modules/panos_state_snapshot.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/modules/panos_active_in_ha.py b/plugins/modules/panos_active_in_ha.py index 5d10c1d7d..eff95c0c0 100644 --- a/plugins/modules/panos_active_in_ha.py +++ b/plugins/modules/panos_active_in_ha.py @@ -33,7 +33,7 @@ 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) - - pan-os-upgrade-assurance can be obtained from PyPI U(https://pypi.org/project/panos-upgrade-assurance) + - panos-upgrade-assurance can be obtained from PyPI U(https://pypi.org/project/panos-upgrade-assurance) notes: - Panorama is not supported. - Check mode is not supported. diff --git a/plugins/modules/panos_readiness_checks.py b/plugins/modules/panos_readiness_checks.py index a53e4a364..8512452f7 100644 --- a/plugins/modules/panos_readiness_checks.py +++ b/plugins/modules/panos_readiness_checks.py @@ -35,7 +35,7 @@ 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) - - pan-os-upgrade-assurance can be obtained from PyPI U(https://pypi.org/project/panos-upgrade-assurance) + - panos-upgrade-assurance can be obtained from PyPI U(https://pypi.org/project/panos-upgrade-assurance) notes: - Panorama is not supported. - Check mode is not supported. diff --git a/plugins/modules/panos_snapshot_report.py b/plugins/modules/panos_snapshot_report.py index 81e6e77ab..53969e96c 100644 --- a/plugins/modules/panos_snapshot_report.py +++ b/plugins/modules/panos_snapshot_report.py @@ -38,7 +38,7 @@ 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) - - pan-os-upgrade-assurance can be obtained from PyPI U(https://pypi.python.org/pypi/pan-os-upgrade-assurance) + - panos-upgrade-assurance can be obtained from PyPI U(https://pypi.python.org/pypi/panos-upgrade-assurance) notes: - This is an offline module, no device connection is made. - Check mode is not supported. diff --git a/plugins/modules/panos_state_snapshot.py b/plugins/modules/panos_state_snapshot.py index 304441326..8e4284fa0 100644 --- a/plugins/modules/panos_state_snapshot.py +++ b/plugins/modules/panos_state_snapshot.py @@ -35,7 +35,7 @@ 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) - - pan-os-upgrade-assurance can be obtained from PyPI U(https://pypi.python.org/pypi/pan-os-upgrade-assurance) + - panos-upgrade-assurance can be obtained from PyPI U(https://pypi.python.org/pypi/panos-upgrade-assurance) notes: - Panorama is not supported. - Check mode is not supported. From 37ab39b544321069d28407026bdde30549be7759 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 17 Apr 2024 11:18:00 +0000 Subject: [PATCH 09/23] chore(release): 2.20.0 ## [2.20.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.19.1...v2.20.0) (2024-04-17) ### Features * Add new option to panos_active_in_ha module ([#560](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/560)) ([a2870f5](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/a2870f5d742a6d6dd2e759e101ba1b6fcc9e6ee9)) ### Bug Fixes * Add 'parent_interface' parameter for l2/l3 subinterface modules ([#552](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/552)) ([73c28a8](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/73c28a890ab35784a40ee14a47c11b31f4ffac6d)) * **panos_facts.py:** Fixed virtual systems fact name ([#558](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/558)) ([0d0fd6d](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/0d0fd6d11d3bfd55a3795f32f69f9201fd54f554)) --- CHANGELOG.md | 13 +++++++++++++ docs/source/index.rst | 2 +- galaxy.yml | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89890789b..837bd6c99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [2.20.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.19.1...v2.20.0) (2024-04-17) + + +### Features + +* Add new option to panos_active_in_ha module ([#560](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/560)) ([a2870f5](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/a2870f5d742a6d6dd2e759e101ba1b6fcc9e6ee9)) + + +### Bug Fixes + +* Add 'parent_interface' parameter for l2/l3 subinterface modules ([#552](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/552)) ([73c28a8](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/73c28a890ab35784a40ee14a47c11b31f4ffac6d)) +* **panos_facts.py:** Fixed virtual systems fact name ([#558](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/558)) ([0d0fd6d](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/0d0fd6d11d3bfd55a3795f32f69f9201fd54f554)) + ### [2.19.1](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.19.0...v2.19.1) (2023-12-14) diff --git a/docs/source/index.rst b/docs/source/index.rst index 3ee77d743..c848fff3a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,7 +2,7 @@ Palo Alto Networks Ansible Collection ===================================== -Version: 2.19.1 +Version: 2.20.0 The Palo Alto Networks Ansible collection is a collection of modules that automate configuration and operational tasks on Palo Alto Networks Next diff --git a/galaxy.yml b/galaxy.yml index 4e49599c9..de3d4e5e7 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -10,7 +10,7 @@ namespace: 'paloaltonetworks' name: 'panos' # The version of the collection. Must be compatible with semantic versioning -version: 2.19.1 +version: 2.20.0 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: 'README.md' From c64cd7902b4e4a83c12a53036052a9c82070af1a Mon Sep 17 00:00:00 2001 From: Adrian Celebanski <135693994+acelebanski@users.noreply.github.com> Date: Thu, 16 May 2024 12:50:09 +0200 Subject: [PATCH 10/23] feat: Add additional error handling to some upgrade assurance modules (#561) --- plugins/modules/panos_readiness_checks.py | 27 ++++++++++++++++------- plugins/modules/panos_snapshot_report.py | 12 ++++++---- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/plugins/modules/panos_readiness_checks.py b/plugins/modules/panos_readiness_checks.py index 8512452f7..9625df268 100644 --- a/plugins/modules/panos_readiness_checks.py +++ b/plugins/modules/panos_readiness_checks.py @@ -148,6 +148,7 @@ try: from panos_upgrade_assurance.check_firewall import CheckFirewall + from panos_upgrade_assurance.exceptions import UpdateServerConnectivityException from panos_upgrade_assurance.firewall_proxy import FirewallProxy except ImportError: pass @@ -180,14 +181,24 @@ def main(): checks = CheckFirewall( node=firewall, skip_force_locale=module.params["skip_force_locale"] ) - results = checks.run_readiness_checks(checks_configuration=module.params["checks"]) - - if module.params["force_fail"]: - for check in list(results.keys()): - if results[check]["state"]: - del results[check] - else: - module_failed = True + + try: + results = checks.run_readiness_checks( + checks_configuration=module.params["checks"] + ) + except UpdateServerConnectivityException as exc: + results["active_support"] = { + "state": False, + "reason": getattr(exc, "message", repr(exc)), + } + module_failed = True + else: + if module.params["force_fail"]: + for check in list(results.keys()): + if results[check]["state"]: + del results[check] + else: + module_failed = True module.exit_json(changed=False, response=results, failed=module_failed) diff --git a/plugins/modules/panos_snapshot_report.py b/plugins/modules/panos_snapshot_report.py index 53969e96c..1e45d7c96 100644 --- a/plugins/modules/panos_snapshot_report.py +++ b/plugins/modules/panos_snapshot_report.py @@ -166,6 +166,7 @@ try: import panos_upgrade_assurance from panos_upgrade_assurance.snapshot_compare import SnapshotCompare + from panos_upgrade_assurance.exceptions import SnapshotSchemeMismatchException except ImportError: PUA_AVAILABLE = False pass @@ -198,10 +199,13 @@ def main(): ) ) - results = SnapshotCompare( - left_snapshot=module.params["left_snapshot"], - right_snapshot=module.params["right_snapshot"], - ).compare_snapshots(reports=module.params["reports"]) + try: + results = SnapshotCompare( + left_snapshot=module.params["left_snapshot"], + right_snapshot=module.params["right_snapshot"], + ).compare_snapshots(reports=module.params["reports"]) + except SnapshotSchemeMismatchException as exc: + module.fail_json(msg=getattr(exc, "message", repr(exc))) module.exit_json(changed=False, response=results) From 7f84b21128dabe87c3c9f0bb0eee80d64a71dff7 Mon Sep 17 00:00:00 2001 From: Alp Eren Kose Date: Thu, 8 Aug 2024 17:09:30 +0300 Subject: [PATCH 11/23] chore: bump min ansible-core to 2.15 (#572) --- .github/workflows/ci.yml | 4 +- README.md | 2 +- meta/runtime.yml | 2 +- tests/sanity/ignore-2.14.txt | 113 ------------------ .../{ignore-2.13.txt => ignore-2.17.txt} | 0 5 files changed, 4 insertions(+), 117 deletions(-) delete mode 100644 tests/sanity/ignore-2.14.txt rename tests/sanity/{ignore-2.13.txt => ignore-2.17.txt} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47c18001f..69ce7bcb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,12 +22,12 @@ jobs: strategy: matrix: include: - - ansible: "2.14" - python_ver: "3.11" - ansible: "2.15" python_ver: "3.11" - ansible: "2.16" python_ver: "3.11" + - ansible: "2.17" + python_ver: "3.11" runs-on: ubuntu-latest defaults: run: diff --git a/README.md b/README.md index 070d87c01..44be7b894 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Tested Ansible Versions ----------------------- This collection is tested with the most current Ansible releases. Ansible versions -before 2.14 are **not supported**. +before 2.15 are **not supported**. Python Version -------------- diff --git a/meta/runtime.yml b/meta/runtime.yml index 7632f9264..e422d536c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,5 +1,5 @@ --- -requires_ansible: '>=2.14.0' +requires_ansible: '>=2.15.0' plugin_routing: modules: panos_admin: diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt deleted file mode 100644 index 7a32ca901..000000000 --- a/tests/sanity/ignore-2.14.txt +++ /dev/null @@ -1,113 +0,0 @@ -plugins/httpapi/panos.py validate-modules:missing-gplv3-license -plugins/modules/panos_active_in_ha.py validate-modules:missing-gplv3-license -plugins/modules/panos_address_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_address_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_admin.py validate-modules:missing-gplv3-license -plugins/modules/panos_administrator.py validate-modules:missing-gplv3-license -plugins/modules/panos_admpwd.py validate-modules:missing-gplv3-license -plugins/modules/panos_aggregate_interface.py validate-modules:missing-gplv3-license -plugins/modules/panos_api_key.py validate-modules:missing-gplv3-license -plugins/modules/panos_application_filter.py validate-modules:missing-gplv3-license -plugins/modules/panos_application_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_application_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_aggregate.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_auth.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_conditional_advertisement.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_dampening.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_peer_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_peer.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_policy_filter.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_policy_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp_redistribute.py validate-modules:missing-gplv3-license -plugins/modules/panos_bgp.py validate-modules:missing-gplv3-license -plugins/modules/panos_cert_gen_ssh.py validate-modules:missing-gplv3-license -plugins/modules/panos_check.py validate-modules:missing-gplv3-license -plugins/modules/panos_commit_firewall.py validate-modules:missing-gplv3-license -plugins/modules/panos_commit_panorama.py validate-modules:missing-gplv3-license -plugins/modules/panos_commit_push.py validate-modules:missing-gplv3-license -plugins/modules/panos_commit.py validate-modules:missing-gplv3-license -plugins/modules/panos_config_element.py validate-modules:missing-gplv3-license -plugins/modules/panos_custom_url_category.py validate-modules:missing-gplv3-license -plugins/modules/panos_dag_tags.py validate-modules:missing-gplv3-license -plugins/modules/panos_dag.py validate-modules:missing-gplv3-license -plugins/modules/panos_decryption_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_device_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_dhcp_relay_ipv6_address.py validate-modules:missing-gplv3-license -plugins/modules/panos_dhcp_relay.py validate-modules:missing-gplv3-license -plugins/modules/panos_dhcp.py validate-modules:missing-gplv3-license -plugins/modules/panos_dynamic_updates.py validate-modules:missing-gplv3-license -plugins/modules/panos_dynamic_user_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_edl.py validate-modules:missing-gplv3-license -plugins/modules/panos_email_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_email_server.py validate-modules:missing-gplv3-license -plugins/modules/panos_export.py validate-modules:missing-gplv3-license -plugins/modules/panos_gre_tunnel.py validate-modules:missing-gplv3-license -plugins/modules/panos_ha.py validate-modules:missing-gplv3-license -plugins/modules/panos_http_profile_header.py validate-modules:missing-gplv3-license -plugins/modules/panos_http_profile_param.py validate-modules:missing-gplv3-license -plugins/modules/panos_http_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_http_server.py validate-modules:missing-gplv3-license -plugins/modules/panos_ike_crypto_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_ike_gateway.py validate-modules:missing-gplv3-license -plugins/modules/panos_import.py validate-modules:missing-gplv3-license -plugins/modules/panos_interface.py validate-modules:missing-gplv3-license -plugins/modules/panos_ipsec_ipv4_proxyid.py validate-modules:missing-gplv3-license -plugins/modules/panos_ipsec_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_ipsec_tunnel.py validate-modules:missing-gplv3-license -plugins/modules/panos_ipv6_address.py validate-modules:missing-gplv3-license -plugins/modules/panos_l2_subinterface.py validate-modules:missing-gplv3-license -plugins/modules/panos_l3_subinterface.py validate-modules:missing-gplv3-license -plugins/modules/panos_lic.py validate-modules:missing-gplv3-license -plugins/modules/panos_loadcfg.py validate-modules:missing-gplv3-license -plugins/modules/panos_log_forwarding_profile_match_list_action.py validate-modules:missing-gplv3-license -plugins/modules/panos_log_forwarding_profile_match_list.py validate-modules:missing-gplv3-license -plugins/modules/panos_log_forwarding_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_loopback_interface.py validate-modules:missing-gplv3-license -plugins/modules/panos_management_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_match_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_mgtconfig.py validate-modules:missing-gplv3-license -plugins/modules/panos_nat_rule_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_nat_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_nat_rule2.py validate-modules:missing-gplv3-license -plugins/modules/panos_object_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_op.py validate-modules:missing-gplv3-license -plugins/modules/panos_pbf_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_pg.py validate-modules:missing-gplv3-license -plugins/modules/panos_query_rules.py validate-modules:missing-gplv3-license -plugins/modules/panos_readiness_checks.py validate-modules:missing-gplv3-license -plugins/modules/panos_redistribution.py validate-modules:missing-gplv3-license -plugins/modules/panos_region.py validate-modules:missing-gplv3-license -plugins/modules/panos_registered_ip_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_registered_ip.py validate-modules:missing-gplv3-license -plugins/modules/panos_restart.py validate-modules:missing-gplv3-license -plugins/modules/panos_sag.py validate-modules:missing-gplv3-license -plugins/modules/panos_schedule_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_security_rule_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_security_rule.py validate-modules:missing-gplv3-license -plugins/modules/panos_service_group.py validate-modules:missing-gplv3-license -plugins/modules/panos_service_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_snapshot_report.py validate-modules:missing-gplv3-license -plugins/modules/panos_snmp_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_snmp_v2c_server.py validate-modules:missing-gplv3-license -plugins/modules/panos_snmp_v3_server.py validate-modules:missing-gplv3-license -plugins/modules/panos_software.py validate-modules:missing-gplv3-license -plugins/modules/panos_state_snapshot.py validate-modules:missing-gplv3-license -plugins/modules/panos_static_route.py validate-modules:missing-gplv3-license -plugins/modules/panos_syslog_profile.py validate-modules:missing-gplv3-license -plugins/modules/panos_syslog_server.py validate-modules:missing-gplv3-license -plugins/modules/panos_tag_object.py validate-modules:missing-gplv3-license -plugins/modules/panos_template_stack.py validate-modules:missing-gplv3-license -plugins/modules/panos_template_variable.py validate-modules:missing-gplv3-license -plugins/modules/panos_template.py validate-modules:missing-gplv3-license -plugins/modules/panos_tunnel.py validate-modules:missing-gplv3-license -plugins/modules/panos_type_cmd.py validate-modules:missing-gplv3-license -plugins/modules/panos_userid.py validate-modules:missing-gplv3-license -plugins/modules/panos_virtual_router_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_virtual_router.py validate-modules:missing-gplv3-license -plugins/modules/panos_virtual_wire.py validate-modules:missing-gplv3-license -plugins/modules/panos_vlan_interface.py validate-modules:missing-gplv3-license -plugins/modules/panos_vlan.py validate-modules:missing-gplv3-license -plugins/modules/panos_vm_auth_key.py validate-modules:missing-gplv3-license -plugins/modules/panos_zone_facts.py validate-modules:missing-gplv3-license -plugins/modules/panos_zone.py validate-modules:missing-gplv3-license diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.17.txt similarity index 100% rename from tests/sanity/ignore-2.13.txt rename to tests/sanity/ignore-2.17.txt From db6c32c7b9303f7b5b66f7169babca7f52f4ed87 Mon Sep 17 00:00:00 2001 From: Alp Eren Kose Date: Thu, 29 Aug 2024 18:33:07 +0300 Subject: [PATCH 12/23] fix(panos_security_rule): state merged with existing values (#570) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce default_values param in helper function instead of sdk_params default values to avoid issue with default values being merged to existing configuration. * Introduce preset_values param in helper function which takes panos predefined possible values to overcome the issue with updating / replacing list type parameters with defaults (e.g. when “any” was present for source IP for an existing rule and user passed an IP address to be merged) * Also fixes panos_template mode xpath error on second run --- plugins/module_utils/panos.py | 99 ++++++++++++++++---- plugins/modules/panos_security_rule.py | 125 +++++++++++++------------ plugins/modules/panos_template.py | 5 + 3 files changed, 154 insertions(+), 75 deletions(-) diff --git a/plugins/module_utils/panos.py b/plugins/module_utils/panos.py index dffb513dd..8bce488b0 100644 --- a/plugins/module_utils/panos.py +++ b/plugins/module_utils/panos.py @@ -139,6 +139,8 @@ def __init__( self.parents = () self.sdk_params = {} self.extra_params = {} + self.default_values = {} + self.preset_values = {} self.reference_operations = () self.ansible_to_sdk_param_mapping = {} self.with_uuid = False @@ -489,6 +491,11 @@ def process(self, module): ansible_param, ansible_param ) spec[sdk_param] = module.params.get(ansible_param) + if ansible_param in self.preset_values.keys(): + self.preset_values[sdk_param] = self.preset_values.pop(ansible_param) + if ansible_param in self.default_values.keys(): + self.default_values[sdk_param] = self.default_values.pop(ansible_param) + if self.with_uuid: spec["uuid"] = module.params["uuid"] if self.with_target: @@ -690,27 +697,40 @@ def apply_state( if not item.equal(obj, compare_children=True): result["changed"] = True obj.extend(other_children) - result["after"] = self.describe(obj) - result["diff"]["after"] = eltostr(obj) if not module.check_mode: if self.with_update_in_apply_state: - for param in obj.about().keys(): - if getattr(item, param) != getattr(obj, param): + for key, obj_value in obj.about().items(): + # NOTE checking defaults for with_update_in_apply_state doesnot have + # a use for now as template, stack and device group dont have + # defaults in the SDK + # it also breaks panos_template as SDK has `mode` attribute set + # to "normal" by default, but there is no xpath for this. + # if obj_value is None: + # setattr(obj, key, self._get_default_value(obj, key)) + if getattr(item, key) != getattr(obj, key): try: - obj.update(param) + obj.update(key) except PanDeviceError as e: module.fail_json( - msg="Failed update {0}: {1}".format( - param, e - ) + msg="Failed update {0}: {1}".format(key, e) ) + result["after"] = self.describe(obj) + result["diff"]["after"] = eltostr(obj) else: + for key, obj_value in obj.about().items(): + if obj_value is None: + setattr(obj, key, self._get_default_value(obj, key)) + result["after"] = self.describe(obj) + result["diff"]["after"] = eltostr(obj) try: obj.apply() except PanDeviceError as e: module.fail_json(msg="Failed apply: {0}".format(e)) break else: + for key, obj_value in obj.about().items(): + if obj_value is None: + setattr(obj, key, self._get_default_value(obj, key)) result["changed"] = True result["before"] = None result["after"] = self.describe(obj) @@ -829,15 +849,29 @@ def apply_state( updated_params = set([]) for key, obj_value in obj.about().items(): item_value = getattr(item, key, None) - if obj_value is not None: + if obj_value: if isinstance(obj_value, list) or isinstance(item_value, list): if not item_value: item_value = [] - for elm in obj_value: - if elm not in item_value: - updated_params.add(key) - item_value.append(elm) - setattr(item, key, item_value) + if isinstance(obj_value, str): + obj_value = [obj_value] + # if current config or obj to create is one of the preset values + # (dropdown options in UI) then replace it with the obj value + # since values like "any" can not be in place with other values. + if ( + preset_values := self.preset_values.get(key, None) + ) and ( + set(item_value).issubset(preset_values) + or set(obj_value).issubset(preset_values) + ): + updated_params.add(key) + setattr(item, key, obj_value) + else: + for elm in obj_value: + if elm not in item_value: + updated_params.add(key) + item_value.append(elm) + setattr(item, key, item_value) elif item_value != obj_value: updated_params.add(key) setattr(item, key, obj_value) @@ -854,7 +888,10 @@ def apply_state( msg="Failed update {0}: {1}".format(param, e) ) break - else: + else: # create new record with merge + for key, obj_value in obj.about().items(): + if obj_value is None: + setattr(obj, key, self._get_default_value(obj, key)) result["before"] = None result["after"] = self.describe(obj) result["diff"] = { @@ -1139,6 +1176,30 @@ def _describe(self, elm): return ans + def _get_default_value(self, obj, key): + """Returns default value for an sdk param in Ansible module. + + Args: + obj: The pandevice object to fetch defaults from SDK. + key: sdk param name to get default value for. + + Returns: + Default value of sdk param if defined in Ansible module default_values or + fetch from SDK defaults as a fallback. + + """ + # TODO get default values from pan-os-python SDK + # obj._params is not public attribute on SDK which provide default values + # either make it public accessible or provide a method + # NOTE create a temp object with defaults and use values from this temp object + # to fetch defaults for None values and set it for the object to create + obj_default = obj.__class__() + if (default_value := self.default_values.get(key, None)) is None: + # set default value from SDK if not found in module default_values + default_value = getattr(obj_default, key, None) + + return default_value + def matches_gathered_filter(self, item, logic): """Returns True if the item and its contents matches the logic given. @@ -1368,6 +1429,8 @@ def get_connection( parents=None, sdk_params=None, extra_params=None, + default_values=None, + preset_values=None, reference_operations=None, ansible_to_sdk_param_mapping=None, with_uuid=False, @@ -1745,6 +1808,10 @@ class in the package (e.g. - "VirtualRouter"). If the class is a singleton renames[k] = sdk_name spec[k] = sdk_params[k] helper.sdk_params = sdk_params + if preset_values is not None: + helper.preset_values = preset_values + if default_values is not None: + helper.default_values = default_values if with_gathered_filter: if "gathered_filter" in spec: @@ -1821,7 +1888,7 @@ def __init__( with_state=False, with_enabled_state=False, *args, - **kwargs + **kwargs, ): spec = {} diff --git a/plugins/modules/panos_security_rule.py b/plugins/modules/panos_security_rule.py index 6c72d8412..b79b0f20c 100644 --- a/plugins/modules/panos_security_rule.py +++ b/plugins/modules/panos_security_rule.py @@ -25,10 +25,12 @@ short_description: Manage security rule policy on PAN-OS devices or Panorama management console. description: > - Security policies allow you to enforce rules and take action, and can be as - general or specific as needed. + general or specific as needed. - The policy rules are compared against the incoming traffic in sequence, and - because the first rule that matches the traffic is applied, the more specific - rules must precede the more general ones. + because the first rule that matches the traffic is applied, the more specific + rules must precede the more general ones. + - Defaults in spec descriptions apply when I(state=present)/I(state=replaced), + or when creating a new resource with I(state=merged). author: - Ivan Bojer (@ivanbojer) - Robert Hagen (@stealthllama) @@ -59,13 +61,12 @@ type: str source_zone: description: - - List of source zones. - default: ["any"] + - List of source zones. Defaults to I(["any"]). type: list elements: str source_ip: description: - - List of source addresses. + - List of source addresses. Defaults to I(["any"]). - This can be an IP address, an address object/group, etc. - When referencing predefined EDLs, use config names of the EDLS not their full names. The config names can be found with the CLI... @@ -74,13 +75,12 @@ panw-highrisk-ip-list panw-highrisk-ip-list panw-known-ip-list panw-known-ip-list panw-torexit-ip-list panw-torexit-ip-list - default: ["any"] type: list elements: str source_user: - description: + description: > - Use users to enforce policy for individual users or a group of users. - default: ["any"] + Defaults to I(["any"]). type: list elements: str hip_profiles: @@ -97,13 +97,12 @@ elements: str destination_zone: description: - - List of destination zones. - default: ["any"] + - List of destination zones. Defaults to I(["any"]). type: list elements: str destination_ip: description: - - List of destination addresses. + - List of destination addresses. Defaults to I(["any"]). - This can be an IP address, an address object/group, etc. - When referencing predefined EDLs, use config names of the EDLS not their full names. The config names can be found with the CLI... @@ -112,34 +111,31 @@ panw-highrisk-ip-list panw-highrisk-ip-list panw-known-ip-list panw-known-ip-list panw-torexit-ip-list panw-torexit-ip-list - default: ["any"] type: list elements: str application: - description: + description: > - List of applications, application groups, and/or application filters. - default: ["any"] + Defaults to I(["any"]). type: list elements: str service: description: - - List of services and/or service groups. - default: ['application-default'] + - List of services and/or service groups. Defaults to I(["application-default"]). type: list elements: str category: description: - - List of destination URL categories. + - List of destination URL categories. Defaults to I(["any"]). - When referencing predefined EDLs, use config names of the EDLS not their full names. The config names can be found with the CLI... request system external-list show type predefined-url name panw-auth-portal-exclude-list panw-auth-portal-exclude-list - default: ["any"] type: list elements: str action: description: - - Action to apply once rules matches. + - Action to apply to the rule. Defaults to I("allow"). type: str choices: - allow @@ -148,20 +144,17 @@ - reset-client - reset-server - reset-both - default: "allow" log_setting: description: - Log forwarding profile. type: str log_start: description: - - Whether to log at session start. - default: false + - Whether to log at session start. Defaults to I(false). type: bool log_end: description: - - Whether to log at session end. - default: true + - Whether to log at session end. Defaults to I(true). type: bool description: description: @@ -169,13 +162,12 @@ type: str rule_type: description: - - Type of security rule (version 6.1 of PanOS and above). + - Type of security rule (version 6.1 of PanOS and above). Defaults to I("universal"). type: str choices: - universal - intrazone - interzone - default: 'universal' tag_name: description: - List of tags associated with the rule. @@ -183,18 +175,15 @@ elements: str negate_source: description: - - Match on the reverse of the 'source_ip' attribute - default: false + - Match on the reverse of the 'source_ip' attribute. Defaults to I(false). type: bool negate_destination: description: - - Match on the reverse of the 'destination_ip' attribute - default: false + - Match on the reverse of the 'destination_ip' attribute. Defaults to I(false). type: bool disabled: description: - - Disable this rule. - default: false + - Disable this rule. Defaults to I(false). type: bool schedule: description: @@ -205,9 +194,9 @@ - Send 'ICMP Unreachable'. Used with 'deny', 'drop', and 'reset' actions. type: bool disable_server_response_inspection: - description: + description: > - Disables packet inspection from the server to the client. Useful under heavy server load conditions. - default: false + Defaults to I(false). type: bool group_profile: description: > @@ -399,25 +388,16 @@ def main(): sdk_cls=("policies", "SecurityRule"), sdk_params=dict( rule_name=dict(required=True, sdk_param="name"), - source_zone=dict( - type="list", elements="str", default=["any"], sdk_param="fromzone" - ), - source_ip=dict( - type="list", elements="str", default=["any"], sdk_param="source" - ), - source_user=dict(type="list", elements="str", default=["any"]), + source_zone=dict(type="list", elements="str", sdk_param="fromzone"), + source_ip=dict(type="list", elements="str", sdk_param="source"), + source_user=dict(type="list", elements="str"), hip_profiles=dict(type="list", elements="str"), - destination_zone=dict( - type="list", elements="str", default=["any"], sdk_param="tozone" - ), - destination_ip=dict( - type="list", elements="str", default=["any"], sdk_param="destination" - ), - application=dict(type="list", elements="str", default=["any"]), - service=dict(type="list", elements="str", default=["application-default"]), - category=dict(type="list", elements="str", default=["any"]), + destination_zone=dict(type="list", elements="str", sdk_param="tozone"), + destination_ip=dict(type="list", elements="str", sdk_param="destination"), + application=dict(type="list", elements="str"), + service=dict(type="list", elements="str"), + category=dict(type="list", elements="str"), action=dict( - default="allow", choices=[ "allow", "deny", @@ -428,21 +408,20 @@ def main(): ], ), log_setting=dict(), - log_start=dict(type="bool", default=False), - log_end=dict(type="bool", default=True), + log_start=dict(type="bool"), + log_end=dict(type="bool"), description=dict(), rule_type=dict( - default="universal", choices=["universal", "intrazone", "interzone"], sdk_param="type", ), tag_name=dict(type="list", elements="str", sdk_param="tag"), - negate_source=dict(type="bool", default=False), - negate_destination=dict(type="bool", default=False), - disabled=dict(type="bool", default=False), + negate_source=dict(type="bool"), + negate_destination=dict(type="bool"), + disabled=dict(type="bool"), schedule=dict(), icmp_unreachable=dict(type="bool"), - disable_server_response_inspection=dict(type="bool", default=False), + disable_server_response_inspection=dict(type="bool"), group_profile=dict(sdk_param="group"), antivirus=dict(sdk_param="virus"), spyware=dict(), @@ -457,6 +436,34 @@ def main(): # TODO(gfreeman) - remove this in the next role release. devicegroup=dict(), ), + default_values=dict( + source_zone=["any"], + source_ip=["any"], + source_user=["any"], + destination_zone=["any"], + destination_ip=["any"], + application=["any"], + service=["application-default"], + category=["any"], + action="allow", + log_start=False, + log_end=True, + rule_type="universal", + negate_source=False, + negate_destination=False, + disabled=False, + disable_server_response_inspection=False, + ), + preset_values=dict( + source_zone=["any"], + source_ip=["any"], + source_user=["any", "pre-logon", "known-user", "unknown"], + destination_zone=["any", "multicast"], + destination_ip=["any"], + application=["any"], + service=["application-default", "any"], + category=["any"], + ), ) module = AnsibleModule( diff --git a/plugins/modules/panos_template.py b/plugins/modules/panos_template.py index 89ce4670e..e93a34103 100644 --- a/plugins/modules/panos_template.py +++ b/plugins/modules/panos_template.py @@ -60,6 +60,10 @@ - The default vsys in case of a single vsys firewall. type: str default: vsys1 + mode: + description: + - Mode for template. + type: str """ EXAMPLES = """ @@ -117,6 +121,7 @@ def main(): description=dict(), devices=dict(type="list", elements="str"), default_vsys=dict(default="vsys1"), + mode=dict(), ), ) From be5525893ede40034d0a02ca23f7db5f97b97d41 Mon Sep 17 00:00:00 2001 From: Akira Yokochi Date: Mon, 16 Sep 2024 18:30:34 +0900 Subject: [PATCH 13/23] docs: update required python and ansible-core versions (#565) Co-authored-by: Alp Eren Kose --- docs/source/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index c848fff3a..e6532a4bc 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -20,8 +20,8 @@ Installation This collection has the following environment requirements: -* Python 3.8 or higher -* Ansible 2.9 or higher +* Python 3.9 or higher +* ansible-core 2.15 or higher Install the collection using `ansible-galaxy`: From 8092af3b64f135a2013d42130027d2740c89414d Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 16 Sep 2024 15:34:58 +0300 Subject: [PATCH 14/23] ci: Update docs to build with ansible-core 2.15 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69ce7bcb8..90747566e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -218,7 +218,7 @@ jobs: uses: Gr1N/setup-poetry@v8 - name: Add ansible-core - run: poetry add ansible-core^2.14 + run: poetry add ansible-core^2.15 - name: Add antsibull-docs run: poetry add antsibull-docs^1.11.0 From ddee190848278053e313d6da75c424facd88a1f1 Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 16 Sep 2024 15:53:51 +0300 Subject: [PATCH 15/23] docs(panos_security_rule): syntax update for lists in descriptions --- plugins/modules/panos_security_rule.py | 38 ++++++++++++++------------ 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/plugins/modules/panos_security_rule.py b/plugins/modules/panos_security_rule.py index b79b0f20c..44be8674a 100644 --- a/plugins/modules/panos_security_rule.py +++ b/plugins/modules/panos_security_rule.py @@ -24,13 +24,17 @@ module: panos_security_rule short_description: Manage security rule policy on PAN-OS devices or Panorama management console. description: > - - Security policies allow you to enforce rules and take action, and can be as - general or specific as needed. - - The policy rules are compared against the incoming traffic in sequence, and - because the first rule that matches the traffic is applied, the more specific - rules must precede the more general ones. - - Defaults in spec descriptions apply when I(state=present)/I(state=replaced), - or when creating a new resource with I(state=merged). + Following rules apply for security policies: + + - Security policies allow you to enforce rules and take action, and can be as + general or specific as needed. + + - The policy rules are compared against the incoming traffic in sequence, and + because the first rule that matches the traffic is applied, the more specific + rules must precede the more general ones. + + - Defaults in spec descriptions apply when I(state=present)/I(state=replaced), + or when creating a new resource with I(state=merged). author: - Ivan Bojer (@ivanbojer) - Robert Hagen (@stealthllama) @@ -78,18 +82,18 @@ type: list elements: str source_user: - description: > + description: - Use users to enforce policy for individual users or a group of users. - Defaults to I(["any"]). + Defaults to I(["any"]). type: list elements: str hip_profiles: - description: > + description: - If you are using GlobalProtect with host information profile (HIP) enabled, you can also base the policy on information collected by GlobalProtect. For example, the user access level can be determined HIP that notifies the firewall about the user's local configuration. - - NOTE: If I(state=present) or I(state=replaced), and you're running + - NOTE If I(state=present) or I(state=replaced), and you're running PAN-OS < 10.0.0, then this will have a default of I(["any"]). - If you are using PAN-OS >= 10.0.0, please do not use this parameter as it was removed from PAN-OS in 10.0.0. @@ -114,9 +118,9 @@ type: list elements: str application: - description: > + description: - List of applications, application groups, and/or application filters. - Defaults to I(["any"]). + Defaults to I(["any"]). type: list elements: str service: @@ -194,14 +198,14 @@ - Send 'ICMP Unreachable'. Used with 'deny', 'drop', and 'reset' actions. type: bool disable_server_response_inspection: - description: > + description: - Disables packet inspection from the server to the client. Useful under heavy server load conditions. - Defaults to I(false). + Defaults to I(false). type: bool group_profile: - description: > + description: - Security profile group that is already defined in the system. This property supersedes antivirus, - vulnerability, spyware, url_filtering, file_blocking, data_filtering, and wildfire_analysis properties. + vulnerability, spyware, url_filtering, file_blocking, data_filtering, and wildfire_analysis properties. type: str antivirus: description: From d0be81567251da6e47e6e85ebf635f84087c6589 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 16 Sep 2024 13:32:30 +0000 Subject: [PATCH 16/23] chore(release): 2.21.0 ## [2.21.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.20.0...v2.21.0) (2024-09-16) ### Features * Add additional error handling to some upgrade assurance modules ([#561](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/561)) ([c64cd79](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/c64cd7902b4e4a83c12a53036052a9c82070af1a)) ### Bug Fixes * **panos_security_rule:** state merged with existing values ([#570](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/570)) ([db6c32c](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/db6c32c7b9303f7b5b66f7169babca7f52f4ed87)) --- CHANGELOG.md | 12 ++++++++++++ docs/source/index.rst | 2 +- galaxy.yml | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 837bd6c99..9519410f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [2.21.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.20.0...v2.21.0) (2024-09-16) + + +### Features + +* Add additional error handling to some upgrade assurance modules ([#561](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/561)) ([c64cd79](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/c64cd7902b4e4a83c12a53036052a9c82070af1a)) + + +### Bug Fixes + +* **panos_security_rule:** state merged with existing values ([#570](https://github.com/PaloAltoNetworks/pan-os-ansible/issues/570)) ([db6c32c](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/db6c32c7b9303f7b5b66f7169babca7f52f4ed87)) + ## [2.20.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.19.1...v2.20.0) (2024-04-17) diff --git a/docs/source/index.rst b/docs/source/index.rst index e6532a4bc..a10200c46 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,7 +2,7 @@ Palo Alto Networks Ansible Collection ===================================== -Version: 2.20.0 +Version: 2.21.0 The Palo Alto Networks Ansible collection is a collection of modules that automate configuration and operational tasks on Palo Alto Networks Next diff --git a/galaxy.yml b/galaxy.yml index de3d4e5e7..0878ba38d 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -10,7 +10,7 @@ namespace: 'paloaltonetworks' name: 'panos' # The version of the collection. Must be compatible with semantic versioning -version: 2.20.0 +version: 2.21.0 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: 'README.md' From 38727087df51e2e547611053a3f5767e6e04400c Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 16 Sep 2024 16:55:59 +0300 Subject: [PATCH 17/23] fix: new release for failed ci From 75c6ce884886d1d83acdcfb50a12e877fb75f982 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 16 Sep 2024 14:23:14 +0000 Subject: [PATCH 18/23] chore(release): 2.21.1 ### [2.21.1](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.21.0...v2.21.1) (2024-09-16) ### Bug Fixes * new release for failed ci ([3872708](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/38727087df51e2e547611053a3f5767e6e04400c)) --- CHANGELOG.md | 7 +++++++ docs/source/index.rst | 2 +- galaxy.yml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9519410f2..52ead6062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### [2.21.1](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.21.0...v2.21.1) (2024-09-16) + + +### Bug Fixes + +* new release for failed ci ([3872708](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/38727087df51e2e547611053a3f5767e6e04400c)) + ## [2.21.0](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.20.0...v2.21.0) (2024-09-16) diff --git a/docs/source/index.rst b/docs/source/index.rst index a10200c46..de782abe4 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,7 +2,7 @@ Palo Alto Networks Ansible Collection ===================================== -Version: 2.21.0 +Version: 2.21.1 The Palo Alto Networks Ansible collection is a collection of modules that automate configuration and operational tasks on Palo Alto Networks Next diff --git a/galaxy.yml b/galaxy.yml index 0878ba38d..3a1b89ecc 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -10,7 +10,7 @@ namespace: 'paloaltonetworks' name: 'panos' # The version of the collection. Must be compatible with semantic versioning -version: 2.21.0 +version: 2.21.1 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: 'README.md' From 905b1eb76236d1560deb249bb7c048aa455721c2 Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Thu, 19 Sep 2024 12:54:07 +0300 Subject: [PATCH 19/23] fix: requirements.txt update python version and remove hashes --- requirements.txt | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index bb86da67f..a9ca3999f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,4 @@ -pan-os-python==1.8.0 ; python_version >= "3.8" and python_version < "4.0" \ - --hash=sha256:843972122ef4c5bfd17354070e3ada1285e243325f5e7cf7fd969150048becd4 \ - --hash=sha256:da9153fe4a961a43d36016851ab06df45a37ea8612ed36b3b5b528f8394f34f5 -pan-python==0.17.0 ; python_version >= "3.8" and python_version < "4.0" \ - --hash=sha256:9c074ea2f69a63996a6fefe8935d60dca61660e14715ac19d257ea9b1c41c6e2 \ - --hash=sha256:f4674e40763c46d5933244b3059a57884e4e28205ef6d0f9ce2dc2013e3db010 -xmltodict==0.12.0 ; python_version >= "3.8" and python_version < "4.0" \ - --hash=sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21 \ - --hash=sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051 -panos-upgrade-assurance==0.3.0 ; python_version >= "3.8" and python_version < "4.0" \ - --hash=sha256:0e5bb1a1f5bf317086fe118fb80f5d03c1aa1426c8ecdcda657983f392accc63 \ - --hash=sha256:88bfc470f9bfa09ed22c919f8328782868c649d44e97a06c8d29c32e0211c257 \ No newline at end of file +pan-os-python==1.8.0 ; python_version >= "3.9" and python_version < "4.0" +pan-python==0.17.0 ; python_version >= "3.9" and python_version < "4.0" +xmltodict==0.12.0 ; python_version >= "3.9" and python_version < "4.0" +panos-upgrade-assurance==0.3.0 ; python_version >= "3.9" and python_version < "4.0" From 620b4ef96a0a951e1ad57cb1683af635e94d6ccf Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Thu, 19 Sep 2024 13:07:16 +0300 Subject: [PATCH 20/23] chore: Makefile requirements export only main without hashes Include "--only=main --without-hashes" in poetry export command. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bb7262bb8..27be46b93 100644 --- a/Makefile +++ b/Makefile @@ -60,4 +60,4 @@ new-sanity: ## Sanity tests for Ansible v2.11 and above .PHONY: reqs reqs: ## Recreate the requirements.txt file - poetry export -f requirements.txt --output requirements.txt + poetry export -f requirements.txt --output requirements.txt --only=main --without-hashes From 0fdd990f62d1c9a82e0ecc319f12893eb418f707 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 19 Sep 2024 10:39:45 +0000 Subject: [PATCH 21/23] chore(release): 2.21.2 ### [2.21.2](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.21.1...v2.21.2) (2024-09-19) ### Bug Fixes * requirements.txt update python version and remove hashes ([905b1eb](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/905b1eb76236d1560deb249bb7c048aa455721c2)) --- CHANGELOG.md | 7 +++++++ docs/source/index.rst | 2 +- galaxy.yml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52ead6062..9677e6ede 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### [2.21.2](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.21.1...v2.21.2) (2024-09-19) + + +### Bug Fixes + +* requirements.txt update python version and remove hashes ([905b1eb](https://github.com/PaloAltoNetworks/pan-os-ansible/commit/905b1eb76236d1560deb249bb7c048aa455721c2)) + ### [2.21.1](https://github.com/PaloAltoNetworks/pan-os-ansible/compare/v2.21.0...v2.21.1) (2024-09-16) diff --git a/docs/source/index.rst b/docs/source/index.rst index de782abe4..326740995 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,7 +2,7 @@ Palo Alto Networks Ansible Collection ===================================== -Version: 2.21.1 +Version: 2.21.2 The Palo Alto Networks Ansible collection is a collection of modules that automate configuration and operational tasks on Palo Alto Networks Next diff --git a/galaxy.yml b/galaxy.yml index 3a1b89ecc..964d6271a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -10,7 +10,7 @@ namespace: 'paloaltonetworks' name: 'panos' # The version of the collection. Must be compatible with semantic versioning -version: 2.21.1 +version: 2.21.2 # The path to the Markdown (.md) readme file. This path is relative to the root of the collection readme: 'README.md' From 2375a93512b512ce1119319de94875276317e0b1 Mon Sep 17 00:00:00 2001 From: Alp Kose Date: Mon, 23 Sep 2024 12:17:18 +0300 Subject: [PATCH 22/23] test(integration): docs and setup minor update for integration tests --- tests/integration/README.md | 11 ++++++++--- tests/integration/inventory.example | 21 ++++++++++++--------- tests/integration/setup.yml | 1 + 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/integration/README.md b/tests/integration/README.md index 154785950..dfda7d864 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -9,6 +9,11 @@ Test playbooks assume that firewalls have the following initial configuration: - DHCP management configuration - a CA certificate with key named `local-ca` marked as `forward trust` +And panoramas to have: + +- `Test-DG` device group +- `Test-Template` template + Add firewalls to `firewall` group in inventory, Panorama instances to `panoramas` group (see `inventory.example`): @@ -28,13 +33,13 @@ booted, and save a copy of the config into `blank.xml` on the device. ### Run a single test ``` -ansible-playbook -i inventory run_single_test.yml -e test=test_panos_address_object +ansible-playbook -i inventory.ini run_single_test.yml -e test=test_panos_address_object ``` ### Run all tests ``` -ansible-playbook -i inventory run_all_tests.yml +ansible-playbook -i inventory.ini run_all_tests.yml ``` ## Writing a test @@ -140,4 +145,4 @@ template: '{{ template | default(omit) }}' ``` The built-in Ansible module [assert](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/assert_module.html) -is used to check results. \ No newline at end of file +is used to check results. diff --git a/tests/integration/inventory.example b/tests/integration/inventory.example index 3b8bdf4e4..e29b5ed33 100644 --- a/tests/integration/inventory.example +++ b/tests/integration/inventory.example @@ -1,15 +1,18 @@ [firewalls] -panos-10 ansible_host=192.168.55.10 +panos-10 ansible_host=192.168.55.10 ip_address=192.168.55.10 [panoramas] panorama-10 ip_address=192.168.55.5 [all:vars] -ansible_user=admin -ansible_password=something - -ansible_network_os=mrichardson03.panos.panos -ansible_connection=httpapi -ansible_httpapi_port=443 -ansible_httpapi_use_ssl=True -ansible_httpapi_validate_certs=False +username=admin +password=something + +# ansible_user=admin +# ansible_password=something + +# ansible_network_os=mrichardson03.panos.panos +# ansible_connection=httpapi +# ansible_httpapi_port=443 +# ansible_httpapi_use_ssl=True +# ansible_httpapi_validate_certs=False diff --git a/tests/integration/setup.yml b/tests/integration/setup.yml index 0383b514e..eb67fff9e 100644 --- a/tests/integration/setup.yml +++ b/tests/integration/setup.yml @@ -19,6 +19,7 @@ until: result is not failed and (result.stdout | from_json).response.result == 'yes' retries: 5 delay: 300 + when: inventory_hostname in groups['firewalls'] - name: Save copy of blank config paloaltonetworks.panos.panos_op: From 91d873da168b2613642ab54098a1a375833394cc Mon Sep 17 00:00:00 2001 From: Alp Eren Kose Date: Wed, 2 Oct 2024 15:40:53 +0300 Subject: [PATCH 23/23] ci: introduce Ansible CI (#585) --- .github/do-release.sh | 2 +- .github/workflows/_discover_python_ver.yml | 28 +++ .github/workflows/ci.yml | 103 ++++++++- .github/workflows/ee.yml | 246 +++++++++++++++++++++ .releaserc.json | 5 +- pyproject.toml | 6 + 6 files changed, 379 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/_discover_python_ver.yml create mode 100644 .github/workflows/ee.yml diff --git a/.github/do-release.sh b/.github/do-release.sh index 37156abef..b9e2daebc 100755 --- a/.github/do-release.sh +++ b/.github/do-release.sh @@ -2,4 +2,4 @@ ansible-galaxy collection build ansible-galaxy collection publish paloaltonetworks-panos-* --server release_galaxy -ansible-galaxy collection publish paloaltonetworks-panos-* --server automation_hub \ No newline at end of file +ansible-galaxy collection publish paloaltonetworks-panos-* --server automation_hub diff --git a/.github/workflows/_discover_python_ver.yml b/.github/workflows/_discover_python_ver.yml new file mode 100644 index 000000000..e8307eeb6 --- /dev/null +++ b/.github/workflows/_discover_python_ver.yml @@ -0,0 +1,28 @@ +name: (sub) Discover Python version + +defaults: + run: + shell: bash + +permissions: + contents: read + +on: + workflow_call: + outputs: + pyversion: + description: A discovered Python version + value: ${{ jobs.pyversion.outputs.pyversion }} + +jobs: + pyversion: + name: Discover minimum Python version + runs-on: ubuntu-latest + outputs: + pyversion: ${{ steps.pyversion.outputs.pyversion }} + steps: + - name: checkout code + uses: actions/checkout@v4 + - name: discover Python version + id: pyversion + uses: PaloAltoNetworks/pan-os-upgrade-assurance/.github/actions/discover_python_version@v0.3.1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90747566e..97334d6c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ on: env: NAMESPACE: paloaltonetworks COLLECTION_NAME: panos - PYTHON_VERSION: 3.8 jobs: @@ -109,9 +108,14 @@ jobs: cd .github/workflows python -m tox -- ../.. + pyversion: + name: Discover minimum Python version + uses: ./.github/workflows/_discover_python_ver.yml + format: name: Code Format Check runs-on: ubuntu-latest + needs: pyversion defaults: run: working-directory: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} @@ -123,7 +127,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ needs.pyversion.outputs.pyversion }} - name: Install Poetry uses: Gr1N/setup-poetry@v8 @@ -139,6 +143,10 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: [sanity, tox, lint, format] runs-on: ubuntu-latest + outputs: + new_release_published: ${{ steps.release.outputs.new_release_published }} + new_release_version: ${{ steps.release.outputs.new_release_version }} + new_release_git_tag: ${{ steps.release.outputs.new_release_git_tag }} steps: - name: Checkout @@ -192,12 +200,12 @@ jobs: docs: name: docs if: github.event_name == 'push' && github.ref == 'refs/heads/main' - needs: [release] + needs: [release, pyversion] runs-on: ubuntu-latest defaults: run: - working-directory: ./ansible_collections/paloaltonetworks/panos + working-directory: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} steps: # Just a note here: The Ansible stuff is apparently doing realpath @@ -207,12 +215,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - path: ./ansible_collections/paloaltonetworks/panos + path: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: ${{ needs.pyversion.outputs.pyversion }} - name: Install Poetry uses: Gr1N/setup-poetry@v8 @@ -247,8 +255,8 @@ jobs: run: | cd ../../../.. mv pan-os-ansible the_repo - mv the_repo/ansible_collections/paloaltonetworks/panos pan-os-ansible - mkdir -p pan-os-ansible/ansible_collections/paloaltonetworks/panos + mv the_repo/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} pan-os-ansible + mkdir -p pan-os-ansible/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@v4.4.3 @@ -257,3 +265,82 @@ jobs: branch: gh-pages folder: docs/html clean: true + + rc: + name: Check rc EE + runs-on: ubuntu-latest + needs: [sanity, tox, lint, format] + if: (github.event_name == 'push' && github.ref == 'refs/heads/develop') + outputs: + rc: ${{ steps.rc.outputs.new_release_published }} + new_release_version: ${{ steps.rc.outputs.new_release_version }} + + steps: + - name: checkout code + uses: actions/checkout@v4 + + - name: setup node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + + - name: install dependencies + run: | + npm install --save-dev semantic-release + npm install @semantic-release/commit-analyzer -D + npm install conventional-changelog-conventionalcommits -D + npm install @semantic-release/changelog -D + npm install @semantic-release/git -D + npm install @semantic-release/exec -D + # npx semantic-release + # npm ci + + - name: trick semantic check + id: rc + run: | + # Trick semantic-release into thinking we're not in a CI environment + OUTPUT="$(bash -c "unset GITHUB_ACTIONS && unset GITHUB_EVENT_NAME && npx semantic-release --dry-run --no-ci --branches '${GITHUB_REF#refs/heads/}'")" + # print output + echo "$OUTPUT" + # grep with semver regex - \K means to start matching from here in Perl regex + NEW_RELEASE_VERSION=$(echo "$OUTPUT" | grep -oP 'The next release version is \K(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?' || echo -n "") + echo "new_release_version=$NEW_RELEASE_VERSION" >> "$GITHUB_OUTPUT" + + if [ -z "$NEW_RELEASE_VERSION" ]; then + echo "new_release_published=false" >> "$GITHUB_OUTPUT" + else + echo "new_release_published=true" >> "$GITHUB_OUTPUT" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REF: ${{ github.ref }} + + # below does NOT work because semantic-release expects branch name in the config even in dry-run + # but we run rc check in non main branches + # - name: rc check + # id: rc + # uses: cycjimmy/semantic-release-action@v4 + # with: + # dry_run: true + # semantic_version: 17.1.1 + # extra_plugins: | + # conventional-changelog-conventionalcommits@^4.4.0 + # @semantic-release/changelog@^5.0.1 + # @semantic-release/git@^9.0.0 + # @semantic-release/exec@^5.0.00 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build_dev_ee: + name: dev_ee + needs: rc + if: needs.rc.outputs.rc == 'true' + uses: ./.github/workflows/ee.yml + + build_prod_ee: + name: release_ee + needs: release + uses: ./.github/workflows/ee.yml + with: + release: true + release_tag: ${{ needs.release.outputs.new_release_git_tag }} diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml new file mode 100644 index 000000000..753de7689 --- /dev/null +++ b/.github/workflows/ee.yml @@ -0,0 +1,246 @@ +name: Ansible EE Image + +on: + workflow_call: + inputs: + release: + description: Prepare EE for a release + type: boolean + default: false + release_tag: # tag starting with 'v' like v1.2.3 + description: Git tag for release to prepare EE + type: string + required: false + workflow_dispatch: + inputs: + release: + description: EE for a release or development + type: boolean + default: false + +env: + NAMESPACE: paloaltonetworks + COLLECTION_NAME: panos + +jobs: + + build_ee: + name: Ansible EE + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + # if event == push (same event from workflow_call) and inputs.release == true + # release_tag must be given as input + # checkout tag and prepare EE on tag + # elif event == workflow_dispatch and inputs.release == true + # workflow must be run on a tag + # checkout tag and prepare EE on tag + # else - could be workflow_call or workflow_dispatch with release false + # normal checkout - it will checkout whatever the workflow is run on + # prepare EE on branch + - name: check and findout the tag + id: tag + # outputs tag name as v1.2.3 and version as 1.2.3 + run: | + if [[ "${{ github.event_name }}" == "push" && + "${{ inputs.release }}" == "true" ]]; then + if [[ "${{ inputs.release_tag }}" != "v"* ]]; then + echo "release_tag (${{ inputs.release_tag }}) must be provided when workflow_call called with release." + exit 1 + fi + TAG_VERSION=$(echo "${{inputs.release_tag}}" | sed 's#v##') + echo "name=${{inputs.release_tag}}" >> $GITHUB_OUTPUT + echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT + echo "Ansible EE will be prepared for release ${{ inputs.release_tag }}" + elif [[ "${{ github.event_name }}" == "workflow_dispatch" && + "${{ inputs.release }}" == "true" ]]; then + if [[ "${GITHUB_REF}" != "refs/tags/v"* ]]; then + echo "workflow_dispatch must be run on a release tag when release is selected - run on ${GITHUB_REF}" + exit 1 + fi + TAG_NAME=$(echo "${GITHUB_REF}" | sed 's#refs/tags/##') + TAG_VERSION=$(echo "${TAG_NAME}" | sed 's#v##') + echo "name=$TAG_NAME" >> $GITHUB_OUTPUT + echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT + echo "Ansible EE will be prepared for release $TAG_NAME" + else + echo "Ansible EE will be prepared for branch ${GITHUB_REF#refs/heads/}" + fi + env: + GITHUB_REF: ${{ github.ref }} + + # checkout tag for releae otherwise checkout branch + - name: check out code + uses: actions/checkout@v4 + with: + # if tag is empty; github.ref else tag.outputs.name + ref: ${{ steps.tag.outputs.name == '' && github.ref || steps.tag.outputs.name }} + + - name: discover Python version + id: pyversion + uses: PaloAltoNetworks/pan-os-upgrade-assurance/.github/actions/discover_python_version@v0.3.1 + + - name: install Python + uses: actions/setup-python@v4 + with: + python-version: ${{ steps.pyversion.outputs.pyversion }} + cache: pip + + - name: install Poetry + uses: Gr1N/setup-poetry@v8 + + - name: prep Poetry venv + run: | + poetry env use ${{ steps.pyversion.outputs.pyversion }} + poetry lock + poetry install --with ansible-ee --without dev --no-root + + - name: set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # produce docker tags for semver if on a tag, otherwise take ref branch name + # latest tag is only produced for semver operating on a tag + - name: determine docker tags and labels + id: meta + uses: docker/metadata-action@v5 + with: + context: git # git - this ensures to reference the current git context instead of workflow context (context info ref/sha) + images: ghcr.io/paloaltonetworks/pan-os-ansible + tags: | + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} + type=ref,event=branch + type=ref,event=tag + + # take pan-os-ansible from galaxy for a release, but local build for develop + # ref - https://github.com/ansible-collections/community.dns/blob/main/.github/workflows/ee.yml#L96-L98 + - name: Build collection from development branch + run: | + ansible-galaxy collection build + if: ${{ inputs.release == false }} + + - name: create base EE file + run: | + cat > execution-environment.yml <=2.15.0rc2,<2.16 + ansible_runner: + package_pip: ansible-runner + system: | + git-core [platform:rpm] + python3.9-devel [platform:rpm compile] + libcurl-devel [platform:rpm compile] + sshpass [platform:rpm] + rsync [platform:rpm] + epel-release [platform:rpm] + unzip [platform:rpm] + galaxy: requirements.yml + python: requirements-ee.txt + + additional_build_steps: + append_base: + - RUN \$PYCMD -m pip install -U pip + append_final: + # SymLink `python` -> `python3.9` + - RUN alternatives --install /usr/bin/python python /usr/bin/python3.9 39 + + EOF + + - name: append build files to EE for development + run: | + COLLECTION_FILENAME="$(ls "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)" + + # append to existing EE file + cat >> execution-environment.yml < requirements.yml < requirements.yml < requirements-ee.txt < Posted by [semantic-release](https://github.com/semantic-release/semantic-release) bot" + "successComment": ":tada: This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:\n\nThe release is available on [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/paloaltonetworks/panos) and [GitHub release](https://github.com/PaloAltoNetworks/pan-os-ansible/releases)\n\n> Posted by [semantic-release](https://github.com/semantic-release/semantic-release) bot", + "failTitle": false } ] ], "preset": "conventionalcommits" -} \ No newline at end of file +} diff --git a/pyproject.toml b/pyproject.toml index 3d51a63a1..8df7c6fb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,12 @@ chardet = "3.0.4" idna = "2.8" requests = "^2.22.0" +[tool.poetry.group.ansible-ee] +optional = true + +[tool.poetry.group.ansible-ee.dependencies] +ansible-builder = "^3.0.0" + [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api" \ No newline at end of file