From: Patricia Reinoso Date: Tue, 25 Apr 2023 15:58:32 +0000 (+0200) Subject: Remove Temporal Libjuju X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=258a9a6b60242783ce8f6eb61cb5718371c5aa1e;p=osm%2FN2VC.git Remove Temporal Libjuju Change-Id: I3e2c038f58e9d78ee1a227334ba78d2a57223eaf Signed-off-by: Patricia Reinoso --- diff --git a/n2vc/temporal_libjuju.py b/n2vc/temporal_libjuju.py deleted file mode 100644 index 5f8429a..0000000 --- a/n2vc/temporal_libjuju.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2023 Canonical Ltd. -# 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. - -import logging -from dataclasses import dataclass -from typing import List - -from juju.controller import Controller -from juju.model import Model - -from n2vc.exceptions import ( - JujuControllerFailedConnecting, - JujuModelAlreadyExists, -) - - -@dataclass -class ConnectionInfo: - """Information to connect to juju controller""" - - endpoint: str - user: str - password: str - cacert: str - cloud_name: str - cloud_credentials: str - - def __repr__(self): - return f"{self.__class__.__name__}(endpoint: {self.endpoint}, user: {self.user}, password: ******, caert: ******)" - - def __str__(self): - return f"{self.__class__.__name__}(endpoint: {self.endpoint}, user: {self.user}, password: ******, caert: ******)" - - -class Libjuju: - def __init__(self, connection_info: ConnectionInfo) -> None: - self.logger = logging.getLogger("temporal_libjuju") - self.connection_info = connection_info - - async def get_controller(self) -> Controller: - controller = Controller() - try: - await controller.connect( - endpoint=self.connection_info.endpoint, - username=self.connection_info.user, - password=self.connection_info.password, - cacert=self.connection_info.cacert, - ) - return controller - except Exception as e: - self.logger.error( - "Error connecting to controller={}: {}".format( - self.connection_info.endpoint, e - ) - ) - await self.disconnect_controller(controller) - raise JujuControllerFailedConnecting(str(e)) - - async def disconnect_controller(self, controller: Controller) -> None: - if controller: - await controller.disconnect() - - async def disconnect_model(self, model: Model): - if model: - await model.disconnect() - - async def add_model(self, model_name: str): - """Exception is raised if model_name already exists""" - model = None - controller = None - try: - controller = await self.get_controller() - if await self.model_exists(model_name, controller=controller): - raise JujuModelAlreadyExists( - "Cannot create model {}".format(model_name) - ) - self.logger.debug("Creating model {}".format(model_name)) - model = await controller.add_model( - model_name, - cloud_name=self.connection_info.cloud_name, - credential_name=self.connection_info.cloud_credentials, - ) - finally: - await self.disconnect_model(model) - await self.disconnect_controller(controller) - - async def model_exists( - self, model_name: str, controller: Controller = None - ) -> bool: - """Returns True if model exists. False otherwhise.""" - need_to_disconnect = False - try: - if not controller: - controller = await self.get_controller() - need_to_disconnect = True - - return model_name in await controller.list_models() - finally: - if need_to_disconnect: - await self.disconnect_controller(controller) - - async def get_model(self, controller: Controller, model_name: str) -> Model: - return await controller.get_model(model_name) - - async def list_models(self) -> List[str]: - """List models in controller.""" - try: - controller = await self.get_controller() - return await controller.list_models() - finally: - await self.disconnect_controller(controller) - - async def destroy_model(self, model_name: str, force=False) -> None: - controller = None - model = None - - try: - controller = await self.get_controller() - if not await self.model_exists(model_name, controller=controller): - self.logger.warn(f"Model {model_name} doesn't exist") - return - - self.logger.debug(f"Getting model {model_name} to destroy") - model = await self.get_model(controller, model_name) - await self.disconnect_model(model) - - await controller.destroy_model( - model_name, destroy_storage=True, force=force, max_wait=60 - ) - - except Exception as e: - self.logger.warn(f"Failed deleting model {model_name}: {e}") - raise e - finally: - await self.disconnect_model(model) - await self.disconnect_controller(controller) diff --git a/n2vc/tests/unit/test_temporal_libjuju.py b/n2vc/tests/unit/test_temporal_libjuju.py deleted file mode 100644 index a599b04..0000000 --- a/n2vc/tests/unit/test_temporal_libjuju.py +++ /dev/null @@ -1,291 +0,0 @@ -####################################################################################### -# Copyright ETSI Contributors and Others. -# -# 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. - -import asyncio -import asynctest -import logging -import juju - -from n2vc.temporal_libjuju import Libjuju, ConnectionInfo -from n2vc.exceptions import ( - JujuControllerFailedConnecting, - JujuModelAlreadyExists, -) - -cacert = """-----BEGIN CERTIFICATE----- -SOMECERT ------END CERTIFICATE-----""" - - -@asynctest.mock.patch("n2vc.temporal_libjuju.Controller") -class LibjujuTestCase(asynctest.TestCase): - def setUp( - self, - mock_base64_to_cacert=None, - ): - self.loop = asyncio.get_event_loop() - self.connection_info = ConnectionInfo( - "1.2.3.4:17070", "user", "secret", cacert, "k8s_cloud", "k8s_credentials" - ) - logging.disable(logging.CRITICAL) - self.libjuju = Libjuju(self.connection_info) - - -@asynctest.mock.patch("juju.controller.Controller.connect") -class GetControllerTest(LibjujuTestCase): - def setUp(self): - super(GetControllerTest, self).setUp() - - def test_get_controller(self, mock_connect): - controller = self.loop.run_until_complete(self.libjuju.get_controller()) - self.assertIsInstance(controller, juju.controller.Controller) - mock_connect.assert_called_with( - endpoint=self.connection_info.endpoint, - username=self.connection_info.user, - password=self.connection_info.password, - cacert=self.connection_info.cacert, - ) - - @asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_controller") - def test_exception( - self, - mock_disconnect_controller, - mock_connect, - ): - mock_connect.side_effect = Exception() - controller = None - with self.assertRaises(JujuControllerFailedConnecting): - controller = self.loop.run_until_complete(self.libjuju.get_controller()) - self.assertIsNone(controller) - mock_disconnect_controller.assert_called() - - -class DisconnectTest(LibjujuTestCase): - def setUp(self): - super(DisconnectTest, self).setUp() - - @asynctest.mock.patch("juju.model.Model.disconnect") - def test_disconnect_model(self, mock_disconnect): - self.loop.run_until_complete(self.libjuju.disconnect_model(juju.model.Model())) - mock_disconnect.assert_called_once() - - @asynctest.mock.patch("juju.controller.Controller.disconnect") - def test_disconnect_controller(self, mock_disconnect): - self.loop.run_until_complete( - self.libjuju.disconnect_controller(juju.controller.Controller()) - ) - mock_disconnect.assert_called_once() - - -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.get_controller") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.model_exists") -@asynctest.mock.patch("juju.controller.Controller.add_model") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_controller") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_model") -class AddModelTest(LibjujuTestCase): - def setUp(self): - super(AddModelTest, self).setUp() - - def test_existing_model_raises_exception( - self, - mock_disconnect_model, - mock_disconnect_controller, - mock_add_model, - mock_model_exists, - mock_get_controller, - ): - mock_model_exists.return_value = True - mock_get_controller.return_value = juju.controller.Controller() - with self.assertRaises(JujuModelAlreadyExists): - self.loop.run_until_complete(self.libjuju.add_model("existing_model")) - mock_get_controller.assert_called() - mock_add_model.assert_not_called() - mock_disconnect_controller.assert_called() - - def test_non_existing_model( - self, - mock_disconnect_model, - mock_disconnect_controller, - mock_add_model, - mock_model_exists, - mock_get_controller, - ): - mock_model_exists.return_value = False - mock_get_controller.return_value = juju.controller.Controller() - new_model_name = "nonexisting_model" - self.loop.run_until_complete(self.libjuju.add_model(new_model_name)) - mock_add_model.assert_called_once_with( - new_model_name, - cloud_name=self.connection_info.cloud_name, - credential_name=self.connection_info.cloud_credentials, - ) - mock_disconnect_controller.assert_called() - mock_disconnect_model.assert_called() - - -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.get_controller") -@asynctest.mock.patch("juju.controller.Controller.list_models") -class ModelExistsTest(LibjujuTestCase): - def setUp(self): - super(ModelExistsTest, self).setUp() - - async def test_existing_model( - self, - mock_list_models, - mock_get_controller, - ): - model_name = "existing_model" - mock_list_models.return_value = [model_name] - self.assertTrue( - await self.libjuju.model_exists(model_name, juju.controller.Controller()) - ) - - @asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_controller") - async def test_no_controller( - self, - mock_disconnect_controller, - mock_list_models, - mock_get_controller, - ): - model_name = "existing_model" - mock_list_models.return_value = [model_name] - mock_get_controller.return_value = juju.controller.Controller() - self.assertTrue(await self.libjuju.model_exists(model_name)) - mock_disconnect_controller.assert_called_once() - - async def test_non_existing_model( - self, - mock_list_models, - mock_get_controller, - ): - mock_list_models.return_value = [] - self.assertFalse( - await self.libjuju.model_exists( - "not_existing_model", juju.controller.Controller() - ) - ) - - -@asynctest.mock.patch("juju.controller.Controller.get_model") -class GetModelTest(LibjujuTestCase): - def setUp(self): - super(GetModelTest, self).setUp() - - def test_get_model( - self, - mock_get_model, - ): - mock_get_model.return_value = juju.model.Model() - model = self.loop.run_until_complete( - self.libjuju.get_model(juju.controller.Controller(), "model") - ) - self.assertIsInstance(model, juju.model.Model) - - -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.get_controller") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_controller") -@asynctest.mock.patch("juju.controller.Controller.list_models") -class ListModelsTest(LibjujuTestCase): - def setUp(self): - super(ListModelsTest, self).setUp() - - def test_containing( - self, - mock_list_models, - mock_disconnect_controller, - mock_get_controller, - ): - expected_list = ["existingmodel"] - mock_get_controller.return_value = juju.controller.Controller() - mock_list_models.return_value = expected_list - models = self.loop.run_until_complete(self.libjuju.list_models()) - - mock_disconnect_controller.assert_called_once() - self.assertEquals(models, expected_list) - - -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.get_controller") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.get_model") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.model_exists") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_model") -@asynctest.mock.patch("n2vc.temporal_libjuju.Libjuju.disconnect_controller") -@asynctest.mock.patch("juju.controller.Controller.destroy_model") -class DestroyModelTest(LibjujuTestCase): - def setUp(self): - super(DestroyModelTest, self).setUp() - - def test_model_is_destroyed( - self, - mock_destroy, - mock_disconnect_controller, - mock_disconnect_model, - mock_model_exists, - mock_get_model, - mock_get_controller, - ): - mock_get_controller.return_value = juju.controller.Controller() - mock_model_exists.return_value = True - mock_get_model.return_value = juju.model.Model() - model_name = "model_to_destroy" - force = True - - self.loop.run_until_complete(self.libjuju.destroy_model(model_name, force)) - mock_destroy.assert_called_with( - model_name, destroy_storage=True, force=force, max_wait=60 - ) - mock_disconnect_controller.assert_called() - mock_disconnect_model.assert_called() - - def test_not_existing_model( - self, - mock_destroy, - mock_disconnect_controller, - mock_disconnect_model, - mock_model_exists, - mock_get_model, - mock_get_controller, - ): - mock_get_controller.return_value = juju.controller.Controller() - mock_model_exists.return_value = False - model_name = "model_to_destroy" - force = True - - self.loop.run_until_complete(self.libjuju.destroy_model(model_name, force)) - mock_destroy.assert_not_called() - mock_get_model.assert_not_called() - mock_disconnect_controller.assert_called() - mock_disconnect_model.assert_called() - - def test_raise_exception( - self, - mock_destroy, - mock_disconnect_controller, - mock_disconnect_model, - mock_model_exists, - mock_get_model, - mock_get_controller, - ): - mock_get_controller.return_value = juju.controller.Controller() - mock_model_exists.return_value = True - mock_get_model.side_effect = Exception() - model_name = "model_to_destroy" - force = False - - with self.assertRaises(Exception): - self.loop.run_until_complete(self.libjuju.destroy_model(model_name, force)) - mock_destroy.assert_not_called() - mock_disconnect_controller.assert_called() - mock_disconnect_model.assert_called()