diff --git a/plugins/modules/ndo_ipsla_monitoring_policy.py b/plugins/modules/ndo_ipsla_monitoring_policy.py new file mode 100644 index 00000000..22baa7cb --- /dev/null +++ b/plugins/modules/ndo_ipsla_monitoring_policy.py @@ -0,0 +1,433 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Shreyas Srish (@shrsr) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", +} + +DOCUMENTATION = r""" +--- +module: ndo_ipsla_monitoring_policy +short_description: Manage IPSLA Monitoring Policies on Cisco Nexus Dashboard Orchestrator (NDO). +description: +- Manage IPSLA Monitoring Policies on Cisco Nexus Dashboard Orchestrator (NDO). +- This module is only supported on ND v3.1 (NDO v4.3) and later. +author: +- Shreyas Srish (@shrsr) +options: + template: + description: + - The name of the template. + - The template must be a tenant template. + type: str + required: true + ipsla_monitoring_policy: + description: + - The name of the IPSLA Monitoring Policy. + type: str + aliases: [ name ] + ipsla_monitoring_policy_uuid: + description: + - The uuid of the IPSLA Monitoring Policy. + - This parameter is required when the O(ipsla_monitoring_policy) needs to be updated. + type: str + aliases: [ uuid ] + sla_type: + description: + - The type of SLA. + type: str + choices: [ http, tcp, icmp, l2ping ] + default: icmp + destination_port: + description: + - The port used for SLA. + type: int + default: 0 + http_version: + description: + - The HTTP version used for SLA. + type: str + choices: [ HTTP10, HTTP11 ] + default: HTTP10 + http_uri: + description: + - The URI used for HTTP SLA. + type: str + sla_frequency: + description: + - The frequency of SLA monitoring. + type: int + default: 60 + detect_multiplier: + description: + - The detection multiplier for SLA. + type: int + default: 3 + req_data_size: + description: + - The size of the request data. + type: int + default: 28 + type_of_service: + description: + - The IPv4 Type of Service. + type: int + default: 0 + operation_timeout: + description: + - The operation_timeout for SLA. + type: int + default: 900 + threshold: + description: + - The threshold for SLA. + type: int + default: 900 + ipv6_traffic_class: + description: + - The IPv6 Traffic Class. + type: int + default: 0 + state: + description: + - Use C(absent) for removing. + - Use C(query) for listing an object or multiple objects. + - Use C(present) for creating or updating. + type: str + choices: [ absent, query, present ] + default: query +extends_documentation_fragment: cisco.mso.modules +""" + +EXAMPLES = r""" +- name: Create a new IPSLA monitoring policy + cisco.mso.ndo_ipsla_monitoring_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy + sla_type: http + http_version: HTTP11 + http_uri: /test + sla_frequency: 120 + detect_multiplier: 5 + req_data_size: 64 + type_of_service: 16 + operation_timeout: 1000 + threshold: 1000 + ipv6_traffic_class: 32 + state: present + +- name: Query an IPSLA monitoring policy with template_name + cisco.mso.ndo_ipsla_monitoring_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy + state: query + register: query_one + +- name: Query all IPSLA monitoring policies in the template + cisco.mso.ndo_ipsla_monitoring_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + state: query + register: query_all + +- name: Delete an IPSLA monitoring policy + cisco.mso.ndo_ipsla_monitoring_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy + state: absent +""" + +RETURN = r""" +""" + +import copy +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, +) + + +def main(): + argument_spec = mso_argument_spec() + argument_spec.update( + template=dict(type="str", required=True), + ipsla_monitoring_policy=dict(type="str", aliases=["name"]), + ipsla_monitoring_policy_uuid=dict(type="str", aliases=["uuid"]), + sla_type=dict(type="str", choices=["http", "tcp", "icmp", "l2ping"], default="icmp"), + destination_port=dict(type="int", default=0), + http_version=dict(type="str", choices=["HTTP10", "HTTP11"], default="HTTP10"), + http_uri=dict(type="str"), + sla_frequency=dict(type="int", default=60), + detect_multiplier=dict(type="int", default=3), + req_data_size=dict(type="int", default=28), + type_of_service=dict(type="int", default=0), + operation_timeout=dict(type="int", default=900), + threshold=dict(type="int", default=900), + ipv6_traffic_class=dict(type="int", default=0), + state=dict(type="str", default="query", choices=["absent", "query", "present"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["ipsla_monitoring_policy"]], + ["state", "present", ["ipsla_monitoring_policy"]], + ], + ) + + mso = MSOModule(module) + + template = module.params.get("template") + ipsla_monitoring_policy = module.params.get("ipsla_monitoring_policy") + ipsla_monitoring_policy_uuid = module.params.get("ipsla_monitoring_policy_uuid") + sla_type = module.params.get("sla_type") + destination_port = module.params.get("destination_port") + http_version = module.params.get("http_version") + http_uri = module.params.get("http_uri") + sla_frequency = module.params.get("sla_frequency") + detect_multiplier = module.params.get("detect_multiplier") + req_data_size = module.params.get("req_data_size") + type_of_service = module.params.get("type_of_service") + operation_timeout = module.params.get("operation_timeout") + threshold = module.params.get("threshold") + ipv6_traffic_class = module.params.get("ipv6_traffic_class") + state = module.params.get("state") + + if sla_frequency not in range(1, 301): + mso.fail_json(msg="Invalid value provided for sla_frequency: {0}; it must be in the range 1 - 300".format(sla_frequency)) + + if detect_multiplier not in range(1, 101): + mso.fail_json(msg="Invalid value provided for detect_multiplier: {0}; it must be in the range 1 - 100".format(detect_multiplier)) + + if req_data_size not in range(0, 17514): + mso.fail_json(msg="Invalid value provided for req_data_size: {0}; it must be in the range 0 - 17513".format(req_data_size)) + + if type_of_service not in range(0, 256): + mso.fail_json(msg="Invalid value provided for type_of_service: {0}; it must be in the range 0 - 255".format(type_of_service)) + + if operation_timeout > (sla_frequency * 1000): + mso.fail_json( + msg="Invalid value provided for operation_timeout: {0}; must be less than or equal to: {1}".format(operation_timeout, (sla_frequency * 1000)) + ) + + if threshold > operation_timeout: + mso.fail_json( + msg="Invalid value provided for threshold: {0}; it must be less than or equal to the operation_timeout: {1}".format(threshold, operation_timeout) + ) + + if ipv6_traffic_class not in range(0, 256): + mso.fail_json(msg="Invalid value provided for ipv6_traffic_class: {0}; it must be in the range 0 - 255".format(ipv6_traffic_class)) + + if sla_type == "http": + destination_port = 80 + + ops = [] + match = None + + mso_template = MSOTemplate(mso, "tenant", template) + mso_template.validate_template("tenantPolicy") + + path = "/tenantPolicyTemplate/template/ipslaMonitoringPolicies" + existing_ipsla_policies = mso_template.template.get("tenantPolicyTemplate", {}).get("template", {}).get("ipslaMonitoringPolicies", []) + if ipsla_monitoring_policy: + object_description = "IPSLA Monitoring Policy" + if ipsla_monitoring_policy_uuid: + match = mso_template.get_object_by_uuid( + object_description, + existing_ipsla_policies, + ipsla_monitoring_policy_uuid, + ) + else: + kv_list = [KVPair("name", ipsla_monitoring_policy)] + match = mso_template.get_object_by_key_value_pairs(object_description, existing_ipsla_policies, kv_list) + if match: + mso.existing = mso.previous = copy.deepcopy(match.details) + else: + mso.existing = mso.previous = existing_ipsla_policies + + if state == "present": + if match: + if ipsla_monitoring_policy and match.details.get("name") != ipsla_monitoring_policy: + ops.append( + dict( + op="replace", + path="{0}/{1}/name".format(path, match.index), + value=ipsla_monitoring_policy, + ) + ) + match.details["name"] = ipsla_monitoring_policy + + if sla_type and match.details.get("slaType") != sla_type: + ops.append( + dict( + op="replace", + path="{0}/{1}/slaType".format(path, match.index), + value=sla_type, + ) + ) + match.details["slaType"] = sla_type + + if destination_port is not None and match.details.get("slaPort") != destination_port: + ops.append( + dict( + op="replace", + path="{0}/{1}/slaPort".format(path, match.index), + value=destination_port, + ) + ) + match.details["slaPort"] = destination_port + + if http_version is not None and match.details.get("httpVersion") != http_version: + ops.append( + dict( + op="replace", + path="{0}/{1}/httpVersion".format(path, match.index), + value=http_version, + ) + ) + match.details["httpVersion"] = http_version + + if http_uri is not None and match.details.get("httpUri") != http_uri: + ops.append( + dict( + op="replace", + path="{0}/{1}/httpUri".format(path, match.index), + value=http_uri, + ) + ) + match.details["httpUri"] = http_uri + + if sla_frequency is not None and match.details.get("slaFrequency") != sla_frequency: + ops.append( + dict( + op="replace", + path="{0}/{1}/slaFrequency".format(path, match.index), + value=sla_frequency, + ) + ) + match.details["slaFrequency"] = sla_frequency + + if detect_multiplier is not None and match.details.get("slaDetectMultiplier") != detect_multiplier: + ops.append( + dict( + op="replace", + path="{0}/{1}/slaDetectMultiplier".format(path, match.index), + value=detect_multiplier, + ) + ) + match.details["slaDetectMultiplier"] = detect_multiplier + + if req_data_size is not None and match.details.get("reqDataSize") != req_data_size: + ops.append( + dict( + op="replace", + path="{0}/{1}/reqDataSize".format(path, match.index), + value=req_data_size, + ) + ) + match.details["reqDataSize"] = req_data_size + + if type_of_service is not None and match.details.get("ipv4ToS") != type_of_service: + ops.append( + dict( + op="replace", + path="{0}/{1}/ipv4ToS".format(path, match.index), + value=type_of_service, + ) + ) + match.details["ipv4ToS"] = type_of_service + + if operation_timeout is not None and match.details.get("timeout") != operation_timeout: + ops.append( + dict( + op="replace", + path="{0}/{1}/timeout".format(path, match.index), + value=operation_timeout, + ) + ) + match.details["timeout"] = operation_timeout + + if threshold is not None and match.details.get("threshold") != threshold: + ops.append( + dict( + op="replace", + path="{0}/{1}/threshold".format(path, match.index), + value=threshold, + ) + ) + match.details["threshold"] = threshold + + if ipv6_traffic_class is not None and match.details.get("ipv6TrfClass") != ipv6_traffic_class: + ops.append( + dict( + op="replace", + path="{0}/{1}/ipv6TrfClass".format(path, match.index), + value=ipv6_traffic_class, + ) + ) + match.details["ipv6TrfClass"] = ipv6_traffic_class + + mso.sanitize(match.details) + + else: + payload = { + "name": ipsla_monitoring_policy, + "slaType": sla_type, + "slaPort": destination_port, + "httpVersion": http_version, + "httpUri": http_uri, + "slaFrequency": sla_frequency, + "slaDetectMultiplier": detect_multiplier, + "reqDataSize": req_data_size, + "ipv4ToS": type_of_service, + "timeout": operation_timeout, + "threshold": threshold, + "ipv6TrfClass": ipv6_traffic_class, + } + + ops.append(dict(op="add", path="{0}/-".format(path), value=payload)) + + mso.sanitize(payload) + + mso.existing = mso.proposed + + elif state == "absent": + if match: + ops.append(dict(op="remove", path="{0}/{1}".format(path, match.index))) + mso.existing = {} + + if not module.check_mode and ops: + mso.request(mso_template.template_path, method="PATCH", data=ops) + + mso.exit_json() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/ndo_ipsla_monitoring_policy/aliases b/tests/integration/targets/ndo_ipsla_monitoring_policy/aliases new file mode 100644 index 00000000..5042c9c0 --- /dev/null +++ b/tests/integration/targets/ndo_ipsla_monitoring_policy/aliases @@ -0,0 +1,2 @@ +# No ACI MultiSite infrastructure, so not enabled +# unsupported diff --git a/tests/integration/targets/ndo_ipsla_monitoring_policy/tasks/main.yml b/tests/integration/targets/ndo_ipsla_monitoring_policy/tasks/main.yml new file mode 100644 index 00000000..58882884 --- /dev/null +++ b/tests/integration/targets/ndo_ipsla_monitoring_policy/tasks/main.yml @@ -0,0 +1,434 @@ +# Test code for the MSO modules +# Copyright: (c) 2024, Shreyas Srish (@shrsr) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI MultiSite host, username and password + ansible.builtin.fail: + msg: 'Please define the following variables: mso_hostname, mso_username and mso_password.' + when: mso_hostname is not defined or mso_username is not defined or mso_password is not defined + +# CLEAN ENVIRONMENT +- name: Set vars + ansible.builtin.set_fact: + mso_info: &mso_info + host: '{{ mso_hostname }}' + username: '{{ mso_username }}' + password: '{{ mso_password }}' + validate_certs: '{{ mso_validate_certs | default(false) }}' + use_ssl: '{{ mso_use_ssl | default(true) }}' + use_proxy: '{{ mso_use_proxy | default(true) }}' + output_level: '{{ mso_output_level | default("info") }}' + +# QUERY VERSION +- name: Query MSO version + cisco.mso.mso_version: + <<: *mso_info + state: query + register: version + +- name: Execute tasks only for MSO version > 4.3 + when: version.current.version is version('4.3', '>=') + block: + + - name: Ensure sites exists + cisco.mso.mso_site: + <<: *mso_info + site: '{{ item.site }}' + apic_username: '{{ apic_username }}' + apic_password: '{{ apic_password }}' + apic_site_id: '{{ item.apic_site_id }}' + urls: + - https://{{ apic_hostname }} + state: present + loop: + - {site: "ansible_test", apic_site_id: 101} + - {site: "ansible_test_2", apic_site_id: 102} + + - name: Ensure tenant exist + cisco.mso.mso_tenant: + <<: *mso_info + tenant: '{{ item }}' + users: + - '{{ mso_username }}' + sites: + - '{{ mso_site | default("ansible_test") }}' + - ansible_test_2 + state: present + loop: + - ansible_test + + - name: Ensure templates do not exist + cisco.mso.ndo_template: &template_absent + <<: *mso_info + name: ansible_tenant_template + template_type: tenant + tenant: ansible_test + state: absent + + - name: Ensure schemas do not exist + cisco.mso.mso_schema: &remove_schemas + <<: *mso_info + schema: '{{ mso_schema | default("ansible_test") }}' + state: absent + + - name: Ensure schema with template exists + cisco.mso.mso_schema_template: + <<: *mso_info + schema: '{{ mso_schema | default("ansible_test") }}' + tenant: ansible_test + template: ansible_test + state: present + + - name: Ensure templates exist + cisco.mso.ndo_template: + <<: *template_absent + state: present + + # CREATE + + - name: Create a new IPSLA monitoring policy (check_mode) + cisco.mso.ndo_ipsla_monitoring_policy: &create_ipsla_monitoring_policy + <<: *mso_info + template: ansible_tenant_template + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy + sla_frequency: 60 + state: present + check_mode: true + register: cm_create_new_ipsla_monitoring_policy + + - name: Create a new IPSLA monitoring policy + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + register: nm_create_new_ipsla_monitoring_policy + + - name: Create a new IPSLA monitoring policy again + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + register: nm_create_new_ipsla_monitoring_policy_again + + - name: Assert IPSLA monitoring policy was created + assert: + that: + - cm_create_new_ipsla_monitoring_policy is changed + - cm_create_new_ipsla_monitoring_policy.previous == {} + - cm_create_new_ipsla_monitoring_policy.current.name == "ansible_test_ipsla_monitoring_policy" + - cm_create_new_ipsla_monitoring_policy.current.slaType == "icmp" + - cm_create_new_ipsla_monitoring_policy.current.slaFrequency == 60 + - nm_create_new_ipsla_monitoring_policy is changed + - nm_create_new_ipsla_monitoring_policy.previous == {} + - nm_create_new_ipsla_monitoring_policy.current.name == "ansible_test_ipsla_monitoring_policy" + - nm_create_new_ipsla_monitoring_policy.current.slaType == "icmp" + - nm_create_new_ipsla_monitoring_policy.current.slaFrequency == 60 + - nm_create_new_ipsla_monitoring_policy_again is not changed + - nm_create_new_ipsla_monitoring_policy_again.previous.name == "ansible_test_ipsla_monitoring_policy" + - nm_create_new_ipsla_monitoring_policy_again.previous.slaType == "icmp" + - nm_create_new_ipsla_monitoring_policy_again.previous.slaFrequency == 60 + - nm_create_new_ipsla_monitoring_policy_again.current.name == "ansible_test_ipsla_monitoring_policy" + - nm_create_new_ipsla_monitoring_policy_again.current.slaType == "icmp" + - nm_create_new_ipsla_monitoring_policy_again.current.slaFrequency == 60 + + # UPDATE + + - name: Update an IPSLA monitoring policy (check_mode) + cisco.mso.ndo_ipsla_monitoring_policy: &update_ipsla_monitoring_policy + <<: *create_ipsla_monitoring_policy + sla_type: http + http_version: HTTP11 + http_uri: /test + sla_frequency: 120 + detect_multiplier: 5 + req_data_size: 64 + type_of_service: 16 + operation_timeout: 1000 + threshold: 1000 + ipv6_traffic_class: 32 + check_mode: true + register: cm_update_ipsla_monitoring_policy + + - name: Update an IPSLA monitoring policy (normal_mode) + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *update_ipsla_monitoring_policy + register: nm_update_ipsla_monitoring_policy + + - name: Update an IPSLA monitoring policy again + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *update_ipsla_monitoring_policy + register: nm_update_ipsla_monitoring_policy_again + + - name: Assert IPSLA monitoring policy was updated + assert: + that: + - cm_update_ipsla_monitoring_policy is changed + - cm_update_ipsla_monitoring_policy.previous.slaType == "icmp" + - cm_update_ipsla_monitoring_policy.current.slaType == "http" + - cm_update_ipsla_monitoring_policy.previous.slaPort == 0 + - cm_update_ipsla_monitoring_policy.current.slaPort == 80 + - cm_update_ipsla_monitoring_policy.previous.httpVersion == "HTTP10" + - cm_update_ipsla_monitoring_policy.current.httpVersion == "HTTP11" + - cm_update_ipsla_monitoring_policy.previous.httpUri == "/" + - cm_update_ipsla_monitoring_policy.current.httpUri == "/test" + - cm_update_ipsla_monitoring_policy.previous.slaFrequency == 60 + - cm_update_ipsla_monitoring_policy.current.slaFrequency == 120 + - cm_update_ipsla_monitoring_policy.previous.slaDetectMultiplier == 3 + - cm_update_ipsla_monitoring_policy.current.slaDetectMultiplier == 5 + - cm_update_ipsla_monitoring_policy.previous.reqDataSize == 28 + - cm_update_ipsla_monitoring_policy.current.reqDataSize == 64 + - cm_update_ipsla_monitoring_policy.previous.ipv4ToS == 0 + - cm_update_ipsla_monitoring_policy.current.ipv4ToS == 16 + - cm_update_ipsla_monitoring_policy.previous.timeout == 900 + - cm_update_ipsla_monitoring_policy.current.timeout == 1000 + - cm_update_ipsla_monitoring_policy.previous.threshold == 900 + - cm_update_ipsla_monitoring_policy.current.threshold == 1000 + - cm_update_ipsla_monitoring_policy.previous.ipv6TrfClass == 0 + - cm_update_ipsla_monitoring_policy.current.ipv6TrfClass == 32 + - nm_update_ipsla_monitoring_policy is changed + - nm_update_ipsla_monitoring_policy.previous.slaType == "icmp" + - nm_update_ipsla_monitoring_policy.current.slaType == "http" + - nm_update_ipsla_monitoring_policy.previous.slaPort == 0 + - nm_update_ipsla_monitoring_policy.current.slaPort == 80 + - nm_update_ipsla_monitoring_policy.previous.httpVersion == "HTTP10" + - nm_update_ipsla_monitoring_policy.current.httpVersion == "HTTP11" + - nm_update_ipsla_monitoring_policy.previous.httpUri == "/" + - nm_update_ipsla_monitoring_policy.current.httpUri == "/test" + - nm_update_ipsla_monitoring_policy.previous.slaFrequency == 60 + - nm_update_ipsla_monitoring_policy.current.slaFrequency == 120 + - nm_update_ipsla_monitoring_policy.previous.slaDetectMultiplier == 3 + - nm_update_ipsla_monitoring_policy.current.slaDetectMultiplier == 5 + - nm_update_ipsla_monitoring_policy.previous.reqDataSize == 28 + - nm_update_ipsla_monitoring_policy.current.reqDataSize == 64 + - nm_update_ipsla_monitoring_policy.previous.ipv4ToS == 0 + - nm_update_ipsla_monitoring_policy.current.ipv4ToS == 16 + - nm_update_ipsla_monitoring_policy.previous.timeout == 900 + - nm_update_ipsla_monitoring_policy.current.timeout == 1000 + - nm_update_ipsla_monitoring_policy.previous.threshold == 900 + - nm_update_ipsla_monitoring_policy.current.threshold == 1000 + - nm_update_ipsla_monitoring_policy.previous.ipv6TrfClass == 0 + - nm_update_ipsla_monitoring_policy.current.ipv6TrfClass == 32 + - nm_update_ipsla_monitoring_policy_again is not changed + - nm_update_ipsla_monitoring_policy_again.previous.slaType == "http" + - nm_update_ipsla_monitoring_policy_again.current.slaType == "http" + - nm_update_ipsla_monitoring_policy_again.previous.slaPort == 80 + - nm_update_ipsla_monitoring_policy_again.current.slaPort == 80 + - nm_update_ipsla_monitoring_policy_again.previous.httpVersion == "HTTP11" + - nm_update_ipsla_monitoring_policy_again.current.httpVersion == "HTTP11" + - nm_update_ipsla_monitoring_policy_again.previous.httpUri == "/test" + - nm_update_ipsla_monitoring_policy_again.current.httpUri == "/test" + - nm_update_ipsla_monitoring_policy_again.previous.slaFrequency == 120 + - nm_update_ipsla_monitoring_policy_again.current.slaFrequency == 120 + - nm_update_ipsla_monitoring_policy_again.previous.slaDetectMultiplier == 5 + - nm_update_ipsla_monitoring_policy_again.current.slaDetectMultiplier == 5 + - nm_update_ipsla_monitoring_policy_again.previous.reqDataSize == 64 + - nm_update_ipsla_monitoring_policy_again.current.reqDataSize == 64 + - nm_update_ipsla_monitoring_policy_again.previous.ipv4ToS == 16 + - nm_update_ipsla_monitoring_policy_again.current.ipv4ToS == 16 + - nm_update_ipsla_monitoring_policy_again.previous.timeout == 1000 + - nm_update_ipsla_monitoring_policy_again.current.timeout == 1000 + - nm_update_ipsla_monitoring_policy_again.previous.threshold == 1000 + - nm_update_ipsla_monitoring_policy_again.current.threshold == 1000 + - nm_update_ipsla_monitoring_policy_again.previous.ipv6TrfClass == 32 + - nm_update_ipsla_monitoring_policy_again.current.ipv6TrfClass == 32 + + - name: Update an IPSLA monitoring policy destination port + cisco.mso.ndo_ipsla_monitoring_policy: &update_ipsla_monitoring_policy_destination_port + <<: *update_ipsla_monitoring_policy + destination_port: 10 + sla_type: tcp + register: update_ipsla_monitoring_policy_destination_port + + - name: Assert IPSLA monitoring policy destination port was updated + assert: + that: + - update_ipsla_monitoring_policy_destination_port is changed + - update_ipsla_monitoring_policy_destination_port.previous.slaPort == 80 + - update_ipsla_monitoring_policy_destination_port.current.slaPort == 10 + - update_ipsla_monitoring_policy_destination_port.previous.slaType == "http" + - update_ipsla_monitoring_policy_destination_port.current.slaType == "tcp" + + - name: Update an IPSLA monitoring policy name + cisco.mso.ndo_ipsla_monitoring_policy: &update_ipsla_monitoring_policy_name + <<: *update_ipsla_monitoring_policy_destination_port + ipsla_monitoring_policy_uuid: '{{ update_ipsla_monitoring_policy_destination_port.current.uuid }}' + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy_changed + register: nm_update_ipsla_monitoring_policy_name + + - name: Assert IPSLA monitoring policy name was updated + assert: + that: + - nm_update_ipsla_monitoring_policy_name is changed + - nm_update_ipsla_monitoring_policy_name.previous.name == "ansible_test_ipsla_monitoring_policy" + - nm_update_ipsla_monitoring_policy_name.current.name == "ansible_test_ipsla_monitoring_policy_changed" + + # QUERY + + - name: Create another IPSLA monitoring policy + cisco.mso.ndo_ipsla_monitoring_policy: &create_ipsla_monitoring_policy_2 + <<: *create_ipsla_monitoring_policy + ipsla_monitoring_policy: ansible_test_ipsla_monitoring_policy_2 + + - name: Query an IPSLA monitoring policy with template_name + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy_2 + state: query + register: query_one + + - name: Query all IPSLA monitoring policies in the template + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *mso_info + template: ansible_tenant_template + state: query + register: query_all + + - name: Assert IPSLA monitoring policy was queried + assert: + that: + - query_one is not changed + - query_one.current.name == "ansible_test_ipsla_monitoring_policy_2" + - query_all is not changed + - query_all.current | length == 2 + + # ERRORS + + # Error test for invalid sla_frequency + - name: Error sla_frequency provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + sla_frequency: 301 + register: err_sla_frequency_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid sla_frequency + assert: + that: + - err_sla_frequency_create_out_of_range is failed + - err_sla_frequency_create_out_of_range.msg == "Invalid value provided for sla_frequency{{":"}} 301; it must be in the range 1 - 300" + + # Error test for invalid detect_multiplier + - name: Error detect_multiplier provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + detect_multiplier: 101 + register: err_detect_multiplier_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid detect_multiplier + assert: + that: + - err_detect_multiplier_create_out_of_range is failed + - err_detect_multiplier_create_out_of_range.msg == "Invalid value provided for detect_multiplier{{":"}} 101; it must be in the range 1 - 100" + + # Error test for invalid req_data_size + - name: Error req_data_size provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + req_data_size: 17514 + register: err_req_data_size_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid req_data_size + assert: + that: + - err_req_data_size_create_out_of_range is failed + - err_req_data_size_create_out_of_range.msg == "Invalid value provided for req_data_size{{":"}} 17514; it must be in the range 0 - 17513" + + # Error test for invalid type_of_service + - name: Error type_of_service provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + type_of_service: 256 + register: err_type_of_service_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid type_of_service + assert: + that: + - err_type_of_service_create_out_of_range is failed + - err_type_of_service_create_out_of_range.msg == "Invalid value provided for type_of_service{{":"}} 256; it must be in the range 0 - 255" + + # Error test for invalid operation_timeout + - name: Error operation_timeout provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + sla_frequency: 60 + operation_timeout: 61000 + register: err_operation_timeout_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid operation_timeout + assert: + that: + - err_operation_timeout_create_out_of_range is failed + - err_operation_timeout_create_out_of_range.msg == "Invalid value provided for operation_timeout{{":"}} 61000; must be less than or equal to{{":"}} 60000" + + # Error test for invalid threshold + - name: Error threshold provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + operation_timeout: 1000 + threshold: 2000 + register: err_threshold_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid threshold + assert: + that: + - err_threshold_create_out_of_range is failed + - err_threshold_create_out_of_range.msg == "Invalid value provided for threshold{{":"}} 2000; it must be less than or equal to the operation_timeout{{":"}} 1000" + + # Error test for invalid ipv6_traffic_class + - name: Error ipv6_traffic_class provided out of range on create + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *create_ipsla_monitoring_policy + ipv6_traffic_class: 256 + register: err_ipv6_traffic_class_create_out_of_range + ignore_errors: true + + - name: Assert error for invalid ipv6_traffic_class + assert: + that: + - err_ipv6_traffic_class_create_out_of_range is failed + - err_ipv6_traffic_class_create_out_of_range.msg == "Invalid value provided for ipv6_traffic_class{{":"}} 256; it must be in the range 0 - 255" + + # DELETE + + - name: Delete an IPSLA monitoring policy (check_mode) + cisco.mso.ndo_ipsla_monitoring_policy: &delete_ipsla_monitoring_policy + <<: *update_ipsla_monitoring_policy_name + state: absent + check_mode: true + register: cm_delete_ipsla_monitoring_policy + + - name: Delete an IPSLA monitoring policy + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *delete_ipsla_monitoring_policy + register: nm_delete_ipsla_monitoring_policy + + - name: Delete an IPSLA monitoring policy again + cisco.mso.ndo_ipsla_monitoring_policy: + <<: *delete_ipsla_monitoring_policy + register: nm_delete_ipsla_monitoring_policy_again + + - name: Assert IPSLA monitoring policy was deleted + assert: + that: + - cm_delete_ipsla_monitoring_policy is changed + - cm_delete_ipsla_monitoring_policy.previous.name == 'ansible_test_ipsla_monitoring_policy_changed' + - cm_delete_ipsla_monitoring_policy.previous.slaType == 'tcp' + - cm_delete_ipsla_monitoring_policy.current == {} + - nm_delete_ipsla_monitoring_policy is changed + - nm_delete_ipsla_monitoring_policy.previous.name == 'ansible_test_ipsla_monitoring_policy_changed' + - nm_delete_ipsla_monitoring_policy.previous.slaType == 'tcp' + - nm_delete_ipsla_monitoring_policy.current == {} + - nm_delete_ipsla_monitoring_policy_again is not changed + - nm_delete_ipsla_monitoring_policy_again.previous == {} + - nm_delete_ipsla_monitoring_policy_again.current == {} + + # CLEANUP TEMPLATE + + - name: Ensure templates do not exist + cisco.mso.ndo_template: + <<: *template_absent + + - name: Ensure schemas do not exist + cisco.mso.mso_schema: + <<: *remove_schemas