From e477638df61052acc20b043bbc6216f2e51a3c69 Mon Sep 17 00:00:00 2001 From: matancarmeli7 Date: Sun, 5 Feb 2023 12:07:50 +0200 Subject: [PATCH 1/2] add identity unit tests Signed-off-by: matancarmeli7 --- .../identity_controller_servicer_test.py | 61 +++++++++++++++++++ ...> replication_controller_servicer_test.py} | 10 ++- 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 controllers/tests/controller_server/csi_addons/identity_controller_servicer_test.py rename controllers/tests/controller_server/csi_addons/{addons_server_test.py => replication_controller_servicer_test.py} (97%) diff --git a/controllers/tests/controller_server/csi_addons/identity_controller_servicer_test.py b/controllers/tests/controller_server/csi_addons/identity_controller_servicer_test.py new file mode 100644 index 000000000..c938d60b3 --- /dev/null +++ b/controllers/tests/controller_server/csi_addons/identity_controller_servicer_test.py @@ -0,0 +1,61 @@ +import unittest +import grpc +from mock import patch, Mock, call + +from csi_general import identity_pb2 as pb2 +from controllers.servers.csi.csi_addons_server.identity_controller_servicer import IdentityControllerServicer + + +class TestIdentityControllerServicer(unittest.TestCase): + def setUp(self): + self.servicer = IdentityControllerServicer() + self.request = Mock() + self.context = Mock() + + @patch("controllers.common.config.config.identity") + def test_get_identity_succeeds(self, identity_config): + plugin_name = "plugin-name" + version = "1.1.0" + identity_config.name = plugin_name + identity_config.version = version + self.request.volume_capabilities = [] + response = self.servicer.GetIdentity(self.request, self.context) + self.assertEqual(response, pb2.GetIdentityResponse(name=plugin_name, vendor_version=version)) + + @patch("controllers.common.config.config.identity") + def test_get_identity_fails_when_attributes_from_config_are_missing(self, identity_config): + identity_config.mock_add_spec(spec=["name"]) + response = self.servicer.GetIdentity(self.request, self.context) + self.context.set_code.assert_called_once_with(grpc.StatusCode.INTERNAL) + self.assertEqual(response, pb2.GetIdentityResponse()) + + identity_config.mock_add_spec(spec=["version"]) + response = self.servicer.GetIdentity(self.request, self.context) + self.assertEqual(response, pb2.GetIdentityResponse()) + self.context.set_code.assert_called_with(grpc.StatusCode.INTERNAL) + + @patch("controllers.common.config.config.identity") + def test_get_identity_fails_when_name_or_version_are_empty(self, identity_config): + identity_config.name = "" + identity_config.version = "1.1.0" + response = self.servicer.GetIdentity(self.request, self.context) + self.context.set_code.assert_called_once_with(grpc.StatusCode.INTERNAL) + self.assertEqual(response, pb2.GetIdentityResponse()) + + identity_config.name = "name" + identity_config.version = "" + response = self.servicer.GetIdentity(self.request, self.context) + self.assertEqual(response, pb2.GetIdentityResponse()) + self.assertEqual(self.context.set_code.call_args_list, + [call(grpc.StatusCode.INTERNAL), call(grpc.StatusCode.INTERNAL)]) + + def test_get_capabilities_succeeds(self): + response = self.servicer.GetCapabilities(self.request, self.context) + supported_capabilities = 2 + self.assertIn('VolumeReplication', dir(response.capabilities[0])) + self.assertIn('Service', dir(response.capabilities[1])) + self.assertEqual(len(response.capabilities), supported_capabilities) + + def test_probe_succeeds(self): + response = self.servicer.Probe(self.request, self.context) + self.assertEqual(response, pb2.ProbeResponse()) diff --git a/controllers/tests/controller_server/csi_addons/addons_server_test.py b/controllers/tests/controller_server/csi_addons/replication_controller_servicer_test.py similarity index 97% rename from controllers/tests/controller_server/csi_addons/addons_server_test.py rename to controllers/tests/controller_server/csi_addons/replication_controller_servicer_test.py index 08b98d49e..a3c13aef3 100644 --- a/controllers/tests/controller_server/csi_addons/addons_server_test.py +++ b/controllers/tests/controller_server/csi_addons/replication_controller_servicer_test.py @@ -10,13 +10,12 @@ from controllers.servers.csi.csi_addons_server.replication_controller_servicer import ReplicationControllerServicer from controllers.tests import utils from controllers.tests.common.test_settings import VOLUME_NAME, VOLUME_UID, OBJECT_INTERNAL_ID, \ - OTHER_OBJECT_INTERNAL_ID, REPLICATION_NAME, SYSTEM_ID, COPY_TYPE, SECRET_USERNAME_VALUE, SECRET_PASSWORD_VALUE, \ - SECRET_MANAGEMENT_ADDRESS_VALUE, DUMMY_VOLUME_GROUP + OTHER_OBJECT_INTERNAL_ID, REPLICATION_NAME, SYSTEM_ID, COPY_TYPE, SECRET, DUMMY_VOLUME_GROUP from controllers.tests.controller_server.common import mock_get_agent from controllers.tests.controller_server.controller_server.csi_controller_server_test import (CommonControllerTest) from controllers.tests.utils import ProtoBufMock -ADDON_SERVER_PATH = "controllers.servers.csi.csi_addons_server.replication_controller_servicer" +REPLICATION_SERVICER_PATH = "controllers.servers.csi.csi_addons_server.replication_controller_servicer" class BaseReplicationSetUp(unittest.TestCase): @@ -27,11 +26,10 @@ def setUp(self): self.mediator.client = Mock() self.storage_agent = MagicMock() - mock_get_agent(self, ADDON_SERVER_PATH) + mock_get_agent(self, REPLICATION_SERVICER_PATH) self.request = ProtoBufMock() - self.request.secrets = {"username": SECRET_USERNAME_VALUE, "password": SECRET_PASSWORD_VALUE, - "management_address": SECRET_MANAGEMENT_ADDRESS_VALUE} + self.request.secrets = SECRET self.request.volume_id = "{0}:{1};{1}".format("A9000", OBJECT_INTERNAL_ID) self.request.replication_id = "{}:{};{}".format("A9000", OTHER_OBJECT_INTERNAL_ID, VOLUME_UID) self.request.replication_source.volumegroup.volume_group_id = self.request.volume_id From 20f51d4abe9df5d6a590979ca4f01edb98a1b669 Mon Sep 17 00:00:00 2001 From: matancarmeli7 Date: Wed, 15 Feb 2023 10:20:22 +0200 Subject: [PATCH 2/2] add identity controller servicer Signed-off-by: matancarmeli7 --- .../identity_controller_servicer.py | 50 +++++++++++++++++++ controllers/servers/csi/main.py | 3 ++ 2 files changed, 53 insertions(+) create mode 100644 controllers/servers/csi/csi_addons_server/identity_controller_servicer.py diff --git a/controllers/servers/csi/csi_addons_server/identity_controller_servicer.py b/controllers/servers/csi/csi_addons_server/identity_controller_servicer.py new file mode 100644 index 000000000..637254e4e --- /dev/null +++ b/controllers/servers/csi/csi_addons_server/identity_controller_servicer.py @@ -0,0 +1,50 @@ +import grpc + +from csi_general import identity_pb2 as pb2 +from csi_general import identity_pb2_grpc as pb2_grpc + +from controllers.common.config import config as common_config +from controllers.servers.csi.decorators import csi_method +from controllers.servers.csi.exception_handler import build_error_response +from controllers.common.csi_logger import get_stdout_logger + +logger = get_stdout_logger() + + +class IdentityControllerServicer(pb2_grpc.IdentityServicer): + + @csi_method(error_response_type=pb2.GetIdentityResponse) + def GetIdentity(self, request, context): + name = common_config.identity.name + version = common_config.identity.version + + if not name or not version: + message = "plugin name or version cannot be empty" + return build_error_response(message, context, grpc.StatusCode.INTERNAL, pb2.GetIdentityResponse) + + return pb2.GetIdentityResponse(name=name, vendor_version=version) + + def GetCapabilities(self, request, context): + logger.info("GetCapabilities") + response = pb2.GetCapabilitiesResponse( + capabilities=[self._get_replication_capability(), + self._get_controller_capability()]) + + logger.info("finished GetCapabilities") + return response + + def _get_replication_capability(self): + types = pb2.Capability.VolumeReplication.Type + capability_enum_value = types.Value("VOLUME_REPLICATION") + return pb2.Capability( + volume_replication=pb2.Capability.VolumeReplication(type=capability_enum_value)) + + def _get_controller_capability(self): + types = pb2.Capability.Service.Type + capability_enum_value = types.Value("CONTROLLER_SERVICE") + return pb2.Capability( + service=pb2.Capability.Service(type=capability_enum_value)) + + def Probe(self, request, context): + context.set_code(grpc.StatusCode.OK) + return pb2.ProbeResponse() diff --git a/controllers/servers/csi/main.py b/controllers/servers/csi/main.py index 43e779ff9..60c1a5682 100644 --- a/controllers/servers/csi/main.py +++ b/controllers/servers/csi/main.py @@ -13,6 +13,7 @@ from controllers.servers.csi.controller_server.csi_controller_server import CSIControllerServicer from controllers.servers.csi.controller_server.volume_group_server import VolumeGroupControllerServicer from controllers.servers.csi.csi_addons_server.replication_controller_servicer import ReplicationControllerServicer +from controllers.servers.csi.csi_addons_server.identity_controller_servicer import IdentityControllerServicer def main(): @@ -54,7 +55,9 @@ def _add_csi_controller_servicers(controller_server): def _add_csi_addons_servicers(csi_addons_server): replication_servicer = ReplicationControllerServicer() + identity_servicer = IdentityControllerServicer() replication_pb2_grpc.add_ControllerServicer_to_server(replication_servicer, csi_addons_server) + identity_pb2_grpc.add_IdentityServicer_to_server(identity_servicer, csi_addons_server) return csi_addons_server