blob: 9364d931e2646922c8b0aa5555df0f37406fcbff [file] [log] [blame]
quilesj26c78a42019-10-28 18:10:42 +01001##
2# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
3# This file is part of OSM
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15# implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19# For those usages not covered by the Apache License, Version 2.0 please
20# contact with: nfvlabs@tid.es
21##
quilesj26c78a42019-10-28 18:10:42 +010022import asyncio
beierlmf52cb7c2020-04-21 16:36:35 -040023import os
beierlmf52cb7c2020-04-21 16:36:35 -040024import yaml
quilesj26c78a42019-10-28 18:10:42 +010025
lloretgalleg1c83f2e2020-10-22 09:12:35 +000026from n2vc.k8s_helm_base_conn import K8sHelmBaseConnector
27from n2vc.exceptions import K8sException
quilesj26c78a42019-10-28 18:10:42 +010028
lloretgalleg1c83f2e2020-10-22 09:12:35 +000029
30class K8sHelmConnector(K8sHelmBaseConnector):
quilesj26c78a42019-10-28 18:10:42 +010031
32 """
beierlmf52cb7c2020-04-21 16:36:35 -040033 ####################################################################################
34 ################################### P U B L I C ####################################
35 ####################################################################################
quilesj26c78a42019-10-28 18:10:42 +010036 """
37
38 def __init__(
beierlmf52cb7c2020-04-21 16:36:35 -040039 self,
40 fs: object,
41 db: object,
42 kubectl_command: str = "/usr/bin/kubectl",
43 helm_command: str = "/usr/bin/helm",
44 log: object = None,
45 on_update_db=None,
quilesj26c78a42019-10-28 18:10:42 +010046 ):
47 """
lloretgalleg1c83f2e2020-10-22 09:12:35 +000048 Initializes helm connector for helm v2
quilesj26c78a42019-10-28 18:10:42 +010049
50 :param fs: file system for kubernetes and helm configuration
51 :param db: database object to write current operation status
52 :param kubectl_command: path to kubectl executable
53 :param helm_command: path to helm executable
54 :param log: logger
55 :param on_update_db: callback called when k8s connector updates database
56 """
57
58 # parent class
lloretgalleg1c83f2e2020-10-22 09:12:35 +000059 K8sHelmBaseConnector.__init__(
60 self,
61 db=db,
62 log=log,
63 fs=fs,
64 kubectl_command=kubectl_command,
65 helm_command=helm_command,
66 on_update_db=on_update_db,
67 )
quilesj26c78a42019-10-28 18:10:42 +010068
lloretgalleg1c83f2e2020-10-22 09:12:35 +000069 self.log.info("Initializing K8S Helm2 connector")
quilesj26c78a42019-10-28 18:10:42 +010070
quilesj1be06302019-11-29 11:17:11 +000071 # initialize helm client-only
beierlmf52cb7c2020-04-21 16:36:35 -040072 self.log.debug("Initializing helm client-only...")
73 command = "{} init --client-only".format(self._helm_command)
quilesj1be06302019-11-29 11:17:11 +000074 try:
beierlmf52cb7c2020-04-21 16:36:35 -040075 asyncio.ensure_future(
76 self._local_async_exec(command=command, raise_exception_on_error=False)
77 )
quilesj1be06302019-11-29 11:17:11 +000078 # loop = asyncio.get_event_loop()
beierlmf52cb7c2020-04-21 16:36:35 -040079 # loop.run_until_complete(self._local_async_exec(command=command,
80 # raise_exception_on_error=False))
quilesj1be06302019-11-29 11:17:11 +000081 except Exception as e:
beierlmf52cb7c2020-04-21 16:36:35 -040082 self.warning(
83 msg="helm init failed (it was already initialized): {}".format(e)
84 )
quilesj1be06302019-11-29 11:17:11 +000085
lloretgalleg1c83f2e2020-10-22 09:12:35 +000086 self.log.info("K8S Helm2 connector initialized")
quilesj26c78a42019-10-28 18:10:42 +010087
lloretgalleg1c83f2e2020-10-22 09:12:35 +000088 async def inspect_kdu(self, kdu_model: str, repo_url: str = None) -> str:
89
90 self.log.debug(
91 "inspect kdu_model {} from (optional) repo: {}".format(kdu_model, repo_url)
92 )
93
94 return await self._exec_inspect_comand(
95 inspect_command="", kdu_model=kdu_model, repo_url=repo_url
96 )
97
98 """
99 ####################################################################################
100 ################################### P R I V A T E ##################################
101 ####################################################################################
102 """
103
104 def _init_paths_env(self, cluster_name: str, create_if_not_exist: bool = True):
tiernoa5728bf2020-06-25 15:48:52 +0000105 """
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000106 Creates and returns base cluster and kube dirs and returns them.
107 Also created helm3 dirs according to new directory specification, paths are
108 returned and also environment variables that must be provided to execute commands
109
110 Helm 2 directory specification uses helm_home dir:
111
112 The variables assigned for this paths are:
113 - Helm hone: $HELM_HOME
114 - helm kubeconfig: $KUBECONFIG
115
116 :param cluster_name: cluster_name
117 :return: Dictionary with config_paths and dictionary with helm environment variables
tiernoa5728bf2020-06-25 15:48:52 +0000118 """
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000119 base = self.fs.path
120 if base.endswith("/") or base.endswith("\\"):
121 base = base[:-1]
tiernoa5728bf2020-06-25 15:48:52 +0000122
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000123 # base dir for cluster
124 cluster_dir = base + "/" + cluster_name
garciadeblas54771fa2019-12-13 13:39:03 +0100125
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000126 # kube dir
127 kube_dir = cluster_dir + "/" + ".kube"
128 if create_if_not_exist and not os.path.exists(kube_dir):
129 self.log.debug("Creating dir {}".format(kube_dir))
130 os.makedirs(kube_dir)
quilesj26c78a42019-10-28 18:10:42 +0100131
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000132 # helm home dir
133 helm_dir = cluster_dir + "/" + ".helm"
134 if create_if_not_exist and not os.path.exists(helm_dir):
135 self.log.debug("Creating dir {}".format(helm_dir))
136 os.makedirs(helm_dir)
quilesj26c78a42019-10-28 18:10:42 +0100137
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000138 config_filename = kube_dir + "/config"
quilesj26c78a42019-10-28 18:10:42 +0100139
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000140 # 2 - Prepare dictionary with paths
141 paths = {
142 "kube_dir": kube_dir,
143 "kube_config": config_filename,
144 "cluster_dir": cluster_dir,
145 "helm_dir": helm_dir,
146 }
147
148 for file_name, file in paths.items():
149 if "dir" in file_name and not os.path.exists(file):
150 err_msg = "{} dir does not exist".format(file)
151 self.log.error(err_msg)
152 raise K8sException(err_msg)
153
154 # 3 - Prepare environment variables
155 env = {"HELM_HOME": helm_dir, "KUBECONFIG": config_filename}
156
157 return paths, env
158
159 async def _get_services(self, cluster_id, kdu_instance, namespace):
160
161 # init config, env
162 paths, env = self._init_paths_env(
tiernoa5728bf2020-06-25 15:48:52 +0000163 cluster_name=cluster_id, create_if_not_exist=True
beierlmf52cb7c2020-04-21 16:36:35 -0400164 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000165
166 command1 = "{} get manifest {} ".format(self._helm_command, kdu_instance)
167 command2 = "{} get --namespace={} -f -".format(self.kubectl_command, namespace)
168 output, _rc = await self._local_async_exec_pipe(
169 command1, command2, env=env, raise_exception_on_error=True
170 )
171 services = self._parse_services(output)
172
173 return services
174
175 async def _cluster_init(self, cluster_id: str, namespace: str,
176 paths: dict, env: dict):
177 """
178 Implements the helm version dependent cluster initialization:
179 For helm2 it initialized tiller environment if needed
180 """
quilesj26c78a42019-10-28 18:10:42 +0100181
182 # check if tiller pod is up in cluster
beierlmf52cb7c2020-04-21 16:36:35 -0400183 command = "{} --kubeconfig={} --namespace={} get deployments".format(
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000184 self.kubectl_command, paths["kube_config"], namespace
beierlmf52cb7c2020-04-21 16:36:35 -0400185 )
186 output, _rc = await self._local_async_exec(
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000187 command=command, raise_exception_on_error=True, env=env
beierlmf52cb7c2020-04-21 16:36:35 -0400188 )
quilesj26c78a42019-10-28 18:10:42 +0100189
tierno119f7232020-04-21 13:22:26 +0000190 output_table = self._output_to_table(output=output)
quilesj26c78a42019-10-28 18:10:42 +0100191
192 # find 'tiller' pod in all pods
193 already_initialized = False
194 try:
195 for row in output_table:
beierlmf52cb7c2020-04-21 16:36:35 -0400196 if row[0].startswith("tiller-deploy"):
quilesj26c78a42019-10-28 18:10:42 +0100197 already_initialized = True
198 break
beierlmf52cb7c2020-04-21 16:36:35 -0400199 except Exception:
quilesj26c78a42019-10-28 18:10:42 +0100200 pass
201
202 # helm init
203 n2vc_installed_sw = False
204 if not already_initialized:
beierlmf52cb7c2020-04-21 16:36:35 -0400205 self.log.info(
tiernoa5728bf2020-06-25 15:48:52 +0000206 "Initializing helm in client and server: {}".format(cluster_id)
beierlmf52cb7c2020-04-21 16:36:35 -0400207 )
tiernoa5728bf2020-06-25 15:48:52 +0000208 command = "{} --kubeconfig={} --namespace kube-system create serviceaccount {}".format(
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000209 self.kubectl_command, paths["kube_config"], self.service_account
210 )
211 _, _rc = await self._local_async_exec(
212 command=command, raise_exception_on_error=False, env=env
213 )
tiernoa5728bf2020-06-25 15:48:52 +0000214
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000215 command = (
216 "{} --kubeconfig={} create clusterrolebinding osm-tiller-cluster-rule "
217 "--clusterrole=cluster-admin --serviceaccount=kube-system:{}"
218 ).format(self.kubectl_command, paths["kube_config"], self.service_account)
219 _, _rc = await self._local_async_exec(
220 command=command, raise_exception_on_error=False, env=env
221 )
tiernoa5728bf2020-06-25 15:48:52 +0000222
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000223 command = (
224 "{} --kubeconfig={} --tiller-namespace={} --home={} --service-account {} "
225 "init"
226 ).format(
227 self._helm_command,
228 paths["kube_config"],
229 namespace,
230 paths["helm_dir"],
231 self.service_account,
232 )
233 _, _rc = await self._local_async_exec(
234 command=command, raise_exception_on_error=True, env=env
235 )
quilesj26c78a42019-10-28 18:10:42 +0100236 n2vc_installed_sw = True
237 else:
238 # check client helm installation
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000239 check_file = paths["helm_dir"] + "/repository/repositories.yaml"
240 if not self._check_file_exists(
241 filename=check_file, exception_if_not_exists=False
242 ):
tiernoa5728bf2020-06-25 15:48:52 +0000243 self.log.info("Initializing helm in client: {}".format(cluster_id))
beierlmf52cb7c2020-04-21 16:36:35 -0400244 command = (
245 "{} --kubeconfig={} --tiller-namespace={} "
246 "--home={} init --client-only"
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000247 ).format(
248 self._helm_command,
249 paths["kube_config"],
250 namespace,
251 paths["helm_dir"],
252 )
beierlmf52cb7c2020-04-21 16:36:35 -0400253 output, _rc = await self._local_async_exec(
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000254 command=command, raise_exception_on_error=True, env=env
beierlmf52cb7c2020-04-21 16:36:35 -0400255 )
quilesj26c78a42019-10-28 18:10:42 +0100256 else:
beierlmf52cb7c2020-04-21 16:36:35 -0400257 self.log.info("Helm client already initialized")
quilesj26c78a42019-10-28 18:10:42 +0100258
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000259 return n2vc_installed_sw
lloretgallege308c712020-09-02 09:40:38 +0000260
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000261 async def _uninstall_sw(self, cluster_id: str, namespace: str):
262 # uninstall Tiller if necessary
quilesj26c78a42019-10-28 18:10:42 +0100263
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000264 self.log.debug("Uninstalling tiller from cluster {}".format(cluster_id))
quilesj26c78a42019-10-28 18:10:42 +0100265
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000266 # init paths, env
267 paths, env = self._init_paths_env(
tiernoa5728bf2020-06-25 15:48:52 +0000268 cluster_name=cluster_id, create_if_not_exist=True
beierlmf52cb7c2020-04-21 16:36:35 -0400269 )
quilesj26c78a42019-10-28 18:10:42 +0100270
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000271 if not namespace:
272 # find namespace for tiller pod
273 command = "{} --kubeconfig={} get deployments --all-namespaces".format(
274 self.kubectl_command, paths["kube_config"]
275 )
276 output, _rc = await self._local_async_exec(
277 command=command, raise_exception_on_error=False, env=env
278 )
279 output_table = self._output_to_table(output=output)
280 namespace = None
281 for r in output_table:
282 try:
283 if "tiller-deploy" in r[1]:
284 namespace = r[0]
285 break
286 except Exception:
287 pass
quilesj26c78a42019-10-28 18:10:42 +0100288 else:
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000289 msg = "Tiller deployment not found in cluster {}".format(cluster_id)
290 self.log.error(msg)
quilesj26c78a42019-10-28 18:10:42 +0100291
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000292 self.log.debug("namespace for tiller: {}".format(namespace))
quilesj26c78a42019-10-28 18:10:42 +0100293
tierno53555f62020-04-07 11:08:16 +0000294 if namespace:
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000295 # uninstall tiller from cluster
296 self.log.debug("Uninstalling tiller from cluster {}".format(cluster_id))
297 command = "{} --kubeconfig={} --home={} reset".format(
298 self._helm_command, paths["kube_config"], paths["helm_dir"]
beierlmf52cb7c2020-04-21 16:36:35 -0400299 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000300 self.log.debug("resetting: {}".format(command))
301 output, _rc = await self._local_async_exec(
302 command=command, raise_exception_on_error=True, env=env
quilesj26c78a42019-10-28 18:10:42 +0100303 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000304 # Delete clusterrolebinding and serviceaccount.
305 # Ignore if errors for backward compatibility
306 command = (
307 "{} --kubeconfig={} delete clusterrolebinding.rbac.authorization.k8s."
308 "io/osm-tiller-cluster-rule"
309 ).format(self.kubectl_command, paths["kube_config"])
310 output, _rc = await self._local_async_exec(
311 command=command, raise_exception_on_error=False, env=env
quilesj26c78a42019-10-28 18:10:42 +0100312 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000313 command = "{} --kubeconfig={} --namespace kube-system delete serviceaccount/{}".format(
314 self.kubectl_command, paths["kube_config"], self.service_account
315 )
316 output, _rc = await self._local_async_exec(
317 command=command, raise_exception_on_error=False, env=env
318 )
quilesj26c78a42019-10-28 18:10:42 +0100319
320 else:
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000321 self.log.debug("namespace not found")
quilesj26c78a42019-10-28 18:10:42 +0100322
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000323 async def _instances_list(self, cluster_id):
quilesj26c78a42019-10-28 18:10:42 +0100324
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000325 # init paths, env
326 paths, env = self._init_paths_env(
tiernoa5728bf2020-06-25 15:48:52 +0000327 cluster_name=cluster_id, create_if_not_exist=True
beierlmf52cb7c2020-04-21 16:36:35 -0400328 )
quilesj26c78a42019-10-28 18:10:42 +0100329
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000330 command = "{} list --output yaml".format(self._helm_command)
quilesj26c78a42019-10-28 18:10:42 +0100331
beierlmf52cb7c2020-04-21 16:36:35 -0400332 output, _rc = await self._local_async_exec(
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000333 command=command, raise_exception_on_error=True, env=env
beierlmf52cb7c2020-04-21 16:36:35 -0400334 )
quilesj26c78a42019-10-28 18:10:42 +0100335
336 if output and len(output) > 0:
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000337 # parse yaml and update keys to lower case to unify with helm3
338 instances = yaml.load(output, Loader=yaml.SafeLoader).get("Releases")
339 new_instances = []
340 for instance in instances:
341 new_instance = dict((k.lower(), v) for k, v in instance.items())
342 new_instances.append(new_instance)
343 return new_instances
quilesj26c78a42019-10-28 18:10:42 +0100344 else:
345 return []
346
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000347 def _get_inspect_command(self, show_command: str, kdu_model: str, repo_str: str,
348 version: str):
349 inspect_command = "{} inspect {} {}{} {}".format(
350 self._helm_command, show_command, kdu_model, repo_str, version
beierlmf52cb7c2020-04-21 16:36:35 -0400351 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000352 return inspect_command
quilesj1be06302019-11-29 11:17:11 +0000353
quilesj26c78a42019-10-28 18:10:42 +0100354 async def _status_kdu(
beierlmf52cb7c2020-04-21 16:36:35 -0400355 self,
tiernoa5728bf2020-06-25 15:48:52 +0000356 cluster_id: str,
beierlmf52cb7c2020-04-21 16:36:35 -0400357 kdu_instance: str,
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000358 namespace: str = None,
beierlmf52cb7c2020-04-21 16:36:35 -0400359 show_error_log: bool = False,
360 return_text: bool = False,
quilesj26c78a42019-10-28 18:10:42 +0100361 ):
362
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000363 self.log.debug(
364 "status of kdu_instance: {}, namespace: {} ".format(kdu_instance, namespace)
365 )
quilesj26c78a42019-10-28 18:10:42 +0100366
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000367 # init config, env
368 paths, env = self._init_paths_env(
tiernoa5728bf2020-06-25 15:48:52 +0000369 cluster_name=cluster_id, create_if_not_exist=True
beierlmf52cb7c2020-04-21 16:36:35 -0400370 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000371 command = "{} status {} --output yaml".format(self._helm_command, kdu_instance)
quilesj26c78a42019-10-28 18:10:42 +0100372 output, rc = await self._local_async_exec(
373 command=command,
374 raise_exception_on_error=True,
beierlmf52cb7c2020-04-21 16:36:35 -0400375 show_error_log=show_error_log,
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000376 env=env,
quilesj26c78a42019-10-28 18:10:42 +0100377 )
378
quilesj1be06302019-11-29 11:17:11 +0000379 if return_text:
380 return str(output)
381
quilesj26c78a42019-10-28 18:10:42 +0100382 if rc != 0:
383 return None
384
385 data = yaml.load(output, Loader=yaml.SafeLoader)
386
387 # remove field 'notes'
388 try:
beierlmf52cb7c2020-04-21 16:36:35 -0400389 del data.get("info").get("status")["notes"]
quilesj26c78a42019-10-28 18:10:42 +0100390 except KeyError:
391 pass
392
393 # parse field 'resources'
394 try:
beierlmf52cb7c2020-04-21 16:36:35 -0400395 resources = str(data.get("info").get("status").get("resources"))
quilesj26c78a42019-10-28 18:10:42 +0100396 resource_table = self._output_to_table(resources)
beierlmf52cb7c2020-04-21 16:36:35 -0400397 data.get("info").get("status")["resources"] = resource_table
398 except Exception:
quilesj26c78a42019-10-28 18:10:42 +0100399 pass
400
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000401 # set description to lowercase (unify with helm3)
402 try:
403 data.get("info")["description"] = data.get("info").pop("Description")
404 except KeyError:
405 pass
406
quilesj26c78a42019-10-28 18:10:42 +0100407 return data
408
tiernoa5728bf2020-06-25 15:48:52 +0000409 async def _is_install_completed(self, cluster_id: str, kdu_instance: str) -> bool:
quilesj26c78a42019-10-28 18:10:42 +0100410
beierlmf52cb7c2020-04-21 16:36:35 -0400411 status = await self._status_kdu(
tiernoa5728bf2020-06-25 15:48:52 +0000412 cluster_id=cluster_id, kdu_instance=kdu_instance, return_text=False
beierlmf52cb7c2020-04-21 16:36:35 -0400413 )
quilesj26c78a42019-10-28 18:10:42 +0100414
415 # extract info.status.resources-> str
416 # format:
417 # ==> v1/Deployment
418 # NAME READY UP-TO-DATE AVAILABLE AGE
419 # halting-horse-mongodb 0/1 1 0 0s
420 # halting-petit-mongodb 1/1 1 0 0s
421 # blank line
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000422 resources = K8sHelmBaseConnector._get_deep(
423 status, ("info", "status", "resources")
424 )
quilesj26c78a42019-10-28 18:10:42 +0100425
426 # convert to table
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000427 resources = K8sHelmBaseConnector._output_to_table(resources)
quilesj26c78a42019-10-28 18:10:42 +0100428
429 num_lines = len(resources)
430 index = 0
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000431 ready = True
quilesj26c78a42019-10-28 18:10:42 +0100432 while index < num_lines:
433 try:
434 line1 = resources[index]
435 index += 1
436 # find '==>' in column 0
beierlmf52cb7c2020-04-21 16:36:35 -0400437 if line1[0] == "==>":
quilesj26c78a42019-10-28 18:10:42 +0100438 line2 = resources[index]
439 index += 1
440 # find READY in column 1
beierlmf52cb7c2020-04-21 16:36:35 -0400441 if line2[1] == "READY":
quilesj26c78a42019-10-28 18:10:42 +0100442 # read next lines
443 line3 = resources[index]
444 index += 1
445 while len(line3) > 1 and index < num_lines:
446 ready_value = line3[1]
beierlmf52cb7c2020-04-21 16:36:35 -0400447 parts = ready_value.split(sep="/")
quilesj26c78a42019-10-28 18:10:42 +0100448 current = int(parts[0])
449 total = int(parts[1])
450 if current < total:
beierlmf52cb7c2020-04-21 16:36:35 -0400451 self.log.debug("NOT READY:\n {}".format(line3))
quilesj26c78a42019-10-28 18:10:42 +0100452 ready = False
453 line3 = resources[index]
454 index += 1
455
beierlmf52cb7c2020-04-21 16:36:35 -0400456 except Exception:
quilesj26c78a42019-10-28 18:10:42 +0100457 pass
458
459 return ready
460
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000461 def _get_install_command(
462 self, kdu_model, kdu_instance, namespace, params_str, version, atomic, timeout
463 ) -> str:
lloretgallegd99f3f22020-06-29 14:18:30 +0000464
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000465 timeout_str = ""
466 if timeout:
467 timeout_str = "--timeout {}".format(timeout)
lloretgallegd99f3f22020-06-29 14:18:30 +0000468
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000469 # atomic
470 atomic_str = ""
471 if atomic:
472 atomic_str = "--atomic"
473 # namespace
474 namespace_str = ""
475 if namespace:
476 namespace_str = "--namespace {}".format(namespace)
lloretgallegd99f3f22020-06-29 14:18:30 +0000477
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000478 # version
479 version_str = ""
480 if version:
481 version_str = version_str = "--version {}".format(version)
lloretgallegd99f3f22020-06-29 14:18:30 +0000482
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000483 command = (
484 "{helm} install {atomic} --output yaml "
485 "{params} {timeout} --name={name} {ns} {model} {ver}".format(
486 helm=self._helm_command,
487 atomic=atomic_str,
488 params=params_str,
489 timeout=timeout_str,
490 name=kdu_instance,
491 ns=namespace_str,
492 model=kdu_model,
493 ver=version_str,
beierlmf52cb7c2020-04-21 16:36:35 -0400494 )
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000495 )
496 return command
quilesj26c78a42019-10-28 18:10:42 +0100497
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000498 def _get_upgrade_command(
499 self, kdu_model, kdu_instance, namespace, params_str, version, atomic, timeout
500 ) -> str:
quilesj26c78a42019-10-28 18:10:42 +0100501
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000502 timeout_str = ""
503 if timeout:
504 timeout_str = "--timeout {}".format(timeout)
quilesj26c78a42019-10-28 18:10:42 +0100505
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000506 # atomic
507 atomic_str = ""
508 if atomic:
509 atomic_str = "--atomic"
quilesj26c78a42019-10-28 18:10:42 +0100510
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000511 # version
512 version_str = ""
513 if version:
514 version_str = "--version {}".format(version)
quilesj26c78a42019-10-28 18:10:42 +0100515
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000516 command = "{helm} upgrade {atomic} --output yaml {params} {timeout} {name} {model} {ver}"\
517 .format(helm=self._helm_command,
518 atomic=atomic_str,
519 params=params_str,
520 timeout=timeout_str,
521 name=kdu_instance,
522 model=kdu_model,
523 ver=version_str
524 )
525 return command
quilesj26c78a42019-10-28 18:10:42 +0100526
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000527 def _get_rollback_command(self, kdu_instance, namespace, revision) -> str:
528 return "{} rollback {} {} --wait".format(
529 self._helm_command, kdu_instance, revision
530 )
quilesj26c78a42019-10-28 18:10:42 +0100531
lloretgalleg1c83f2e2020-10-22 09:12:35 +0000532 def _get_uninstall_command(self, kdu_instance: str, namespace: str) -> str:
533 return "{} delete --purge {}".format(self._helm_command, kdu_instance)