Skip to content

Commit

Permalink
[ignore] Modify Documentation, required attributes in ndo_virtual_por…
Browse files Browse the repository at this point in the history
…t_channel_interface module. enhance format_interface_descriptions function to format range of interface IDs.
  • Loading branch information
gmicol committed Dec 10, 2024
1 parent adfc6da commit 228cb4f
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 43 deletions.
40 changes: 29 additions & 11 deletions plugins/module_utils/mso.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,20 +318,38 @@ def write_file(module, url, dest, content, resp, tmpsrc=None):
os.remove(tmpsrc)


def format_interface_descriptions(interface_descriptions, node=None):
def format_interface_descriptions(mso, interface_descriptions, node=None):
if interface_descriptions:
formated_interface_descriptions = [
{
"nodeID": node if node is not None else interface_description.get("node"),
"interfaceID": interface_description.get("interface_id", interface_description.get("interfaceID")),
"description": interface_description.get("description"),
}

def format_range_interfaces(format_dict):
ids = format_dict.get("interfaceID")
if re.fullmatch(r"((\d+/)+\d+$)", ids):
yield format_dict
elif re.fullmatch(r"((\d+/)+\d+-\d+$)", ids):
slots = ids.rsplit("/", 1)[0]
range_start, range_stop = ids.rsplit("/", 1)[1].split("-")
if int(range_stop) > int(range_start):
for x in range(int(range_start), int(range_stop) + 1):
copy_format_dict = deepcopy(format_dict)
copy_format_dict.update(interfaceID="{0}/{1}".format(slots, x))
yield copy_format_dict
else:
mso.fail_json(msg="Range start is greater than or equal to range stop for range of IDs '{0}'".format(ids))
else:
mso.fail_json(msg="Incorrect interface ID or range of IDs. Got '{0}'".format(ids))

return [
item
for interface_description in interface_descriptions
for item in format_range_interfaces(
{
"nodeID": node if node is not None else interface_description.get("node"),
"interfaceID": interface_description.get("interface_id", interface_description.get("interfaceID")),
"description": interface_description.get("description"),
}
)
]
else:
formated_interface_descriptions = []

return formated_interface_descriptions
return []


class MSOModule(object):
Expand Down
46 changes: 28 additions & 18 deletions plugins/modules/ndo_virtual_port_channel_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@
description:
- The name of the Interface Policy Group.
type: str
required: true
template:
description:
- The name of the template in which the Interface Policy Group has been created.
type: str
required: true
aliases: [ policy, interface_policy, interface_setting ]
interface_descriptions:
description:
Expand All @@ -104,10 +106,13 @@
description:
- The node ID.
type: str
required: true
interface_id:
description:
- The interface ID.
- The interface ID or a range of IDs.
- Using a range of interface IDs will apply the same O(description) for every ID in range.
type: str
required: true
description:
description:
- The description of the interface.
Expand All @@ -121,6 +126,14 @@
choices: [ absent, query, present ]
default: query
extends_documentation_fragment: cisco.mso.modules
notes:
- The O(template) must exist before using this module in your playbook.
Use M(cisco.mso.ndo_template) to create the Fabric Resource template.
- The O(interface_policy_group) must exist before using this module in your playbook.
Use M(cisco.mso.ndo_interface_setting) to create the Interface Policy Group of type Port Channel.
seealso:
- module: cisco.mso.ndo_template
- module: cisco.mso.ndo_interface_setting
"""

EXAMPLES = r"""
Expand All @@ -145,16 +158,13 @@
interface_descriptions:
- node: 101
interface_id: 1/1
description: My first Ansible Interface for first node
description: My single Ansible Interface for first node
- node: 101
interface_id: 1/10
description: My second Ansible Interface for first node
- node: 101
interface_id: 1/11
description: My third Ansible Interface for first node
interface_id: 1/10-11
description: My group of Ansible Interface for first node
- node: 102
interface_id: 1/2
description: My first Ansible Interface for second node
description: My single Ansible Interface for second node
state: present
register: virtual_port_channel_interface_1
Expand All @@ -176,7 +186,7 @@
template: ansible_fabric_resource_template
name: ansible_virtual_port_channel_interface_changed
state: query
register: query_one
register: query_name
- name: Query a Virtual Port Channel Interface with UUID
cisco.mso.ndo_virtual_port_channel_interface:
Expand All @@ -186,7 +196,7 @@
template: ansible_fabric_resource_template
uuid: "{{ virtual_port_channel_interface_1.current.uuid }}"
state: query
register: query_one_uuid
register: query_uuid
- name: Query all Virtual Port Channel Interfaces in a Fabric Resource Template
cisco.mso.ndo_virtual_port_channel_interface:
Expand Down Expand Up @@ -246,8 +256,8 @@ def main():
interface_policy_group=dict(
type="dict",
options=dict(
name=dict(type="str"),
template=dict(type="str"),
name=dict(type="str", required=True),
template=dict(type="str", required=True),
),
aliases=["policy", "interface_policy", "interface_setting"],
),
Expand All @@ -256,8 +266,8 @@ def main():
type="list",
elements="dict",
options=dict(
node=dict(type="str"),
interface_id=dict(type="str"),
node=dict(type="str", required=True),
interface_id=dict(type="str", required=True),
description=dict(type="str"),
),
),
Expand All @@ -282,10 +292,10 @@ def main():
node_1 = module.params.get("node_1")
node_2 = module.params.get("node_2")
interfaces_node_1 = module.params.get("interfaces_node_1")
if interfaces_node_1:
if isinstance(interfaces_node_1, list):
interfaces_node_1 = ",".join(interfaces_node_1)
interfaces_node_2 = module.params.get("interfaces_node_2")
if interfaces_node_2:
if isinstance(interfaces_node_2, list):
interfaces_node_2 = ",".join(interfaces_node_2)
interface_policy_group = module.params.get("interface_policy_group")
interface_policy_group_uuid = module.params.get("interface_policy_group_uuid")
Expand Down Expand Up @@ -358,7 +368,7 @@ def main():
proposed_payload["node2Details"]["memberInterfaces"] = interfaces_node_2

if interface_descriptions:
interface_descriptions = format_interface_descriptions(interface_descriptions)
interface_descriptions = format_interface_descriptions(mso, interface_descriptions)
if interface_descriptions != mso.existing.get("interfaceDescriptions"):
ops.append(dict(op="replace", path="{0}/{1}/interfaceDescriptions".format(path, match.index), value=interface_descriptions))
proposed_payload["interfaceDescriptions"] = interface_descriptions
Expand All @@ -380,7 +390,7 @@ def main():
},
"policy": interface_policy_group_uuid,
"description": description,
"interfaceDescriptions": format_interface_descriptions(interface_descriptions),
"interfaceDescriptions": format_interface_descriptions(mso, interface_descriptions),
}
mso.sanitize(payload)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@
<<: *template_absent
state: present

- name: Ensure fabric policy template does not exist
cisco.mso.ndo_template: &template_policy_absent
<<: *mso_info
name: ansible_fabric_policy_template
template_type: fabric_policy
state: absent

- name: Create fabric resource template
cisco.mso.ndo_template:
<<: *template_policy_absent
state: present

- name: Create two Interface policy groups of type port channel
cisco.mso.ndo_interface_setting:
<<: *mso_info
template: ansible_fabric_policy_template
name: "{{ item }}"
interface_type: port_channel
state: present
loop:
- ansible_test_interface_policy_group_port_channel
- ansible_test_interface_policy_group_port_channel_2

# CREATE

- name: Create a new virtual port channel interface (check_mode)
Expand All @@ -71,8 +94,8 @@
interfaces_1: 1/1
interfaces_2: 1/1
interface_policy_group:
name: Gaspard_Interface_setting_test
template: Gaspard_FP_3.2_test
name: ansible_test_interface_policy_group_port_channel
template: ansible_fabric_policy_template
interface_descriptions:
- node: 101
interface_id: 1/1
Expand Down Expand Up @@ -200,8 +223,8 @@
cisco.mso.ndo_virtual_port_channel_interface: &update_virtual_port_channel_interface_policy_group
<<: *update_virtual_port_channel_interface_description
interface_policy_group:
name: Gaspard_Interface_setting_test_2
template: Gaspard_FP_3.2_test
name: ansible_test_interface_policy_group_port_channel_2
template: ansible_fabric_policy_template
register: nm_update_virtual_port_channel_interface_policy_group

- name: Update a virtual port channel interface members for first node
Expand Down Expand Up @@ -249,11 +272,8 @@
interfaces_1: 1/1-2
interface_descriptions:
- node: 103
interface_id: 1/1
description: new first Ansible interface test for first node
- node: 103
interface_id: 1/2
description: new second Ansible interface test for first node
interface_id: 1/1-2
description: New group of Ansible interfaces test for first node
register: nm_delete_virtual_port_channel_interface_member

- name: Assert virtual port channel interface update tasks
Expand Down Expand Up @@ -320,10 +340,10 @@
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions | length == 2
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.0.nodeID == "103"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.0.interfaceID == "1/1"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.0.description == "new first Ansible interface test for first node"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.0.description == "New group of Ansible interfaces test for first node"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.1.nodeID == "103"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.1.interfaceID == "1/2"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.1.description == "new second Ansible interface test for first node"
- nm_delete_virtual_port_channel_interface_member.current.interfaceDescriptions.1.description == "New group of Ansible interfaces test for first node"

# QUERY

Expand All @@ -337,8 +357,8 @@
interfaces_1: 1/1
interfaces_2: 1/1
interface_policy_group:
name: Gaspard_Interface_setting_test
template: Gaspard_FP_3.2_test
name: ansible_test_interface_policy_group_port_channel_2
template: ansible_fabric_policy_template
state: present

- name: Query a virtual port channel interface with template_name
Expand All @@ -364,6 +384,80 @@
- query_all.current.0.name == "ansible_virtual_port_channel_interface_changed"
- query_all.current.1.name == "ansible_virtual_port_channel_interface_2"

# ERRORS

- name: Create a new virtual port channel interface without valid range IDs in interface descriptions
cisco.mso.ndo_virtual_port_channel_interface:
<<: *mso_info
template: ansible_fabric_resource_template
virtual_port_channel_interface: ansible_port_channel_interface_error
node_1: 101
node_2: 102
interfaces_1: 1/1-2
interfaces_2: 1/1
interface_policy_group:
name: ansible_test_interface_policy_group_port_channel
template: ansible_fabric_policy_template
interface_descriptions:
- node: 101
interface_id: 1/2-1
description: Incorrect Range starting and ending ID values
state: present
ignore_errors: true
register: nm_create_invalid_range

- name: Create a new virtual port channel interface without valid IDs values in interface descriptions
cisco.mso.ndo_virtual_port_channel_interface:
<<: *mso_info
template: ansible_fabric_resource_template
virtual_port_channel_interface: ansible_port_channel_interface_error
node_1: 101
node_2: 102
interfaces_1: 1/1-2
interfaces_2: 1/1
interface_policy_group:
name: ansible_test_interface_policy_group_port_channel
template: ansible_fabric_policy_template
interface_descriptions:
- node: 101
interface_id: invalid_id
description: Invalid ID value
state: present
ignore_errors: true
register: nm_create_invalid_id

- name: delete first interface policy group of type port channel
cisco.mso.ndo_interface_setting:
<<: *mso_info
template: ansible_fabric_policy_template
name: ansible_test_interface_policy_group_port_channel
interface_type: port_channel
state: absent

- name: Create a new virtual port channel interface without an existing interface policy group
cisco.mso.ndo_virtual_port_channel_interface:
<<: *mso_info
template: ansible_fabric_resource_template
virtual_port_channel_interface: ansible_port_channel_interface_error
node_1: 101
node_2: 102
interfaces_1: 1/1-2
interfaces_2: 1/1
interface_policy_group:
name: ansible_test_interface_policy_group_port_channel
template: ansible_fabric_policy_template
state: present
ignore_errors: true
register: nm_create_without_existing_policy

- name: Assert virtual port channel interface errors tasks
assert:
that:
- nm_create_missing_node.msg == "Missing parameter 'node' for creating a Port Channel Interface"
- nm_create_invalid_range.msg == "Range start is greater than or equal to range stop for range of IDs '1/2-1'"
- nm_create_invalid_range.msg == "Incorrect interface ID or range of IDs. Got 'invalid_id'"
- nm_create_without_existing_policy.msg == "Provided Interface Policy Groups with '[KVPair(key='name', value='ansible_test_interface_policy_group_port_channel')]' not matching existing object(s): ansible_test_interface_policy_group_port_channel_2"

# DELETE

- name: Delete a virtual port channel interface (check_mode)
Expand Down Expand Up @@ -395,9 +489,40 @@
- nm_delete_virtual_port_channel_interface_again is not changed
- nm_delete_virtual_port_channel_interface_again.previous == {}
- nm_delete_virtual_port_channel_interface_again.current == {}


# ERRORS AND NO PORT CHANNEL INTERFACES FOUND

- name: Query all virtual port channel interfaces in the template when all are deleted
cisco.mso.ndo_virtual_port_channel_interface:
<<: *mso_info
template: ansible_fabric_resource_template
state: query
register: query_all_none

- name: Update with non-existing UUID
cisco.mso.ndo_virtual_port_channel_interface:
<<: *mso_info
template: ansible_fabric_resource_template
uuid: non-existing-uuid
state: present
ignore_errors: true
register: update_non_existing_uuid

- name: Assert no Virtual Port Channel Interface found
assert:
that:
- query_all_none is not changed
- query_all_none.current == {}
- update_non_existing_uuid is failed
- update_non_existing_uuid.msg == "Virtual Port Channel Interface with the UUID{{":"}} 'non-existing-uuid' not found"

# CLEANUP TEMPLATE

- name: Ensure templates do not exist
- name: Ensure fabric resource template does not exist
cisco.mso.ndo_template:
<<: *template_absent

- name: Ensure fabric policy template does not exist
cisco.mso.ndo_template:
<<: *template_policy_absent

0 comments on commit 228cb4f

Please sign in to comment.