Pin black version in tox.ini to 23.12.1
[osm/N2VC.git] / n2vc / tests / unit / test_k8s_helm3_conn.py
1 ##
2 # Licensed under the Apache License, Version 2.0 (the "License"); you may
3 # not use this file except in compliance with the License. You may obtain
4 # a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 # License for the specific language governing permissions and limitations
12 # under the License.
13 #
14 # For those usages not covered by the Apache License, Version 2.0 please
15 # contact: alfonso.tiernosepulveda@telefonica.com
16 ##
17
18 import asynctest
19 import logging
20
21 from asynctest.mock import Mock, patch
22 from osm_common.dbmemory import DbMemory
23 from osm_common.fslocal import FsLocal
24 from n2vc.k8s_helm3_conn import K8sHelm3Connector, K8sException
25
26 __author__ = "Isabel Lloret <illoret@indra.es>"
27
28
29 class TestK8sHelm3Conn(asynctest.TestCase):
30 logging.basicConfig(level=logging.DEBUG)
31 logger = logging.getLogger(__name__)
32 logger.setLevel(logging.DEBUG)
33
34 @patch("n2vc.k8s_helm_base_conn.EnvironConfig")
35 async def setUp(self, mock_env):
36 mock_env.return_value = {"stablerepourl": "https://charts.helm.sh/stable"}
37 self.db = Mock(DbMemory())
38 self.fs = asynctest.Mock(FsLocal())
39 self.fs.path = "./tmp/"
40 self.namespace = "testk8s"
41 self.cluster_id = "helm3_cluster_id"
42 self.cluster_uuid = self.cluster_id
43 # pass fake kubectl and helm commands to make sure it does not call actual commands
44 K8sHelm3Connector._check_file_exists = asynctest.Mock(return_value=True)
45 cluster_dir = self.fs.path + self.cluster_id
46 self.env = {
47 "HELM_CACHE_HOME": "{}/.cache/helm".format(cluster_dir),
48 "HELM_CONFIG_HOME": "{}/.config/helm".format(cluster_dir),
49 "HELM_DATA_HOME": "{}/.local/share/helm".format(cluster_dir),
50 "KUBECONFIG": "{}/.kube/config".format(cluster_dir),
51 }
52 self.helm_conn = K8sHelm3Connector(self.fs, self.db, log=self.logger)
53 self.logger.debug("Set up executed")
54
55 @asynctest.fail_on(active_handles=True)
56 async def test_init_env(self):
57 k8s_creds = "false_credentials_string"
58 self.helm_conn._get_namespaces = asynctest.CoroutineMock(return_value=[])
59 self.helm_conn._create_namespace = asynctest.CoroutineMock()
60 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=[])
61 self.helm_conn.repo_add = asynctest.CoroutineMock()
62
63 k8scluster_uuid, installed = await self.helm_conn.init_env(
64 k8s_creds, namespace=self.namespace, reuse_cluster_uuid=self.cluster_id
65 )
66
67 self.assertEqual(
68 k8scluster_uuid,
69 self.cluster_id,
70 "Check cluster_uuid",
71 )
72 self.helm_conn._get_namespaces.assert_called_once_with(self.cluster_id)
73 self.helm_conn._create_namespace.assert_called_once_with(
74 self.cluster_id, self.namespace
75 )
76 self.helm_conn.repo_list.assert_called_once_with(k8scluster_uuid)
77 self.helm_conn.repo_add.assert_called_once_with(
78 k8scluster_uuid, "stable", "https://charts.helm.sh/stable"
79 )
80 self.helm_conn.fs.reverse_sync.assert_called_once_with(
81 from_path=self.cluster_id
82 )
83 self.logger.debug(f"cluster_uuid: {k8scluster_uuid}")
84
85 @asynctest.fail_on(active_handles=True)
86 async def test_repo_add(self):
87 repo_name = "bitnami"
88 repo_url = "https://charts.bitnami.com/bitnami"
89 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=(0, ""))
90
91 await self.helm_conn.repo_add(self.cluster_uuid, repo_name, repo_url)
92
93 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
94 self.helm_conn.fs.reverse_sync.assert_called_once_with(
95 from_path=self.cluster_id
96 )
97 self.assertEqual(
98 self.helm_conn._local_async_exec.call_count,
99 2,
100 "local_async_exec expected 2 calls, called {}".format(
101 self.helm_conn._local_async_exec.call_count
102 ),
103 )
104
105 repo_update_command = (
106 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 repo update {}"
107 ).format(repo_name)
108 repo_add_command = (
109 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 repo add {} {}"
110 ).format(repo_name, repo_url)
111 calls = self.helm_conn._local_async_exec.call_args_list
112 call0_kargs = calls[0][1]
113 self.assertEqual(
114 call0_kargs.get("command"),
115 repo_add_command,
116 "Invalid repo add command: {}".format(call0_kargs.get("command")),
117 )
118 self.assertEqual(
119 call0_kargs.get("env"),
120 self.env,
121 "Invalid env for add command: {}".format(call0_kargs.get("env")),
122 )
123 call1_kargs = calls[1][1]
124 self.assertEqual(
125 call1_kargs.get("command"),
126 repo_update_command,
127 "Invalid repo update command: {}".format(call1_kargs.get("command")),
128 )
129 self.assertEqual(
130 call1_kargs.get("env"),
131 self.env,
132 "Invalid env for update command: {}".format(call1_kargs.get("env")),
133 )
134
135 @asynctest.fail_on(active_handles=True)
136 async def test_repo_list(self):
137 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
138
139 await self.helm_conn.repo_list(self.cluster_uuid)
140
141 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
142 self.helm_conn.fs.reverse_sync.assert_called_once_with(
143 from_path=self.cluster_id
144 )
145 command = "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 repo list --output yaml"
146 self.helm_conn._local_async_exec.assert_called_with(
147 command=command, env=self.env, raise_exception_on_error=False
148 )
149
150 @asynctest.fail_on(active_handles=True)
151 async def test_repo_remove(self):
152 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
153 repo_name = "bitnami"
154 await self.helm_conn.repo_remove(self.cluster_uuid, repo_name)
155
156 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
157 self.helm_conn.fs.reverse_sync.assert_called_once_with(
158 from_path=self.cluster_id
159 )
160 command = "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 repo remove {}".format(
161 repo_name
162 )
163 self.helm_conn._local_async_exec.assert_called_with(
164 command=command, env=self.env, raise_exception_on_error=True
165 )
166
167 @asynctest.fail_on(active_handles=True)
168 async def test_install(self):
169 kdu_model = "stable/openldap:1.2.2"
170 kdu_instance = "stable-openldap-0005399828"
171 db_dict = {}
172 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
173 self.helm_conn._status_kdu = asynctest.CoroutineMock(return_value=None)
174 self.helm_conn._store_status = asynctest.CoroutineMock()
175 self.kdu_instance = "stable-openldap-0005399828"
176 self.helm_conn.generate_kdu_instance_name = Mock(return_value=self.kdu_instance)
177 self.helm_conn._get_namespaces = asynctest.CoroutineMock(return_value=[])
178 self.helm_conn._namespace_exists = asynctest.CoroutineMock(
179 side_effect=self.helm_conn._namespace_exists
180 )
181 self.helm_conn._create_namespace = asynctest.CoroutineMock()
182
183 await self.helm_conn.install(
184 self.cluster_uuid,
185 kdu_model,
186 self.kdu_instance,
187 atomic=True,
188 namespace=self.namespace,
189 db_dict=db_dict,
190 )
191
192 self.helm_conn._namespace_exists.assert_called_once()
193 self.helm_conn._get_namespaces.assert_called_once()
194 self.helm_conn._create_namespace.assert_called_once_with(
195 self.cluster_id, self.namespace
196 )
197 self.helm_conn.fs.sync.assert_has_calls(
198 [
199 asynctest.call(from_path=self.cluster_id),
200 asynctest.call(from_path=self.cluster_id),
201 ]
202 )
203 self.helm_conn.fs.reverse_sync.assert_has_calls(
204 [
205 asynctest.call(from_path=self.cluster_id),
206 asynctest.call(from_path=self.cluster_id),
207 ]
208 )
209 self.helm_conn._store_status.assert_called_with(
210 cluster_id=self.cluster_id,
211 kdu_instance=kdu_instance,
212 namespace=self.namespace,
213 db_dict=db_dict,
214 operation="install",
215 )
216 command = (
217 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 "
218 "install stable-openldap-0005399828 --atomic --output yaml "
219 "--timeout 300s --namespace testk8s stable/openldap --version 1.2.2"
220 )
221 self.helm_conn._local_async_exec.assert_called_with(
222 command=command, env=self.env, raise_exception_on_error=False
223 )
224
225 # Exception test if namespace could not being created for some reason
226 self.helm_conn._namespace_exists.return_value = False
227 self.helm_conn._create_namespace.side_effect = Exception()
228
229 with self.assertRaises(K8sException):
230 await self.helm_conn.install(
231 self.cluster_uuid,
232 kdu_model,
233 self.kdu_instance,
234 atomic=True,
235 namespace=self.namespace,
236 db_dict=db_dict,
237 )
238
239 @asynctest.fail_on(active_handles=True)
240 async def test_namespace_exists(self):
241 self.helm_conn._get_namespaces = asynctest.CoroutineMock()
242
243 self.helm_conn._get_namespaces.return_value = ["testk8s", "kube-system"]
244 result = await self.helm_conn._namespace_exists(self.cluster_id, self.namespace)
245 self.helm_conn._get_namespaces.assert_called_once()
246 self.assertEqual(result, True)
247
248 self.helm_conn._get_namespaces.reset_mock()
249 result = await self.helm_conn._namespace_exists(
250 self.cluster_id, "none-exists-namespace"
251 )
252 self.helm_conn._get_namespaces.assert_called_once()
253 self.assertEqual(result, False)
254
255 @asynctest.fail_on(active_handles=True)
256 async def test_upgrade(self):
257 kdu_model = "stable/openldap:1.2.3"
258 kdu_instance = "stable-openldap-0005399828"
259 db_dict = {}
260 instance_info = {
261 "chart": "openldap-1.2.2",
262 "name": kdu_instance,
263 "namespace": self.namespace,
264 "revision": 1,
265 "status": "DEPLOYED",
266 }
267 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
268 self.helm_conn._store_status = asynctest.CoroutineMock()
269 self.helm_conn.get_instance_info = asynctest.CoroutineMock(
270 return_value=instance_info
271 )
272 # TEST-1 (--force true)
273 await self.helm_conn.upgrade(
274 self.cluster_uuid,
275 kdu_instance,
276 kdu_model,
277 atomic=True,
278 db_dict=db_dict,
279 force=True,
280 )
281 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id)
282 self.helm_conn.fs.reverse_sync.assert_has_calls(
283 [
284 asynctest.call(from_path=self.cluster_id),
285 asynctest.call(from_path=self.cluster_id),
286 ]
287 )
288 self.helm_conn._store_status.assert_called_with(
289 cluster_id=self.cluster_id,
290 kdu_instance=kdu_instance,
291 namespace=self.namespace,
292 db_dict=db_dict,
293 operation="upgrade",
294 )
295 command = (
296 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config "
297 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap "
298 "--namespace testk8s --atomic --force --output yaml --timeout 300s "
299 "--reuse-values --version 1.2.3"
300 )
301 self.helm_conn._local_async_exec.assert_called_with(
302 command=command, env=self.env, raise_exception_on_error=False
303 )
304
305 # TEST-2 (--force false)
306 await self.helm_conn.upgrade(
307 self.cluster_uuid,
308 kdu_instance,
309 kdu_model,
310 atomic=True,
311 db_dict=db_dict,
312 )
313 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id)
314 self.helm_conn.fs.reverse_sync.assert_has_calls(
315 [
316 asynctest.call(from_path=self.cluster_id),
317 asynctest.call(from_path=self.cluster_id),
318 ]
319 )
320 self.helm_conn._store_status.assert_called_with(
321 cluster_id=self.cluster_id,
322 kdu_instance=kdu_instance,
323 namespace=self.namespace,
324 db_dict=db_dict,
325 operation="upgrade",
326 )
327 command = (
328 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config "
329 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap "
330 "--namespace testk8s --atomic --output yaml --timeout 300s "
331 "--reuse-values --version 1.2.3"
332 )
333 self.helm_conn._local_async_exec.assert_called_with(
334 command=command, env=self.env, raise_exception_on_error=False
335 )
336
337 @asynctest.fail_on(active_handles=True)
338 async def test_upgrade_namespace(self):
339 kdu_model = "stable/openldap:1.2.3"
340 kdu_instance = "stable-openldap-0005399828"
341 db_dict = {}
342 instance_info = {
343 "chart": "openldap-1.2.2",
344 "name": kdu_instance,
345 "namespace": self.namespace,
346 "revision": 1,
347 "status": "DEPLOYED",
348 }
349 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
350 self.helm_conn._store_status = asynctest.CoroutineMock()
351 self.helm_conn.get_instance_info = asynctest.CoroutineMock(
352 return_value=instance_info
353 )
354
355 await self.helm_conn.upgrade(
356 self.cluster_uuid,
357 kdu_instance,
358 kdu_model,
359 atomic=True,
360 db_dict=db_dict,
361 namespace="default",
362 )
363 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id)
364 self.helm_conn.fs.reverse_sync.assert_has_calls(
365 [
366 asynctest.call(from_path=self.cluster_id),
367 asynctest.call(from_path=self.cluster_id),
368 ]
369 )
370 self.helm_conn._store_status.assert_called_with(
371 cluster_id=self.cluster_id,
372 kdu_instance=kdu_instance,
373 namespace="default",
374 db_dict=db_dict,
375 operation="upgrade",
376 )
377 command = (
378 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config "
379 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap "
380 "--namespace default --atomic --output yaml --timeout 300s "
381 "--reuse-values --version 1.2.3"
382 )
383 self.helm_conn._local_async_exec.assert_called_with(
384 command=command, env=self.env, raise_exception_on_error=False
385 )
386
387 @asynctest.fail_on(active_handles=True)
388 async def test_scale(self):
389 kdu_model = "stable/openldap:1.2.3"
390 kdu_instance = "stable-openldap-0005399828"
391 db_dict = {}
392 instance_info = {
393 "chart": "openldap-1.2.3",
394 "name": kdu_instance,
395 "namespace": self.namespace,
396 "revision": 1,
397 "status": "DEPLOYED",
398 }
399 repo_list = [
400 {
401 "name": "stable",
402 "url": "https://kubernetes-charts.storage.googleapis.com/",
403 }
404 ]
405 kdu_values = """
406 # Default values for openldap.
407 # This is a YAML-formatted file.
408 # Declare variables to be passed into your templates.
409
410 replicaCount: 1
411 dummy-app:
412 replicas: 2
413 """
414
415 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list)
416 self.helm_conn.values_kdu = asynctest.CoroutineMock(return_value=kdu_values)
417 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
418 self.helm_conn._store_status = asynctest.CoroutineMock()
419 self.helm_conn.get_instance_info = asynctest.CoroutineMock(
420 return_value=instance_info
421 )
422
423 # TEST-1
424 await self.helm_conn.scale(
425 kdu_instance,
426 2,
427 "",
428 kdu_model=kdu_model,
429 cluster_uuid=self.cluster_uuid,
430 atomic=True,
431 db_dict=db_dict,
432 )
433 command = (
434 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config "
435 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap "
436 "--namespace testk8s --atomic --output yaml --set replicaCount=2 --timeout 1800s "
437 "--reuse-values --version 1.2.3"
438 )
439 self.helm_conn._local_async_exec.assert_called_once_with(
440 command=command, env=self.env, raise_exception_on_error=False
441 )
442 # TEST-2
443 await self.helm_conn.scale(
444 kdu_instance,
445 3,
446 "dummy-app",
447 kdu_model=kdu_model,
448 cluster_uuid=self.cluster_uuid,
449 atomic=True,
450 db_dict=db_dict,
451 )
452 command = (
453 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config "
454 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap "
455 "--namespace testk8s --atomic --output yaml --set dummy-app.replicas=3 --timeout 1800s "
456 "--reuse-values --version 1.2.3"
457 )
458 self.helm_conn._local_async_exec.assert_called_with(
459 command=command, env=self.env, raise_exception_on_error=False
460 )
461 self.helm_conn.fs.reverse_sync.assert_called_with(from_path=self.cluster_id)
462 self.helm_conn._store_status.assert_called_with(
463 cluster_id=self.cluster_id,
464 kdu_instance=kdu_instance,
465 namespace=self.namespace,
466 db_dict=db_dict,
467 operation="scale",
468 )
469
470 @asynctest.fail_on(active_handles=True)
471 async def test_rollback(self):
472 kdu_instance = "stable-openldap-0005399828"
473 db_dict = {}
474 instance_info = {
475 "chart": "openldap-1.2.3",
476 "name": kdu_instance,
477 "namespace": self.namespace,
478 "revision": 2,
479 "status": "DEPLOYED",
480 }
481 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
482 self.helm_conn._store_status = asynctest.CoroutineMock()
483 self.helm_conn.get_instance_info = asynctest.CoroutineMock(
484 return_value=instance_info
485 )
486
487 await self.helm_conn.rollback(
488 self.cluster_uuid, kdu_instance=kdu_instance, revision=1, db_dict=db_dict
489 )
490 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id)
491 self.helm_conn.fs.reverse_sync.assert_called_once_with(
492 from_path=self.cluster_id
493 )
494 self.helm_conn._store_status.assert_called_with(
495 cluster_id=self.cluster_id,
496 kdu_instance=kdu_instance,
497 namespace=self.namespace,
498 db_dict=db_dict,
499 operation="rollback",
500 )
501 command = (
502 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 "
503 "rollback stable-openldap-0005399828 1 --namespace=testk8s --wait"
504 )
505 self.helm_conn._local_async_exec.assert_called_once_with(
506 command=command, env=self.env, raise_exception_on_error=False
507 )
508
509 @asynctest.fail_on(active_handles=True)
510 async def test_uninstall(self):
511 kdu_instance = "stable-openldap-0005399828"
512 instance_info = {
513 "chart": "openldap-1.2.2",
514 "name": kdu_instance,
515 "namespace": self.namespace,
516 "revision": 3,
517 "status": "DEPLOYED",
518 }
519 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
520 self.helm_conn._store_status = asynctest.CoroutineMock()
521 self.helm_conn.get_instance_info = asynctest.CoroutineMock(
522 return_value=instance_info
523 )
524
525 await self.helm_conn.uninstall(self.cluster_uuid, kdu_instance)
526 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id)
527 self.helm_conn.fs.reverse_sync.assert_called_once_with(
528 from_path=self.cluster_id
529 )
530 command = (
531 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 uninstall {} --namespace={}"
532 ).format(kdu_instance, self.namespace)
533 self.helm_conn._local_async_exec.assert_called_once_with(
534 command=command, env=self.env, raise_exception_on_error=True
535 )
536
537 @asynctest.fail_on(active_handles=True)
538 async def test_get_services(self):
539 kdu_instance = "test_services_1"
540 service = {"name": "testservice", "type": "LoadBalancer"}
541 self.helm_conn._local_async_exec_pipe = asynctest.CoroutineMock(
542 return_value=("", 0)
543 )
544 self.helm_conn._parse_services = Mock(return_value=["testservice"])
545 self.helm_conn._get_service = asynctest.CoroutineMock(return_value=service)
546
547 services = await self.helm_conn.get_services(
548 self.cluster_uuid, kdu_instance, self.namespace
549 )
550 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
551 self.helm_conn.fs.reverse_sync.assert_called_once_with(
552 from_path=self.cluster_id
553 )
554 self.helm_conn._parse_services.assert_called_once()
555 command1 = (
556 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 get manifest {} --namespace=testk8s"
557 ).format(kdu_instance)
558 command2 = "/usr/bin/kubectl get --namespace={} -f -".format(self.namespace)
559 self.helm_conn._local_async_exec_pipe.assert_called_once_with(
560 command1, command2, env=self.env, raise_exception_on_error=True
561 )
562 self.assertEqual(
563 services, [service], "Invalid service returned from get_service"
564 )
565
566 @asynctest.fail_on(active_handles=True)
567 async def test_get_service(self):
568 service_name = "service1"
569
570 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
571 await self.helm_conn.get_service(
572 self.cluster_uuid, service_name, self.namespace
573 )
574
575 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
576 self.helm_conn.fs.reverse_sync.assert_called_once_with(
577 from_path=self.cluster_id
578 )
579 command = (
580 "/usr/bin/kubectl --kubeconfig=./tmp/helm3_cluster_id/.kube/config "
581 "--namespace=testk8s get service service1 -o=yaml"
582 )
583 self.helm_conn._local_async_exec.assert_called_once_with(
584 command=command, env=self.env, raise_exception_on_error=True
585 )
586
587 @asynctest.fail_on(active_handles=True)
588 async def test_inspect_kdu(self):
589 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
590
591 kdu_model = "stable/openldap:1.2.4"
592 repo_url = "https://kubernetes-charts.storage.googleapis.com/"
593 await self.helm_conn.inspect_kdu(kdu_model, repo_url)
594
595 command = (
596 "/usr/bin/helm3 show all openldap --repo "
597 "https://kubernetes-charts.storage.googleapis.com/ "
598 "--version 1.2.4"
599 )
600 self.helm_conn._local_async_exec.assert_called_with(command=command)
601
602 @asynctest.fail_on(active_handles=True)
603 async def test_help_kdu(self):
604 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
605
606 kdu_model = "stable/openldap:1.2.4"
607 repo_url = "https://kubernetes-charts.storage.googleapis.com/"
608 await self.helm_conn.help_kdu(kdu_model, repo_url)
609
610 command = (
611 "/usr/bin/helm3 show readme openldap --repo "
612 "https://kubernetes-charts.storage.googleapis.com/ "
613 "--version 1.2.4"
614 )
615 self.helm_conn._local_async_exec.assert_called_with(command=command)
616
617 @asynctest.fail_on(active_handles=True)
618 async def test_values_kdu(self):
619 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
620
621 kdu_model = "stable/openldap:1.2.4"
622 repo_url = "https://kubernetes-charts.storage.googleapis.com/"
623 await self.helm_conn.values_kdu(kdu_model, repo_url)
624
625 command = (
626 "/usr/bin/helm3 show values openldap --repo "
627 "https://kubernetes-charts.storage.googleapis.com/ "
628 "--version 1.2.4"
629 )
630 self.helm_conn._local_async_exec.assert_called_with(command=command)
631
632 @asynctest.fail_on(active_handles=True)
633 async def test_get_values_kdu(self):
634 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
635
636 kdu_instance = "stable-openldap-0005399828"
637 await self.helm_conn.get_values_kdu(
638 kdu_instance, self.namespace, self.env["KUBECONFIG"]
639 )
640
641 command = (
642 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 get values "
643 "stable-openldap-0005399828 --namespace=testk8s --output yaml"
644 )
645 self.helm_conn._local_async_exec.assert_called_with(command=command)
646
647 @asynctest.fail_on(active_handles=True)
648 async def test_instances_list(self):
649 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
650
651 await self.helm_conn.instances_list(self.cluster_uuid)
652 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
653 self.helm_conn.fs.reverse_sync.assert_called_once_with(
654 from_path=self.cluster_id
655 )
656 command = "/usr/bin/helm3 list --all-namespaces --output yaml"
657 self.helm_conn._local_async_exec.assert_called_once_with(
658 command=command, env=self.env, raise_exception_on_error=True
659 )
660
661 @asynctest.fail_on(active_handles=True)
662 async def test_status_kdu(self):
663 kdu_instance = "stable-openldap-0005399828"
664 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0))
665
666 await self.helm_conn._status_kdu(
667 self.cluster_id, kdu_instance, self.namespace, yaml_format=True
668 )
669 command = (
670 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 status {} --namespace={} --output yaml"
671 ).format(kdu_instance, self.namespace)
672 self.helm_conn._local_async_exec.assert_called_once_with(
673 command=command,
674 env=self.env,
675 raise_exception_on_error=True,
676 show_error_log=False,
677 )
678
679 @asynctest.fail_on(active_handles=True)
680 async def test_store_status(self):
681 kdu_instance = "stable-openldap-0005399828"
682 db_dict = {}
683 status = {
684 "info": {
685 "description": "Install complete",
686 "status": {
687 "code": "1",
688 "notes": "The openldap helm chart has been installed",
689 },
690 }
691 }
692 self.helm_conn._status_kdu = asynctest.CoroutineMock(return_value=status)
693 self.helm_conn.write_app_status_to_db = asynctest.CoroutineMock(
694 return_value=status
695 )
696
697 await self.helm_conn._store_status(
698 cluster_id=self.cluster_id,
699 kdu_instance=kdu_instance,
700 namespace=self.namespace,
701 db_dict=db_dict,
702 operation="install",
703 )
704 self.helm_conn._status_kdu.assert_called_once_with(
705 cluster_id=self.cluster_id,
706 kdu_instance=kdu_instance,
707 namespace=self.namespace,
708 yaml_format=False,
709 )
710 self.helm_conn.write_app_status_to_db.assert_called_once_with(
711 db_dict=db_dict,
712 status="Install complete",
713 detailed_status=str(status),
714 operation="install",
715 )
716
717 @asynctest.fail_on(active_handles=True)
718 async def test_reset_uninstall_false(self):
719 self.helm_conn._uninstall_sw = asynctest.CoroutineMock()
720
721 await self.helm_conn.reset(self.cluster_uuid, force=False, uninstall_sw=False)
722 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
723 self.helm_conn.fs.file_delete.assert_called_once_with(
724 self.cluster_id, ignore_non_exist=True
725 )
726 self.helm_conn._uninstall_sw.assert_not_called()
727
728 @asynctest.fail_on(active_handles=True)
729 async def test_reset_uninstall(self):
730 kdu_instance = "stable-openldap-0021099429"
731 instances = [
732 {
733 "app_version": "2.4.48",
734 "chart": "openldap-1.2.3",
735 "name": kdu_instance,
736 "namespace": self.namespace,
737 "revision": "1",
738 "status": "deployed",
739 "updated": "2020-10-30 11:11:20.376744191 +0000 UTC",
740 }
741 ]
742 self.helm_conn._get_namespace = Mock(return_value=self.namespace)
743 self.helm_conn._uninstall_sw = asynctest.CoroutineMock()
744 self.helm_conn.instances_list = asynctest.CoroutineMock(return_value=instances)
745 self.helm_conn.uninstall = asynctest.CoroutineMock()
746
747 await self.helm_conn.reset(self.cluster_uuid, force=True, uninstall_sw=True)
748 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id)
749 self.helm_conn.fs.file_delete.assert_called_once_with(
750 self.cluster_id, ignore_non_exist=True
751 )
752 self.helm_conn._get_namespace.assert_called_once_with(
753 cluster_uuid=self.cluster_uuid
754 )
755 self.helm_conn.instances_list.assert_called_once_with(
756 cluster_uuid=self.cluster_uuid
757 )
758 self.helm_conn.uninstall.assert_called_once_with(
759 cluster_uuid=self.cluster_uuid, kdu_instance=kdu_instance
760 )
761 self.helm_conn._uninstall_sw.assert_called_once_with(
762 cluster_id=self.cluster_id, namespace=self.namespace
763 )
764
765 @asynctest.fail_on(active_handles=True)
766 async def test_sync_repos_add(self):
767 repo_list = [
768 {
769 "name": "stable",
770 "url": "https://kubernetes-charts.storage.googleapis.com/",
771 }
772 ]
773 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list)
774
775 def get_one_result(*args, **kwargs):
776 if args[0] == "k8sclusters":
777 return {
778 "_admin": {
779 "helm_chart_repos": ["4b5550a9-990d-4d95-8a48-1f4614d6ac9c"]
780 }
781 }
782 elif args[0] == "k8srepos":
783 return {
784 "_id": "4b5550a9-990d-4d95-8a48-1f4614d6ac9c",
785 "type": "helm-chart",
786 "name": "bitnami",
787 "url": "https://charts.bitnami.com/bitnami",
788 }
789
790 self.helm_conn.db.get_one = asynctest.Mock()
791 self.helm_conn.db.get_one.side_effect = get_one_result
792
793 self.helm_conn.repo_add = asynctest.CoroutineMock()
794 self.helm_conn.repo_remove = asynctest.CoroutineMock()
795
796 deleted_repo_list, added_repo_dict = await self.helm_conn.synchronize_repos(
797 self.cluster_uuid
798 )
799 self.helm_conn.repo_remove.assert_not_called()
800 self.helm_conn.repo_add.assert_called_once_with(
801 self.cluster_uuid, "bitnami", "https://charts.bitnami.com/bitnami"
802 )
803 self.assertEqual(deleted_repo_list, [], "Deleted repo list should be empty")
804 self.assertEqual(
805 added_repo_dict,
806 {"4b5550a9-990d-4d95-8a48-1f4614d6ac9c": "bitnami"},
807 "Repos added should include only one bitnami",
808 )
809
810 @asynctest.fail_on(active_handles=True)
811 async def test_sync_repos_delete(self):
812 repo_list = [
813 {
814 "name": "stable",
815 "url": "https://kubernetes-charts.storage.googleapis.com/",
816 },
817 {"name": "bitnami", "url": "https://charts.bitnami.com/bitnami"},
818 ]
819 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list)
820
821 def get_one_result(*args, **kwargs):
822 if args[0] == "k8sclusters":
823 return {"_admin": {"helm_chart_repos": []}}
824
825 self.helm_conn.db.get_one = asynctest.Mock()
826 self.helm_conn.db.get_one.side_effect = get_one_result
827
828 self.helm_conn.repo_add = asynctest.CoroutineMock()
829 self.helm_conn.repo_remove = asynctest.CoroutineMock()
830
831 deleted_repo_list, added_repo_dict = await self.helm_conn.synchronize_repos(
832 self.cluster_uuid
833 )
834 self.helm_conn.repo_add.assert_not_called()
835 self.helm_conn.repo_remove.assert_called_once_with(self.cluster_uuid, "bitnami")
836 self.assertEqual(
837 deleted_repo_list, ["bitnami"], "Deleted repo list should be bitnami"
838 )
839 self.assertEqual(added_repo_dict, {}, "No repos should be added")