Skip to content

Commit

Permalink
[ignore] Change Documentation and attributes name. Add function to co…
Browse files Browse the repository at this point in the history
…nvert pyhton list of dict into equivalent NDO API format.
  • Loading branch information
gmicol committed Nov 25, 2024
1 parent c2610a3 commit c45f5cf
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 72 deletions.
16 changes: 16 additions & 0 deletions plugins/module_utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,19 @@
"network_control": "cos7",
"unspecified": "cos8",
}

DSCP_KEYS_FORMAT_MAP = {
"dscp_from": ["dscpFrom", TARGET_DSCP_MAP],
"dscp_to": ["dscpTo", TARGET_DSCP_MAP],
"dscp_target": ["dscpTarget", TARGET_DSCP_MAP],
"target_cos": ["targetCos", TARGET_COS_MAP],
"qos_priority": "priority",
}

DOT1P_KEYS_FORMAT_MAP = {
"dot1p_from": ["dot1pFrom", TARGET_COS_MAP],
"dot1p_to": ["dot1pTo", TARGET_COS_MAP],
"dscp_target": ["dscpTarget", TARGET_DSCP_MAP],
"target_cos": ["targetCos", TARGET_COS_MAP],
"qos_priority": "priority",
}
24 changes: 24 additions & 0 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,27 @@ def generate_api_endpoint(path, **kwargs):
# return full_url

return path if not kwargs else "{0}?{1}".format(path, "&".join(["{0}={1}".format(key, value) for key, value in kwargs.items()]))


def format_list_dict(list_dict, keys_map):
"""
Convert an Python list of dictionaries into its equivalent NDO API format.
:param list_dict: The Python list of dictionaries to format. -> List[Dict]
:param keys_map: the mapping from the Ansible argument's keys to NDO API keys. Can also include the map between values -> Dict
:return: The formated dictionary. -> Dict
"""
if list_dict:
def format_dict(d):
formated_dict = {}
if d:
for key, value in keys_map.items():
# keys_map can have values of type list including the API key string and the map conversion for values\
if isinstance(value, list):
formated_dict[value[0]] = value[1].get(list_dict.get(key))
else:
formated_dict[value] = list_dict.get(key)
return formated_dict

formated_list = [format_dict(d) for d in list_dict]
return formated_list
110 changes: 38 additions & 72 deletions plugins/modules/ndo_tenant_custom_qos_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
module: ndo_tenant_custom_qos_policy
short_description: Manage Custom QoS Policies in Tenant Policy Templates on Cisco Nexus Dashboard Orchestrator (NDO).
description:
- Manage Custom QoS Policies in Tenant Policy Templates on Cisco Nexus Dashboard Orchestrator (NDO).
- Manage Custom Quality of Service (QoS) Policies in Tenant Policy Templates on Cisco Nexus Dashboard Orchestrator (NDO).
- This module is only supported on ND v3.1 (NDO v4.3) and later.
author:
- Gaspard Micol (@gmicol)
Expand Down Expand Up @@ -107,7 +107,7 @@
- unspecified
- voice_admit
aliases: [ to ]
target:
dscp_target:
description:
- The DSCP target value.
type: str
Expand Down Expand Up @@ -135,18 +135,18 @@
- expedited_forwarding
- unspecified
- voice_admit
aliases: [ dscp_target ]
aliases: [ target ]
target_cos:
description:
- The target CoS to be driven based on the range of input values of DSCP coming into the fabric.
type: str
choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, unspecified ]
priority:
qos_priority:
description:
- The desired QoS class level to be used.
type: str
choices: [ level1, level2, level3, level4, level5, level6, unspecified ]
aliases: [ prio ]
aliases: [ priority, prio ]
cos_mappings:
description:
- The CoS mappings of the Custom QoS Policy.
Expand All @@ -165,9 +165,9 @@
type: str
choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, unspecified ]
aliases: [ to ]
target:
dscp_target:
description:
- The Dot1P target value.
- The DSCP target value.
type: str
choices:
- af11
Expand All @@ -193,18 +193,18 @@
- expedited_forwarding
- unspecified
- voice_admit
aliases: [ dot1p_target ]
aliases: [ target ]
target_cos:
description:
- The target CoS to be driven based on the range of input values of Dot1P coming into the fabric.
type: str
choices: [ background, best_effort, excellent_effort, critical_applications, video, voice, internetwork_control, network_control, unspecified ]
priority:
qos_priority:
description:
- The desired QoS class level to be used.
type: str
choices: [ level1, level2, level3, level4, level5, level6, unspecified ]
aliases: [ prio ]
aliases: [ priority, prio ]
state:
description:
- Use C(absent) for removing.
Expand Down Expand Up @@ -232,15 +232,15 @@
dscp_mappings:
- dscp_from: af11
dscp_to: af12
target: af11
dscp_target: af11
target_cos: background
priority: level1
qos_priority: level1
cos_mappings:
- dot1p_from: background
dot1p_to: best_effort
target: af11
target_cos: background
priority: level1
qos_priority: level1
state: present
register: custom_qos_policy_1
Expand Down Expand Up @@ -309,7 +309,13 @@
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.cisco.mso.plugins.module_utils.mso import MSOModule, mso_argument_spec
from ansible_collections.cisco.mso.plugins.module_utils.template import MSOTemplate, KVPair
from ansible_collections.cisco.mso.plugins.module_utils.constants import TARGET_DSCP_MAP, TARGET_COS_MAP
from ansible_collections.cisco.mso.plugins.module_utils.utils import format_list_dict
from ansible_collections.cisco.mso.plugins.module_utils.constants import (
TARGET_DSCP_MAP,
TARGET_COS_MAP,
DSCP_KEYS_FORMAT_MAP,
DOT1P_KEYS_FORMAT_MAP,
)


def main():
Expand All @@ -325,12 +331,12 @@ def main():
options=dict(
dscp_from=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["from"]),
dscp_to=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["to"]),
target=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["dscp_target"]),
dscp_target=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["target"]),
target_cos=dict(type="str", choices=list(TARGET_COS_MAP.keys())),
priority=dict(
qos_priority=dict(
type="str",
choices=["level1", "level2", "level3", "level4", "level5", "level6", "unspecified"],
aliases=["prio"],
aliases=["priority", "prio"],
),
),
),
Expand All @@ -340,12 +346,12 @@ def main():
options=dict(
dot1p_from=dict(type="str", choices=list(TARGET_COS_MAP.keys()), aliases=["from"]),
dot1p_to=dict(type="str", choices=list(TARGET_COS_MAP.keys()), aliases=["to"]),
target=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["dot1p_target"]),
dscp_target=dict(type="str", choices=list(TARGET_DSCP_MAP.keys()), aliases=["target"]),
target_cos=dict(type="str", choices=list(TARGET_COS_MAP.keys())),
priority=dict(
qos_priority=dict(
type="str",
choices=["level1", "level2", "level3", "level4", "level5", "level6", "unspecified"],
aliases=["prio"],
aliases=["priority", "prio"],
),
),
),
Expand All @@ -367,8 +373,8 @@ def main():
name = module.params.get("name")
uuid = module.params.get("uuid")
description = module.params.get("description")
dscp_mappings = module.params.get("dscp_mappings")
cos_mappings = module.params.get("cos_mappings")
dscp_mappings = format_list_dict(module.params.get("dscp_mappings"), DSCP_KEYS_FORMAT_MAP)
cos_mappings = format_list_dict(module.params.get("cos_mappings"), DOT1P_KEYS_FORMAT_MAP)
state = module.params.get("state")

template_object = MSOTemplate(mso, "tenant", template)
Expand Down Expand Up @@ -406,38 +412,16 @@ def main():
ops.append(dict(op="replace", path=custom_qos_policy_attrs_path + "/description", value=description))
proposed_payload["description"] = description

if dscp_mappings:
dscp_mappings = [
dict(
dscpFrom=TARGET_DSCP_MAP.get(dscp.get("dscp_from")),
dscpTo=TARGET_DSCP_MAP.get(dscp.get("dscp_to")),
dscpTarget=TARGET_DSCP_MAP.get(dscp.get("target")),
targetCos=TARGET_COS_MAP.get(dscp.get("target_cos")),
priority=dscp.get("priority"),
)
for dscp in dscp_mappings
]
if mso.existing.get("dscpMappings") != dscp_mappings:
ops.append(dict(op="replace", path=custom_qos_policy_attrs_path + "/dscpMappings", value=dscp_mappings))
proposed_payload["dscpMappings"] = dscp_mappings
if dscp_mappings and mso.existing.get("dscpMappings") != dscp_mappings:
ops.append(dict(op="replace", path=custom_qos_policy_attrs_path + "/dscpMappings", value=dscp_mappings))
proposed_payload["dscpMappings"] = dscp_mappings
elif dscp_mappings == [] and mso.existing.get("dscpMappings"):
ops.append(dict(op="remove", path=custom_qos_policy_attrs_path + "/dscpMappings"))
proposed_payload["dscpMappings"] = []

if cos_mappings:
cos_mappings = [
dict(
dot1pFrom=TARGET_COS_MAP.get(cos.get("dot1p_from")),
dot1pTo=TARGET_COS_MAP.get(cos.get("dot1p_to")),
dscpTarget=TARGET_DSCP_MAP.get(cos.get("target")),
targetCos=TARGET_COS_MAP.get(cos.get("target_cos")),
priority=cos.get("priority"),
)
for cos in cos_mappings
]
if mso.existing.get("cosMappings") != cos_mappings:
ops.append(dict(op="replace", path=custom_qos_policy_attrs_path + "/cosMappings", value=cos_mappings))
proposed_payload["cosMappings"] = cos_mappings
if cos_mappings and mso.existing.get("cosMappings") != cos_mappings:
ops.append(dict(op="replace", path=custom_qos_policy_attrs_path + "/cosMappings", value=cos_mappings))
proposed_payload["cosMappings"] = cos_mappings
elif cos_mappings == [] and mso.existing.get("cosMappings"):
ops.append(dict(op="remove", path=custom_qos_policy_attrs_path + "/cosMappings"))
proposed_payload["cosMappings"] = []
Expand All @@ -447,38 +431,20 @@ def main():
payload = dict(
name=name,
description=description,
dscp_mappings=[
dict(
dscpFrom=TARGET_DSCP_MAP.get(dscp.get("dscp_from")),
dscpTo=TARGET_DSCP_MAP.get(dscp.get("dscp_to")),
dscpTarget=TARGET_DSCP_MAP.get(dscp.get("target")),
targetCos=TARGET_COS_MAP.get(dscp.get("target_cos")),
priority=dscp.get("priority"),
)
for dscp in dscp_mappings
],
cos_mappings=[
dict(
dot1pFrom=TARGET_COS_MAP.get(cos.get("dot1p_from")),
dot1pTo=TARGET_COS_MAP.get(cos.get("dot1p_to")),
dscpTarget=TARGET_DSCP_MAP.get(cos.get("target")),
targetCos=TARGET_COS_MAP.get(cos.get("target_cos")),
priority=cos.get("priority"),
)
for cos in cos_mappings
],
dscpMappings=dscp_mappings,
cosMappings=cos_mappings,
)

mso.sanitize(payload)
ops.append(dict(op="add", path="/tenantPolicyTemplate/template/mldSnoopPolicies/-", value=mso.sent))
ops.append(dict(op="add", path="/tenantPolicyTemplate/template/qosPolicies/-", value=mso.sent))

elif state == "absent":
if mso.existing:
ops.append(dict(op="remove", path=custom_qos_policy_attrs_path))

if not module.check_mode and ops:
response_object = mso.request(template_object.template_path, method="PATCH", data=ops)
custom_qos_policies = response_object.get("tenantPolicyTemplate", {}).get("template", {}).get("mldSnoopPolicies", [])
custom_qos_policies = response_object.get("tenantPolicyTemplate", {}).get("template", {}).get("qosPolicies", [])
match = template_object.get_object_by_key_value_pairs(
object_description, custom_qos_policies, [KVPair("uuid", uuid) if uuid else KVPair("name", name)]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@
- query_one_uuid is not changed
- query_one_uuid.current.name == "ansible_test_custom_qos_policy_2"
- query_all is not changed
- query_all.current.0.name == "ansible_test_custom_qos_policy_changed"
- query_all.current.1.name == "ansible_test_custom_qos_policy_2"
- query_all.current | length == 2

# DELETE
Expand Down

0 comments on commit c45f5cf

Please sign in to comment.