diff --git a/plugins/module_utils/bootflash/bootflash_files.py b/plugins/module_utils/bootflash/bootflash_files.py index d74f35db9..31c279866 100644 --- a/plugins/module_utils/bootflash/bootflash_files.py +++ b/plugins/module_utils/bootflash/bootflash_files.py @@ -13,21 +13,21 @@ # limitations under the License. from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type # pylint: disable=invalid-name __author__ = "Allen Robel" import copy import inspect import logging +from typing import Any, Literal -from ..common.api.v1.imagemanagement.rest.imagemgnt.bootflash.bootflash import \ - EpBootflashFiles +from ..common.api.v1.imagemanagement.rest.imagemgnt.bootflash.bootflash import EpBootflashFiles from ..common.conversion import ConversionUtils -from ..common.properties import Properties +from ..common.rest_send_v2 import RestSend +from ..common.results import Results +from ..common.switch_details import SwitchDetails -@Properties.add_rest_send -@Properties.add_results class BootflashFiles: """ ### Summary @@ -107,42 +107,44 @@ class BootflashFiles: ``` """ - def __init__(self): - self.class_name = self.__class__.__name__ + def __init__(self) -> None: + self.class_name: str = self.__class__.__name__ - self.action = "bootflash_delete" - self.conversion = ConversionUtils() + self.action: Literal["bootflash_delete"] = "bootflash_delete" + self.conversion: ConversionUtils = ConversionUtils() # self.diff is keyed on switch ip_address and is updated # in self.update_diff(). - self.diff = {} - self.ep_bootflash_files = EpBootflashFiles() + self.diff: dict[str, Any] = {} + self.ep_bootflash_files: EpBootflashFiles = EpBootflashFiles() - self.ok_to_delete_files_reason = None - self.mandatory_target_keys = [ + self.ok_to_delete_files_reason: str = "" + self.mandatory_target_keys: list[str] = [ "filepath", "ip_address", "serial_number", "supervisor", ] - self.payload = {"deleteFiles": []} - self.switch_details_refreshed = False - - self._filename = None - self._filepath = None - self._ip_address = None - self._partition = None - self._rest_send = None - self._results = None - self._supervisor = None - self._switch_details = None - self._target = None + self.payload: dict[str, list[dict[str, Any]]] = {"deleteFiles": []} + self.switch_details_refreshed: bool = False + + self._filename: str = "" + self._filepath: str = "" + self._ip_address: str = "" + self._partition: str = "" + self._rest_send: RestSend = RestSend({}) + self._results: Results = Results() + self._supervisor: str = "" + self._switch_details: SwitchDetails = SwitchDetails() + self._switch_details.results = Results() + self._switch_details.rest_send = RestSend({}) + self._target: dict[str, str] = {} self.log = logging.getLogger(f"dcnm.{self.class_name}") msg = "ENTERED BootflashQuery(): " msg += f"action {self.action}, " self.log.debug(msg) - def refresh_switch_details(self): + def refresh_switch_details(self) -> None: """ ### Summary If switch details are not already refreshed, refresh them. @@ -152,25 +154,23 @@ def refresh_switch_details(self): - ``switch_details`` is not set. - ``rest_send`` is not set. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] - def raise_exception(property_name): + if not self._rest_send_instantiated(): msg = f"{self.class_name}.{method_name}: " - msg += f"{property_name} must be set before calling {method_name}." + msg += f"rest_send must be set before calling {method_name}." + raise ValueError(f"{msg}") + if not self._switch_details_instantiated(): + msg = f"{self.class_name}.{method_name}: " + msg += f"switch_details must be set before calling {method_name}." raise ValueError(f"{msg}") - - if self.switch_details is None: - raise_exception("switch_details") - # pylint: disable=no-member - if self.rest_send is None: - raise_exception("rest_send") if self.switch_details_refreshed is False: self.switch_details.rest_send = self.rest_send self.switch_details.refresh() self.switch_details_refreshed = True - def ip_address_to_serial_number(self, ip_address): + def ip_address_to_serial_number(self, ip_address: str) -> str: """ ### Summary Convert ip_address to serial_number. @@ -179,7 +179,7 @@ def ip_address_to_serial_number(self, ip_address): - ``ValueError`` if: - switch_details is not set. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] self.refresh_switch_details() @@ -192,7 +192,7 @@ def ip_address_to_serial_number(self, ip_address): raise ValueError(msg) from error return serial_number - def ok_to_delete_files(self, ip_address): + def ok_to_delete_files(self, ip_address: str) -> bool: """ ### Summary - Return True if files can be deleted on the switch with ip_address. @@ -210,34 +210,69 @@ def ok_to_delete_files(self, ip_address): return False return True + def _rest_send_instantiated(self) -> bool: + """ + # Summary + + - Return True if rest_send is properly instantiated. + - Return False otherwise. + + ## Raises + + None + """ + try: + if not self._rest_send.params: + return False + except AttributeError: + return False + return True + + def _switch_details_instantiated(self) -> bool: + """ + # Summary + + - Return True if switch_details is properly instantiated. + - Return False otherwise. + + ## Raises + + None + """ + try: + if not self._switch_details.rest_send.params: + return False + except AttributeError: + return False + return True + def validate_commit_parameters(self) -> None: """ - ### Summary + # Summary + Verify that mandatory prerequisites are met before calling commit. - ### Raises - - ``ValueError`` if: - - rest_send is not set. - - results is not set. - - switch_details is not set. - - payload is not set. + ## Raises + + ### ValueError + + - rest_send is not properly initialized. + - switch_details is not properly initialized. """ # pylint: disable=no-member - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] - def raise_exception(property_name): + def raise_exception(property_name: str) -> None: msg = f"{self.class_name}.{method_name}: " msg += f"{property_name} must be set before calling commit()." raise ValueError(f"{msg}") - if not self.rest_send: + if not self._rest_send_instantiated(): raise_exception("rest_send") - if not self.results: - raise_exception("results") - if not self.switch_details: + if not self._switch_details_instantiated(): raise_exception("switch_details") - def commit(self): + def commit(self) -> None: """ ### Summary Send the payload to delete files. @@ -259,7 +294,7 @@ def commit(self): self.delete_files() - def delete_files(self): + def delete_files(self) -> None: """ ### Summary Delete files that have been added with add_files(). @@ -273,9 +308,7 @@ def delete_files(self): self.rest_send.verb = self.ep_bootflash_files.verb self.rest_send.payload = self.payload self.rest_send.commit() - self.results.response_current = copy.deepcopy( - self.rest_send.response_current - ) + self.results.response_current = copy.deepcopy(self.rest_send.response_current) self.results.result_current = copy.deepcopy(self.rest_send.result_current) else: self.results.result_current = {"success": True, "changed": False} @@ -287,7 +320,7 @@ def delete_files(self): self.results.diff_current = copy.deepcopy(self.diff) self.results.register_task_result() - def validate_prerequisites_for_add_file(self): + def validate_prerequisites_for_add_file(self) -> None: """ ### Summary Verify that mandatory prerequisites are met before calling add_file() @@ -301,9 +334,9 @@ def validate_prerequisites_for_add_file(self): - ``switch_details`` is not set. - ``target`` is not set. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] - def raise_exception(property_name): + def raise_exception(property_name: str) -> None: msg = f"{self.class_name}.{method_name}: " msg += f"{property_name} must be set before calling add_file()." raise ValueError(f"{msg}") @@ -316,12 +349,12 @@ def raise_exception(property_name): raise_exception("ip_address") if not self.supervisor: raise_exception("supervisor") - if not self.switch_details: + if not self._switch_details_instantiated(): raise_exception("switch_details") if not self.target: raise_exception("target") - def partition_and_serial_number_exist_in_payload(self): + def partition_and_serial_number_exist_in_payload(self) -> bool: """ ### Summary - Return True if the partition and serialNumber associated with the @@ -358,10 +391,10 @@ def partition_and_serial_number_exist_in_payload(self): } ] """ - found = False + found: bool = False for item in self.payload["deleteFiles"]: - serial_number = item.get("serialNumber") - partition = item.get("partition") + serial_number: str = item.get("serialNumber", "") + partition: str = item.get("partition", "") if serial_number != self.ip_address_to_serial_number(self.ip_address): continue if partition != self.partition: @@ -370,19 +403,23 @@ def partition_and_serial_number_exist_in_payload(self): break return found - def add_file_to_existing_payload(self): + def add_file_to_existing_payload(self) -> None: """ - ### Summary + # Summary + Add a file to the payload if the following are true: + - The serialNumber and partition associated with the file exist in the payload. - The file does not already exist in the files list for that serialNumber and partition. - ### Raises + ## Raises + None - ### Details + ## Details + We are looking at the following structure. ```json @@ -406,31 +443,37 @@ def add_file_to_existing_payload(self): }, ] } + ``` + """ + serial_number: str = self.ip_address_to_serial_number(self.ip_address) + for item in self.payload["deleteFiles"]: - serial_number = item.get("serialNumber") - partition = item.get("partition") - if serial_number != self.ip_address_to_serial_number(self.ip_address): + if item.get("serialNumber") != serial_number: continue - if partition != self.partition: + if item.get("partition") != self.partition: continue - files = item.get("files") - for file in files: - if ( - file.get("fileName") == self.filename - and file.get("bootflashType") == self.supervisor - ): - return - files.append( + + # Ensure files list exists + if "files" not in item: + item["files"] = [] + + # Check if file already exists (same filename AND supervisor) + for file in item["files"]: + if file.get("fileName") == self.filename and file.get("bootflashType") == self.supervisor: + return # File already in payload + + # Add the new file + item["files"].append( { "bootflashType": self.supervisor, "fileName": self.filename, "filePath": self.filepath, } ) - item.update({"files": files}) + return # Done - exit after finding matching item - def add_file_to_payload(self): + def add_file_to_payload(self) -> None: """ ### Summary Add a file to the payload if the serialNumber and partition do not @@ -455,7 +498,7 @@ def add_file_to_payload(self): else: self.add_file_to_existing_payload() - def add_file(self): + def add_file(self) -> None: """ ### Summary Add a file to the payload. @@ -464,7 +507,7 @@ def add_file(self): - ``ValueError`` if: - The switch does not allow file deletion. """ - method_name = inspect.stack()[0][3] + method_name: str = inspect.stack()[0][3] self.validate_prerequisites_for_add_file() if not self.ok_to_delete_files(self.ip_address): @@ -476,7 +519,7 @@ def add_file(self): self.add_file_to_payload() self.update_diff() - def update_diff(self): + def update_diff(self) -> None: """ ### Summary Update ``diff`` with ``target``. @@ -490,13 +533,13 @@ def update_diff(self): - ``target`` has already been validated to be a dictionary and to contain ``ip_address`` in ``target.setter``. """ - ip_address = self.target.get("ip_address") + ip_address: str = self.target.get("ip_address", "") if ip_address not in self.diff: self.diff[ip_address] = [] self.diff[ip_address].append(self.target) @property - def filepath(self): + def filepath(self) -> str: """ ### Summary Return the current ``filepath``. @@ -516,11 +559,11 @@ def filepath(self): return self._filepath @filepath.setter - def filepath(self, value): + def filepath(self, value: str) -> None: self._filepath = value @property - def filename(self): + def filename(self) -> str: """ ### Summary Return the current ``filename``. @@ -539,11 +582,11 @@ def filename(self): return self._filename @filename.setter - def filename(self, value): + def filename(self, value: str) -> None: self._filename = value @property - def ip_address(self): + def ip_address(self) -> str: """ ### Summary The ip address of the switch on which ``filename`` resides. @@ -560,11 +603,11 @@ def ip_address(self): return self._ip_address @ip_address.setter - def ip_address(self, value): + def ip_address(self, value: str) -> None: self._ip_address = value @property - def partition(self): + def partition(self) -> str: """ ### Summary The partition on which ``filename`` resides. @@ -581,11 +624,93 @@ def partition(self): return self._partition @partition.setter - def partition(self, value): + def partition(self, value: str) -> None: self._partition = value @property - def supervisor(self): + 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] + if not self._rest_send.params: + msg = f"{self.class_name}.{method_name}: " + msg += "RestSend.params must be set before accessing." + raise ValueError(msg) + return self._rest_send + + @rest_send.setter + def rest_send(self, value: RestSend) -> None: + 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 supervisor(self) -> str: """ ### Summary Return the current ``supervisor``. @@ -606,11 +731,11 @@ def supervisor(self): return self._supervisor @supervisor.setter - def supervisor(self, value): + def supervisor(self, value: str) -> None: self._supervisor = value @property - def switch_details(self): + def switch_details(self) -> SwitchDetails: """ ### Summary An instance of the ``SwitchDetails()`` class. @@ -639,7 +764,7 @@ def switch_details(self, value): self._switch_details = value @property - def target(self): + def target(self) -> dict[str, str]: """ ### Summary ``target`` is a dictionary that is used to set the diff passed to @@ -689,7 +814,7 @@ def target(self): return self._target @target.setter - def target(self, value): + def target(self, value: dict[str, str]) -> None: method_name = inspect.stack()[0][3] msg = f"{self.class_name}.{method_name}: " diff --git a/plugins/modules/dcnm_bootflash.py b/plugins/modules/dcnm_bootflash.py index 317670a79..4b7fc4e30 100644 --- a/plugins/modules/dcnm_bootflash.py +++ b/plugins/modules/dcnm_bootflash.py @@ -534,6 +534,8 @@ def commit(self) -> None: self.bootflash_info.results = Results() self.bootflash_info.rest_send = self.rest_send # pylint: disable=no-member self.bootflash_info.switch_details = SwitchDetails() + self.bootflash_info.switch_details.rest_send = self.rest_send + self.bootflash_info.switch_details.results = Results() # Retrieve bootflash contents for the user's switches. switch_list = [] @@ -549,6 +551,7 @@ def commit(self) -> None: self.bootflash_files.rest_send = self.rest_send self.bootflash_files.switch_details = SwitchDetails() self.bootflash_files.switch_details.results = Results() + self.bootflash_files.switch_details.rest_send = self.rest_send # Update BootflashFiles() with the files to delete self.files_to_delete = {} diff --git a/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_deleted.py b/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_deleted.py index 5d4c6e25b..9b460de9c 100644 --- a/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_deleted.py +++ b/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_deleted.py @@ -337,7 +337,9 @@ def responses(): instance.rest_send = rest_send instance.bootflash_files.switch_details = SwitchDetails() instance.bootflash_files.rest_send = rest_send + instance.bootflash_files.switch_details.rest_send = rest_send instance.bootflash_files.switch_details.results = Results() + match = r"Deleted\.update_bootflash_files:\s+" match += r"Error adding file to bootflash_files\.\s+" match += r"Error detail:\s+" @@ -401,6 +403,7 @@ def responses(): instance.rest_send = rest_send instance.bootflash_files.switch_details = SwitchDetails() instance.bootflash_files.rest_send = rest_send + instance.bootflash_files.switch_details.rest_send = rest_send instance.bootflash_files.switch_details.results = Results() match = r"Deleted\.update_bootflash_files:\s+" match += r"Error adding file to bootflash_files\.\s+" diff --git a/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_files.py b/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_files.py index a969e9d44..73d5d7eb8 100644 --- a/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_files.py +++ b/tests/unit/modules/dcnm/dcnm_bootflash/test_bootflash_files.py @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Cisco and/or its affiliates. +# Copyright (c) 2024-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. @@ -20,35 +20,33 @@ from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type # pylint: disable=invalid-name -__copyright__ = "Copyright (c) 2024 Cisco and/or its affiliates." +__copyright__ = "Copyright (c) 2024-2025 Cisco and/or its affiliates." __author__ = "Allen Robel" import copy import inspect import pytest -from ansible_collections.cisco.dcnm.plugins.module_utils.bootflash.bootflash_files import \ - BootflashFiles -from ansible_collections.cisco.dcnm.plugins.module_utils.bootflash.convert_target_to_params import \ - ConvertTargetToParams -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.plugins.module_utils.common.switch_details import \ - SwitchDetails -from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import \ - ResponseGenerator +from ansible_collections.cisco.dcnm.plugins.module_utils.bootflash.bootflash_files import BootflashFiles +from ansible_collections.cisco.dcnm.plugins.module_utils.bootflash.convert_target_to_params import ConvertTargetToParams +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.plugins.module_utils.common.switch_details import SwitchDetails +from ansible_collections.cisco.dcnm.tests.unit.module_utils.common.common_utils import ResponseGenerator from ansible_collections.cisco.dcnm.tests.unit.modules.dcnm.dcnm_bootflash.utils import ( - MockAnsibleModule, configs_deleted, does_not_raise, params_deleted, - payloads_bootflash_files, responses_ep_all_switches, - responses_ep_bootflash_files, targets) + MockAnsibleModule, + configs_deleted, + does_not_raise, + params_deleted, + payloads_bootflash_files, + responses_ep_all_switches, + responses_ep_bootflash_files, + targets, +) def test_bootflash_files_00000() -> None: @@ -77,17 +75,18 @@ def test_bootflash_files_00000() -> None: "serial_number", "supervisor", ] - assert instance.ok_to_delete_files_reason is None + assert instance.ok_to_delete_files_reason == "" assert instance.payload == {"deleteFiles": []} - assert instance.filename is None - assert instance.filepath is None - assert instance.ip_address is None - assert instance.partition is None - assert instance._rest_send is None - assert instance._results is None - assert instance.supervisor is None - assert instance.switch_details is None - assert instance.target is None + assert instance._filename == "" + assert instance._filepath == "" + assert instance._ip_address == "" + assert instance._partition == "" + assert instance._rest_send.params == {} + assert instance._rest_send.class_name == "RestSend" + assert instance._results.class_name == "Results" + assert instance._supervisor == "" + assert instance._switch_details.class_name == "SwitchDetails" + assert instance._target == {} def test_bootflash_files_00100() -> None: @@ -143,39 +142,39 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() convert_target = ConvertTargetToParams() convert_target.target = gen_targets.next convert_target.commit() - instance.filepath = convert_target.filepath - instance.filename = convert_target.filename + instance.filepath = convert_target.filepath or "" + instance.filename = convert_target.filename or "" instance.ip_address = "172.22.150.112" - instance.partition = convert_target.partition - instance.supervisor = convert_target.supervisor - instance.target = convert_target.target + instance.partition = convert_target.partition or "" + instance.supervisor = convert_target.supervisor or "" + instance.target = convert_target.target or {} instance.add_file() convert_target = ConvertTargetToParams() convert_target.target = gen_targets.next convert_target.commit() - instance.filepath = convert_target.filepath - instance.filename = convert_target.filename + instance.filepath = convert_target.filepath or "" + instance.filename = convert_target.filename or "" instance.ip_address = "172.22.150.113" - instance.partition = convert_target.partition - instance.supervisor = convert_target.supervisor - instance.target = convert_target.target + instance.partition = convert_target.partition or "" + instance.supervisor = convert_target.supervisor or "" + instance.target = convert_target.target or {} instance.add_file() instance.commit() assert instance.payload == payloads_bootflash_files(f"{key}a") + assert instance.results.response_current is not None assert instance.results.response_current["RETURN_CODE"] == 200 - assert instance.results.result == [ - {"success": True, "changed": True, "sequence_number": 1} - ] + assert instance.results.result == [{"success": True, "changed": True, "sequence_number": 1}] def test_bootflash_files_00110() -> None: @@ -195,51 +194,23 @@ def test_bootflash_files_00110() -> None: """ with does_not_raise(): instance = BootflashFiles() - instance.results = Results() instance.switch_details = SwitchDetails() - match = r"BootflashFiles.validate_commit_parameters:\s+" + match = r"BootflashFiles\.validate_commit_parameters: " match += r"rest_send must be set before calling commit\(\)\." with pytest.raises(ValueError, match=match): instance.commit() -def test_bootflash_files_00120() -> None: - """ - ### Classes and Methods - - BootflashFiles() - - commit() - - validate_commit_parameters() - - ### Summary - Verify ``ValueError`` is raised if ``results`` is not set before - calling commit. - - ### Test - - ValueError is raised by validate_commit_parameters(). - - Error message matches expectation. - """ - with does_not_raise(): - instance = BootflashFiles() - instance.rest_send = RestSend(params_deleted) - instance.switch_details = SwitchDetails() - - match = r"BootflashFiles.validate_commit_parameters:\s+" - match += r"results must be set before calling commit\(\)\." - with pytest.raises(ValueError, match=match): - instance.commit() - - def test_bootflash_files_00130() -> None: """ ### Classes and Methods - BootflashFiles() - commit() - - validate_commit_parameters() + - switch_details property ### Summary - Verify ``ValueError`` is raised if ``switch_details`` is not set before - calling commit. + Verify `ValueError` is raised if `switch_details` is not set before calling commit. ### Test - ValueError is raised by validate_commit_parameters(). @@ -250,7 +221,7 @@ def test_bootflash_files_00130() -> None: instance.rest_send = RestSend(params_deleted) instance.results = Results() - match = r"BootflashFiles.validate_commit_parameters:\s+" + match = r"BootflashFiles\.validate_commit_parameters: " match += r"switch_details must be set before calling commit\(\)\." with pytest.raises(ValueError, match=match): instance.commit() @@ -298,6 +269,7 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() instance.filepath = "bootflash:/air.txt" @@ -365,6 +337,7 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() instance.filepath = "bootflash:/air.txt" @@ -457,18 +430,19 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() convert_target = ConvertTargetToParams() convert_target.target = gen_targets.next convert_target.commit() - instance.filepath = convert_target.filepath - instance.filename = convert_target.filename + instance.filepath = convert_target.filepath or "" + instance.filename = convert_target.filename or "" instance.ip_address = "172.22.150.112" - instance.partition = convert_target.partition - instance.supervisor = convert_target.supervisor - instance.target = convert_target.target + instance.partition = convert_target.partition or "" + instance.supervisor = convert_target.supervisor or "" + instance.target = convert_target.target or {} match = r"BootflashFiles\.add_file:\s+" match += r"Cannot delete files on switch 172\.22\.150\.112\.\s+" @@ -662,6 +636,12 @@ def test_bootflash_files_00280() -> None: - ValueError is raised by validate_prerequisites_for_add_file(). - Error message matches expectation. """ + rest_send = RestSend(params_deleted) + rest_send.unit_test = True + rest_send.timeout = 1 + rest_send.response_handler = ResponseHandler() + rest_send.sender = Sender() + with does_not_raise(): instance = BootflashFiles() instance.filename = "air.txt" @@ -671,6 +651,8 @@ def test_bootflash_files_00280() -> None: instance.results = Results() instance.supervisor = "active" instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send + instance.switch_details.results = Results() match = r"BootflashFiles.validate_prerequisites_for_add_file:\s+" match += r"target must be set before calling add_file\(\)\." @@ -725,9 +707,8 @@ def test_bootflash_files_00310() -> None: instance = BootflashFiles() instance.switch_details = SwitchDetails() - match = r"BootflashFiles\.refresh_switch_details:\s+" - match += r"rest_send must be set before calling\s+" - match += r"refresh_switch_details\." + match = r"BootflashFiles.refresh_switch_details: " + match += r"rest_send must be set before calling refresh_switch_details\." with pytest.raises(ValueError, match=match): instance.refresh_switch_details() @@ -779,6 +760,7 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() match = r"BootflashFiles\.ip_address_to_serial_number:\s+" @@ -821,11 +803,10 @@ def test_bootflash_files_00500() -> None: instance.switch_details.results = Results() instance.delete_files() + assert instance.results.response_current is not None assert instance.results.response_current["RETURN_CODE"] == 200 assert instance.results.response_current["MESSAGE"] == "No files to delete." - assert instance.results.result == [ - {"success": True, "changed": False, "sequence_number": 1} - ] + assert instance.results.result == [{"success": True, "changed": False, "sequence_number": 1}] def test_bootflash_files_00600() -> None: @@ -871,6 +852,7 @@ def responses(): instance.results = Results() instance.switch_details = SwitchDetails() instance.switch_details.results = Results() + instance.switch_details.rest_send = rest_send instance.payload = payloads_bootflash_files(key) instance.ip_address = "172.22.150.112" instance.partition = "usb1:" @@ -921,6 +903,7 @@ def responses(): instance.rest_send = rest_send instance.results = Results() instance.switch_details = SwitchDetails() + instance.switch_details.rest_send = rest_send instance.switch_details.results = Results() instance.payload = payloads_bootflash_files(key) instance.ip_address = "172.22.150.112" @@ -998,12 +981,10 @@ def test_bootflash_files_00800() -> None: match = r"BootflashFiles.target:\s+" match += r"target must be a dictionary\. Got type str for value foo\." with pytest.raises(TypeError, match=match): - instance.target = "foo" + instance.target = "foo" # type: ignore -@pytest.mark.parametrize( - "parameter", ["filepath", "ip_address", "serial_number", "supervisor"] -) +@pytest.mark.parametrize("parameter", ["filepath", "ip_address", "serial_number", "supervisor"]) def test_bootflash_files_00810(parameter) -> None: """ ### Classes and Methods