From: David Garcia Date: Tue, 23 Feb 2021 10:47:29 +0000 (+0100) Subject: Add generate_kdu_instance_name method in K8sConn X-Git-Tag: branch-sol006v331-start~14 X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=commitdiff_plain;h=c4da25cc55411e6cea1e83d29c206bce421f0728 Add generate_kdu_instance_name method in K8sConn The reason for adding this method is for LCM to call it before calling K8sConn.install(). That way, LCM can record it in the DB before finishing the instantiation of the KDU. This will help fixing bug 1412. Change-Id: Iacf71c4d2040dbdc966cff2bddd697c4ea1c9a06 Signed-off-by: David Garcia --- diff --git a/n2vc/k8s_conn.py b/n2vc/k8s_conn.py index 5bdc8ac..058f5ba 100644 --- a/n2vc/k8s_conn.py +++ b/n2vc/k8s_conn.py @@ -33,6 +33,9 @@ class K8sConnector(abc.ABC, Loggable): ################################### P U B L I C #################################### #################################################################################### """ + @staticmethod + def generate_kdu_instance_name(**kwargs): + raise NotImplementedError("Method not implemented") def __init__(self, db: object, log: object = None, on_update_db=None): """ @@ -136,6 +139,7 @@ class K8sConnector(abc.ABC, Loggable): self, cluster_uuid: str, kdu_model: str, + kdu_instance: str, atomic: bool = True, timeout: float = 300, params: dict = None, @@ -154,6 +158,7 @@ class K8sConnector(abc.ABC, Loggable): - a name of chart/bundle available via the repos known by OSM - a path to a packaged chart/bundle - a path to an unpacked chart/bundle directory or a URL + :param kdu_instance: Kdu instance name :param atomic: If set, installation process purges chart/bundle on fail, also will wait until all the K8s objects are active :param timeout: Time in seconds to wait for the install of the chart/bundle diff --git a/n2vc/k8s_helm3_conn.py b/n2vc/k8s_helm3_conn.py index f79816d..6afadbf 100644 --- a/n2vc/k8s_helm3_conn.py +++ b/n2vc/k8s_helm3_conn.py @@ -71,6 +71,7 @@ class K8sHelm3Connector(K8sHelmBaseConnector): self, cluster_uuid: str, kdu_model: str, + kdu_instance: str, atomic: bool = True, timeout: float = 300, params: dict = None, @@ -95,22 +96,25 @@ class K8sHelm3Connector(K8sHelmBaseConnector): if namespace not in namespaces: await self._create_namespace(cluster_id, namespace) - kdu_instance = await self._install_impl(cluster_id, - kdu_model, - paths, - env, - atomic=atomic, - timeout=timeout, - params=params, - db_dict=db_dict, - kdu_name=kdu_name, - namespace=namespace) + await self._install_impl( + cluster_id, + kdu_model, + paths, + env, + kdu_instance, + atomic=atomic, + timeout=timeout, + params=params, + db_dict=db_dict, + kdu_name=kdu_name, + namespace=namespace, + ) # sync fs self.fs.reverse_sync(from_path=cluster_id) self.log.debug("Returning kdu_instance {}".format(kdu_instance)) - return kdu_instance + return True async def inspect_kdu(self, kdu_model: str, repo_url: str = None) -> str: diff --git a/n2vc/k8s_helm_base_conn.py b/n2vc/k8s_helm_base_conn.py index af22ecc..a79f038 100644 --- a/n2vc/k8s_helm_base_conn.py +++ b/n2vc/k8s_helm_base_conn.py @@ -293,6 +293,7 @@ class K8sHelmBaseConnector(K8sConnector): kdu_model: str, paths: dict, env: dict, + kdu_instance: str, atomic: bool = True, timeout: float = 300, params: dict = None, @@ -313,23 +314,6 @@ class K8sHelmBaseConnector(K8sConnector): version = str(parts[1]) kdu_model = parts[0] - # generate a name for the release. Then, check if already exists - kdu_instance = None - while kdu_instance is None: - kdu_instance = self._generate_release_name(kdu_model) - try: - result = await self._status_kdu( - cluster_id=cluster_id, - kdu_instance=kdu_instance, - namespace=namespace, - show_error_log=False, - ) - if result is not None: - # instance already exists: generate a new one - kdu_instance = None - except K8sException: - pass - command = self._get_install_command(kdu_model, kdu_instance, namespace, params_str, version, atomic, timeout) @@ -389,8 +373,6 @@ class K8sHelmBaseConnector(K8sConnector): self.log.error(msg) raise K8sException(msg) - return kdu_instance - async def upgrade( self, cluster_uuid: str, @@ -1377,7 +1359,8 @@ class K8sHelmBaseConnector(K8sConnector): return params_str @staticmethod - def _generate_release_name(chart_name: str): + def generate_kdu_instance_name(**kwargs): + chart_name = kwargs["kdu_model"] # check embeded chart (file or dir) if chart_name.startswith("/"): # extract file or directory name diff --git a/n2vc/k8s_helm_conn.py b/n2vc/k8s_helm_conn.py index fdae32f..ad230b5 100644 --- a/n2vc/k8s_helm_conn.py +++ b/n2vc/k8s_helm_conn.py @@ -92,6 +92,7 @@ class K8sHelmConnector(K8sHelmBaseConnector): self, cluster_uuid: str, kdu_model: str, + kdu_instance: str, atomic: bool = True, timeout: float = 300, params: dict = None, @@ -110,22 +111,25 @@ class K8sHelmConnector(K8sHelmBaseConnector): cluster_name=cluster_id, create_if_not_exist=True ) - kdu_instance = await self._install_impl(cluster_id, - kdu_model, - paths, - env, - atomic=atomic, - timeout=timeout, - params=params, - db_dict=db_dict, - kdu_name=kdu_name, - namespace=namespace) + await self._install_impl( + cluster_id, + kdu_model, + paths, + env, + kdu_instance, + atomic=atomic, + timeout=timeout, + params=params, + db_dict=db_dict, + kdu_name=kdu_name, + namespace=namespace, + ) # sync fs self.fs.reverse_sync(from_path=cluster_id) self.log.debug("Returning kdu_instance {}".format(kdu_instance)) - return kdu_instance + return True async def inspect_kdu(self, kdu_model: str, repo_url: str = None) -> str: diff --git a/n2vc/k8s_juju_conn.py b/n2vc/k8s_juju_conn.py index db34994..85e24f2 100644 --- a/n2vc/k8s_juju_conn.py +++ b/n2vc/k8s_juju_conn.py @@ -303,6 +303,7 @@ class K8sJujuConnector(K8sConnector): self, cluster_uuid: str, kdu_model: str, + kdu_instance: str, atomic: bool = True, timeout: float = 1800, params: dict = None, @@ -314,6 +315,7 @@ class K8sJujuConnector(K8sConnector): :param cluster_uuid str: The UUID of the cluster to install to :param kdu_model str: The name or path of a bundle to install + :param kdu_instance: Kdu instance name :param atomic bool: If set, waits until the model is active and resets the cluster on failure. :param timeout int: The time, in seconds, to wait for the install @@ -341,11 +343,6 @@ class K8sJujuConnector(K8sConnector): os.chdir(new_workdir) bundle = "local:{}".format(kdu_model) - if kdu_name: - kdu_instance = "{}-{}".format(kdu_name, db_dict["filter"]["_id"]) - else: - kdu_instance = db_dict["filter"]["_id"] - self.log.debug("Checking for model named {}".format(kdu_instance)) # Create the new model @@ -377,7 +374,7 @@ class K8sJujuConnector(K8sConnector): bundle, model_name=kdu_instance, wait=atomic, timeout=timeout ) os.chdir(previous_workdir) - return kdu_instance + return True async def instances_list(self, cluster_uuid: str) -> list: """ @@ -804,3 +801,13 @@ class K8sJujuConnector(K8sConnector): base64.b64decode(token).decode("utf-8"), base64.b64decode(client_certificate_data).decode("utf-8"), ) + + @staticmethod + def generate_kdu_instance_name(**kwargs): + db_dict = kwargs.get("db_dict") + kdu_name = kwargs.get("kdu_name", None) + if kdu_name: + kdu_instance = "{}-{}".format(kdu_name, db_dict["filter"]["_id"]) + else: + kdu_instance = db_dict["filter"]["_id"] + return kdu_instance diff --git a/n2vc/tests/unit/test_k8s_helm3_conn.py b/n2vc/tests/unit/test_k8s_helm3_conn.py index df3e1c3..3b81323 100644 --- a/n2vc/tests/unit/test_k8s_helm3_conn.py +++ b/n2vc/tests/unit/test_k8s_helm3_conn.py @@ -134,25 +134,24 @@ class TestK8sHelm3Conn(asynctest.TestCase): self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) self.helm_conn._status_kdu = asynctest.CoroutineMock(return_value=None) self.helm_conn._store_status = asynctest.CoroutineMock() - self.helm_conn._generate_release_name = Mock(return_value="stable-openldap-0005399828") + self.kdu_instance = "stable-openldap-0005399828" + self.helm_conn.generate_kdu_instance_name = Mock(return_value=self.kdu_instance) self.helm_conn._get_namespaces = asynctest.CoroutineMock(return_value=[]) self.helm_conn._create_namespace = asynctest.CoroutineMock() - kdu_instance = await self.helm_conn.install(self.cluster_uuid, - kdu_model, - atomic=True, - namespace=self.namespace, - db_dict=db_dict) + await self.helm_conn.install( + self.cluster_uuid, + kdu_model, + self.kdu_instance, + atomic=True, + namespace=self.namespace, + db_dict=db_dict + ) self.helm_conn._get_namespaces.assert_called_once() self.helm_conn._create_namespace.assert_called_once_with(self.cluster_id, self.namespace) self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) self.helm_conn.fs.reverse_sync.assert_called_once_with(from_path=self.cluster_id) - self.helm_conn._generate_release_name.assert_called_once_with("stable/openldap") - self.helm_conn._status_kdu.assert_called_once_with(cluster_id=self.cluster_id, - kdu_instance=kdu_instance, - namespace=self.namespace, - show_error_log=False) self.helm_conn._store_status.assert_called_with(cluster_id=self.cluster_id, kdu_instance=kdu_instance, namespace=self.namespace, diff --git a/n2vc/tests/unit/test_k8s_helm_conn.py b/n2vc/tests/unit/test_k8s_helm_conn.py index 51edbd6..1eb5775 100644 --- a/n2vc/tests/unit/test_k8s_helm_conn.py +++ b/n2vc/tests/unit/test_k8s_helm_conn.py @@ -118,21 +118,19 @@ class TestK8sHelmConn(asynctest.TestCase): self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) self.helm_conn._status_kdu = asynctest.CoroutineMock(return_value=None) self.helm_conn._store_status = asynctest.CoroutineMock() - self.helm_conn._generate_release_name = Mock(return_value="stable-openldap-0005399828") + self.helm_conn.generate_kdu_instance_name = Mock(return_value=kdu_instance) - kdu_instance = await self.helm_conn.install(self.cluster_uuid, - kdu_model, - atomic=True, - namespace=self.namespace, - db_dict=db_dict) + await self.helm_conn.install( + self.cluster_uuid, + kdu_model, + kdu_instance, + atomic=True, + namespace=self.namespace, + db_dict=db_dict + ) self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) self.helm_conn.fs.reverse_sync.assert_called_once_with(from_path=self.cluster_id) - self.helm_conn._generate_release_name.assert_called_once_with("stable/openldap") - self.helm_conn._status_kdu.assert_called_once_with(cluster_id=self.cluster_id, - kdu_instance=kdu_instance, - namespace=self.namespace, - show_error_log=False) self.helm_conn._store_status.assert_called_with(cluster_id=self.cluster_id, kdu_instance=kdu_instance, namespace=self.namespace, diff --git a/n2vc/tests/unit/test_k8s_juju_conn.py b/n2vc/tests/unit/test_k8s_juju_conn.py index 388c08f..f486649 100644 --- a/n2vc/tests/unit/test_k8s_juju_conn.py +++ b/n2vc/tests/unit/test_k8s_juju_conn.py @@ -325,105 +325,102 @@ class InstallTest(K8sJujuConnTestCase): self.http_bundle = "https://example.com/bundle.yaml" self.kdu_name = "kdu_name" self.cluster_uuid = "cluster" + self.kdu_instance = "{}-{}".format(self.kdu_name, "id") self.k8s_juju_conn.libjuju.add_model = AsyncMock() self.k8s_juju_conn.libjuju.deploy = AsyncMock() def test_success_local(self, mock_chdir): - expected_kdu_instance = "{}-{}".format(self.kdu_name, "id") - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.local_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, db_dict=self.db_dict, timeout=1800, ) ) - self.assertEqual(kdu_instance, expected_kdu_instance) self.assertEqual(mock_chdir.call_count, 2) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( "local:{}".format(self.local_bundle), - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, ) def test_success_cs(self, mock_chdir): - expected_kdu_instance = "{}-{}".format(self.kdu_name, "id") - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.cs_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, db_dict=self.db_dict, timeout=1800, ) ) - self.assertEqual(kdu_instance, expected_kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( self.cs_bundle, - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, ) def test_success_http(self, mock_chdir): - expected_kdu_instance = "{}-{}".format(self.kdu_name, "id") - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.http_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, db_dict=self.db_dict, timeout=1800, ) ) - self.assertEqual(kdu_instance, expected_kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( self.http_bundle, - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, ) def test_success_not_kdu_name(self, mock_chdir): - expected_kdu_instance = "id" - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.cs_bundle, + self.kdu_instance, atomic=True, db_dict=self.db_dict, timeout=1800, ) ) - self.assertEqual(kdu_instance, expected_kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( self.cs_bundle, - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, ) @@ -431,10 +428,11 @@ class InstallTest(K8sJujuConnTestCase): def test_missing_db_dict(self, mock_chdir): kdu_instance = None with self.assertRaises(K8sException): - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.cs_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, timeout=1800, @@ -447,71 +445,67 @@ class InstallTest(K8sJujuConnTestCase): @asynctest.mock.patch("os.getcwd") def test_getcwd_exception(self, mock_getcwd, mock_chdir): mock_getcwd.side_effect = FileNotFoundError() - expected_kdu_instance = "{}-{}".format(self.kdu_name, "id") - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.cs_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, db_dict=self.db_dict, timeout=1800, ) ) - self.assertEqual(kdu_instance, expected_kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( self.cs_bundle, - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, ) def test_missing_bundle(self, mock_chdir): - kdu_instance = None with self.assertRaises(K8sException): - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, "", + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, timeout=1800, db_dict=self.db_dict, ) ) - self.assertIsNone(kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_not_called() self.k8s_juju_conn.libjuju.deploy.assert_not_called() def test_missing_exception(self, mock_chdir): - expected_kdu_instance = "{}-{}".format(self.kdu_name, "id") - kdu_instance = None self.k8s_juju_conn.libjuju.deploy.side_effect = Exception() with self.assertRaises(Exception): - kdu_instance = self.loop.run_until_complete( + self.loop.run_until_complete( self.k8s_juju_conn.install( self.cluster_uuid, self.local_bundle, + self.kdu_instance, atomic=True, kdu_name=self.kdu_name, db_dict=self.db_dict, timeout=1800, ) ) - self.assertIsNone(kdu_instance) self.k8s_juju_conn.libjuju.add_model.assert_called_once_with( - model_name=expected_kdu_instance, + model_name=self.kdu_instance, cloud_name=self.cluster_uuid, credential_name="cred-{}".format(self.cluster_uuid), ) self.k8s_juju_conn.libjuju.deploy.assert_called_once_with( "local:{}".format(self.local_bundle), - model_name=expected_kdu_instance, + model_name=self.kdu_instance, wait=True, timeout=1800, )