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