Fixes for scaling proxy and native charm 42/10442/1
authoraktas <emin.aktas@ulakhaberlesme.com.tr>
Sun, 21 Feb 2021 16:36:20 +0000 (19:36 +0300)
committergarciadav <david.garcia@canonical.com>
Wed, 3 Mar 2021 15:28:02 +0000 (16:28 +0100)
With changes in here, it can remove application while scaling in
and it can add application existed k8s proxy charm model.

Change-Id: If4fd378fdafd925fa1750ce4769506b44adc233c
Signed-off-by: aktas <emin.aktas@ulakhaberlesme.com.tr>
(cherry picked from commit d1d5541e1fd65d04675edae6e82f3d8a9035592c)

n2vc/n2vc_juju_conn.py
n2vc/tests/unit/test_n2vc_juju_conn.py

index 2566b0c..5435c4e 100644 (file)
@@ -543,13 +543,14 @@ class N2VCJujuConnector(N2VCConnector):
 
         _, ns_id, _, _, _ = self._get_namespace_components(namespace=namespace)
         model_name = '{}-k8s'.format(ns_id)
 
         _, ns_id, _, _, _ = self._get_namespace_components(namespace=namespace)
         model_name = '{}-k8s'.format(ns_id)
-        cloud = cloud_name or self.k8s_cloud
-        credential = credential_name or cloud_name if cloud_name else self.k8s_cloud
-        await self.libjuju.add_model(
-            model_name,
-            cloud_name=cloud,
-            credential_name=credential
-        )
+        if not await self.libjuju.model_exists(model_name):
+            cloud = cloud_name or self.k8s_cloud
+            credential = credential_name or cloud_name if cloud_name else self.k8s_cloud
+            await self.libjuju.add_model(
+                model_name,
+                cloud_name=cloud,
+                credential_name=credential
+            )
         application_name = self._get_application_name(namespace)
 
         try:
         application_name = self._get_application_name(namespace)
 
         try:
@@ -762,7 +763,8 @@ class N2VCJujuConnector(N2VCConnector):
         self.log.info("Namespace {} deleted".format(namespace))
 
     async def delete_execution_environment(
         self.log.info("Namespace {} deleted".format(namespace))
 
     async def delete_execution_environment(
-        self, ee_id: str, db_dict: dict = None, total_timeout: float = None
+        self, ee_id: str, db_dict: dict = None, total_timeout: float = None,
+            scaling_in: bool = False
     ):
         self.log.info("Deleting execution environment ee_id={}".format(ee_id))
 
     ):
         self.log.info("Deleting execution environment ee_id={}".format(ee_id))
 
@@ -775,12 +777,20 @@ class N2VCJujuConnector(N2VCConnector):
         model_name, application_name, _machine_id = self._get_ee_id_components(
             ee_id=ee_id
         )
         model_name, application_name, _machine_id = self._get_ee_id_components(
             ee_id=ee_id
         )
-
-        # destroy the application
         try:
         try:
-            await self.libjuju.destroy_model(
-                model_name=model_name, total_timeout=total_timeout
-            )
+            if not scaling_in:
+                # destroy the model
+                # TODO: should this be removed?
+                await self.libjuju.destroy_model(
+                    model_name=model_name, total_timeout=total_timeout
+                )
+            else:
+                # get juju model and observer
+                controller = await self.libjuju.get_controller()
+                model = await self.libjuju.get_model(controller, model_name)
+                # destroy the application
+                await self.libjuju.destroy_application(
+                    model=model, application_name=application_name)
         except Exception as e:
             raise N2VCException(
                 message=(
         except Exception as e:
             raise N2VCException(
                 message=(
index bad5fc3..64b93cc 100644 (file)
@@ -81,6 +81,7 @@ class GetMetricssTest(N2VCJujuConnTestCase):
         mock_get_metrics.assert_called_once()
 
 
         mock_get_metrics.assert_called_once()
 
 
+@asynctest.mock.patch("n2vc.libjuju.Libjuju.model_exists")
 @asynctest.mock.patch("osm_common.fslocal.FsLocal.file_exists")
 @asynctest.mock.patch(
     "osm_common.fslocal.FsLocal.path", new_callable=asynctest.PropertyMock, create=True
 @asynctest.mock.patch("osm_common.fslocal.FsLocal.file_exists")
 @asynctest.mock.patch(
     "osm_common.fslocal.FsLocal.path", new_callable=asynctest.PropertyMock, create=True
@@ -92,8 +93,9 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
         super(K8sProxyCharmsTest, self).setUp()
 
     def test_success(
         super(K8sProxyCharmsTest, self).setUp()
 
     def test_success(
-        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists,
+        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists, mock_model_exists
     ):
     ):
+        mock_model_exists.return_value = None
         mock_file_exists.return_value = True
         mock_path.return_value = "/path"
         ee_id = self.loop.run_until_complete(
         mock_file_exists.return_value = True
         mock_path.return_value = "/path"
         ee_id = self.loop.run_until_complete(
@@ -131,6 +133,7 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
         mock_deploy_charm,
         mock_path,
         mock_file_exists,
         mock_deploy_charm,
         mock_path,
         mock_file_exists,
+        mock_model_exists,
     ):
         mock_k8s_cloud.return_value = None
         with self.assertRaises(JujuK8sProxycharmNotSupported):
     ):
         mock_k8s_cloud.return_value = None
         with self.assertRaises(JujuK8sProxycharmNotSupported):
@@ -142,7 +145,7 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
             self.assertIsNone(ee_id)
 
     def test_no_artifact_path(
             self.assertIsNone(ee_id)
 
     def test_no_artifact_path(
-        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists,
+        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists, mock_model_exists,
     ):
         with self.assertRaises(N2VCBadArgumentsException):
             ee_id = self.loop.run_until_complete(
     ):
         with self.assertRaises(N2VCBadArgumentsException):
             ee_id = self.loop.run_until_complete(
@@ -153,7 +156,7 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
             self.assertIsNone(ee_id)
 
     def test_no_db(
             self.assertIsNone(ee_id)
 
     def test_no_db(
-        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists,
+        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists, mock_model_exists,
     ):
         with self.assertRaises(N2VCBadArgumentsException):
             ee_id = self.loop.run_until_complete(
     ):
         with self.assertRaises(N2VCBadArgumentsException):
             ee_id = self.loop.run_until_complete(
@@ -164,7 +167,7 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
             self.assertIsNone(ee_id)
 
     def test_file_not_exists(
             self.assertIsNone(ee_id)
 
     def test_file_not_exists(
-        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists,
+        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists, mock_model_exists,
     ):
         mock_file_exists.return_value = False
         with self.assertRaises(N2VCBadArgumentsException):
     ):
         mock_file_exists.return_value = False
         with self.assertRaises(N2VCBadArgumentsException):
@@ -176,8 +179,9 @@ class K8sProxyCharmsTest(N2VCJujuConnTestCase):
             self.assertIsNone(ee_id)
 
     def test_exception(
             self.assertIsNone(ee_id)
 
     def test_exception(
-        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists,
+        self, mock_add_model, mock_deploy_charm, mock_path, mock_file_exists, mock_model_exists,
     ):
     ):
+        mock_model_exists.return_value = None
         mock_file_exists.return_value = True
         mock_path.return_value = "/path"
         mock_deploy_charm.side_effect = Exception()
         mock_file_exists.return_value = True
         mock_path.return_value = "/path"
         mock_deploy_charm.side_effect = Exception()