From f7f93b2c7a8bf3730fe4f82a9f4a30bb2ee89b68 Mon Sep 17 00:00:00 2001 From: Tomer Haskalovitch Date: Tue, 15 Jul 2025 10:40:07 +0300 Subject: [PATCH] mgr/dashboard: add help for nvmeof cli Signed-off-by: Tomer Haskalovitch --- .../mgr/dashboard/controllers/nvmeof.py | 97 ++++++++++--------- src/pybind/mgr/dashboard/openapi.yaml | 6 ++ .../mgr/dashboard/services/nvmeof_cli.py | 12 ++- .../mgr/dashboard/tests/test_nvmeof_cli.py | 42 ++++++++ 4 files changed, 111 insertions(+), 46 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/nvmeof.py b/src/pybind/mgr/dashboard/controllers/nvmeof.py index 34517159533a2..7fe19fcd3a999 100644 --- a/src/pybind/mgr/dashboard/controllers/nvmeof.py +++ b/src/pybind/mgr/dashboard/controllers/nvmeof.py @@ -32,8 +32,9 @@ else: @APIRouter("/nvmeof/gateway", Scope.NVME_OF) @APIDoc("NVMe-oF Gateway Management API", "NVMe-oF Gateway") class NVMeoFGateway(RESTController): - @EndpointDoc("Get information about the NVMeoF gateway") + @NvmeofCLICommand("nvmeof gw info", model.GatewayInfo) + @EndpointDoc("Get information about the NVMeoF gateway") @convert_to_model(model.GatewayInfo) @handle_nvmeof_error def list(self, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -57,6 +58,7 @@ else: @ReadPermission @Endpoint('GET', '/version') @NvmeofCLICommand("nvmeof gw version", model.GatewayVersion) + @EndpointDoc("Get the version of the NVMeoF gateway") @convert_to_model(model.GatewayVersion) @handle_nvmeof_error def version(self, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -70,6 +72,7 @@ else: @ReadPermission @Endpoint('GET', '/log_level') @NvmeofCLICommand("nvmeof gw get_log_level", model.GatewayLogLevelInfo) + @EndpointDoc("Get NVMeoF gateway log level information") @convert_to_model(model.GatewayLogLevelInfo) @handle_nvmeof_error def get_log_level(self, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -82,6 +85,7 @@ else: @ReadPermission @Endpoint('PUT', '/log_level') @NvmeofCLICommand("nvmeof gw set_log_level", model.RequestStatus) + @EndpointDoc("Set NVMeoF gateway log levels") @convert_to_model(model.RequestStatus) @handle_nvmeof_error def set_log_level(self, log_level: str, gw_group: Optional[str] = None, @@ -99,6 +103,7 @@ else: @ReadPermission @Endpoint('GET', '/log_level') @NvmeofCLICommand("nvmeof spdk_log_level get", model.SpdkNvmfLogFlagsAndLevelInfo) + @EndpointDoc("Get NVMeoF gateway spdk log levels") @convert_to_model(model.SpdkNvmfLogFlagsAndLevelInfo) @handle_nvmeof_error def get_spdk_log_level( @@ -114,6 +119,7 @@ else: @ReadPermission @Endpoint('PUT', '/log_level') @NvmeofCLICommand("nvmeof spdk_log_level set", model.RequestStatus) + @EndpointDoc("Set NVMeoF gateway spdk log levels") @convert_to_model(model.RequestStatus) @handle_nvmeof_error def set_spdk_log_level(self, log_level: Optional[str] = None, @@ -133,6 +139,7 @@ else: @ReadPermission @Endpoint('PUT', '/log_level/disable') @NvmeofCLICommand("nvmeof spdk_log_level disable", model.RequestStatus) + @EndpointDoc("Disable NVMeoF gateway spdk log") @convert_to_model(model.RequestStatus) @handle_nvmeof_error def disable_spdk_log_level( @@ -149,9 +156,9 @@ else: @APIRouter("/nvmeof/subsystem", Scope.NVME_OF) @APIDoc("NVMe-oF Subsystem Management API", "NVMe-oF Subsystem") class NVMeoFSubsystem(RESTController): - @EndpointDoc("List all NVMeoF subsystems") @pick(field="subsystems") @NvmeofCLICommand("nvmeof subsystem list", model.SubsystemList) + @EndpointDoc("List all NVMeoF subsystems") @convert_to_model(model.SubsystemList) @handle_nvmeof_error def list(self, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -159,6 +166,8 @@ else: NVMeoFClient.pb2.list_subsystems_req() ) + @pick(field="subsystems", first=True) + @NvmeofCLICommand("nvmeof subsystem get", model.SubsystemList) @EndpointDoc( "Get information from a specific NVMeoF subsystem", parameters={ @@ -166,8 +175,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick(field="subsystems", first=True) - @NvmeofCLICommand("nvmeof subsystem get", model.SubsystemList) @convert_to_model(model.SubsystemList) @handle_nvmeof_error def get(self, nqn: str, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -175,6 +182,8 @@ else: NVMeoFClient.pb2.list_subsystems_req(subsystem_nqn=nqn) ) + @empty_response + @NvmeofCLICommand("nvmeof subsystem add", model.RequestStatus) @EndpointDoc( "Create a new NVMeoF subsystem", parameters={ @@ -184,8 +193,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof subsystem add", model.RequestStatus) @convert_to_model(model.SubsystemStatus) @handle_nvmeof_error def create(self, nqn: str, enable_ha: bool = True, max_namespaces: int = 4096, @@ -196,6 +203,8 @@ else: ) ) + @empty_response + @NvmeofCLICommand("nvmeof subsystem del", model.RequestStatus) @EndpointDoc( "Delete an existing NVMeoF subsystem", parameters={ @@ -204,8 +213,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof subsystem del", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def delete(self, nqn: str, force: Optional[str] = "false", gw_group: Optional[str] = None, @@ -259,6 +266,8 @@ else: @APIRouter("/nvmeof/subsystem/{nqn}/listener", Scope.NVME_OF) @APIDoc("NVMe-oF Subsystem Listener Management API", "NVMe-oF Subsystem Listener") class NVMeoFListener(RESTController): + @pick("listeners") + @NvmeofCLICommand("nvmeof listener list", model.ListenerList) @EndpointDoc( "List all NVMeoF listeners", parameters={ @@ -266,8 +275,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick("listeners") - @NvmeofCLICommand("nvmeof listener list", model.ListenerList) @convert_to_model(model.ListenerList) @handle_nvmeof_error def list(self, nqn: str, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -275,6 +282,8 @@ else: NVMeoFClient.pb2.list_listeners_req(subsystem=nqn) ) + @empty_response + @NvmeofCLICommand("nvmeof listener add", model.RequestStatus) @EndpointDoc( "Create a new NVMeoF listener", parameters={ @@ -286,8 +295,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof listener add", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def create( @@ -309,6 +316,8 @@ else: ) ) + @empty_response + @NvmeofCLICommand("nvmeof listener del", model.RequestStatus) @EndpointDoc( "Delete an existing NVMeoF listener", parameters={ @@ -320,8 +329,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof listener del", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def delete( @@ -348,6 +355,8 @@ else: @APIRouter("/nvmeof/subsystem/{nqn}/namespace", Scope.NVME_OF) @APIDoc("NVMe-oF Subsystem Namespace Management API", "NVMe-oF Subsystem Namespace") class NVMeoFNamespace(RESTController): + @pick("namespaces") + @NvmeofCLICommand("nvmeof ns list", model.NamespaceList) @EndpointDoc( "List all NVMeoF namespaces in a subsystem", parameters={ @@ -355,8 +364,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick("namespaces") - @NvmeofCLICommand("nvmeof ns list", model.NamespaceList) @convert_to_model(model.NamespaceList) @handle_nvmeof_error def list(self, nqn: str, gw_group: Optional[str] = None, traddr: Optional[str] = None): @@ -364,6 +371,8 @@ else: NVMeoFClient.pb2.list_namespaces_req(subsystem=nqn) ) + @pick("namespaces", first=True) + @NvmeofCLICommand("nvmeof ns get", model.NamespaceList) @EndpointDoc( "Get info from specified NVMeoF namespace", parameters={ @@ -372,8 +381,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick("namespaces", first=True) - @NvmeofCLICommand("nvmeof ns get", model.NamespaceList) @convert_to_model(model.NamespaceList) @handle_nvmeof_error def get(self, nqn: str, nsid: str, gw_group: Optional[str] = None, @@ -384,6 +391,7 @@ else: @ReadPermission @Endpoint('GET', '{nsid}/io_stats') + @NvmeofCLICommand("nvmeof ns get_io_stats", model.NamespaceIOStats) @EndpointDoc( "Get IO stats from specified NVMeoF namespace", parameters={ @@ -392,7 +400,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @NvmeofCLICommand("nvmeof ns get_io_stats", model.NamespaceIOStats) @convert_to_model(model.NamespaceIOStats) @handle_nvmeof_error def io_stats(self, nqn: str, nsid: str, gw_group: Optional[str] = None, @@ -402,6 +409,7 @@ else: subsystem_nqn=nqn, nsid=int(nsid)) ) + @NvmeofCLICommand("nvmeof ns add", model.NamespaceCreation) @EndpointDoc( "Create a new NVMeoF namespace", parameters={ @@ -425,7 +433,6 @@ else: ) }, ) - @NvmeofCLICommand("nvmeof ns add", model.NamespaceCreation) @convert_to_model(model.NamespaceCreation) @handle_nvmeof_error def create( @@ -465,6 +472,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/set_qos') + @NvmeofCLICommand("nvmeof ns set_qos", model=model.RequestStatus) @EndpointDoc( "set QOS for specified NVMeoF namespace", parameters={ @@ -482,7 +490,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns set_qos", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def set_qos( @@ -514,6 +521,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/change_load_balancing_group') + @NvmeofCLICommand("nvmeof ns change_load_balancing_group", model=model.RequestStatus) @EndpointDoc( "set the load balancing group for specified NVMeoF namespace", parameters={ @@ -524,7 +532,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns change_load_balancing_group", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def change_load_balancing_group( @@ -546,6 +553,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/resize') + @NvmeofCLICommand("nvmeof ns resize", model=model.RequestStatus) @EndpointDoc( "resize the specified NVMeoF namespace", parameters={ @@ -556,7 +564,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns resize", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def resize( @@ -578,6 +585,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/add_host') + @NvmeofCLICommand("nvmeof ns add_host", model=model.RequestStatus) @EndpointDoc( "Adds a host to the specified NVMeoF namespace", parameters={ @@ -593,7 +601,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns add_host", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def add_host( @@ -614,6 +621,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/del_host') + @NvmeofCLICommand("nvmeof ns del_host", model=model.RequestStatus) @EndpointDoc( "Removes a host from the specified NVMeoF namespace", parameters={ @@ -624,7 +632,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns del_host", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def del_host( @@ -645,6 +652,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/change_visibility') + @NvmeofCLICommand("nvmeof ns change_visibility", model=model.RequestStatus) @EndpointDoc( "changes the visibility of the specified NVMeoF namespace to all or selected hosts", parameters={ @@ -655,7 +663,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns change_visibility", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def change_visibility( @@ -678,6 +685,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/set_auto_resize') + @NvmeofCLICommand("nvmeof ns set_auto_resize", model=model.RequestStatus) @EndpointDoc( "Enable or disable namespace auto resize when RBD image is resized", parameters={ @@ -692,7 +700,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns set_auto_resize", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def set_auto_resize( @@ -713,6 +720,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/set_rbd_trash_image') + @NvmeofCLICommand("nvmeof ns set_rbd_trash_image", model=model.RequestStatus) @EndpointDoc( "changes the trash image on delete of the specified NVMeoF \ namespace to all or selected hosts", @@ -724,7 +732,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns set_rbd_trash_image", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def set_rbd_trash_image( @@ -748,6 +755,7 @@ else: @ReadPermission @Endpoint('PUT', '{nsid}/refresh_size') + @NvmeofCLICommand("nvmeof ns refresh_size", model=model.RequestStatus) @EndpointDoc( "refresh the specified NVMeoF namespace to current RBD image size", parameters={ @@ -757,7 +765,6 @@ else: "traddr": Param(str, "NVMeoF gateway address", True, None), }, ) - @NvmeofCLICommand("nvmeof ns refresh_size", model=model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def refresh_size( @@ -775,6 +782,8 @@ else: ) ) + @pick("namespaces", first=True) + @NvmeofCLICommand("nvmeof ns update", model.NamespaceList) @EndpointDoc( "Update an existing NVMeoF namespace", parameters={ @@ -790,8 +799,6 @@ else: "trash_image": Param(bool, "Trash RBD image after removing namespace") }, ) - @pick("namespaces", first=True) - @NvmeofCLICommand("nvmeof ns update", model.NamespaceList) @convert_to_model(model.NamespaceList) @handle_nvmeof_error def update( @@ -865,6 +872,8 @@ else: ) return response + @empty_response + @NvmeofCLICommand("nvmeof ns del", model.RequestStatus) @EndpointDoc( "Delete an existing NVMeoF namespace", parameters={ @@ -874,8 +883,6 @@ else: "force": Param(str, "Force remove the RBD image") }, ) - @empty_response - @NvmeofCLICommand("nvmeof ns del", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def delete( @@ -903,6 +910,8 @@ else: @APIDoc("NVMe-oF Subsystem Host Allowlist Management API", "NVMe-oF Subsystem Host Allowlist") class NVMeoFHost(RESTController): + @pick('hosts') + @NvmeofCLICommand("nvmeof host list", model.HostsInfo) @EndpointDoc( "List all allowed hosts for an NVMeoF subsystem", parameters={ @@ -912,8 +921,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick('hosts') - @NvmeofCLICommand("nvmeof host list", model.HostsInfo) @convert_to_model(model.HostsInfo, finalize=_update_hosts) @handle_nvmeof_error def list( @@ -924,6 +931,8 @@ else: NVMeoFClient.pb2.list_hosts_req(subsystem=nqn, clear_alerts=clear_alerts) ) + @empty_response + @NvmeofCLICommand("nvmeof host add", model.RequestStatus) @EndpointDoc( "Allow hosts to access an NVMeoF subsystem", parameters={ @@ -932,8 +941,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof host add", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def create( @@ -945,6 +952,8 @@ else: dhchap_key=dhchap_key, psk=psk) ) + @empty_response + @NvmeofCLICommand("nvmeof host del", model.RequestStatus) @EndpointDoc( "Disallow hosts from accessing an NVMeoF subsystem", parameters={ @@ -953,8 +962,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof host del", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def delete(self, nqn: str, host_nqn: str, gw_group: Optional[str] = None, @@ -963,6 +970,8 @@ else: NVMeoFClient.pb2.remove_host_req(subsystem_nqn=nqn, host_nqn=host_nqn) ) + @empty_response + @NvmeofCLICommand("nvmeof host change_key", model.RequestStatus) @EndpointDoc( "Change host DH-HMAC-CHAP key", parameters={ @@ -972,8 +981,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof host change_key", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def change_key( @@ -986,6 +993,8 @@ else: dhchap_key=dhchap_key) ) + @empty_response + @NvmeofCLICommand("nvmeof host del_key", model.RequestStatus) @EndpointDoc( "Delete host DH-HMAC-CHAP key", parameters={ @@ -994,8 +1003,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @empty_response - @NvmeofCLICommand("nvmeof host del_key", model.RequestStatus) @convert_to_model(model.RequestStatus) @handle_nvmeof_error def del_key( @@ -1011,6 +1018,8 @@ else: @APIRouter("/nvmeof/subsystem/{nqn}/connection", Scope.NVME_OF) @APIDoc("NVMe-oF Subsystem Connection Management API", "NVMe-oF Subsystem Connection") class NVMeoFConnection(RESTController): + @pick("connections") + @NvmeofCLICommand("nvmeof connection list", model.ConnectionList) @EndpointDoc( "List all NVMeoF Subsystem Connections", parameters={ @@ -1018,8 +1027,6 @@ else: "gw_group": Param(str, "NVMeoF gateway group", True, None), }, ) - @pick("connections") - @NvmeofCLICommand("nvmeof connection list", model.ConnectionList) @convert_to_model(model.ConnectionList) @handle_nvmeof_error def list(self, nqn: Optional[str] = None, diff --git a/src/pybind/mgr/dashboard/openapi.yaml b/src/pybind/mgr/dashboard/openapi.yaml index be1ff6b5af12f..7d43c179985fd 100755 --- a/src/pybind/mgr/dashboard/openapi.yaml +++ b/src/pybind/mgr/dashboard/openapi.yaml @@ -8319,6 +8319,7 @@ paths: trace. security: - jwt: [] + summary: Get NVMeoF gateway log level information tags: - NVMe-oF Gateway put: @@ -8359,6 +8360,7 @@ paths: trace. security: - jwt: [] + summary: Set NVMeoF gateway log levels tags: - NVMe-oF Gateway /api/nvmeof/gateway/version: @@ -8391,6 +8393,7 @@ paths: trace. security: - jwt: [] + summary: Get the version of the NVMeoF gateway tags: - NVMe-oF Gateway /api/nvmeof/spdk/log_level: @@ -8428,6 +8431,7 @@ paths: trace. security: - jwt: [] + summary: Get NVMeoF gateway spdk log levels tags: - NVMe-oF SPDK put: @@ -8470,6 +8474,7 @@ paths: trace. security: - jwt: [] + summary: Set NVMeoF gateway spdk log levels tags: - NVMe-oF SPDK /api/nvmeof/spdk/log_level/disable: @@ -8509,6 +8514,7 @@ paths: trace. security: - jwt: [] + summary: Disable NVMeoF gateway spdk log tags: - NVMe-oF SPDK /api/nvmeof/subsystem: diff --git a/src/pybind/mgr/dashboard/services/nvmeof_cli.py b/src/pybind/mgr/dashboard/services/nvmeof_cli.py index f1887d86da219..3e10e7f13a50e 100644 --- a/src/pybind/mgr/dashboard/services/nvmeof_cli.py +++ b/src/pybind/mgr/dashboard/services/nvmeof_cli.py @@ -198,11 +198,17 @@ class AnnotatedDataTextOutputFormatter(OutputFormatter): class NvmeofCLICommand(CLICommand): + desc: str + def __init__(self, prefix, model: Type[NamedTuple], perm='rw', poll=False): super().__init__(prefix, perm, poll) self._output_formatter = AnnotatedDataTextOutputFormatter() self._model = model + def _use_api_endpoint_desc_if_available(self, func): + if not self.desc and hasattr(func, 'doc_info'): + self.desc = func.doc_info.get('summary', '') + def __call__(self, func) -> HandlerFuncType: # type: ignore # pylint: disable=useless-super-delegation """ @@ -211,7 +217,11 @@ class NvmeofCLICommand(CLICommand): function it wraps compared to CLICmmand, breaking a Liskov substitution principal, hence triggering linters alerts. """ - return super().__call__(func) + resp = super().__call__(func) + + self._use_api_endpoint_desc_if_available(func) + + return resp def call(self, mgr: Any, diff --git a/src/pybind/mgr/dashboard/tests/test_nvmeof_cli.py b/src/pybind/mgr/dashboard/tests/test_nvmeof_cli.py index bceaa7f04c127..fd3583e6c6e27 100644 --- a/src/pybind/mgr/dashboard/tests/test_nvmeof_cli.py +++ b/src/pybind/mgr/dashboard/tests/test_nvmeof_cli.py @@ -7,6 +7,7 @@ from unittest.mock import MagicMock import pytest from mgr_module import CLICommand, HandleCommandResult +from ..controllers import EndpointDoc from ..model.nvmeof import CliFlags, CliHeader from ..services.nvmeof_cli import AnnotatedDataTextOutputFormatter, \ NvmeofCLICommand, convert_from_bytes @@ -122,6 +123,47 @@ class TestNvmeofCLICommand: assert result.stderr == '' base_call_return_none_mock.assert_called_once() + def test_command_empty_desc_by_default(self, sample_command): + assert NvmeofCLICommand.COMMANDS[sample_command].desc == '' + + def test_command_with_endpointdoc_get_desc(self): + test_cmd = "test command1" + test_desc = 'test desc1' + + class Model(NamedTuple): + a: str + b: int + + @NvmeofCLICommand(test_cmd, Model) + @EndpointDoc(test_desc) + def func(_): # noqa # pylint: disable=unused-variable + return {'a': '1', 'b': 2} + + assert NvmeofCLICommand.COMMANDS[test_cmd].desc == test_desc + + del NvmeofCLICommand.COMMANDS[test_cmd] + assert test_cmd not in NvmeofCLICommand.COMMANDS + + def test_command_with_endpointdoc_and_docstr_get_docstr(self): + test_cmd = "test command1" + test_desc = 'test desc1' + test_docstr = 'test docstr' + + class Model(NamedTuple): + a: str + b: int + + @NvmeofCLICommand(test_cmd, Model) + @EndpointDoc(test_desc) + def func(_): # noqa # pylint: disable=unused-variable + """test docstr""" + return {'a': '1', 'b': 2} + + assert NvmeofCLICommand.COMMANDS[test_cmd].desc == test_docstr + + del NvmeofCLICommand.COMMANDS[test_cmd] + assert test_cmd not in NvmeofCLICommand.COMMANDS + class TestNVMeoFConfCLI(unittest.TestCase, CLICommandTestMixin): def setUp(self): -- 2.39.5