From daeeec85b7c8b1fa51c2f385dad9d67010750dbf Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 20 Jun 2025 23:43:28 +0530 Subject: [PATCH 1/3] "Inventory - Refactoring Integration Tests - Verifying NDFC State with Playbook Task Configuration, using Pydantic and Python Action Plugin." --- .gitignore | 3 +- playbooks/roles/dcnm_inventory/dcnm_hosts.yml | 12 + playbooks/roles/dcnm_inventory/dcnm_tests.yml | 17 + .../integration/ndfc_inventory_validate.py | 214 +++++++ .../templates/dcnm_inventory_conf.j2 | 65 ++ .../targets/dcnm_inventory/files/.gitkeep | 0 .../targets/dcnm_inventory/tasks/dcnm.yaml | 24 - .../targets/dcnm_inventory/tasks/main.yaml | 51 +- .../dcnm_inventory/tests/base_tasks.yaml | 67 +++ .../dcnm_inventory/tests/conf_prep_tasks.yaml | 11 + .../dcnm_inventory/tests/dcnm/deleted.yaml | 263 ++++---- .../dcnm_inventory/tests/dcnm/merged.yaml | 562 +++++++++++------- .../dcnm_inventory/tests/dcnm/overridden.yaml | 227 ++++--- .../dcnm_inventory/tests/dcnm/poap.yaml | 399 +++++++------ .../dcnm_inventory/tests/dcnm/query.yaml | 326 +++++----- .../dcnm_inventory/tests/dcnm/rma.yaml | 300 ++++++---- .../dcnm_inventory/tests/dcnm/sanity.yaml | 265 +++++---- tests/sanity/ignore-2.17.txt | 3 + tests/sanity/ignore-2.18.txt | 2 + 19 files changed, 1806 insertions(+), 1005 deletions(-) create mode 100644 playbooks/roles/dcnm_inventory/dcnm_hosts.yml create mode 100644 playbooks/roles/dcnm_inventory/dcnm_tests.yml create mode 100644 plugins/action/tests/integration/ndfc_inventory_validate.py create mode 100644 tests/integration/targets/dcnm_fabric/templates/dcnm_inventory_conf.j2 create mode 100644 tests/integration/targets/dcnm_inventory/files/.gitkeep delete mode 100644 tests/integration/targets/dcnm_inventory/tasks/dcnm.yaml create mode 100644 tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml create mode 100644 tests/integration/targets/dcnm_inventory/tests/conf_prep_tasks.yaml diff --git a/.gitignore b/.gitignore index c1155ddad..b0712fe3b 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,5 @@ venv.bak/ # Ignore Integration Tests Files Directories tests/integration/targets/ndfc_interface/files -tests/integration/targets/dcnm_network/files \ No newline at end of file +tests/integration/targets/dcnm_network/files +tests/integration/targets/dcnm_inventory/files \ No newline at end of file diff --git a/playbooks/roles/dcnm_inventory/dcnm_hosts.yml b/playbooks/roles/dcnm_inventory/dcnm_hosts.yml new file mode 100644 index 000000000..602b4274f --- /dev/null +++ b/playbooks/roles/dcnm_inventory/dcnm_hosts.yml @@ -0,0 +1,12 @@ +ndfc: + children: + prod: + hosts: + 192.168.1.1: + ansible_connection: ansible.netcommon.httpapi + ansible_httpapi_use_ssl: true + ansible_httpapi_validate_certs: false + ansible_python_interpreter: auto_silent + ansible_network_os: cisco.dcnm.dcnm + ansible_user: admin + ansible_password: password \ No newline at end of file diff --git a/playbooks/roles/dcnm_inventory/dcnm_tests.yml b/playbooks/roles/dcnm_inventory/dcnm_tests.yml new file mode 100644 index 000000000..3de830f89 --- /dev/null +++ b/playbooks/roles/dcnm_inventory/dcnm_tests.yml @@ -0,0 +1,17 @@ +--- +- hosts: ndfc + gather_facts: no + connection: ansible.netcommon.httpapi + + vars: + ansible_switch1: 192.168.2.4 + ansible_switch2: 192.168.2.5 + ansible_switch3: 192.168.2.6 + ansible_it_fabric: test-fabric + deploy: false + switch_username: admin + switch_password: password + + roles: + - dcnm_inventory + tags: always \ No newline at end of file diff --git a/plugins/action/tests/integration/ndfc_inventory_validate.py b/plugins/action/tests/integration/ndfc_inventory_validate.py new file mode 100644 index 000000000..0cca7d4f9 --- /dev/null +++ b/plugins/action/tests/integration/ndfc_inventory_validate.py @@ -0,0 +1,214 @@ +from __future__ import absolute_import, division, print_function +from ansible.utils.display import Display +from ansible.plugins.action import ActionBase +from typing import List, Dict, Optional, Union +from pydantic import BaseModel, model_validator, validator, ValidationError +import re +import json +__metaclass__ = type + +display = Display() + + +class ConfigData(BaseModel): + role: Optional[str] = None + seed_ip: Optional[str] = None + + +class NDFCData(BaseModel): + ipAddress: Optional[str] = None + switchRoleEnum: Optional[str] = None + switchRole: Optional[str] = None + + +class InventoryValidate(BaseModel): + config_data: Optional[List[ConfigData]] = None + ndfc_data: Optional[Union[List[NDFCData], str]] = None + ignore_fields: Optional[Dict[str, int]] = None + response: Union[bool, str] = None + + @validator('config_data', pre=True) + @classmethod + def parse_config_data(cls, value): + """ + Validates and transforms the config_data input. + Accepts a dictionary or list of dictionaries and converts them to ConfigData objects. + + Args: + value: The input data to validate (dict, list, or None) + Returns: + List of ConfigData objects or None + Raises: + ValueError: If the input format is invalid + """ + if isinstance(value, dict): + return [ConfigData.parse_obj(value)] + if isinstance(value, list): + try: + return [ConfigData.parse_obj(item) for item in value] + except ValidationError as e: + raise ValueError(f"Invalid format in Config Data: {e}") + elif value is None: + return None + else: + raise ValueError("Config Data must be a single/list of dictionary, or None.") + + @validator('ndfc_data', pre=True) + @classmethod + def parse_ndfc_data(cls, value): + """ + Validates and transforms the ndfc_data input. + Accepts a string (error message) or list of dictionaries and converts to NDFCData objects. + Args: + value: The NDFC response data (str or list) + Returns: + List of NDFCData objects or the original error string + Raises: + ValueError: If the input format is invalid + """ + if isinstance(value, str): + return value + if isinstance(value, list): + try: + return [NDFCData.parse_obj(item) for item in value] + except ValidationError as e: + raise ValueError(f"Invalid format in NDFC Response: {e}") + else: + raise ValueError("NDFC Response must be a list of dictionaries or an error string") + + @model_validator(mode='after') + @classmethod + def validate_lists_equality(cls, values): + """ + Validates that the configuration data matches the NDFC response data. + Performs matching based on seed_ip and role, respecting ignore_fields settings. + Args: + values: The model instance after individual field validation + Returns: + "True" if validation is successful, "False" otherwise + """ + config_data = values.config_data + ndfc_data = values.ndfc_data + ignore_fields = values.ignore_fields + response = values.response + + if isinstance(ndfc_data, str): + if config_data is None and ndfc_data == "The queried switch is not part of the fabric configured": + values.response = "True" + return values + else: + print(" NDFC Query returned an Invalid Response\n") + return values + + missing_ips = [] + role_mismatches = {} + ndfc_data_copy = ndfc_data.copy() + matched_indices_two = set() + + for config_data_item in config_data: + found_match = False + config_data_item_dict = config_data_item.dict(exclude_none=True) + for i, ndfc_data_item in enumerate(ndfc_data_copy): + ndfc_data_item = ndfc_data_item.dict(include=set(['ipAddress', 'switchRole'] + list(config_data_item_dict.keys()))) + if i in matched_indices_two: + continue + + seed_ip_match = False + role_match = False + + ip_address_two = ndfc_data_item.get('ipAddress') + switch_role_two = ndfc_data_item.get('switchRole') + role_one = config_data_item_dict.get('role') + if switch_role_two is not None: + switch_role_two = re.sub(r'[^a-zA-Z0-9]', '', switch_role_two.lower()) + if role_one is not None: + role_one = re.sub(r'[^a-zA-Z0-9]', '', role_one.lower()) + seed_ip_one = config_data_item_dict.get('seed_ip') + + if ((seed_ip_one is not None and ip_address_two is not None and ip_address_two == seed_ip_one) or (ignore_fields['seed_ip'])): + seed_ip_match = True + + if ((role_one is not None and switch_role_two is not None and switch_role_two == role_one) or (ignore_fields['role'])) : + role_match = True + + if seed_ip_match and role_match: + matched_indices_two.add(i) + found_match = True + if ignore_fields['seed_ip']: + break + elif ((seed_ip_match and role_one is not None and switch_role_two is not None and switch_role_two != role_one) or (ignore_fields['role'])): + role_mismatches.setdefault((seed_ip_one or ip_address_two), {"expected_role": role_one, "response_role": switch_role_two}) + matched_indices_two.add(i) # Consider it a partial match to avoid further matching + found_match = True + if ignore_fields['seed_ip']: + break + + if not found_match and config_data_item_dict is not None and config_data_item_dict.get('seed_ip') is not None: + missing_ips.append(config_data_item_dict.get('seed_ip')) + + if not missing_ips and not role_mismatches: + values.response = True + else: + print("Invalid Data:\n ") + if not missing_ips: + print(missing_ips) + if not role_mismatches: + print(json.dumps(role_mismatches, indent=2)) + return values + + +class ActionModule(ActionBase): + """ + Ansible action plugin for validating NDFC inventory data. + Compares test data against NDFC response data and validates according to specified mode. + """ + + def run(self, tmp=None, task_vars=None): + """ + Execute the action plugin logic. + Args: + tmp: Temporary directory + task_vars: Variables available to the task + Returns: + dict: Results dictionary with success/failure status and appropriate messages + """ + results = super(ActionModule, self).run(tmp, task_vars) + results['failed'] = False + ndfc_data = self._task.args['ndfc_data'] + test_data = self._task.args['test_data'] + response = False + + if 'changed' in self._task.args: + changed = self._task.args['changed'] + if not changed: + results['failed'] = True + results['msg'] = 'Changed is "false"' + return results + + if len(ndfc_data['response']) == 0: + results['failed'] = True + results['msg'] = 'No response data found' + return results + + ignore_fields = {"seed_ip": 0, "role": 0} + + if 'mode' in self._task.args: + mode = self._task.args['mode'].lower() + if mode == 'ip': + # In IP mode, we ignore role matching + ignore_fields['role'] = 1 + elif mode == 'role': + # In role mode, we ignore IP matching + ignore_fields['seed_ip'] = 1 + + validation_result = InventoryValidate(config_data=test_data, ndfc_data=ndfc_data['response'], ignore_fields=ignore_fields, response=response) + validation_output = InventoryValidate.model_validate(validation_result) + + if validation_output.response: + results['failed'] = False + results['msg'] = 'Validation Successful!' + else: + results['failed'] = True + results['msg'] = 'Validation Failed! Please check output above.' + + return results diff --git a/tests/integration/targets/dcnm_fabric/templates/dcnm_inventory_conf.j2 b/tests/integration/targets/dcnm_fabric/templates/dcnm_inventory_conf.j2 new file mode 100644 index 000000000..db8bb3702 --- /dev/null +++ b/tests/integration/targets/dcnm_fabric/templates/dcnm_inventory_conf.j2 @@ -0,0 +1,65 @@ +--- +# This NDFC test data structure is auto-generated +# DO NOT EDIT MANUALLY +# + +# ------------------------------ +# Fabric Switches +# ------------------------------ + +{% if switch_conf is iterable %} +{% set switch_list = [] %} +{% for switch in switch_conf %} +{% set switch_item = {} %} +{% if switch.seed_ip is defined %} +{% set _ = switch_item.update({'seed_ip': switch.seed_ip | default('') }) %} +{% endif %} +{% set _ = switch_item.update({'user_name': switch_username}) %} +{% set _ = switch_item.update({'password': switch_password}) %} +{% if switch.role is defined %} +{% set _ = switch_item.update({'role': switch.role | default('') }) %} +{% endif %} +{% if switch.poap is defined %} +{% for sw_poap_item in switch.poap %} +{% set poap_item = {} %} +{% if sw_poap_item.preprovision_serial is defined and sw_poap_item.preprovision_serial %} +{% set _ = poap_item.update({'preprovision_serial': sw_poap_item.preprovision_serial}) %} +{% endif %} +{% if sw_poap_item.serial_number is defined and sw_poap_item.serial_number %} +{% set _ = poap_item.update({'serial_number': sw_poap_item.serial_number}) %} +{% endif %} +{% if sw_poap_item.model is defined and sw_poap_item.model %} +{% set _ = poap_item.update({'model': sw_poap_item.model}) %} +{% endif %} +{% if sw_poap_item.version is defined and sw_poap_item.version %} +{% set _ = poap_item.update({'version': sw_poap_item.version}) %} +{% endif %} +{% if sw_poap_item.hostname is defined and sw_poap_item.hostname %} +{% set _ = poap_item.update({'hostname': sw_poap_item.hostname}) %} +{% endif %} +{% if sw_poap_item.config_data is defined %} +{% set poap_config_item = {} %} +{% for sw_poap_config_item in sw_poap_item.config_data %} +{% set _ = poap_config_item.update({sw_poap_config_item: sw_poap_item.config_data[sw_poap_config_item]}) %} +{% endfor %} +{% set _ = poap_item.update({'config_data': poap_config_item}) %} +{% endif %} +{% set _ = switch_item.update({'poap': [poap_item]}) %} +{% endfor %} +{% else %} +{% if switch.auth_proto is defined %} +{% set _ = switch_item.update({'auth_proto': switch.auth_proto | default('') }) %} +{% endif %} +{% if switch.max_hops is defined %} +{% set _ = switch_item.update({'max_hops': switch.max_hops | default('') }) %} +{% endif %} +{% if switch.preserve_config is defined %} +{% set _ = switch_item.update({'preserve_config': switch.preserve_config | default('') }) %} +{% else %} +{% set _ = switch_item.update({'preserve_config': false }) %} +{% endif %} +{% endif %} +{% set _ = switch_list.append(switch_item) %} +{% endfor %} +{{ switch_list | to_nice_yaml(indent=2) }} +{% endif %} \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/files/.gitkeep b/tests/integration/targets/dcnm_inventory/files/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/targets/dcnm_inventory/tasks/dcnm.yaml b/tests/integration/targets/dcnm_inventory/tasks/dcnm.yaml deleted file mode 100644 index a92ff1618..000000000 --- a/tests/integration/targets/dcnm_inventory/tasks/dcnm.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -- name: collect dcnm test cases - find: - paths: "{{ role_path }}/tests/dcnm" - patterns: "{{ testcase }}.yaml" - connection: local - register: dcnm_cases - tags: sanity - -- set_fact: - test_cases: - files: "{{ dcnm_cases.files }}" - tags: sanity - -- name: set test_items - set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" - tags: sanity - -- name: run test cases (connection=httpapi) - include: "{{ test_case_to_run }}" - with_items: "{{ test_items }}" - loop_control: - loop_var: test_case_to_run - tags: sanity diff --git a/tests/integration/targets/dcnm_inventory/tasks/main.yaml b/tests/integration/targets/dcnm_inventory/tasks/main.yaml index e2c92c5f8..b05dafae9 100644 --- a/tests/integration/targets/dcnm_inventory/tasks/main.yaml +++ b/tests/integration/targets/dcnm_inventory/tasks/main.yaml @@ -1,41 +1,16 @@ --- +- name: Discover NDFC Test Cases + ansible.builtin.find: + paths: "{{ role_path }}/tests/dcnm" + patterns: "{{ testcase }}.yaml" + connection: local + register: ndfc_testcases -- set_fact: - controller_version: "Unable to determine controller version" - tags: sanity +- name: Build List of Test Items + ansible.builtin.set_fact: test_items="{{ ndfc_testcases.files | map(attribute='path') | list }}" -- name: Determine version of DCNM or NDFC - cisco.dcnm.dcnm_rest: - method: GET - path: /appcenter/cisco/ndfc/api/about/version - register: result - ignore_errors: yes - tags: sanity - -- set_fact: - controller_version: "{{ result.response['DATA']['version'][0:2] | int }}" - when: ( result.response['DATA']['version'] is search("\d\d.\d+") ) - ignore_errors: yes - tags: sanity - -- name: Determine version of DCNM or NDFC - cisco.dcnm.dcnm_rest: - method: GET - path: /fm/fmrest/about/version - register: result - ignore_errors: yes - tags: sanity - -- set_fact: - controller_version: "{{ result.response['DATA']['version'][0:2] | int }}" - when: ( result.response['DATA']['version'] is search("\d\d.\d+") ) - ignore_errors: yes - tags: sanity - -# No need to continue if we cannot determine the DCNM/NDFC controller version -- assert: - that: - - 'controller_version != "Unable to determine controller version"' - tags: sanity - -- { include: dcnm.yaml, tags: ['dcnm'] } +- name: Run NDFC Test Cases + ansible.builtin.include_tasks: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml b/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml new file mode 100644 index 000000000..588445eb3 --- /dev/null +++ b/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml @@ -0,0 +1,67 @@ +--- +- name: Test Entry Point - [dcnm_inventory] + ansible.builtin.debug: + msg: + - "----------------------------------------------------------------" + - "+ Executing Base Tests - [dcnm_inventory] +" + - "----------------------------------------------------------------" + +# -------------------------------- +# Create Dictionary of Test Data +# -------------------------------- +- name: Base - Setup Internal TestCase Variables + ansible.builtin.set_fact: + test_data: + test_fabric: "{{ ansible_it_fabric }}" + sw1: "{{ ansible_switch1 }}" + sw2: "{{ ansible_switch2 }}" + sw3: "{{ ansible_switch3 }}" + deploy: "{{ deploy }}" + delegate_to: localhost + +# ---------------------------------------------- +# Create Module Payloads using Jinja2 Templates +# ---------------------------------------------- + +- name: Base - Prepare Configuration + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{test_data.sw1}}" + auth_proto: MD5 + max_hops: 0 + role: leaf + - seed_ip: "{{test_data.sw2}}" + auth_proto: MD5 + max_hops: 0 + role: spine + - seed_ip: "{{test_data.sw3}}" + auth_proto: MD5 + max_hops: 0 + role: border + delegate_to: localhost + + +- name: Import Configuration Prepare Tasks + vars: + file: base + import_tasks: conf_prep_tasks.yml + +# ---------------------------------------------- +# Test Setup +# ---------------------------------------------- +- name: Base - Query Fabric Existence + cisco.dcnm.dcnm_fabric: + state: query + config: + - FABRIC_NAME: "{{ test_data.test_fabric }}" + register: query_result + +- assert: + that: + - query_result.result[0].found == true + fail_msg: "Fabric '{{ test_data.test_fabric }}' not found." + +- name: Base - Clean Up Existing Devices in Fabric + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: deleted \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/conf_prep_tasks.yaml b/tests/integration/targets/dcnm_inventory/tests/conf_prep_tasks.yaml new file mode 100644 index 000000000..119007a05 --- /dev/null +++ b/tests/integration/targets/dcnm_inventory/tests/conf_prep_tasks.yaml @@ -0,0 +1,11 @@ +--- +- name: Build Fabric Base Config Data + ansible.builtin.template: + src: dcnm_inventory_conf.j2 + dest: "{{ role_path }}/files/ndfc_inventory_{{file}}_conf.yaml" + delegate_to: localhost + +- name: Access Fabric Configuration Data and Save to Local Variable + ansible.builtin.set_fact: + "{{ 'ndfc_fabric_' + file +'_conf' }}": "{{ lookup('file', '{{ role_path }}/files/ndfc_inventory_{{file}}_conf.yaml') | from_yaml }}" + delegate_to: localhost \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml index cd2263da4..44a1b6398 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml @@ -1,143 +1,202 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" - -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" - -- name: DELETED - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result +--- -- assert: - that: - - 'result.response.DATA != None' +- name: Import DCNM Inventory Base Tasks + import_tasks: ../base_tasks.yml + tags: deleted -- name: DELETED - setup - Clean up any existing devices +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- +# TC - 1 +- name: Deleted TC1 - Prepare Switches in Fabric - GreenField Deployment cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_base_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: deleted -- name: DELETED - Merge a Switch using GreenField Deployment +- name: Deleted TC1 - Query Inventory State in Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: deleted + +- name: Deleted TC1 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" + changed: "{{merged_result.changed}}" register: result + tags: deleted -- assert: - that: - - 'result.changed == true' - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -############################################# -# DELETED ## -############################################# - -- name: DELETED - Delete a Switch +# TC - 2 +- name: Deleted TC2 - Delete a Switch from the Fabric cisco.dcnm.dcnm_inventory: &conf_del - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted config: - - seed_ip: "{{ ansible_switch1 }}" - register: result + - seed_ip: "{{ test_data.sw1 }}" + register: delete_result + tags: deleted -- assert: - that: - - 'result.changed == true' - - 'result.response[0].RETURN_CODE == 200' +- name: Deleted TC2 - Prepare Test Data + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: "{{ ndfc_fabric_base_conf | rejectattr('seed_ip', 'equalto', test_data.sw1) | list }}" + delegate_to: localhost + tags: deleted -- name: DELETED - conf1 - DEL - Idempotence +- name: Deleted TC2 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: deleted + +- name: Deleted TC2 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + changed: "{{ delete_result.changed }}" + register: result + tags: deleted + +# TC - 3 +- name: Deleted TC3 - Removing a previously Deleted Switch - Idempotence cisco.dcnm.dcnm_inventory: *conf_del register: result + tags: deleted - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is not part of the fabric and cannot be deleted"' + tags: deleted -- name: DELETED - Merge a Switch using BrownField Deployment - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: True # boolean, default is true - register: result - -- assert: - that: - - 'result.changed == true' - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -- name: DELETED - Delete all Switch without config element +# TC - 4 +- name: Deleted TC4 - Delete all Switches from Fabric cisco.dcnm.dcnm_inventory: &conf_del_all - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - register: result + register: delete_result + tags: deleted -- assert: - that: - - 'result.changed == true' - - 'result.response[0].RETURN_CODE == 200' +- name: Deleted TC4 - Prepare Test Data + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: + delegate_to: localhost + tags: deleted -- name: DELETED - conf1 - DEL ALL - Idempotence - cisco.dcnm.dcnm_inventory: *conf_del_all +- name: Deleted TC4 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: deleted + +- name: Deleted TC4 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + changed: "{{ delete_result.changed }}" register: result + tags: deleted + +# TC - 5 +- name: Deleted TC5 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + role: leaf + preserve_config: true + delegate_to: localhost + tags: deleted + +- name: Import Configuration Prepare Tasks + vars: + file: delete + import_tasks: ../conf_prep_tasks.yml + tags: deleted + +- name: Deleted TC5 - Merge a Switch using BrownField Deployment + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_delete_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: deleted -- assert: - that: - - 'result.changed == false' - - 'result.response == "The switch provided is not part of the fabric and cannot be deleted"' +- name: Deleted TC5 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: deleted + +- name: Deleted TC5 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + changed: "{{ merged_result.changed }}" + register: result + tags: deleted -- name: DELETED - Delete a Switch without seed_ip +# TC - 6 +- name: Deleted TC6 - Delete a Switch without seed_ip cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted config: - seed_ip: register: result ignore_errors: yes + tags: deleted - assert: that: - 'result.changed == false' - '"Invalid parameters in playbook: seed_ip : Required parameter not found" in result.msg' + tags: deleted -############################################## -## CLEAN-UP ## -############################################## +# TC - 7 +- name: Deleted TC7 - Prepare Config + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: + delegate_to: localhost + tags: deleted + +- name: Deleted TC7 - Delete all Switches from Fabric + cisco.dcnm.dcnm_inventory: *conf_del_all + register: delete_result + tags: deleted -- name: DELETED - setup - Clean up any existing devices +- name: Deleted TC7 - Query Inventory State in Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted \ No newline at end of file + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: deleted + +- name: Deleted TC7 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + changed: "{{ delete_result.changed }}" + register: result + tags: deleted + +# TC - 8 +- name: Deleted TC8 - Delete all Switches from Fabric - Idempotence + cisco.dcnm.dcnm_inventory: *conf_del_all + register: result + tags: deleted + +- assert: + that: + - 'result.changed == false' + - 'result.response == "The switch provided is not part of the fabric and cannot be deleted"' + tags: deleted \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml index 0fe62e737..289efb905 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml @@ -1,311 +1,451 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" - -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" - -- name: MERGED - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result - -- assert: - that: - - 'result.response.DATA != None' - -- name: MERGED - setup - Clean up any existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted +--- -############################################## -## MERGED ## -############################################## +- name: Import DCNM Inventory Base Tasks + import_tasks: ../base_tasks.yml + tags: merged -- name: MERGED - Merge a Switch using GreenField Deployment +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- +# TC - 1 +- name: Merged TC1 - Merge a Switch using GreenField Deployment cisco.dcnm.dcnm_inventory: &conf - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - register: result - -- assert: - that: - - 'result.changed == true' + config: "{{ ndfc_fabric_base_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: merged -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Merged TC1 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC1 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" + changed: "{{ merged_result.changed }}" + register: result + tags: merged -- name: MERGED - conf1 - GF - Idempotence +# TC - 2 +- name: Merged TC2 - Idempotence cisco.dcnm.dcnm_inventory: *conf register: result + tags: merged - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' + tags: merged -- name: MERGED - setup - Clean up any existing devices +# TC - 3 +- name: Merged TC3 - Clean up Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: delete_result + tags: merged + +- name: Merged TC3 - Prepare Test Data + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: + delegate_to: localhost + tags: merged -- name: MERGED - Merge a Switch using BrownField Deployment +- name: Merged TC3 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC3 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + changed: "{{ delete_result.changed }}" + register: result + tags: merged + +# TC - 4 +- name: Merged TC4 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + max_hops: 0 + role: leaf + auth_proto: MD5 + preserve_config: true + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC4 - Merge a Switch using BrownField Deployment cisco.dcnm.dcnm_inventory: &conf_bf - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: True # boolean, default is true - register: result - -- assert: - that: - - 'result.changed == true' + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: merged -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Merged TC4 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC4 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_merge_conf }}" + changed: "{{ merged_result.changed }}" + register: result + tags: merged -- name: MERGED - conf2 -BF- Idempotence +# TC - 5 +- name: Merged TC5 - Verify Idempotence cisco.dcnm.dcnm_inventory: *conf_bf register: result + tags: merged - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' + tags: merged -- name: MERGED - setup - Clean up any existing devices +# TC - 6 +- name: Merged TC6 - Clean up Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - -- name: MERGED - Merge a Switch using GreenField Deployment - Using default role/auth_proto + register: deleted_result + tags: merged + +- name: Merged TC6 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + max_hops: 0 + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC6 - Merge a Switch using GreenField Deployment - Using default role/auth_proto cisco.dcnm.dcnm_inventory: &conf_def - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - preserve_config: False # boolean, default is true + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: merged + +- name: Merged TC6 - Prepare Config + ansible.builtin.set_fact: + ndfc_fabric_mergev_conf: + - seed_ip: "{{ test_data.sw1 }}" + role: leaf # default role in NDFC + delegate_to: localhost + tags: merged + +- name: Merged TC6 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC6 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_mergev_conf }}" + changed: "{{ merged_result.changed }}" register: result + tags: merged -- assert: - that: - - 'result.changed == true' - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -- name: MERGED - conf1 - GF - Idempotence +# TC - 7 +- name: Merged TC7 - Verify Idempotence cisco.dcnm.dcnm_inventory: *conf_def register: result + tags: merged - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' + tags: merged -- name: MERGED - setup - Clean up any existing devices +# TC - 8 +- name: Merged TC8 - Clean up Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - -- name: Add Switch with Border Gateways and MD5 to fabric + register: deleted_result + tags: merged + +- name: Merged TC8 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + max_hops: 0 + role: border_gateway + auth_proto: MD5 + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + role: border_gateway + auth_proto: MD5 + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC8 - Add Switch with Border Gateways and MD5 to Fabric cisco.dcnm.dcnm_inventory: &conf_role - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - max_hops: 0 - preserve_config: false - role: border_gateway - auth_proto: MD5 - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - - seed_ip: "{{ ansible_switch2 }}" - max_hops: 0 - preserve_config: false - role: border_gateway - auth_proto: MD5 - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - register: result - -- assert: - that: - - 'result.changed == true' + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: merged -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -- name: Wait for 40 secs - wait_for: - timeout: 40 +- name: Merged TC8 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC8 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_merge_conf }}" + changed: "{{ merged_result.changed }}" + register: result + tags: merged -- name: Add Switch with Border Gateways and MD5 to fabric - idempotence +# TC - 9 +- name: Merged TC9 - Verify Idempotence cisco.dcnm.dcnm_inventory: *conf_role register: result + tags: merged - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' + tags: merged -- name: MERGED - setup - Clean up any existing devices +# TC - 10 +- name: Merged TC10 - Clean up Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - -- name: MERGED - Merge a Switch using GreenField Deployment with non zero max hop - cisco.dcnm.dcnm_inventory: &conf_hop - fabric: "{{ ansible_it_fabric }}" + register: deleted_result + tags: merged + +- name: Merged TC10 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + max_hops: 2 + role: leaf + auth_proto: MD5 + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC10 - Merge a Switch using GreenField Deployment - Non-Zero Max Hop Config + cisco.dcnm.dcnm_inventory: &conf_mh + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 2 - role: leaf - preserve_config: False - register: result - -- assert: - that: - - 'result.changed == true' + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: merged -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -- name: MERGED - conf_hope - MH - Idempotence - cisco.dcnm.dcnm_inventory: *conf_hop +- name: Merged TC10 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: merged + +- name: Merged TC10 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_merge_conf }}" + changed: "{{ merged_result.changed }}" register: result + tags: merged + +# TC - 11 +- name: Merged TC11 - Merge a Switch using GreenField Deployment - Idempotence + cisco.dcnm.dcnm_inventory: *conf_mh + register: merged_result + tags: merged - assert: that: - - 'result.changed == false' - - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' + - 'merged_result.changed == false' + - 'merged_result.response == "The switch provided is already part of the fabric and cannot be created again"' + tags: merged -- name: MERGED - setup - Clean up any existing devices +# TC - 12 +- name: Merged TC12 - Clean up Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: deleted_result + tags: merged -- name: MERGED - Merge a Switch without seed_ip - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: merged - config: +# TC - 13 +- name: Merged TC13 - Prepare Config + ansible.builtin.set_fact: + switch_conf: - seed_ip: - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - register: result + role: leaf + auth_proto: MD5 + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC13 - Merge a Switch without seed_ip + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" ignore_errors: yes + register: merged_result + tags: merged - assert: that: - - 'result.changed == false' - - '"Invalid parameters in playbook: seed_ip : Required parameter not found" in result.msg' + - 'merged_result.changed == false' + - '"Invalid parameters in playbook: seed_ip : Required parameter not found" in merged_result.msg' + tags: merged + +# TC - 14 +- name: Merged TC14 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + auth_proto: MD5 + max_hops: 0 + role: invalid + delegate_to: localhost + tags: merged + +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged -- name: MERGED - Merge a Switch with invalid role choice +- name: Merged TC14 - Merge a Switch with Invalid Role cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: nnnnddd # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - register: result + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result ignore_errors: yes + tags: merged - assert: that: - - 'result.changed == false' - - '"Invalid choice provided" in result.msg' + - 'merged_result.changed == false' + - '"Invalid choice " in merged_result.msg' + tags: merged + +# TC - 15 +- name: Merged TC15 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + auth_proto: MD55DM + max_hops: 0 + role: leaf + delegate_to: localhost + tags: merged -- name: MERGED - Merge a Switch with invalid auth choice +- name: Import Configuration Prepare Tasks + vars: + file: merge + import_tasks: ../conf_prep_tasks.yml + tags: merged + +- name: Merged TC15 - Merge a Switch with invalid auth choice cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD55DM # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - register: result + config: "{{ ndfc_fabric_merge_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result ignore_errors: yes + tags: merged - assert: that: - - 'result.changed == false' - - '"Invalid choice provided" in result.msg' - + - 'merged_result.changed == false' + - '"Invalid choice " in merged_result.msg' + tags: merged -- name: MERGED - Merge a Switch without a config +# TC - 16 +- name: Merged TC16 - Merge a Switch without a config cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - register: result + register: merged_result ignore_errors: yes + tags: merged - assert: that: - - 'result.changed == false' - - '"config: element is mandatory for this state merged" in result.msg' + - 'merged_result.changed == false' + - '"config: element is mandatory for this state merged" in merged_result.msg' + tags: merged -############################################## -## CLEAN-UP ## -############################################## +# ---------------------------------------------- +# Cleanup Fabric Switches +# ---------------------------------------------- -- name: MERGED - setup - Clean up any existing devices +- name: Merged - Clean Up Switches from Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: result + tags: merged \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml index 2f46b99d3..7716e3e1f 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml @@ -1,94 +1,167 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" - -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" - -- name: OVERRIDDEN - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result - -- assert: - that: - - 'result.response.DATA != None' - -- name: OVERRIDDEN - setup - Clean up any existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted +--- +- name: Import DCNM Inventory Base Tasks + import_tasks: ../base_tasks.yml + tags: overridden + +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- + +# TC - 1 +- name: Overridden TC1 - Prepare Switches in Fabric - GreenField Deployment + cisco.dcnm.dcnm_inventory: &conf + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_base_conf }}" + deploy: "{{ test_data.deploy }}" + register: merged_result + tags: overridden -- name: OVERRIDDEN - Merge a Switch using GreenField Deployment +- name: Overridden TC1 - Query Inventory State in Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: overridden + +- name: Overridden TC1 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" + changed: " {{ merged_result.changed }}" register: result + tags: overridden -- assert: - that: - - 'result.changed == true' - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - -############################################## -## OVERRIDDEN ## -############################################## - -- name: OVERRIDDEN - Update a New Switch using GreenField Deployment - Delete and Create - default role - cisco.dcnm.dcnm_inventory: &conf_over - fabric: "{{ ansible_it_fabric }}" - state: overridden - config: - - seed_ip: "{{ ansible_switch2 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - preserve_config: False # boolean, default is true +# TC - 2 +- name: Overridden TC2 - Verify Idempotence + cisco.dcnm.dcnm_inventory: *conf register: result + tags: overridden - assert: that: - - 'result.changed == true' + - 'result.changed == false' + tags: overridden + +# TC - 3 +- name: Overridden TC3 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + role: spine + preserve_config: false + delegate_to: localhost + tags: overridden + +- name: Import Configuration Prepare Tasks + vars: + file: overridden + import_tasks: ../conf_prep_tasks.yml + tags: overridden + +- name: Overridden TC3 - Override Existing Switch - Removes Other Switches from Fabric + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: overridden + config: "{{ ndfc_fabric_overridden_conf }}" + deploy: "{{ test_data.deploy }}" + register: overridden_result + tags: overridden -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Overridden TC3 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: overridden + +- name: Overridden TC3 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_overridden_conf }}" + changed: "{{ overridden_result.changed }}" + register: result + tags: overridden + +# TC - 4 +- name: Overridden TC4 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + role: leaf + preserve_config: false + delegate_to: localhost + tags: overridden + +- name: Import Configuration Prepare Tasks + vars: + file: overridden + import_tasks: ../conf_prep_tasks.yml + tags: overridden + +- name: Overridden TC4 - New Role for the Existing Switch + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: overridden + config: "{{ ndfc_fabric_overridden_conf }}" + deploy: "{{ test_data.deploy }}" + register: overridden_result + tags: overridden -- name: OVERRIDDEN - conf1 - OV - Idempotence - cisco.dcnm.dcnm_inventory: *conf_over +- name: Overridden TC4 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: overridden + +- name: Overridden TC4 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_overridden_conf }}" + changed: "{{ overridden_result.changed }}" register: result + tags: overridden + +# TC - 5 +- name: Overridden TC5 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + preserve_config: false + delegate_to: localhost + tags: overridden + +- name: Import Configuration Prepare Tasks + vars: + file: overridden + import_tasks: ../conf_prep_tasks.yml + tags: overridden + +- name: Overridden TC5 - Unspecified Role for the Existing Switch (Default, Leaf) + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: overridden + config: "{{ ndfc_fabric_overridden_conf }}" + deploy: "{{ test_data.deploy }}" + register: overridden_result + tags: overridden - assert: that: - - 'result.changed == false' - - 'result.response == "The switch provided is already part of the fabric and there is no more device to delete in the fabric"' + - 'overridden_result.changed == false' + tags: overridden -############################################## -## CLEAN-UP ## -############################################## +# ---------------------------------------------- +# Cleanup Fabric Switches +# ---------------------------------------------- -- name: OVERRIDDEN - setup - Clean up any existing devices +- name: Overridden - Cleanup Fabric Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted \ No newline at end of file + fabric: "{{ test_data.test_fabric }}" + state: deleted + register: result + tags: overridden \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml index fb8c13708..5453d41a1 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml @@ -1,27 +1,39 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: +--- +- name: Test Entry Point - [dcnm_inventory - Poap] + ansible.builtin.debug: + msg: + - "----------------------------------------------------------------" + - "+ Executing Poap Tests - [dcnm_inventory] +" + - "----------------------------------------------------------------" + tags: poap + +- name: Poap - Setup Internal TestCase Variables + ansible.builtin.set_fact: + test_data: + test_fabric: "{{ ansible_it_fabric }}" + sw1: "{{ ansible_switch1 }}" + sw1_serial: "1ABC23DEFGH" + sw2: "{{ ansible_switch2 }}" + sw2_serial: "1ABC23DEFHI" + poap_model: "ABC-D1230a" + poap_version: "1.2(3)" + poap_hostname: "Poap-SW" + poap_modulesModel: "['ABC-D1230a']" + poap_gateway: "192.168.2.1/24" + sw3: "{{ ansible_switch3 }}" + deploy: "{{ deploy }}" poap_enabled: False - -- set_fact: poap_switch_present: False - -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" - -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" + found_fabric: False + delegate_to: localhost + tags: poap # Below commented tasks are sample tasks to enable Bootstrap and DHCP along with DHCP configs # Please make sure you provide correct values for required fields # Fabric config has many NDFC/DCNM auto generated values, so always GET the configs first # and then set the required values. -# -# - name: POAP MERGED - Get the configs of the fabric deployed. +# # +# - name: Poap Merged - Get the configs of the fabric deployed. # cisco.dcnm.dcnm_rest: # method: GET # path: "{{ rest_path }}" @@ -36,237 +48,256 @@ # result.response.DATA.nvPairs["MGMT_GW"] = "192.168.1.1" # result.response.DATA.nvPairs["MGMT_PREFIX"] = "24" # -# - name: POAP MERGED - Configure Bootstrap and DHCP on Fabric +# - name: Poap Merged - Configure Bootstrap and DHCP on Fabric # cisco.dcnm.dcnm_rest: # method: PUT # path: "{{ rest_path }}" # json_data: "{{ result.response.DATA }}" # -- name: POAP MERGED - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result - -- assert: +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- +# Base Tests +- name: Poap Base Task - Query Fabric Existence + cisco.dcnm.dcnm_fabric: + state: query + config: + - FABRIC_NAME: "{{ test_data.test_fabric }}" + register: query_result + tags: poap + +- name: Poap Base Task - Check Fabric + ansible.builtin.set_fact: + found_fabric: True + fabric_data: "{{ item }}" + when: item['fabricName'] == "{{ test_data.test_fabric }}" + loop: "{{ query_result.response[0].DATA }}" + tags: poap + +- name: Poap Base Task - Assert Fabric Existence + assert: that: - - 'result.response.DATA != None' + - found_fabric == true + fail_msg: "Fabric '{{ test_data.test_fabric }}' not found." + tags: poap -- set_fact: +- name: Poap Base Task - Set Variable + ansible.builtin.set_fact: poap_enabled: True - when: result.response.DATA.nvPairs["BOOTSTRAP_ENABLE"] == "true" + when: fabric_data.nvPairs["BOOTSTRAP_ENABLE"] == "true" + tags: poap -- name: POAP MERGED - setup - Clean up any existing devices +- name: Poap Base Task - Prepare Validate Config + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: + delegate_to: localhost + tags: poap + +- name: Poap Base Task - Clean Up Existing Devices in Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: deleted_result + tags: poap -############################################## -## MERGED ## -############################################## +- name: Poap Base Task - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: poap + +- name: Poap Base Task - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" + register: result + tags: poap -- name: POAP MERGED - Pre-provision switch Configuration - cisco.dcnm.dcnm_inventory: &conf_prepro - fabric: '{{ ansible_it_fabric }}' - state: merged # Only 2 options supported merged/query for poap config - config: - # All the values below are mandatory if poap configuration is being done - state is merged - - seed_ip: '{{ ansible_prepro_switch }}' +# ---------------------------------------------- # +# Merged # +# ---------------------------------------------- # + +# TC - 1 +- name: Poap TC1 - Prepare Configuration + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" user_name: '{{ switch_username }}' password: '{{ switch_password }}' - role: border_gateway + role: border poap: - - preprovision_serial: '{{ ansible_prepro_serial }}' - model: '{{ ansible_prepro_model }}' - version: '{{ ansible_prepro_swversion }}' - hostname: '{{ ansible_prepro_hostname }}' - config_data: - modulesModel: '{{ ansible_modules_model }}' - gateway: '{{ ansible_bstrap_gateway }}' + - preprovision_serial: "{{ test_data.sw2_serial }}" + model: "{{ test_data.poap_model }}" + version: "{{ test_data.poap_version }}" + hostname: "{{ test_data.poap_hostname }}" + config_data: + modulesModel: ["N9K-C9300v"] + gateway: "10.15.15.1/24" when: poap_enabled == True - register: result + delegate_to: localhost + tags: poap -- assert: - that: - - 'result.changed == true' - when: (poap_enabled == True) +- name: Import Configuration Prepare Tasks + vars: + file: poap + import_tasks: ../conf_prep_tasks.yml + when: poap_enabled == True + tags: poap -- assert: - that: - - 'item["RETURN_CODE"] == 200' - when: (poap_enabled == True) - loop: '{{ result.response }}' +- name: Poap TC1 - Merged - Pre-provisioned Switch Configuration + cisco.dcnm.dcnm_inventory: &conf_prepro + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_poap_conf }}" + deploy: "{{ test_data.deploy }}" + when: poap_enabled == True + register: merged_result + tags: poap -- name: POAP MERGED - Pre-provision switch Configuration - Idempotence - cisco.dcnm.dcnm_inventory: *conf_prepro +- name: Poap TC1 - Merged - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + when: poap_enabled == True + register: query_result + tags: poap + +- name: Poap TC1 - Merged - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_poap_conf }}" + changed: "{{ merged_result.changed }}" when: poap_enabled == True register: result + tags: poap + +# TC - 2 +- name: Poap TC2 - Merged - Verify Idempotence + cisco.dcnm.dcnm_inventory: *conf_prepro + when: poap_enabled == True + register: merged_result + tags: poap - assert: that: - - 'result.changed == false' - - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' - when: (poap_enabled == True) - -- name: POAP MERGED - setup - Clean up any existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted - when: (poap_enabled == True) + - 'merged_result.changed == false' + - 'merged_result.response == "The switch provided is already part of the fabric and cannot be created again"' + when: poap_enabled == True + tags: poap -- name: POAP MERGED - Query for POAP enabled swicthes +# TC - 3 +- name: Poap TC3 - Query for POAP enabled swicthes cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" query_poap: True state: query when: poap_enabled == True - register: result + register: query_result + tags: poap - assert: that: - - 'result.response != None' + - 'query_result.response != None' when: poap_enabled == True + tags: poap -- name: Check poap query for switches +- name: Poap TC3 - Check Query for POAP enabled swicthes set_fact: poap_switch_present: True - when: (poap_enabled == True and (item['serialNumber'] == '{{ ansible_poap_serial }}')) - loop: '{{ result.response }}' + when: (poap_enabled == True and (item['serialNumber'] == "{{ test_data.sw2_serial }}")) + loop: "{{ query_result.response }}" ignore_errors: yes + tags: poap -- name: POAP MERGED - Poap, Pre-provision and discovered switch Configuration - cisco.dcnm.dcnm_inventory: &conf_poap - fabric: '{{ ansible_it_fabric }}' - state: merged # Only 2 options supported merged/query for poap config - config: - # All the values below are mandatory if poap configuration is being done - state is merged - - seed_ip: '{{ ansible_poap_switch }}' - user_name: '{{ switch_username }}' - password: '{{ switch_password }}' +# TC - 4 +- name: Poap TC4 - Prepare Configuration + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" role: border_gateway poap: - - serial_number: '{{ ansible_poap_serial }}' - model: '{{ ansible_poap_model }}' - version: '{{ ansible_poap_swversion }}' - hostname: '{{ ansible_poap_hostname }}' + - serial_number: "{{ test_data.sw1_serial }}" + model: "{{ test_data.poap_model }}" + version: "{{ test_data.poap_version }}" + hostname: "{{ test_data.poap_hostname }}" config_data: - modulesModel: '{{ ansible_modules_model }}' - gateway: '{{ ansible_bstrap_gateway }}' - - seed_ip: '{{ ansible_switch1 }}' - user_name: '{{ switch_username }}' - password: '{{ switch_password }}' + modulesModel: "{{ test_data.poap_modulesModel }}" + gateway: "{{ test_data.poap_gateway }}" + - seed_ip: "{{ test_data.sw3 }}" auth_proto: MD5 - max_hops: 0 - preserve_config: False role: spine - - seed_ip: '{{ ansible_prepro_switch }}' - user_name: '{{ switch_username }}' - password: '{{ switch_password }}' + - seed_ip: "{{test_data.sw2}}" role: border poap: - - preprovision_serial: '{{ ansible_prepro_serial }}' - model: '{{ ansible_prepro_model }}' - version: '{{ ansible_prepro_swversion }}' - hostname: '{{ ansible_prepro_hostname }}' + - preprovision_serial: "{{ test_data.sw2_serial }}" + model: "{{ test_data.poap_model }}" + version: "{{ test_data.poap_version }}" + hostname: "{{ test_data.poap_hostname }}" config_data: - modulesModel: '{{ ansible_modules_model }}' - gateway: '{{ ansible_bstrap_gateway }}' + modulesModel: "{{ test_data.poap_modulesModel }}" + gateway: "{{ test_data.poap_gateway }}" when: (poap_enabled == True and poap_switch_present == True) - register: result + delegate_to: localhost + tags: poap -- assert: - that: - - 'result.changed == true' +- name: Import Configuration Prepare Tasks + vars: + file: poap + import_tasks: ../conf_prep_tasks.yml + when: poap_enabled == True + tags: poap + +- name: Poap TC4 - Merge Config + cisco.dcnm.dcnm_inventory: &conf_poap + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_poap_conf }}" + deploy: "{{ test_data.deploy }}" when: (poap_enabled == True and poap_switch_present == True) + register: merged_result + tags: poap -- assert: - that: - - 'item["RETURN_CODE"] == 200' +- name: Poap TC4 - Merged - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + when: poap_enabled == True + register: query_result + tags: poap + +- name: Poap TC4 - Merged - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_poap_conf }}" + changed: "{{ merged_result.changed }}" when: (poap_enabled == True and poap_switch_present == True) - loop: '{{ result.response }}' + register: result + tags: poap -- name: POAP MERGED - Poap, Pre-provision and discovered switch Configuration - Idempotence +# TC - 5 +- name: Poap TC5 - Verify Idempotence cisco.dcnm.dcnm_inventory: *conf_poap when: (poap_enabled == True and poap_switch_present == True) register: result + tags: poap - assert: that: - 'result.changed == false' - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' when: (poap_enabled == True and poap_switch_present == True) + tags: poap -- name: POAP MERGED - setup - Clean up any existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted - when: (poap_enabled == True) - -############################################# -# QUERY ## -############################################# +# ---------------------------------------------- +# Cleanup Fabric Switches +# ---------------------------------------------- -- name: POAP QUERY - Pre-provision switch Configuration +- name: Poap - Clean Up Existing Devices cisco.dcnm.dcnm_inventory: - fabric: '{{ ansible_it_fabric }}' - state: merged # Only 2 options supported merged/query for poap config - config: - # All the values below are mandatory if poap configuration is being done - state is merged - - seed_ip: '{{ ansible_prepro_switch }}' - user_name: '{{ switch_username }}' - password: '{{ switch_password }}' - role: border_gateway - poap: - - preprovision_serial: '{{ ansible_prepro_serial }}' - model: '{{ ansible_prepro_model }}' - version: '{{ ansible_prepro_swversion }}' - hostname: '{{ ansible_prepro_hostname }}' - config_data: - modulesModel: '{{ ansible_modules_model }}' - gateway: '{{ ansible_bstrap_gateway }}' - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - when: (poap_enabled == True) - register: result - -- assert: - that: - - 'result.changed == true' - when: (poap_enabled == True) - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - when: (poap_enabled == True) - loop: '{{ result.response }}' - -- name: POAP QUERY - Query a Switch without a config element - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: query - when: (poap_enabled == True) - register: result - -- assert: - that: - - '"{{ ansible_prepro_switch }}" or "{{ ansible_switch1 }}" in result.response[0].ipAddress' - - '"border gateway" or "leaf" in result.response[0].switchRole' - - '"{{ ansible_prepro_switch }}" or "{{ ansible_switch1 }}" in result.response[1].ipAddress' - - '"border gateway" or "leaf" in result.response[1].switchRole' - when: (poap_enabled == True) - -############################################## -## CLEAN-UP ## -############################################## - -- name: POAP QUERY - cleanup - Clean up any existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + when: (poap_enabled == True) + register: deleted_result + tags: poap \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml index 728e05b30..daae18cf0 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml @@ -1,198 +1,238 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" - -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" - -- name: QUERY - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result +--- +- name: Import DCNM Inventory Base Tasks + import_tasks: ../base_tasks.yml + tags: query -- assert: - that: - - 'result.response.DATA != None' +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- -- name: QUERY - setup - Clean up any existing devices +# TC - 1 +- name: Query TC1 - Merge a Switch using GreenField Deployment cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_base_conf }}" + deploy: "{{ test_data.deploy }}" + register: create_result + tags: query -- name: QUERY - Merge a Switch using GreenField Deployment +- name: Query TC1 - Query Inventory State in Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: query + +- name: Query TC1 - Validate Test Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" + changed: "{{ create_result.changed }}" register: result - -- assert: - that: - - 'result.changed == true' - -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' - - -############################################# -# QUERY ## -############################################# - -- name: QUERY - Query a Switch - Hostname and Role must match + tags: query + +# TC - 2 +- name: Query TC2 - Prepare Test Config + ansible.builtin.set_fact: + ndfc_fabric_query_conf: + - seed_ip: "{{ test_data.sw1 }}" + role: leaf + delegate_to: localhost + tags: query + +- name: Query TC2 - Query a Switch - Verify HostIP and Role Match cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query - config: - - seed_ip: "{{ ansible_switch1 }}" - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] + config: "{{ ndfc_fabric_query_conf }}" + register: query_result + tags: query + +- name: Query TC2 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_query_conf }}" register: result + tags: query -- assert: - that: - - 'result.response[0].ipAddress == "{{ ansible_switch1 }}"' - - 'result.response[0].switchRole == "leaf"' - -- name: QUERY - Query a Switch without a config element +# TC - 3 +- name: Query TC3 - Query a Switch without a Config element cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query + register: query_result + tags: query + +- name: Query TC3 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" register: result + tags: query -- assert: - that: - - 'result.response[0].ipAddress == "{{ ansible_switch1 }}"' - - 'result.response[0].switchRole == "leaf"' +# TC - 4 +- name: Query TC4 - Prepare Test Config + ansible.builtin.set_fact: + ndfc_fabric_query_conf: + - seed_ip: "{{ test_data.sw1 }}" + delegate_to: localhost + tags: query -- name: QUERY - Query a Switch without role - Role does not need to match +- name: Query TC4 - Query a Switch Without Role - Role Mismatch Ignored cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query - config: - - seed_ip: "{{ ansible_switch1 }}" + config: "{{ ndfc_fabric_query_conf }}" + register: query_result + tags: query + +- name: Query TC4 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_query_conf }}" + mode: "ip" register: result + tags: query -- assert: - that: - - 'result.response[0].ipAddress == "{{ ansible_switch1 }}"' +# TC - 5 +- name: Query TC5 - Prepare Test Config + ansible.builtin.set_fact: + ndfc_fabric_query_conf: + - role: leaf + delegate_to: localhost + tags: query -- name: QUERY - Query a Switch without seed ip - Seed IP does not need to match +- name: Query TC5 - Query Fabric Without Seed_ip - IP Mismatch Ignored cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query - config: - - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] + config: "{{ ndfc_fabric_query_conf }}" + register: query_result + tags: query + +- name: Query TC5 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_query_conf }}" + mode: "role" register: result + tags: query -- assert: - that: - - 'result.response[0].switchRole == "leaf"' - -- name: QUERY - Query a Switch with wrong role +# TC - 6 +- name: Query TC6 - Query a Switch with Incorrect Role cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query config: - - seed_ip: "{{ ansible_switch1 }}" - role: spine # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - register: result + - seed_ip: "{{ test_data.sw1 }}" + role: spine + register: query_result + tags: query - assert: that: - - '"The queried switch is not part of the fabric configured" in result.response' + - '"The queried switch is not part of the fabric configured" in query_result.response' + tags: query -- name: QUERY - Delete all Switch without config element +# TC - 7 +- name: Query TC7 - Delete all Switches from Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - register: result + register: deleted_result + tags: query -- assert: - that: - - 'result.changed == true' - - 'result.response[0].RETURN_CODE == 200' +- name: Query TC7 - Prepare Test Config + ansible.builtin.set_fact: + ndfc_fabric_query_conf: + delegate_to: localhost + tags: query -- name: QUERY - Query a non available Switch +- name: Query TC7 - Query Fabric State cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query - config: - - seed_ip: "{{ ansible_switch1 }}" - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] + config: "{{ ndfc_fabric_query_conf }}" + register: query_result + tags: query + +- name: Query TC7 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_query_conf }}" + changed: "{{ deleted_result.changed }}" register: result + tags: query + +# TC - 8 +- name: Query TC8 - Query a non available Switch + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: query + config: + - seed_ip: "{{ test_data.sw1 }}" + role: leaf + register: query_result + tags: query - assert: that: - - '"The queried switch is not part of the fabric configured" in result.response' - -- name: Add Switch with Border Gateways and MD5 to fabric - cisco.dcnm.dcnm_inventory: &conf_role - fabric: "{{ ansible_it_fabric }}" - state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" + - '"The queried switch is not part of the fabric configured" in query_result.response' + tags: query + +# TC - 9 +- name: Query TC9 - Prepare Config + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" max_hops: 0 - preserve_config: false - role: border_gateway auth_proto: MD5 - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - - seed_ip: "{{ ansible_switch2 }}" - max_hops: 0 - preserve_config: false role: border_gateway + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 auth_proto: MD5 - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - register: result - + role: border_gateway + delegate_to: localhost + tags: query -- assert: - that: - - 'result.changed == true' +- name: Import Configuration Prepare Tasks + vars: + file: query + import_tasks: ../conf_prep_tasks.yml + tags: query -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Query TC9 - Add Switch with Border Gateways to Fabric + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_query_conf }}" + deploy: "{{ test_data.deploy }}" + register: create_result + tags: query -- name: QUERY - Query a Switch without a config element +- name: Query TC9 - Query Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query + register: query_result + tags: query + +- name: Query TC9 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_query_conf }}" + changed: "{{ create_result.changed }}" register: result + tags: query -- assert: - that: - - '"{{ ansible_switch2 }}" or "{{ ansible_switch1 }}" in result.response[0].ipAddress' - - 'result.response[0].switchRole == "border gateway"' - - '"{{ ansible_switch2 }}" or "{{ ansible_switch1 }}" in result.response[1].ipAddress' - - 'result.response[1].switchRole == "border gateway"' - -############################################## -## CLEAN-UP ## -############################################## +# ---------------------------------------------- +# Cleanup Fabric Switches +# ---------------------------------------------- -- name: QUERY - cleanup - Clean up any existing devices +- name: Query - Cleanup Fabric cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: result + tags: query \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml index c1ad424e2..38f43db1f 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml @@ -1,137 +1,220 @@ -############################################## -## SETUP ## -############################################## - -- set_fact: - rma_enabled: False +--- +- name: Test Entry Point - [dcnm_inventory - RMA] + ansible.builtin.debug: + msg: + - "----------------------------------------------------------------" + - "+ Executing RMA Tests - [dcnm_inventory] +" + - "----------------------------------------------------------------" + tags: rma + +- name: RMA - Setup Internal TestCase Variables + ansible.builtin.set_fact: + test_data: + test_fabric: "{{ ansible_it_fabric }}" + sw1: "{{ ansible_switch1 }}" + sw1_serial: "1ABC23DEFGH" + sw1_rma_serial: "1ABC23DERMA" + rma_model: "SW1-K1234v" + rma_version: "12.3(4)" + rma_hostname: "RMA-SW" + rma_modulesModel: "['SW1-K1234v']" + rma_gateway: "192.168.2.1/24" + deploy: "{{ deploy }}" + rma_enabled: False + rma_switch_present: False + found_fabric: False + delegate_to: localhost + tags: rma + +# - name: RMA - Setup Rest Variables +# ansible.builtin.set_fact: +# - set_fact: +# mode_maintenance: "/rest/control/fabrics/{{ test_data.test_fabric }}/switches/{{ ansible_switch1_serial }}/maintenance-mode" +# mode_deploy: "/rest/control/fabrics/{{ test_data.test_fabric }}/switches/{{ ansible_switch1_serial }}/deploy-maintenance-mode" +# when: controller_version == "11" +# tags: rma + +- name: RMA - Setup Rest Variables + ansible.builtin.set_fact: + mode_maintenance: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ test_data.test_fabric }}/switches/{{ test_data.sw1_serial }}/maintenance-mode" + mode_deploy: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ test_data.test_fabric }}/switches/{{ test_data.sw1_serial }}/deploy-maintenance-mode" + tags: rma +# when: controller_version >= "12" + +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- +# Base Tests +- name: RMA Base Task - Query Fabric Existence + cisco.dcnm.dcnm_fabric: + state: query + config: + - FABRIC_NAME: "{{ test_data.test_fabric }}" + register: query_result + tags: rma + +- name: RMA Base Task - Check Fabric + ansible.builtin.set_fact: + found_fabric: True + fabric_data: "{{ item }}" + when: item['fabricName'] == "{{ test_data.test_fabric }}" + loop: "{{ query_result.response[0].DATA }}" + tags: rma + +- name: RMA Base Task - Assert Fabric Existence + assert: + that: + - found_fabric == true + fail_msg: "Fabric '{{ test_data.test_fabric }}' not found." + tags: rma -- set_fact: - rma_switch_present: False +- name: RMA Base Task - Set Variable + ansible.builtin.set_fact: + rma_enabled: True + when: fabric_data.nvPairs["BOOTSTRAP_ENABLE"] == "true" + tags: rma -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - mode_maintenance: "/rest/control/fabrics/test_net/switches/{{ ansible_switch1_serial }}/maintenance-mode" - mode_deploy: "/rest/control/fabrics/test_net/switches/{{ ansible_switch1_serial }}/deploy-maintenance-mode" - when: controller_version == "11" +# TC1 +- name: RMA TC1 - Prepare Validate Config + ansible.builtin.set_fact: + ndfc_fabric_delete_conf: + delegate_to: localhost + tags: rma -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - mode_maintenance: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/test_net/switches/{{ ansible_switch1_serial }}/maintenance-mode" - mode_deploy: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/test_net/switches/{{ ansible_switch1_serial }}/deploy-maintenance-mode" - when: controller_version >= "12" +- name: RMA TC1 - Clean Up Existing Switches + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: deleted + register: deleted_result + tags: rma -- name: RMA - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" +- name: RMA TC1 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: rma + +- name: RMA TC1 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_delete_conf }}" register: result + tags: rma -- assert: - that: - - 'result.response.DATA != None' +# Tasks to add a switch to fabric and to configure and deploy +# the switch in maintenance mode. +# Please note that the switch should be shutdown after configuring it +# in maintenance mode -- set_fact: - rma_enabled: True - when: result.response.DATA.nvPairs["BOOTSTRAP_ENABLE"] == "true" +# TC2 +- name: RMA TC2 - Prepare Configuration + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" + auth_proto: MD5 + max_hops: 0 + when: rma_enabled == True + delegate_to: localhost + tags: rma + +- name: Import Configuration Prepare Tasks + vars: + file: rma + import_tasks: ../conf_prep_tasks.yml + when: rma_enabled == True + tags: rma -#- name: RMA - setup - Clean up any existing devices -# cisco.dcnm.dcnm_inventory: -# fabric: "{{ ansible_it_fabric }}" -# state: deleted +- name: RMA TC2 - Add Switch to the Fabric + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + state: merged + config: "{{ ndfc_fabric_rma_conf }}" + deploy: "{{ test_data.deploy }}" + when: rma_enabled == True + register: merged_result + tags: rma -- debug: msg="!!! WARNING !!! Skipping Test Because rma_enabled Setting is False" - when: rma_enabled == False +- name: RMA TC2 - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + when: rma_enabled == True + register: query_result + tags: rma + +- name: RMA TC2 - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_rma_conf }}" + mode: "ip" + register: result + when: rma_enabled == True + tags: rma -- name: RMA - Query for POAP enabled swicthes +- name: RMA TC2 - Query for POAP enabled swicthes cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" query_poap: True state: query when: rma_enabled == True - register: result + register: query_result + tags: rma - assert: that: - - 'result.response != None' + - 'query_result.response != None' when: rma_enabled == True + tags: rma -- name: RMA - Check poap query for switches +- name: RMA TC2 - Check Query for POAP enabled swicthes set_fact: rma_switch_present: True - when: (rma_enabled == True and (item['serialNumber'] == '{{ ansible_rma_serial }}')) - loop: '{{ result.response }}' + when: (rma_enabled == True and (item['serialNumber'] == "{{ test_data.sw1_serial }}")) + loop: "{{ query_result.response }}" ignore_errors: yes + tags: rma + +- name: RMA TC2 - Configure Maintenance Mode in Switch + cisco.dcnm.dcnm_rest: + method: POST + path: "{{ mode_maintenance }}" + when: (rma_enabled == True and rma_switch_present == True) + register: result + tags: rma -############################################## -## RMA TEST ## -############################################## +- name: RMA TC2 - Configure Deploy Mode in Switch + cisco.dcnm.dcnm_rest: + method: POST + path: "{{ mode_deploy }}" + when: (rma_enabled == True and rma_switch_present == True) + register: result + tags: rma -# Sample plays to add a switch to fabric and to configure and deploy -# the switch in maintenance mode -# -# Please note that the switch should be shutdown after configuring it -# in maintenance mode -# -#- name: RMA - Add switch to the fabric -# cisco.dcnm.dcnm_inventory: -# fabric: '{{ ansible_it_fabric }}' -# state: merged -# config: -# - seed_ip: '{{ ansible_switch1 }}' -# user_name: '{{ switch_username }}' -# password: '{{ switch_password }}' -# auth_proto: MD5 -# max_hops: 0 -# preserve_config: False -# when: (rma_enabled == True and rma_switch_present == True) -# register: result -# -#- assert: -# that: -# - 'result.changed == true' -# when: (rma_enabled == True and rma_switch_present == True) -# -#- assert: -# that: -# - 'item["RETURN_CODE"] == 200' -# when: (rma_enabled == True and rma_switch_present == True) -# loop: '{{ result.response }}' -# -#- name: RMA - Configure maintenance mode in switch. -# cisco.dcnm.dcnm_rest: -# method: POST -# path: "{{ mode_maintenance }}" -# when: (rma_enabled == True and rma_switch_present == True) -# register: result -# -#- name: RMA - Configure maintenance mode in switch. -# cisco.dcnm.dcnm_rest: -# method: POST -# path: "{{ mode_deploy }}" -# when: (rma_enabled == True and rma_switch_present == True) -# register: result -# -#- name: RMA - sleep for 5 minute -# wait_for: -# timeout: 300 +- name: RMA TC2 - sleep for 1 minute + wait_for: + timeout: 60 + tags: rma + +# TC3 - block: - - name: RMA - RMA the existing switch + - name: RMA TC3 - RMA the Existing Switch cisco.dcnm.dcnm_inventory: - fabric: '{{ ansible_it_fabric }}' + fabric: '{{ test_data.test_fabric }}' state: merged config: - - seed_ip: '{{ ansible_switch1 }}' + - seed_ip: '{{ test_data.sw1 }}' user_name: '{{ switch_username }}' password: '{{ switch_password }}' rma: - - serial_number: '{{ ansible_rma_serial }}' - old_serial: '{{ ansible_switch1_serial }}' - model: '{{ ansible_rma_model }}' - version: '{{ ansible_rma_swversion }}' - hostname: '{{ ansible_rma_hostname }}' + - serial_number: '{{ test_data.sw1_rma_serial }}' + old_serial: '{{ test_data.sw1_serial }}' + model: '{{ test_data.rma_model }}' + version: '{{ test_data.rma_model }}' + hostname: '{{ test_data.rma_hostname }}' config_data: - modulesModel: '{{ ansible_rma_modules }}' - gateway: '{{ ansible_bstrap_gateway }}' + modulesModel: '{{ test_data.rma_modulesModel }}' + gateway: '{{ test_data.rma_gateway }}' register: result - assert: @@ -143,12 +226,15 @@ - 'item["RETURN_CODE"] == 200' loop: '{{ result.response }}' when: (rma_enabled == True and rma_switch_present == True) + tags: rma -############################################## -## CLEAN-UP ## -############################################## +# ---------------------------------------------- +# Cleanup Fabric Switches +# ---------------------------------------------- -- name: RMA - cleanup - Clean up any existing devices +- name: RMA - Clean Up - Remove Existing Switches cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted + register: result + tags: rma \ No newline at end of file diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml index 6043ad44c..c358f3473 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml @@ -1,68 +1,44 @@ -############################################## -## SETUP ## -############################################## +--- -- set_fact: - rest_path: "/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version == "11" +- name: Import DCNM Inventory Base Tasks + import_tasks: ../base_tasks.yml tags: sanity -- set_fact: - rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ ansible_it_fabric }}" - when: controller_version >= "12" - tags: sanity - -- name: SANITY- MERGED - Verify if fabric is deployed. - cisco.dcnm.dcnm_rest: - method: GET - path: "{{ rest_path }}" - register: result - tags: sanity - -- assert: - that: - - 'result.response.DATA != None' - tags: sanity +# ---------------------------------------------- +# Run Test Cases +# ---------------------------------------------- -- name: SANITY- DELETED - setup - Clean up existing devices - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - state: deleted - register: result - tags: sanity +# ---------------------------------------------- # +# Merged # +# ---------------------------------------------- # -############################################## -## MERGED ## -############################################## - -- name: SANITY- MERGED - Merge a Switch using GreenField Deployment +# TC - 1 +- name: Sanity TC1 - Merged - Prepare Switches in Fabric - GreenField Deployment cisco.dcnm.dcnm_inventory: &conf - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: merged - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - preserve_config: False # boolean, default is true - register: result + config: "{{ ndfc_fabric_base_conf }}" + deploy: "{{ test_data.deploy }}" + register: create_result tags: sanity -- assert: - that: - - 'result.changed == true' +- name: Sanity TC1 - Merged - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result tags: sanity -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Sanity TC1 - Merged - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_base_conf }}" + changed: "{{ create_result.changed }}" + register: result tags: sanity -- name: SANITY- MERGED - conf1 - GF - Idempotence +# TC - 2 +- name: Sanity TC2 - Merged - Idempotence cisco.dcnm.dcnm_inventory: *conf register: result tags: sanity @@ -73,59 +49,82 @@ - 'result.response == "The switch provided is already part of the fabric and cannot be created again"' tags: sanity -############################################# -# QUERY ## -############################################# +# ---------------------------------------------- # +# Query # +# ---------------------------------------------- # + +# TC - 3 +- name: Sanity TC3 - Query - Prepare Conf + ansible.builtin.set_fact: + ndfc_fabric_sanity_conf: + - seed_ip: "{{ test_data.sw1 }}" + role: leaf + delegate_to: localhost + tags: sanity -- name: SANITY- QUERY - Query a Switch - Hostname and Role must match +- name: Sanity TC3 - Query - Query a Switch - Hostname and Role must match cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: query - config: - - seed_ip: "{{ ansible_switch1 }}" - role: leaf # default is Leaf - choose from [Leaf, Spine, Border, Border Spine, Border Gateway, Border Gateway Spine - # Super Spine, Border Super Spine, Border Gateway Super Spine] - register: result + config: "{{ ndfc_fabric_sanity_conf }}" + register: query_result tags: sanity -- assert: - that: - - 'result.response[0].ipAddress == "{{ ansible_switch1 }}"' - - 'result.response[0].switchRole == "leaf"' - tags: sanity +- name: Sanity TC3 - Query - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_sanity_conf }}" + changed: "{{ create_result.changed }}" + register: result + tags: sanity +# ---------------------------------------------- # +# Overridden # +# ---------------------------------------------- # +# TC - 4 +- name: Sanity TC4 - Overridden - Prepare Conf + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw2 }}" + max_hops: 0 + role: leaf + preserve_config: false + delegate_to: localhost + tags: sanity -############################################## -## OVERRIDDEN ## -############################################## +- name: Import Configuration Prepare Tasks + vars: + file: sanity + import_tasks: ../conf_prep_tasks.yml + tags: sanity -- name: SANITY- OVERRIDDEN - Update a New Switch using GreenField Deployment - Delete and Create - default role +- name: Sanity TC4 - Overridden - Update a New Switch using GreenField Deployment - Delete and Create - default role cisco.dcnm.dcnm_inventory: &conf_over - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: overridden - config: - - seed_ip: "{{ ansible_switch2 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - preserve_config: False # boolean, default is true + config: "{{ ndfc_fabric_sanity_conf }}" + deploy: "{{ test_data.deploy }}" register: result tags: sanity -- assert: - that: - - 'result.changed == true' - tags: sanity +- name: Sanity TC4 - Overridden - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: sanity -- assert: - that: - - 'item["RETURN_CODE"] == 200' - loop: '{{ result.response }}' +- name: Sanity TC4 - Overridden - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_sanity_conf }}" + changed: "{{ create_result.changed }}" + register: result tags: sanity -- name: SANITY- OVERRIDDEN - conf1 - OV - Idempotence +# TC - 5 +- name: Sanity TC5 - Overridden - Idempotence cisco.dcnm.dcnm_inventory: *conf_over register: result tags: sanity @@ -136,48 +135,78 @@ - 'result.response == "The switch provided is already part of the fabric and there is no more device to delete in the fabric"' tags: sanity -############################################## -## CLEAN-UP ## -############################################## +# ---------------------------------------------- # +# Clean-up # +# ---------------------------------------------- # -- name: SANITY- DELETED - setup - Clean up existing devices +# TC - 6 +- name: Sanity TC6 - Deleted - Clean up Existing devices cisco.dcnm.dcnm_inventory: &clean - fabric: "{{ ansible_it_fabric }}" + fabric: "{{ test_data.test_fabric }}" state: deleted - config: - - seed_ip: "{{ ansible_switch2 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" - max_hops: 0 - preserve_config: False # boolean, default is true + config: "{{ ndfc_fabric_sanity_conf }}" + register: deleted_result + tags: sanity + +- name: Sanity TC6 - Reset - Prepare Conf + ansible.builtin.set_fact: + ndfc_fabric_sanity_conf: + delegate_to: localhost + tags: sanity + +- name: Sanity TC6 - Deleted - Query Inventory State in Fabric + cisco.dcnm.dcnm_inventory: + state: query + fabric: "{{ test_data.test_fabric }}" + register: query_result + tags: sanity + +- name: Sanity TC6 - Deleted - Validate NDFC Data + cisco.dcnm.tests.integration.ndfc_inventory_validate: + ndfc_data: "{{ query_result }}" + test_data: "{{ ndfc_fabric_sanity_conf }}" + changed: "{{ deleted_result.changed }}" register: result tags: sanity -- name: SANITY- DELETED - conf1 - OV - Idempotence +# TC - 7 +- name: Sanity TC7 - Deleted - Idempotence cisco.dcnm.dcnm_inventory: *clean register: result tags: sanity -############################################## -## RESET FABRIC ## -############################################## +- assert: + that: + - 'result.changed == false' + - 'result.response == "The switch provided is not part of the fabric and cannot be deleted"' -- name: SANITY- RESET - setup switches in fabric - cisco.dcnm.dcnm_inventory: - fabric: "{{ ansible_it_fabric }}" - config: - - seed_ip: "{{ ansible_switch1 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" +# ---------------------------------------------- # +# Reset Fabric # +# ---------------------------------------------- # + +# TC - 8 +- name: Sanity TC8 - Reset - Prepare Conf + ansible.builtin.set_fact: + switch_conf: + - seed_ip: "{{ test_data.sw1 }}" max_hops: 0 - preserve_config: False # boolean, default is true - - seed_ip: "{{ ansible_switch2 }}" - auth_proto: MD5 # choose from [MD5, SHA, MD5_DES, MD5_AES, SHA_DES, SHA_AES] - user_name: "{{ switch_username }}" - password: "{{ switch_password }}" + preserve_config: false + - seed_ip: "{{ test_data.sw2 }}" max_hops: 0 - preserve_config: False # boolean, default is true + preserve_config: false + delegate_to: localhost + tags: sanity + +- name: Import Configuration Prepare Tasks + vars: + file: sanity + import_tasks: ../conf_prep_tasks.yml + tags: sanity + +- name: Sanity TC8 - Reset - Setup Switches in Fabric + cisco.dcnm.dcnm_inventory: + fabric: "{{ test_data.test_fabric }}" + config: "{{ ndfc_fabric_sanity_conf }}" register: result tags: sanity + \ No newline at end of file diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt index 833ac9cc5..065cb862c 100644 --- a/tests/sanity/ignore-2.17.txt +++ b/tests/sanity/ignore-2.17.txt @@ -1,3 +1,6 @@ +plugins/action/tests/integration/ndfc_inventory_validate.py action-plugin-docs +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.10!skip +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.11!skip plugins/action/tests/integration/ndfc_network_validate.py action-plugin-docs plugins/action/tests/integration/ndfc_network_validate.py import-3.10!skip plugins/action/tests/integration/ndfc_network_validate.py import-3.11!skip diff --git a/tests/sanity/ignore-2.18.txt b/tests/sanity/ignore-2.18.txt index 0678bbd23..9f7306bbb 100644 --- a/tests/sanity/ignore-2.18.txt +++ b/tests/sanity/ignore-2.18.txt @@ -1,3 +1,5 @@ +plugins/action/tests/integration/ndfc_inventory_validate.py action-plugin-docs +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.11!skip plugins/action/tests/integration/ndfc_network_validate.py action-plugin-docs plugins/action/tests/integration/ndfc_network_validate.py import-3.11!skip plugins/action/tests/integration/ndfc_pc_members_validate.py action-plugin-docs From 19c7f747cd0dab8f00f2c1b4bfbf41c167588e9a Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 20 Jun 2025 23:50:25 +0530 Subject: [PATCH 2/3] "Fixing File Names for Importing Tests" --- .../targets/dcnm_inventory/tests/base_tasks.yaml | 2 +- .../dcnm_inventory/tests/dcnm/deleted.yaml | 4 ++-- .../dcnm_inventory/tests/dcnm/merged.yaml | 16 ++++++++-------- .../dcnm_inventory/tests/dcnm/overridden.yaml | 8 ++++---- .../targets/dcnm_inventory/tests/dcnm/poap.yaml | 4 ++-- .../targets/dcnm_inventory/tests/dcnm/query.yaml | 4 ++-- .../targets/dcnm_inventory/tests/dcnm/rma.yaml | 2 +- .../dcnm_inventory/tests/dcnm/sanity.yaml | 6 +++--- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml b/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml index 588445eb3..67baec5b6 100644 --- a/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/base_tasks.yaml @@ -44,7 +44,7 @@ - name: Import Configuration Prepare Tasks vars: file: base - import_tasks: conf_prep_tasks.yml + import_tasks: conf_prep_tasks.yaml # ---------------------------------------------- # Test Setup diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml index 44a1b6398..4343d7daa 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/deleted.yaml @@ -1,7 +1,7 @@ --- - name: Import DCNM Inventory Base Tasks - import_tasks: ../base_tasks.yml + import_tasks: ../base_tasks.yaml tags: deleted # ---------------------------------------------- @@ -118,7 +118,7 @@ - name: Import Configuration Prepare Tasks vars: file: delete - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: deleted - name: Deleted TC5 - Merge a Switch using BrownField Deployment diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml index 289efb905..133a9fafd 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/merged.yaml @@ -1,7 +1,7 @@ --- - name: Import DCNM Inventory Base Tasks - import_tasks: ../base_tasks.yml + import_tasks: ../base_tasks.yaml tags: merged # ---------------------------------------------- @@ -88,7 +88,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC4 - Merge a Switch using BrownField Deployment @@ -146,7 +146,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC6 - Merge a Switch using GreenField Deployment - Using default role/auth_proto @@ -218,7 +218,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC8 - Add Switch with Border Gateways and MD5 to Fabric @@ -278,7 +278,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC10 - Merge a Switch using GreenField Deployment - Non-Zero Max Hop Config @@ -339,7 +339,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC13 - Merge a Switch without seed_ip @@ -372,7 +372,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC14 - Merge a Switch with Invalid Role @@ -405,7 +405,7 @@ - name: Import Configuration Prepare Tasks vars: file: merge - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: merged - name: Merged TC15 - Merge a Switch with invalid auth choice diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml index 7716e3e1f..c8dc7d552 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/overridden.yaml @@ -1,6 +1,6 @@ --- - name: Import DCNM Inventory Base Tasks - import_tasks: ../base_tasks.yml + import_tasks: ../base_tasks.yaml tags: overridden # ---------------------------------------------- @@ -57,7 +57,7 @@ - name: Import Configuration Prepare Tasks vars: file: overridden - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: overridden - name: Overridden TC3 - Override Existing Switch - Removes Other Switches from Fabric @@ -98,7 +98,7 @@ - name: Import Configuration Prepare Tasks vars: file: overridden - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: overridden - name: Overridden TC4 - New Role for the Existing Switch @@ -138,7 +138,7 @@ - name: Import Configuration Prepare Tasks vars: file: overridden - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: overridden - name: Overridden TC5 - Unspecified Role for the Existing Switch (Default, Leaf) diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml index 5453d41a1..8ef913239 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/poap.yaml @@ -142,7 +142,7 @@ - name: Import Configuration Prepare Tasks vars: file: poap - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml when: poap_enabled == True tags: poap @@ -245,7 +245,7 @@ - name: Import Configuration Prepare Tasks vars: file: poap - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml when: poap_enabled == True tags: poap diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml index daae18cf0..e8a257977 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/query.yaml @@ -1,6 +1,6 @@ --- - name: Import DCNM Inventory Base Tasks - import_tasks: ../base_tasks.yml + import_tasks: ../base_tasks.yaml tags: query # ---------------------------------------------- @@ -199,7 +199,7 @@ - name: Import Configuration Prepare Tasks vars: file: query - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: query - name: Query TC9 - Add Switch with Border Gateways to Fabric diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml index 38f43db1f..f4fba7a8c 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/rma.yaml @@ -121,7 +121,7 @@ - name: Import Configuration Prepare Tasks vars: file: rma - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml when: rma_enabled == True tags: rma diff --git a/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml b/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml index c358f3473..3fbb53487 100644 --- a/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml +++ b/tests/integration/targets/dcnm_inventory/tests/dcnm/sanity.yaml @@ -1,7 +1,7 @@ --- - name: Import DCNM Inventory Base Tasks - import_tasks: ../base_tasks.yml + import_tasks: ../base_tasks.yaml tags: sanity # ---------------------------------------------- @@ -96,7 +96,7 @@ - name: Import Configuration Prepare Tasks vars: file: sanity - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: sanity - name: Sanity TC4 - Overridden - Update a New Switch using GreenField Deployment - Delete and Create - default role @@ -200,7 +200,7 @@ - name: Import Configuration Prepare Tasks vars: file: sanity - import_tasks: ../conf_prep_tasks.yml + import_tasks: ../conf_prep_tasks.yaml tags: sanity - name: Sanity TC8 - Reset - Setup Switches in Fabric From 31692609579f02828e02f92491359e73fc18af3c Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 21 Jun 2025 00:04:37 +0530 Subject: [PATCH 3/3] "Fix Sanity Import Errors" --- tests/sanity/ignore-2.15.txt | 4 ++++ tests/sanity/ignore-2.16.txt | 3 +++ 2 files changed, 7 insertions(+) diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt index 03f562703..90bc11f6b 100644 --- a/tests/sanity/ignore-2.15.txt +++ b/tests/sanity/ignore-2.15.txt @@ -1,3 +1,7 @@ +plugins/action/tests/integration/ndfc_inventory_validate.py action-plugin-docs +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.9!skip +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.10!skip +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.11!skip plugins/action/tests/integration/ndfc_network_validate.py action-plugin-docs plugins/action/tests/integration/ndfc_network_validate.py import-3.9!skip plugins/action/tests/integration/ndfc_network_validate.py import-3.10!skip diff --git a/tests/sanity/ignore-2.16.txt b/tests/sanity/ignore-2.16.txt index 833ac9cc5..065cb862c 100644 --- a/tests/sanity/ignore-2.16.txt +++ b/tests/sanity/ignore-2.16.txt @@ -1,3 +1,6 @@ +plugins/action/tests/integration/ndfc_inventory_validate.py action-plugin-docs +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.10!skip +plugins/action/tests/integration/ndfc_inventory_validate.py import-3.11!skip plugins/action/tests/integration/ndfc_network_validate.py action-plugin-docs plugins/action/tests/integration/ndfc_network_validate.py import-3.10!skip plugins/action/tests/integration/ndfc_network_validate.py import-3.11!skip