diff --git a/plugins/module_utils/fabric/config_save.py b/plugins/module_utils/fabric/config_save.py index 7de137c3d..33d94312e 100644 --- a/plugins/module_utils/fabric/config_save.py +++ b/plugins/module_utils/fabric/config_save.py @@ -21,8 +21,7 @@ import inspect import logging -from ..common.api.v1.lan_fabric.rest.control.fabrics.fabrics import \ - EpFabricConfigSave +from ..common.api.v1.lan_fabric.rest.control.fabrics.fabrics import EpFabricConfigSave from ..common.conversion import ConversionUtils from ..common.properties import Properties diff --git a/plugins/module_utils/fabric/config_save_v2.py b/plugins/module_utils/fabric/config_save_v2.py index 1d39e8e95..c7faa50b5 100644 --- a/plugins/module_utils/fabric/config_save_v2.py +++ b/plugins/module_utils/fabric/config_save_v2.py @@ -23,8 +23,7 @@ import inspect import logging -from ..common.api.v1.lan_fabric.rest.control.fabrics.fabrics import \ - EpFabricConfigSave +from ..common.api.v1.lan_fabric.rest.control.fabrics.fabrics import EpFabricConfigSave from ..common.conversion import ConversionUtils from ..common.rest_send_v2 import RestSend from ..common.results_v2 import Results diff --git a/plugins/module_utils/fabric/fabric_summary_v2.py b/plugins/module_utils/fabric/fabric_summary_v2.py index 0ed719000..ea3e4f6a5 100644 --- a/plugins/module_utils/fabric/fabric_summary_v2.py +++ b/plugins/module_utils/fabric/fabric_summary_v2.py @@ -25,6 +25,7 @@ import inspect import json import logging +from typing import Any, Literal from ..common.api.v1.lan_fabric.rest.control.switches.switches import EpFabricSummary from ..common.conversion import ConversionUtils @@ -35,7 +36,9 @@ class FabricSummary: """ - Populate ``dict`` ``self.data`` with fabric summary information. + # Summary + + Populate dict `self.data` with fabric summary information. Convenience properties are provided to access the data, including: @@ -45,8 +48,9 @@ class FabricSummary: - @border_gateway_count - @in_sync_count - @out_of_sync_count + - @fabric_is_empty - self.data will contain the following structure. + After a successful call to `refresh()`, `self.data` will contain the following structure. ```python { @@ -73,7 +77,8 @@ class FabricSummary: } } ``` - Usage: + + ## Usage ```python # params is typically obtained from ansible_module.params @@ -96,26 +101,27 @@ class FabricSummary: instance.refresh() fabric_summary = instance.data device_count = instance.device_count + fabric_is_empty = instance.fabric_is_empty ``` etc... """ def __init__(self): - self.class_name = self.__class__.__name__ + self.class_name: str = self.__class__.__name__ - self.log = logging.getLogger(f"dcnm.{self.class_name}") + self.log: logging.Logger = logging.getLogger(f"dcnm.{self.class_name}") - self.data: dict[str, dict] = {"switchSWVersions": {}, "switchHealth": {}, "switchHWVersions": {}, "switchConfig": {}, "switchRoles": {}} - self.ep_fabric_summary = EpFabricSummary() - self.conversion = ConversionUtils() + self.data: dict[str, dict[str, Any]] = {} + self._conversion: ConversionUtils = ConversionUtils() + self._ep_fabric_summary: EpFabricSummary = EpFabricSummary() + self._results: Results = Results() + self._rest_send: RestSend = RestSend(params={}) # set to True in refresh() after a successful request to the controller # Used by getter properties to ensure refresh() has been called prior # to returning data. - self.refreshed = False + self.refreshed: bool = False - self._rest_send: RestSend = RestSend({}) - self._results: Results = Results() self._border_gateway_count: int = 0 self._device_count: int = 0 self._fabric_name: str = "" @@ -127,53 +133,71 @@ def __init__(self): def _update_device_counts(self): """ - - From the controller response, update class properties - pertaining to device counts. - - By the time refresh() calls this method, self.data - has been verified, so no need to verify it here. + # Summary + + From the controller response, update class properties pertaining to device counts. + + ## Raises + + ### ValueError + + - `self.data` is empty. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] msg = f"{self.class_name}.{method_name}: " msg = f"self.data: {json.dumps(self.data, indent=4, sort_keys=True)}" self.log.debug(msg) - if self.data is None: + if not self.data: msg = f"{self.class_name}.{method_name}: " - msg += "self.data is None. Unable to update device counts." + msg += "self.data is empty. Unable to update device counts." raise ValueError(msg) self._border_gateway_count = self.data.get("switchRoles", {}).get("border gateway", 0) self._leaf_count = self.data.get("switchRoles", {}).get("leaf", 0) self._spine_count = self.data.get("switchRoles", {}).get("spine", 0) - self._device_count = self.leaf_count + self.spine_count + self.border_gateway_count + self._device_count = self._leaf_count + self._spine_count + self._border_gateway_count - def _set_fabric_summary_endpoint(self): + def _set_fabric_summary_endpoint(self) -> None: """ - - Set the fabric_summary endpoint. - - Raise ``ValueError`` if unable to retrieve the endpoint. + # Summary + + Set the fabric_summary endpoint. + + ## Raises + + ### ValueError + + - Unable to retrieve the endpoint. """ try: - self.ep_fabric_summary.fabric_name = self.fabric_name - # pylint: disable=no-member - self.rest_send.path = self.ep_fabric_summary.path - self.rest_send.verb = self.ep_fabric_summary.verb + self._ep_fabric_summary.fabric_name = self.fabric_name + self.rest_send.path = self._ep_fabric_summary.path + self.rest_send.verb = self._ep_fabric_summary.verb except ValueError as error: msg = "Error retrieving fabric_summary endpoint. " msg += f"Detail: {error}" self.log.debug(msg) raise ValueError(msg) from error - def _verify_controller_response(self): + def _verify_controller_response(self) -> None: """ - - Raise ``ControllerResponseError`` if RETURN_CODE != 200. - - Raise ``ControllerResponseError`` if DATA is missing or empty. + # Summary + + Verify the controller response after a refresh(). + + ## Raises + + ### ControllerResponseError + + - RETURN_CODE != 200. + - DATA is missing or empty. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] - # pylint: disable=no-member - controller_return_code = self.rest_send.response_current.get("RETURN_CODE", None) - controller_message = self.rest_send.response_current.get("MESSAGE", None) + controller_return_code = self._rest_send.response_current.get("RETURN_CODE", None) + controller_message = self._rest_send.response_current.get("MESSAGE", None) if controller_return_code != 200: msg = f"{self.class_name}.{method_name}: " msg += "Failed to retrieve fabric_summary for fabric_name " @@ -185,35 +209,40 @@ def _verify_controller_response(self): # DATA is set to an empty dict in refresh() if the controller response # does not contain a DATA key. - if self.data is None: - msg = f"{self.class_name}.{method_name}: " - msg += "Controller responded with missing DATA." - raise ControllerResponseError(msg) - if len(self.data) == 0: + if not self.data: msg = f"{self.class_name}.{method_name}: " msg += "Controller responded with missing or empty DATA." raise ControllerResponseError(msg) - def refresh(self): + def refresh(self) -> None: """ - - Refresh fabric summary info from the controller and - populate ``self.data`` with the result. - - ``self.data`` is a ``dict`` of fabric summary info for one fabric. - - raise ``ValueError`` if ``fabric_name`` is not set. - - raise ``ValueError`` if unable to retrieve fabric_summary endpoint. - - raise ``ValueError`` if ``_update_device_counts()`` fails. - - raise ``ControllerResponseError`` if the controller - ``RETURN_CODE`` != 200 + # Summary + + Refresh fabric summary info from the controller and populate `self.data` with the result. + + `self.data` is a dict of fabric summary info for one fabric. + + # Raises + + ## `ValueError` if + + - `fabric_name` is not set. + - `rest_send` is not properly configured (rest_send.params is empty). + - Unable to retrieve fabric_summary endpoint. + - `_update_device_counts()` fails. + + ## `ControllerResponseError` if + + - The controller `RETURN_CODE` != 200 """ - method_name = inspect.stack()[0][3] - if self.fabric_name is None: + method_name: str = inspect.stack()[0][3] + if self.fabric_name == "": msg = f"{self.class_name}.{method_name}: " msg += f"Set {self.class_name}.fabric_name prior to calling " msg += f"{self.class_name}.refresh()." raise ValueError(msg) - # pylint: disable=no-member - if self.rest_send is None: + if self._rest_send.params == {}: msg = f"{self.class_name}.{method_name}: " msg += f"Set {self.class_name}.rest_send prior to calling " msg += f"{self.class_name}.refresh()." @@ -229,22 +258,22 @@ def refresh(self): # We save the current check_mode value, set rest_send.check_mode # to False so the request will be sent to the controller, and then # restore the original check_mode value. - save_check_mode = self.rest_send.check_mode - self.rest_send.check_mode = False - self.rest_send.commit() - self.rest_send.check_mode = save_check_mode - self.data = copy.deepcopy(self.rest_send.response_current.get("DATA", {})) - + save_check_mode = self._rest_send.check_mode + self._rest_send.check_mode = False + self._rest_send.commit() + self._rest_send.check_mode = save_check_mode + self.data = copy.deepcopy(self._rest_send.response_current.get("DATA", {})) msg = f"self.data: {json.dumps(self.data, indent=4, sort_keys=True)}" self.log.debug(msg) - self.results.response_current = self.rest_send.response_current - self.results.response = self.rest_send.response_current - self.results.result_current = self.rest_send.result_current - self.results.result = self.rest_send.result_current + self.results.response_current = self._rest_send.response_current + self.results.result_current = self._rest_send.result_current + # TODO: We are leaving these commented out for now. We need to look into how + # these are used downstream (e.g. in fabric_delete, fabric_update, etc.) + # self.results.add_response(self._rest_send.response_current) + # self.results.add_result(self._rest_send.result_current) self.results.register_task_result() - # pylint: enable=no-member try: self._verify_controller_response() except ControllerResponseError as error: @@ -255,9 +284,17 @@ def refresh(self): self.refreshed = True self._update_device_counts() - def verify_refresh_has_been_called(self, attempted_method_name): + def verify_refresh_has_been_called(self, attempted_method_name: str) -> None: """ - - raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Verify that `refresh()` has been called prior to accessing properties that depend on `refresh()`. + + # Raises + + ## ValueError + + - `refresh()` has not been called. """ if self.refreshed is True: return @@ -266,12 +303,19 @@ def verify_refresh_has_been_called(self, attempted_method_name): raise ValueError(msg) @property - def all_data(self) -> dict: + def all_data(self) -> dict[str, dict[str, Any]]: """ - - Return raw fabric summary data from the controller. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return raw fabric summary data from the controller. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: @@ -281,10 +325,17 @@ def all_data(self) -> dict: @property def border_gateway_count(self) -> int: """ - - Return the number of border gateway devices in fabric fabric_name. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return the number of border gateway devices in fabric fabric_name. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: @@ -294,10 +345,17 @@ def border_gateway_count(self) -> int: @property def device_count(self) -> int: """ - - Return the total number of devices in fabric fabric_name. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return the total number of devices in fabric fabric_name. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: @@ -307,10 +365,17 @@ def device_count(self) -> int: @property def fabric_is_empty(self) -> bool: """ - - Return True if the fabric is empty. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return True if the fabric is empty. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: @@ -322,29 +387,42 @@ def fabric_is_empty(self) -> bool: @property def fabric_name(self) -> str: """ + # Summary + - getter: Return the fabric_name to query. - setter: Set the fabric_name to query. - - setter: Raise ``ValueError`` if fabric_name is not a string. - - setter: Raise ``ValueError`` if fabric_name is invalid (i.e. - the controller would return an error due to invalid characters). + + ## Raises + + ### ValueError + + - setter: fabric_name is not a string. + - setter: fabric_name is invalid (i.e. the controller would return an error due to invalid characters). """ return self._fabric_name @fabric_name.setter def fabric_name(self, value: str): try: - self.conversion.validate_fabric_name(value) - except ValueError as error: + self._conversion.validate_fabric_name(value) + except (TypeError, ValueError) as error: raise ValueError(error) from error self._fabric_name = value @property def leaf_count(self) -> int: """ - - Return the number of leaf devices in fabric fabric_name. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return the number of leaf devices in fabric fabric_name. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: @@ -354,37 +432,95 @@ def leaf_count(self) -> int: @property def rest_send(self) -> RestSend: """ + # Summary + An instance of the RestSend class. + + ## Raises + + - setter: `TypeError` if the value is not an instance of RestSend. + - setter: `ValueError` if RestSend.params is not set. + + ## getter + + Return an instance of the RestSend class. + + ## setter + + Set an instance of the RestSend class. """ + method_name: str = inspect.stack()[0][3] return self._rest_send @rest_send.setter def rest_send(self, value: RestSend) -> None: - if not value.params: - method_name = inspect.stack()[0][3] - msg = f"{self.class_name}.{method_name}: " - msg += "rest_send must have params set." - raise ValueError(msg) + method_name: str = inspect.stack()[0][3] + _class_have: str = "" + _class_need: Literal["RestSend"] = "RestSend" + msg = f"{self.class_name}.{method_name}: " + msg += f"value must be an instance of {_class_need}. " + msg += f"Got value {value} of type {type(value).__name__}." + try: + _class_have = value.class_name + except AttributeError as error: + msg += f" Error detail: {error}." + raise TypeError(msg) from error + if _class_have != _class_need: + raise TypeError(msg) self._rest_send = value @property def results(self) -> Results: """ + # Summary + An instance of the Results class. + + ## Raises + + - setter: `TypeError` if the value is not an instance of Results. + + ## getter + + Return an instance of the Results class. + + ## setter + + Set an instance of the Results class. """ return self._results @results.setter def results(self, value: Results) -> None: + method_name: str = inspect.stack()[0][3] + _class_have: str = "" + _class_need: Literal["Results"] = "Results" + msg = f"{self.class_name}.{method_name}: " + msg += f"value must be an instance of {_class_need}. " + msg += f"Got value {value} of type {type(value).__name__}." + try: + _class_have = value.class_name + except AttributeError as error: + msg += f" Error detail: {error}." + raise TypeError(msg) from error + if _class_have != _class_need: + raise TypeError(msg) self._results = value @property def spine_count(self) -> int: """ - - Return the number of spine devices in fabric fabric_name. - - Raise ``ValueError`` if ``refresh()`` has not been called. + # Summary + + Return the number of spine devices in fabric fabric_name. + + ## Raises + + ### ValueError + + - `refresh()` has not been called. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] try: self.verify_refresh_has_been_called(method_name) except ValueError as error: diff --git a/plugins/module_utils/fabric/template_get.py b/plugins/module_utils/fabric/template_get.py index fa3afb52d..67b03eaee 100644 --- a/plugins/module_utils/fabric/template_get.py +++ b/plugins/module_utils/fabric/template_get.py @@ -22,8 +22,7 @@ import inspect import logging -from ..common.api.v1.configtemplate.rest.config.templates.templates import \ - EpTemplate +from ..common.api.v1.configtemplate.rest.config.templates.templates import EpTemplate from ..common.exceptions import ControllerResponseError from ..common.properties import Properties diff --git a/plugins/module_utils/fabric/template_get_all.py b/plugins/module_utils/fabric/template_get_all.py index dc742f7c6..4d0392763 100644 --- a/plugins/module_utils/fabric/template_get_all.py +++ b/plugins/module_utils/fabric/template_get_all.py @@ -22,8 +22,7 @@ import inspect import logging -from ..common.api.v1.configtemplate.rest.config.templates.templates import \ - EpTemplates +from ..common.api.v1.configtemplate.rest.config.templates.templates import EpTemplates from ..common.exceptions import ControllerResponseError from ..common.properties import Properties diff --git a/plugins/module_utils/fabric_group/create.py b/plugins/module_utils/fabric_group/create.py index 5705d7a91..ed465f674 100644 --- a/plugins/module_utils/fabric_group/create.py +++ b/plugins/module_utils/fabric_group/create.py @@ -44,7 +44,7 @@ class FabricGroupCreate(FabricGroupCommon): ```python from ansible_collections.cisco.dcnm.plugins.module_utils.fabric_group.create import FabricGroupCreate - from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results + from ansible_collections.cisco.dcnm.plugins.module_utils.common.results_v2 import Results payloads = [ { "FABRIC_NAME": "fabric1", "BGP_AS": 65000 }, { "FABRIC_NAME": "fabric2", "BGP_AS": 65001 } diff --git a/plugins/module_utils/fabric_group/fabric_group_details.py b/plugins/module_utils/fabric_group/fabric_group_details.py index 337fdb3f1..33b155088 100644 --- a/plugins/module_utils/fabric_group/fabric_group_details.py +++ b/plugins/module_utils/fabric_group/fabric_group_details.py @@ -53,7 +53,7 @@ class FabricGroupDetails: ```python from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend - from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results + from ansible_collections.cisco.dcnm.plugins.module_utils.common.results_v2 import Results from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_dcnm import Sender params = {"check_mode": False, "state": "merged"} @@ -83,7 +83,7 @@ class FabricGroupDetails: ```python from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend - from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results + from ansible_collections.cisco.dcnm.plugins.module_utils.common.results_v2 import Results from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_dcnm import Sender params = {"check_mode": False, "state": "merged"} diff --git a/plugins/module_utils/fabric_group/fabric_groups.py b/plugins/module_utils/fabric_group/fabric_groups.py index dee267acc..71d15ee16 100644 --- a/plugins/module_utils/fabric_group/fabric_groups.py +++ b/plugins/module_utils/fabric_group/fabric_groups.py @@ -498,7 +498,7 @@ class FabricGroups: ```python from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend - from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results + from ansible_collections.cisco.dcnm.plugins.module_utils.common.results_v2 import Results from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_dcnm import Sender params = {"check_mode": False, "state": "merged"} diff --git a/plugins/module_utils/fabric_group/query.py b/plugins/module_utils/fabric_group/query.py index 2e3067c96..2f563088f 100644 --- a/plugins/module_utils/fabric_group/query.py +++ b/plugins/module_utils/fabric_group/query.py @@ -47,7 +47,7 @@ class FabricGroupQuery: ```python from ansible_collections.cisco.dcnm.plugins.module_utils.fabric_group.query import FabricGroupQuery - from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results + from ansible_collections.cisco.dcnm.plugins.module_utils.common.results_v2 import Results from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend params = {"state": "query", "check_mode": False} diff --git a/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary_V2.json b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary_V2.json new file mode 100644 index 000000000..c88826705 --- /dev/null +++ b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary_V2.json @@ -0,0 +1,389 @@ +{ + "test_notes": [ + "Mocked responses for FabricSummary (v2) class.", + "Includes responses for config_deploy, fabric_delete, fabric_summary_v2, and fabric_update_bulk tests.", + "As of 2025-11-24, only the responses for fabric_summary_v2 tests are actively used.", + "Other responses are retained for potential future use when config_deploy, fabric_delete, and fabric_update_bulk are updated to use FabricSummary (v2)." + ], + "test_fabric_config_deploy_00200a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_config_deploy_00210a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_config_deploy_00220a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00040a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00042a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00043a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00044a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00050a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": { + "leaf": 4 + }, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_delete_00051a": { + "DATA": { + "timestamp": 1713467047741, + "status": 404, + "error": "Not Found", + "path": "/rest/control/switches/MyFabric/overview" + }, + "MESSAGE": "Not Found", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 404 + }, + "test_fabric_summary_v2_00033a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_summary_v2_00034a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_summary_v2_00035a": { + "DATA": { + "timestamp": 1713467047741, + "status": 404, + "error": "Not Found", + "path": "/rest/control/switches/MyFabric/overview" + }, + "MESSAGE": "Not Found", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 404 + }, + "test_fabric_summary_v2_00036a": { + "TEST_NOTES": [ + "DATA is missing.", + "This should never happen, but we need to handle it gracefully." + ], + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/MyFabric/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00031a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00032a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00033a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00034a": { + "DATA": { + "switchConfig": {}, + "switchHWVersions": {}, + "switchHealth": {}, + "switchRoles": {}, + "switchSWVersions": {} + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00035a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00040a": { + "DATA": { + "timestamp": 1713467047741, + "status": 404, + "error": "Not Found", + "path": "/rest/control/switches/MyFabric/overview" + }, + "MESSAGE": "Not Found", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 404 + }, + "test_fabric_update_bulk_00130a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00140a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 + } +} diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_config_save.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_config_save.py index 21ee30a04..a8888aac0 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_config_save.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_config_save.py @@ -32,19 +32,18 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import \ - ResponseHandler -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import \ - Sender -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import Sender +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - MockAnsibleModule, does_not_raise, fabric_config_save_fixture, params, - responses_ep_fabric_config_save) + MockAnsibleModule, + does_not_raise, + fabric_config_save_fixture, + params, + responses_ep_fabric_config_save, +) def test_fabric_config_save_00010(fabric_config_save) -> None: @@ -99,9 +98,7 @@ def test_fabric_config_save_00010(fabric_config_save) -> None: ("My*Fabric", pytest.raises(ValueError, match=MATCH_00020b), True), ], ) -def test_fabric_config_save_00020( - fabric_config_save, fabric_name, expected, does_raise -) -> None: +def test_fabric_config_save_00020(fabric_config_save, fabric_name, expected, does_raise) -> None: """ Classes and Methods - FabricConfigSave @@ -151,9 +148,7 @@ def test_fabric_config_save_00020( ({10}, True, pytest.raises(TypeError, match=MATCH_00030)), ], ) -def test_fabric_config_save_00030( - fabric_config_save, value, does_raise, expected -) -> None: +def test_fabric_config_save_00030(fabric_config_save, value, does_raise, expected) -> None: """ Classes and Methods - FabricConfigSave @@ -191,9 +186,7 @@ def test_fabric_config_save_00030( ({10}, True, pytest.raises(TypeError, match=MATCH_00040)), ], ) -def test_fabric_config_save_00040( - fabric_config_save, value, does_raise, expected -) -> None: +def test_fabric_config_save_00040(fabric_config_save, value, does_raise, expected) -> None: """ Classes and Methods - FabricConfigSave diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_name_v2.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_name_v2.py index 976a2313f..e3d105418 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_name_v2.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_name_v2.py @@ -33,19 +33,16 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import \ - ResponseHandler -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import \ - Sender -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import Sender +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, fabric_details_by_name_v2_fixture, - responses_fabric_details_by_name_v2) + does_not_raise, + fabric_details_by_name_v2_fixture, + responses_fabric_details_by_name_v2, +) PARAMS = {"state": "query", "check_mode": False} diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_nv_pair_v2.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_nv_pair_v2.py index fb92b8d36..a2658b305 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_nv_pair_v2.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_by_nv_pair_v2.py @@ -33,19 +33,16 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import \ - ResponseHandler -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import \ - Sender -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import Sender +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, fabric_details_by_nv_pair_v2_fixture, - responses_fabric_details_by_nv_pair_v2) + does_not_raise, + fabric_details_by_nv_pair_v2_fixture, + responses_fabric_details_by_nv_pair_v2, +) PARAMS = {"state": "query", "check_mode": False} @@ -155,18 +152,9 @@ def responses(): assert False in instance.results.changed assert True not in instance.results.changed - assert ( - instance.filtered_data.get("f1", {}).get("nvPairs", {}).get("FEATURE_PTP", None) - == "false" - ) - assert ( - instance.filtered_data.get("f2", {}).get("nvPairs", {}).get("FEATURE_PTP", None) - == "false" - ) - assert ( - instance.filtered_data.get("f3", {}).get("nvPairs", {}).get("FEATURE_PTP", None) - is None - ) + assert instance.filtered_data.get("f1", {}).get("nvPairs", {}).get("FEATURE_PTP", None) == "false" + assert instance.filtered_data.get("f2", {}).get("nvPairs", {}).get("FEATURE_PTP", None) == "false" + assert instance.filtered_data.get("f3", {}).get("nvPairs", {}).get("FEATURE_PTP", None) is None def test_fabric_details_by_nv_pair_v2_00210(fabric_details_by_nv_pair_v2) -> None: diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_v2.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_v2.py index d08dfb34e..5017ba37e 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_v2.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_details_v2.py @@ -32,22 +32,14 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.api.v1.lan_fabric.rest.control.fabrics.fabrics import \ - EpFabrics -from ansible_collections.cisco.dcnm.plugins.module_utils.common.conversion import \ - ConversionUtils -from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import \ - ResponseHandler -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import \ - Sender -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator -from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, fabric_details_v2_fixture, responses_fabric_details_v2) +from ansible_collections.cisco.dcnm.plugins.module_utils.common.api.v1.lan_fabric.rest.control.fabrics.fabrics import EpFabrics +from ansible_collections.cisco.dcnm.plugins.module_utils.common.conversion import ConversionUtils +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import Sender +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import does_not_raise, fabric_details_v2_fixture, responses_fabric_details_v2 def test_fabric_details_v2_00000(fabric_details_v2) -> None: @@ -342,10 +334,7 @@ def responses(): assert False not in instance.results.failed assert False in instance.results.changed assert True not in instance.results.changed - assert ( - instance.all_data.get("VXLAN_Fabric", {}).get("nvPairs", {}).get("FABRIC_NAME") - == "VXLAN_Fabric" - ) + assert instance.all_data.get("VXLAN_Fabric", {}).get("nvPairs", {}).get("FABRIC_NAME") == "VXLAN_Fabric" def test_fabric_details_v2_00140(fabric_details_v2, monkeypatch) -> None: @@ -594,9 +583,7 @@ def test_fabric_details_v2_00400(fabric_details_v2) -> None: (RestSend({"state": "merged", "check_mode": False}), False, does_not_raise()), ], ) -def test_fabric_details_v2_00500( - fabric_details_v2, param, does_raise, expected -) -> None: +def test_fabric_details_v2_00500(fabric_details_v2, param, does_raise, expected) -> None: """ ### Classes and Methods - FabricDetails() diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_summary_v2.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_summary_v2.py new file mode 100644 index 000000000..5d480d4d3 --- /dev/null +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_summary_v2.py @@ -0,0 +1,811 @@ +# Copyright (c) 2025 Cisco and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# See the following regarding *_fixture imports +# https://pylint.pycqa.org/en/latest/user_guide/messages/warning/redefined-outer-name.html +# Due to the above, we also need to disable unused-import +# Also, fixtures need to use *args to match the signature of the function they are mocking +# pylint: disable=unused-import +# pylint: disable=redefined-outer-name +# pylint: disable=protected-access +# pylint: disable=unused-argument +# pylint: disable=invalid-name +""" +Unit tests for FabricSummary (v2) class +""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +__copyright__ = "Copyright (c) 2025 Cisco and/or its affiliates." +__author__ = "Allen Robel" + +import inspect + +import pytest +from ansible_collections.cisco.dcnm.plugins.module_utils.common.exceptions import ControllerResponseError +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send_v2 import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.sender_file import Sender +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( + does_not_raise, + fabric_summary_v2_fixture, + responses_fabric_summary_v2, +) + + +def test_fabric_summary_v2_00010(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon + - __init__() + - FabricSummary + - __init__() + + Test + - Class attributes are initialized to expected values + - Exception is not raised + """ + with does_not_raise(): + instance = fabric_summary_v2 + assert instance.class_name == "FabricSummary" + assert instance.data == {} + assert instance.refreshed is False + assert instance._conversion.class_name == "ConversionUtils" + assert instance._ep_fabric_summary.class_name == "EpFabricSummary" + assert instance._results.class_name == "Results" + assert instance._border_gateway_count == 0 + assert instance._device_count == 0 + assert instance._fabric_name == "" + assert instance._leaf_count == 0 + assert instance._spine_count == 0 + + +def test_fabric_summary_v2_00030(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + + Summary + - Verify FabricSummary().refresh() raises ``ValueError`` + when ``FabricSummary().fabric_name`` is not set. + + Code Flow - Setup + - FabricSummary() is instantiated + - FabricSummary().rest_send is set + + Code Flow - Test + - FabricSummary().refresh() is called without having + first set FabricSummary().fabric_name + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + + def responses(): + yield {"key": "value"} + + with does_not_raise(): + sender = Sender() + sender.gen = ResponseGenerator(responses()) + instance = fabric_summary_v2 + instance.rest_send = RestSend(params={"check_mode": False, "state": "query"}) + instance.rest_send.sender = sender + + match = r"FabricSummary\.refresh: " + match += r"Set FabricSummary\.fabric_name prior to calling " + match += r"FabricSummary\.refresh\(\)\." + with pytest.raises(ValueError, match=match): + instance.refresh() + + +def test_fabric_summary_v2_00031(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + + Summary + - Verify FabricSummary().refresh() raises ``ValueError`` + when ``FabricSummary().rest_send`` is not set. + + Code Flow - Setup + - FabricSummary() is instantiated + - FabricSummary().fabric_name is set + + Code Flow - Test + - FabricSummary().refresh() is called without having + first set FabricSummary().rest_send + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + instance.fabric_name = "MyFabric" + + match = r"FabricSummary\.refresh: " + match += r"Set FabricSummary\.rest_send prior to calling " + match += r"FabricSummary\.refresh\(\)\." + with pytest.raises(ValueError, match=match): + instance.refresh() + + +def test_fabric_summary_v2_00032(monkeypatch, fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + - _set_fabric_summary_endpoint() + + Summary + - Verify that FabricSummary()._set_fabric_summary_endpoint() + re-raises ``ValueError`` when EpFabricSummary() raises + ``ValueError``. + """ + + class MockEpFabricSummary: # pylint: disable=too-few-public-methods + """ + Mock the EpFabricSummary.fabric_name getter property to raise ``ValueError``. + """ + + def validate_fabric_name(self, value="MyFabric"): + """ + Mocked method required for test, but not relevant to test result. + """ + + @property + def fabric_name(self): + """ + - Mocked fabric_name property getter + """ + + @fabric_name.setter + def fabric_name(self, value): + """ + - Mocked fabric_name property setter + """ + msg = "mocked MockEpFabricSummary().fabric_name setter exception." + raise ValueError(msg) + + def responses(): + yield {"key": "value"} + + with does_not_raise(): + instance = fabric_summary_v2 + monkeypatch.setattr(instance, "_ep_fabric_summary", MockEpFabricSummary()) + instance.fabric_name = "MyFabric" + sender = Sender() + sender.gen = ResponseGenerator(responses()) + instance.rest_send = RestSend(params={"check_mode": False, "state": "query"}) + instance.rest_send.sender = sender + + match = r"Error retrieving fabric_summary endpoint\. Detail: mocked MockEpFabricSummary\(\)\.fabric_name setter exception\." + + with pytest.raises(ValueError, match=match): + instance.refresh() + + +def test_fabric_summary_v2_00033(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + - _update_device_counts() + + Summary + - Verify refresh() success case with populated fabric: + - RETURN_CODE is 200. + - Controller response contains one fabric (f1). + - Fabric contains 2x leaf, 1x spine, 1x border_gateway. + + Code Flow - Setup + - FabricSummary() is instantiated + - FabricSummary().RestSend() is instantiated + - FabricSummary().Results() is instantiated + - FabricSummary().refresh() is called + - responses_FabricSummary contains a dict with: + - RETURN_CODE == 200 + - DATA == [] + + Code Flow - Test + - FabricSummary().refresh() is called + + Expected Result + - Exception is not raised + - instance.data returns expected fabric data + - Results() are updated + - FabricSummary().refreshed is True + - FabricSummary()._properties are updated + """ + method_name = inspect.stack()[0][3] + key = f"{method_name}a" + + def responses(): + yield responses_fabric_summary_v2(key) + + sender = Sender() + sender.gen = ResponseGenerator(responses()) + rest_send = RestSend(params={"check_mode": False, "state": "query"}) + rest_send.unit_test = True + rest_send.timeout = 1 + rest_send.response_handler = ResponseHandler() + rest_send.sender = sender + with does_not_raise(): + instance = fabric_summary_v2 + instance.rest_send = rest_send + instance.fabric_name = "MyFabric" + + with does_not_raise(): + instance.refresh() + + assert isinstance(instance.results.diff, list) + assert isinstance(instance.results.result, list) + assert isinstance(instance.results.response, list) + + assert len(instance.results.diff) == 1 + assert len(instance.results.result) == 1 + assert len(instance.results.response) == 1 + + assert instance.results.response[0].get("RETURN_CODE", None) == 200 + assert instance.results.result[0].get("found", None) is True + assert instance.results.result[0].get("success", None) is True + + assert False in instance.results.failed + assert True not in instance.results.failed + assert False in instance.results.changed + assert True not in instance.results.changed + + assert instance.data.get("switchRoles", {}).get("leaf", None) == 2 + assert instance.data.get("switchRoles", {}).get("spine", None) == 1 + assert instance.data.get("switchRoles", {}).get("border gateway", None) == 1 + assert instance.border_gateway_count == 1 + assert instance.device_count == 4 + assert instance.leaf_count == 2 + assert instance.spine_count == 1 + assert instance.fabric_is_empty is False + + +def test_fabric_summary_v2_00034(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + - _update_device_counts() + + Summary + - Verify refresh() success case with empty fabric: + - RETURN_CODE is 200. + - Controller response contains one fabric (f1). + - Fabric does not contain any switches. + + Code Flow - Setup + - FabricSummary() is instantiated + - FabricSummary().RestSend() is instantiated + - FabricSummary().Results() is instantiated + - FabricSummary().refresh() is called + - responses_FabricSummary contains a dict with: + - RETURN_CODE == 200 + - DATA == [] + + Code Flow - Test + - FabricSummary().refresh() is called + + Expected Result + - Exception is not raised + - instance.all_data returns expected fabric data + - Results() are updated + - FabricSummary().refreshed is True + - FabricSummary()._properties are updated + """ + method_name = inspect.stack()[0][3] + key = f"{method_name}a" + + def responses(): + yield responses_fabric_summary_v2(key) + + sender = Sender() + sender.gen = ResponseGenerator(responses()) + rest_send = RestSend(params={"check_mode": False, "state": "query"}) + rest_send.unit_test = True + rest_send.timeout = 1 + rest_send.response_handler = ResponseHandler() + rest_send.sender = sender + + with does_not_raise(): + instance = fabric_summary_v2 + instance.rest_send = rest_send + instance.fabric_name = "MyFabric" + + with does_not_raise(): + instance.refresh() + + assert instance.refreshed is True + + assert isinstance(instance.results.diff, list) + assert isinstance(instance.results.result, list) + assert isinstance(instance.results.response, list) + + assert len(instance.results.diff) == 1 + assert len(instance.results.result) == 1 + assert len(instance.results.response) == 1 + + assert instance.results.response[0].get("RETURN_CODE", None) == 200 + assert instance.results.result[0].get("found", None) is True + assert instance.results.result[0].get("success", None) is True + + assert False in instance.results.failed + assert True not in instance.results.failed + assert False in instance.results.changed + assert True not in instance.results.changed + + assert instance.all_data.get("switchRoles", {}).get("leaf", None) is None + assert instance.all_data.get("switchRoles", {}).get("spine", None) is None + assert instance.all_data.get("switchRoles", {}).get("border gateway", None) is None + assert instance.border_gateway_count == 0 + assert instance.device_count == 0 + assert instance.leaf_count == 0 + assert instance.spine_count == 0 + assert instance.fabric_is_empty is True + + +def test_fabric_summary_v2_00035(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + - _update_device_counts() + + Summary + - Verify refresh() failure case: + - RETURN_CODE is 404. + - Controller response when fabric does not exist + + Code Flow - Setup + - FabricSummary() is instantiated. + - FabricSummary().RestSend() is instantiated. + - FabricSummary().fabric_name is set to a fabric that does not exist. + - FabricSummary().refresh() is called. + - responses_FabricSummary contains a dict with: + - RETURN_CODE == 404 + - DATA == { + "timestamp": 1713467047741, + "status": 404, + "error": "Not Found", + "path": "/rest/control/switches/MyFabric/overview" + } + + Code Flow - Test + - FabricSummary().refresh() is called + + Expected Result + - ``ControllerResponseException`` is raised + - instance.data contains error data + - Results() are updated + - FabricSummary().refreshed is False + - FabricSummary()._properties remain at their default values + """ + method_name = inspect.stack()[0][3] + key = f"{method_name}a" + + def responses(): + yield responses_fabric_summary_v2(key) + + sender = Sender() + sender.gen = ResponseGenerator(responses()) + rest_send = RestSend(params={"check_mode": False, "state": "query"}) + rest_send.unit_test = True + rest_send.timeout = 1 + rest_send.response_handler = ResponseHandler() + rest_send.sender = sender + + with does_not_raise(): + instance = fabric_summary_v2 + instance.rest_send = rest_send + instance.rest_send.unit_test = True + instance.rest_send.timeout = 1 + instance.fabric_name = "MyFabric" + + match = r"FabricSummary\._verify_controller_response:\s+" + match += r"Failed to retrieve fabric_summary for fabric_name MyFabric\.\s+" + match += r"RETURN_CODE: 404\.\s+" + match += r"MESSAGE: Not Found\." + with pytest.raises(ControllerResponseError, match=match): + instance.refresh() + + assert instance.refreshed is False + + assert isinstance(instance.results.diff, list) + assert isinstance(instance.results.result, list) + assert isinstance(instance.results.response, list) + + assert len(instance.results.diff) == 1 + assert len(instance.results.result) == 1 + assert len(instance.results.response) == 1 + + assert instance.results.response[0].get("RETURN_CODE", None) == 404 + assert instance.results.result[0].get("found", None) is False + assert instance.results.result[0].get("success", None) is True + + assert False in instance.results.failed + assert True not in instance.results.failed + assert False in instance.results.changed + assert True not in instance.results.changed + + assert instance.data.get("switchRoles", {}).get("leaf", None) is None + assert instance.data.get("switchRoles", {}).get("spine", None) is None + assert instance.data.get("switchRoles", {}).get("border gateway", None) is None + + +def test_fabric_summary_v2_00036(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - refresh() + - _update_device_counts() + + Summary + - Verify refresh() failure case: + - RETURN_CODE is 200. + - DATA field is missing in the response. + - This shouldn't happen, but we need to handle it. + + Code Flow - Setup + - FabricSummary() is instantiated. + - FabricSummary().RestSend() is instantiated. + - FabricSummary().fabric_name is set to a fabric that does not exist. + - FabricSummary().refresh() is called. + - responses_FabricSummary contains a dict with: + - RETURN_CODE == 200 + - DATA missing + + Code Flow - Test + - FabricSummary().refresh() is called + + Expected Result + - ``ValueError`` is raised in FabricSummary()._verify_controller_response() + - instance.data is empty + - Results() are updated + - FabricSummary().refreshed is False + - FabricSummary()._properties remain at their default values + """ + method_name = inspect.stack()[0][3] + key = f"{method_name}a" + + def responses(): + yield responses_fabric_summary_v2(key) + + sender = Sender() + sender.gen = ResponseGenerator(responses()) + rest_send = RestSend(params={"check_mode": False, "state": "query"}) + rest_send.unit_test = True + rest_send.timeout = 1 + rest_send.response_handler = ResponseHandler() + rest_send.sender = sender + + with does_not_raise(): + instance = fabric_summary_v2 + instance.rest_send = rest_send + instance.rest_send.unit_test = True + instance.rest_send.timeout = 1 + instance.fabric_name = "MyFabric" + + match = r"FabricSummary.\_verify_controller_response:\s+" + match += r"Controller responded with missing or empty DATA\." + with pytest.raises(ControllerResponseError, match=match): + instance.refresh() + + assert instance.refreshed is False + + assert instance.data == {} + + assert isinstance(instance.results.diff, list) + assert isinstance(instance.results.result, list) + assert isinstance(instance.results.response, list) + + assert len(instance.results.diff) == 1 + assert len(instance.results.result) == 1 + assert len(instance.results.response) == 1 + + assert instance.results.response[0].get("RETURN_CODE", None) == 200 + assert instance.results.result[0].get("found", None) is True + assert instance.results.result[0].get("success", None) is True + + assert False in instance.results.failed + assert True not in instance.results.failed + assert False in instance.results.changed + assert True not in instance.results.changed + + +def test_fabric_summary_v2_00040(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - all_data getter + + Summary + - Verify FabricSummary().all_data raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().all_data is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.all_data\." + with pytest.raises(ValueError, match=match): + instance.all_data # pylint: disable=pointless-statement + + +def test_fabric_summary_v2_00050(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - border_gateway_count getter + + Summary + - Verify FabricSummary().border_gateway_count raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().border_gateway_count is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.border_gateway_count\." + with pytest.raises(ValueError, match=match): + instance.border_gateway_count # pylint: disable=pointless-statement + + +def test_fabric_summary_v2_00060(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - device_count getter + + Summary + - Verify FabricSummary().device_count raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().device_count is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.device_count\." + with pytest.raises(ValueError, match=match): + instance.device_count # pylint: disable=pointless-statement + + +def test_fabric_summary_v2_00070(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - fabric_is_empty getter + + Summary + - Verify FabricSummary().fabric_is_empty raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().fabric_is_empty is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.fabric_is_empty\." + with pytest.raises(ValueError, match=match): + instance.fabric_is_empty # pylint: disable=pointless-statement + + +MATCH_00080a = r"ConversionUtils\.validate_fabric_name: " +MATCH_00080a += r"Invalid fabric name\. " +MATCH_00080a += r"Expected string\. Got.*\." + +MATCH_00080b = r"ConversionUtils\.validate_fabric_name: " +MATCH_00080b += r"Invalid fabric name:.*\. " +MATCH_00080b += "Fabric name must start with a letter A-Z or a-z and " +MATCH_00080b += r"contain only the characters in: \[A-Z,a-z,0-9,-,_\]\." + + +@pytest.mark.parametrize( + "fabric_name, expected, does_raise", + [ + ("MyFabric", does_not_raise(), False), + ("My_Fabric", does_not_raise(), False), + ("My-Fabric", does_not_raise(), False), + ("M", does_not_raise(), False), + (1, pytest.raises(ValueError, match=MATCH_00080a), True), + ({}, pytest.raises(ValueError, match=MATCH_00080a), True), + ([1, 2, 3], pytest.raises(ValueError, match=MATCH_00080a), True), + ("1", pytest.raises(ValueError, match=MATCH_00080b), True), + ("-MyFabric", pytest.raises(ValueError, match=MATCH_00080b), True), + ("_MyFabric", pytest.raises(ValueError, match=MATCH_00080b), True), + ("1MyFabric", pytest.raises(ValueError, match=MATCH_00080b), True), + ("My Fabric", pytest.raises(ValueError, match=MATCH_00080b), True), + ("My*Fabric", pytest.raises(ValueError, match=MATCH_00080b), True), + ], +) +def test_fabric_summary_v2_00080(fabric_summary_v2, fabric_name, expected, does_raise) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - fabric_name setter/getter + + Summary + - Verify FabricSummary().fabric_name re-raises ``ValueError`` + when fabric_name is invalid. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().fabric_name is set to a value that would + cause the controller to return an error. + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + with expected: + instance.fabric_name = fabric_name + if does_raise is False: + assert instance.fabric_name == fabric_name + + +def test_fabric_summary_v2_00090(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - leaf_count getter + + Summary + - Verify FabricSummary().leaf_count raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().leaf_count is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.leaf_count\." + with pytest.raises(ValueError, match=match): + instance.leaf_count # pylint: disable=pointless-statement + + +def test_fabric_summary_v2_00100(fabric_summary_v2) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - FabricSummary() + - __init__() + - spine_count getter + + Summary + - Verify FabricSummary().spine_count raises ``ValueError`` + when ``FabricSummary().refresh()`` has not been called. + + Code Flow - Setup + - FabricSummary() is instantiated + + Code Flow - Test + - FabricSummary().spine_count is accessed without having + first called FabricSummary().refresh() + + Expected Result + - ``ValueError`` is raised + - Exception message matches expected + """ + with does_not_raise(): + instance = fabric_summary_v2 + + match = r"FabricSummary\.refresh\(\) must be called before " + match += r"accessing FabricSummary\.spine_count\." + with pytest.raises(ValueError, match=match): + instance.spine_count # pylint: disable=pointless-statement diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_types.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_types.py index 8b2f951f6..1a16a1ca7 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_types.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_types.py @@ -28,8 +28,7 @@ __author__ = "Allen Robel" import pytest -from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, fabric_types_fixture) +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import does_not_raise, fabric_types_fixture def test_fabric_types_00010(fabric_types) -> None: @@ -78,9 +77,7 @@ def test_fabric_types_00010(fabric_types) -> None: ), ], ) -def test_fabric_types_00020( - fabric_types, fabric_type, template_name, does_raise, expected -) -> None: +def test_fabric_types_00020(fabric_types, fabric_type, template_name, does_raise, expected) -> None: """ Classes and Methods - FabricTypes @@ -147,9 +144,7 @@ def test_fabric_types_00030(fabric_types) -> None: ), ], ) -def test_fabric_types_00040( - fabric_types, fabric_type, parameters, does_raise, expected -) -> None: +def test_fabric_types_00040(fabric_types, fabric_type, parameters, does_raise, expected) -> None: """ Classes and Methods - FabricTypes diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_param_info.py b/tests/unit/modules/dcnm/dcnm_fabric/test_param_info.py index fd7833a43..b689616f3 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_param_info.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_param_info.py @@ -33,10 +33,8 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.param_info import \ - ParamInfo -from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, templates_param_info) +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.param_info import ParamInfo +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import does_not_raise, templates_param_info def test_param_info_00010() -> None: diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_ruleset.py b/tests/unit/modules/dcnm/dcnm_fabric/test_ruleset.py index 13f3b5450..109b13f04 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_ruleset.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_ruleset.py @@ -33,12 +33,9 @@ import re import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.conversion import \ - ConversionUtils -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.ruleset import \ - RuleSet -from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - does_not_raise, templates_ruleset) +from ansible_collections.cisco.dcnm.plugins.module_utils.common.conversion import ConversionUtils +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.ruleset import RuleSet +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import does_not_raise, templates_ruleset def test_ruleset_00010() -> None: @@ -118,9 +115,9 @@ def test_ruleset_00030() -> None: instance = RuleSet() instance.template = templates_ruleset(key) instance.refresh() - assert instance.ruleset.get("ADVERTISE_PIP_ON_BORDER", {}).get("terms", {}).get( - "na" - ) == [{"operator": "!=", "parameter": "ADVERTISE_PIP_BGP", "value": True}] + assert instance.ruleset.get("ADVERTISE_PIP_ON_BORDER", {}).get("terms", {}).get("na") == [ + {"operator": "!=", "parameter": "ADVERTISE_PIP_BGP", "value": True} + ] @pytest.mark.parametrize("bad_value", [("BAD_STRING"), (None), (10), ([10]), ({10})]) diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_template_get.py b/tests/unit/modules/dcnm/dcnm_fabric/test_template_get.py index 8efa11e95..0b933886d 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_template_get.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_template_get.py @@ -32,17 +32,16 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.exceptions import \ - ControllerResponseError -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.common.exceptions import ControllerResponseError +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - MockAnsibleModule, does_not_raise, responses_template_get, - template_get_fixture) + MockAnsibleModule, + does_not_raise, + responses_template_get, + template_get_fixture, +) def test_template_get_00000(template_get) -> None: diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_template_get_all.py b/tests/unit/modules/dcnm/dcnm_fabric/test_template_get_all.py index e97c99558..bbaa4f224 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_template_get_all.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_template_get_all.py @@ -32,17 +32,16 @@ import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.common.exceptions import \ - ControllerResponseError -from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send import \ - RestSend -from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import \ - Results -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.common.exceptions import ControllerResponseError +from ansible_collections.cisco.dcnm.plugins.module_utils.common.rest_send import RestSend +from ansible_collections.cisco.dcnm.plugins.module_utils.common.results import Results +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.utils import ( - MockAnsibleModule, does_not_raise, responses_template_get_all, - template_get_all_fixture) + MockAnsibleModule, + does_not_raise, + responses_template_get_all, + template_get_all_fixture, +) def test_template_get_all_00000(template_get_all) -> None: @@ -304,10 +303,7 @@ def mock_dcnm_send(*args, **kwargs): instance.refresh() assert isinstance(instance.templates, dict) assert instance.templates.get("Easy_Fabric", {}).get("name") == "Easy_Fabric" - assert ( - instance.templates.get("Easy_Fabric_Classic", {}).get("templateType") - == "FABRIC" - ) + assert instance.templates.get("Easy_Fabric_Classic", {}).get("templateType") == "FABRIC" assert len(instance.response) == 1 assert len(instance.result) == 1 assert instance.result_current.get("success", None) is True diff --git a/tests/unit/modules/dcnm/dcnm_fabric/utils.py b/tests/unit/modules/dcnm/dcnm_fabric/utils.py index e5e0a8c1d..430066599 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/utils.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/utils.py @@ -14,7 +14,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - from __future__ import absolute_import, division, print_function __metaclass__ = type # pylint: disable=invalid-name @@ -23,42 +22,25 @@ from contextlib import contextmanager import pytest -from ansible_collections.ansible.netcommon.tests.unit.modules.utils import \ - AnsibleFailJson -from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import \ - ResponseHandler -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.common import \ - FabricCommon -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.config_deploy import \ - FabricConfigDeploy -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.config_save import \ - FabricConfigSave -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.create import ( - FabricCreate, FabricCreateBulk, FabricCreateCommon) -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.delete import \ - FabricDelete -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import \ - FabricDetails as FabricDetailsV2 -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import \ - FabricDetailsByName as FabricDetailsByNameV2 -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import \ - FabricDetailsByNvPair as FabricDetailsByNvPairV2 -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_summary import \ - FabricSummary -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_types import \ - FabricTypes -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.query import \ - FabricQuery -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.replaced import \ - FabricReplacedBulk -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.template_get import \ - TemplateGet -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.template_get_all import \ - TemplateGetAll -from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.update import \ - FabricUpdateBulk -from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.fixture import \ - load_fixture +from ansible_collections.ansible.netcommon.tests.unit.modules.utils import AnsibleFailJson +from ansible_collections.cisco.dcnm.plugins.module_utils.common.response_handler import ResponseHandler +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.common import FabricCommon +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.config_deploy import FabricConfigDeploy +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.config_save import FabricConfigSave +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.create import FabricCreate, FabricCreateBulk, FabricCreateCommon +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.delete import FabricDelete +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import FabricDetails as FabricDetailsV2 +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import FabricDetailsByName as FabricDetailsByNameV2 +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_details_v2 import FabricDetailsByNvPair as FabricDetailsByNvPairV2 +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_summary import FabricSummary +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_summary_v2 import FabricSummary as FabricSummaryV2 +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.fabric_types import FabricTypes +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.query import FabricQuery +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.replaced import FabricReplacedBulk +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.template_get import TemplateGet +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.template_get_all import TemplateGetAll +from ansible_collections.cisco.dcnm.plugins.module_utils.fabric.update import FabricUpdateBulk +from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_fabric.fixture import load_fixture params = { "state": "merged", @@ -223,6 +205,14 @@ def fabric_summary_fixture(): return FabricSummary() +@pytest.fixture(name="fabric_summary_v2") +def fabric_summary_v2_fixture(): + """ + Return FabricSummary() instance. + """ + return FabricSummaryV2() + + @pytest.fixture(name="fabric_types") def fabric_types_fixture(): """ @@ -491,6 +481,16 @@ def responses_fabric_summary(key: str) -> dict[str, str]: return data +def responses_fabric_summary_v2(key: str) -> dict[str, str]: + """ + Return responses for FabricSummary (v2) + """ + data_file = "responses_FabricSummary_V2" + data = load_fixture(data_file).get(key) + print(f"{data_file}: {key} : {data}") + return data + + def responses_fabric_update_bulk(key: str) -> dict[str, str]: """ Return responses for FabricUpdateBulk