From: quilesj Date: Fri, 29 Nov 2019 11:17:11 +0000 (+0000) Subject: Adding inspect methods for K8s X-Git-Tag: v7.0.0rc1~8 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F59%2F8259%2F2;p=osm%2FN2VC.git Adding inspect methods for K8s Change-Id: I45fba22073e7dfdfab2f3a1d1cca1f0705145e0c Signed-off-by: quilesj --- diff --git a/n2vc/k8s_conn.py b/n2vc/k8s_conn.py index d951c2c..11fb43e 100644 --- a/n2vc/k8s_conn.py +++ b/n2vc/k8s_conn.py @@ -63,7 +63,7 @@ class K8sConnector(abc.ABC, Loggable): self, k8s_creds: str, namespace: str = 'kube-system', - reuse_cluster_uuid = None + reuse_cluster_uuid=None ) -> (str, bool): """ It prepares a given K8s cluster environment to run Charts or juju Bundles on both sides: @@ -237,30 +237,33 @@ class K8sConnector(abc.ABC, Loggable): @abc.abstractmethod async def inspect_kdu( self, - kdu_model: str + kdu_model: str, + repo_url: str = None ) -> str: """ - These calls will retrieve from the Charm/Bundle: + These calls will retrieve from the Chart/Bundle: - The list of configurable values and their defaults (e.g. in Charts, it would retrieve the contents of `values.yaml`). - If available, any embedded help file (e.g. `readme.md`) embedded in the Chart/Bundle. - :param cluster_uuid: the cluster to get the information :param kdu_model: chart/bundle reference - :return: If successful, it will return a dictionary containing the list of available parameters - and their default values + :param repo_url: optional, reposotory URL (None if tar.gz, URl in other cases, even stable URL) + :return: + + If successful, it will return the available parameters and their default values as provided by the backend. """ @abc.abstractmethod async def help_kdu( self, - kdu_model: str + kdu_model: str, + repo_url: str = None ) -> str: """ - :param cluster_uuid: the cluster to get the information :param kdu_model: chart/bundle reference + :param repo_url: optional, reposotory URL (None if tar.gz, URl in other cases, even stable URL) :return: If successful, it will return the contents of the 'readme.md' """ diff --git a/n2vc/k8s_helm_conn.py b/n2vc/k8s_helm_conn.py index eac34d4..2b15d76 100644 --- a/n2vc/k8s_helm_conn.py +++ b/n2vc/k8s_helm_conn.py @@ -83,6 +83,16 @@ class K8sHelmConnector(K8sConnector): self._helm_command = helm_command self._check_file_exists(filename=helm_command, exception_if_not_exists=True) + # initialize helm client-only + self.debug('Initializing helm client-only...') + command = '{} init --client-only'.format(self._helm_command) + try: + asyncio.ensure_future(self._local_async_exec(command=command, raise_exception_on_error=False)) + # loop = asyncio.get_event_loop() + # loop.run_until_complete(self._local_async_exec(command=command, raise_exception_on_error=False)) + except Exception as e: + self.warning(msg='helm init failed (it was already initialized): {}'.format(e)) + self.info('K8S Helm connector initialized') async def init_env( @@ -186,7 +196,8 @@ class K8sHelmConnector(K8sConnector): kube_dir, helm_dir, config_filename, cluster_dir = \ self._get_paths(cluster_name=cluster_uuid, create_if_not_exist=True) - command = '{} --kubeconfig={} --home={} repo list --output yaml'.format(self._helm_command, config_filename, helm_dir) + command = '{} --kubeconfig={} --home={} repo list --output yaml'\ + .format(self._helm_command, config_filename, helm_dir) output, rc = await self._local_async_exec(command=command, raise_exception_on_error=True) if output and len(output) > 0: @@ -310,9 +321,6 @@ class K8sHelmConnector(K8sConnector): self.debug('installing {} in cluster {}'.format(kdu_model, cluster_uuid)) - start = time.time() - end = start + timeout - # config filename kube_dir, helm_dir, config_filename, cluster_dir = \ self._get_paths(cluster_name=cluster_uuid, create_if_not_exist=True) @@ -351,7 +359,7 @@ class K8sHelmConnector(K8sConnector): if result is not None: # instance already exists: generate a new one kdu_instance = None - except: + except Exception as e: kdu_instance = None # helm repo install @@ -450,9 +458,6 @@ class K8sHelmConnector(K8sConnector): self.debug('upgrading {} in cluster {}'.format(kdu_model, cluster_uuid)) - start = time.time() - end = start + timeout - # config filename kube_dir, helm_dir, config_filename, cluster_dir = \ self._get_paths(cluster_name=cluster_uuid, create_if_not_exist=True) @@ -502,7 +507,7 @@ class K8sHelmConnector(K8sConnector): ) # wait for execution task - await asyncio.wait([ exec_task ]) + await asyncio.wait([exec_task]) # cancel status task status_task.cancel() @@ -634,40 +639,47 @@ class K8sHelmConnector(K8sConnector): async def inspect_kdu( self, - kdu_model: str + kdu_model: str, + repo_url: str = None ) -> str: - self.debug('inspect kdu_model {}'.format(kdu_model)) + self.debug('inspect kdu_model {} from (optional) repo: {}'.format(kdu_model, repo_url)) + + return await self._exec_inspect_comand(inspect_command='', kdu_model=kdu_model, repo_url=repo_url) - command = '{} inspect values {}'\ - .format(self._helm_command, kdu_model) + async def values_kdu( + self, + kdu_model: str, + repo_url: str = None + ) -> str: - output, rc = await self._local_async_exec(command=command) + self.debug('inspect kdu_model values {} from (optional) repo: {}'.format(kdu_model, repo_url)) - return output + return await self._exec_inspect_comand(inspect_command='values', kdu_model=kdu_model, repo_url=repo_url) async def help_kdu( self, - kdu_model: str - ): + kdu_model: str, + repo_url: str = None + ) -> str: - self.debug('help kdu_model {}'.format(kdu_model)) + self.debug('inspect kdu_model {} readme.md from repo: {}'.format(kdu_model, repo_url)) - command = '{} inspect readme {}'\ - .format(self._helm_command, kdu_model) - - output, rc = await self._local_async_exec(command=command, raise_exception_on_error=True) - - return output + return await self._exec_inspect_comand(inspect_command='readme', kdu_model=kdu_model, repo_url=repo_url) async def status_kdu( self, cluster_uuid: str, kdu_instance: str - ): - - return await self._status_kdu(cluster_uuid=cluster_uuid, kdu_instance=kdu_instance, show_error_log=True) + ) -> str: + # call internal function + return await self._status_kdu( + cluster_uuid=cluster_uuid, + kdu_instance=kdu_instance, + show_error_log=True, + return_text=True + ) """ ################################################################################################## @@ -675,11 +687,32 @@ class K8sHelmConnector(K8sConnector): ################################################################################################## """ + async def _exec_inspect_comand( + self, + inspect_command: str, + kdu_model: str, + repo_url: str = None + ): + + repo_str = '' + if repo_url: + repo_str = ' --repo {}'.format(repo_url) + idx = kdu_model.find('/') + if idx >= 0: + idx += 1 + kdu_model = kdu_model[idx:] + + inspect_command = '{} inspect {} {}{}'.format(self._helm_command, inspect_command, kdu_model, repo_str) + output, rc = await self._local_async_exec(command=inspect_command, encode_utf8=True) + + return output + async def _status_kdu( self, cluster_uuid: str, kdu_instance: str, - show_error_log: bool = False + show_error_log: bool = False, + return_text: bool = False ): self.debug('status of kdu_instance {}'.format(kdu_instance)) @@ -697,6 +730,9 @@ class K8sHelmConnector(K8sConnector): show_error_log=show_error_log ) + if return_text: + return str(output) + if rc != 0: return None @@ -800,7 +836,7 @@ class K8sHelmConnector(K8sConnector): kdu_instance: str ) -> bool: - status = await self.status_kdu(cluster_uuid=cluster_uuid, kdu_instance=kdu_instance) + status = await self._status_kdu(cluster_uuid=cluster_uuid, kdu_instance=kdu_instance, return_text=False) # extract info.status.resources-> str # format: @@ -877,7 +913,6 @@ class K8sHelmConnector(K8sConnector): # params for use in -f file # returns values file option and filename (in order to delete it at the end) def _params_to_file_option(self, cluster_uuid: str, params: dict) -> (str, str): - params_str = '' if params and len(params) > 0: kube_dir, helm_dir, config_filename, cluster_dir = \ @@ -894,7 +929,7 @@ class K8sHelmConnector(K8sConnector): for key in params: value = params.get(key) if '!!yaml' in str(value): - value = yaml.safe_load(value[7:]) + value = yaml.load(value[7:]) params2[key] = value values_file = get_random_number() + '.yaml' @@ -1022,7 +1057,8 @@ class K8sHelmConnector(K8sConnector): self, command: str, raise_exception_on_error: bool = False, - show_error_log: bool = True + show_error_log: bool = True, + encode_utf8: bool = False ) -> (str, int): command = K8sHelmConnector._remove_multiple_spaces(command) @@ -1046,8 +1082,10 @@ class K8sHelmConnector(K8sConnector): output = '' if stdout: output = stdout.decode('utf-8').strip() + # output = stdout.decode() if stderr: output = stderr.decode('utf-8').strip() + # output = stderr.decode() if return_code != 0 and show_error_log: self.debug('Return code (FAIL): {}\nOutput:\n{}'.format(return_code, output)) @@ -1057,6 +1095,10 @@ class K8sHelmConnector(K8sConnector): if raise_exception_on_error and return_code != 0: raise Exception(output) + if encode_utf8: + output = output.encode('utf-8').strip() + output = str(output).replace('\\n', '\n') + return output, return_code except Exception as e: @@ -1102,4 +1144,3 @@ class K8sHelmConnector(K8sConnector): if exception_if_not_exists: self.error(msg) raise Exception(msg) -