Coverage for n2vc/tests/unit/test_k8s_helm3_conn.py: 100%

335 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-05-07 06:04 +0000

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 

18import asynctest 

19import logging 

20 

21from asynctest.mock import Mock, patch 

22from osm_common.dbmemory import DbMemory 

23from osm_common.fslocal import FsLocal 

24from n2vc.k8s_helm3_conn import K8sHelm3Connector, K8sException 

25 

26__author__ = "Isabel Lloret <illoret@indra.es>" 

27 

28 

29class 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.helm_conn._repo_to_oci_url = Mock(return_value=None) 

176 self.kdu_instance = "stable-openldap-0005399828" 

177 self.helm_conn.generate_kdu_instance_name = Mock(return_value=self.kdu_instance) 

178 self.helm_conn._get_namespaces = asynctest.CoroutineMock(return_value=[]) 

179 self.helm_conn._namespace_exists = asynctest.CoroutineMock( 

180 side_effect=self.helm_conn._namespace_exists 

181 ) 

182 self.helm_conn._create_namespace = asynctest.CoroutineMock() 

183 

184 await self.helm_conn.install( 

185 self.cluster_uuid, 

186 kdu_model, 

187 self.kdu_instance, 

188 atomic=True, 

189 namespace=self.namespace, 

190 db_dict=db_dict, 

191 ) 

192 

193 self.helm_conn._namespace_exists.assert_called_once() 

194 self.helm_conn._get_namespaces.assert_called_once() 

195 self.helm_conn._create_namespace.assert_called_once_with( 

196 self.cluster_id, self.namespace 

197 ) 

198 self.helm_conn.fs.sync.assert_has_calls( 

199 [ 

200 asynctest.call(from_path=self.cluster_id), 

201 asynctest.call(from_path=self.cluster_id), 

202 ] 

203 ) 

204 self.helm_conn.fs.reverse_sync.assert_has_calls( 

205 [ 

206 asynctest.call(from_path=self.cluster_id), 

207 asynctest.call(from_path=self.cluster_id), 

208 ] 

209 ) 

210 self.helm_conn._store_status.assert_called_with( 

211 cluster_id=self.cluster_id, 

212 kdu_instance=kdu_instance, 

213 namespace=self.namespace, 

214 db_dict=db_dict, 

215 operation="install", 

216 ) 

217 command = ( 

218 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 " 

219 "install stable-openldap-0005399828 --atomic --output yaml " 

220 "--timeout 300s --namespace testk8s stable/openldap --version 1.2.2" 

221 ) 

222 self.helm_conn._local_async_exec.assert_called_with( 

223 command=command, env=self.env, raise_exception_on_error=False 

224 ) 

225 

226 # Exception test if namespace could not being created for some reason 

227 self.helm_conn._namespace_exists.return_value = False 

228 self.helm_conn._create_namespace.side_effect = Exception() 

229 

230 with self.assertRaises(K8sException): 

231 await self.helm_conn.install( 

232 self.cluster_uuid, 

233 kdu_model, 

234 self.kdu_instance, 

235 atomic=True, 

236 namespace=self.namespace, 

237 db_dict=db_dict, 

238 ) 

239 

240 @asynctest.fail_on(active_handles=True) 

241 async def test_namespace_exists(self): 

242 self.helm_conn._get_namespaces = asynctest.CoroutineMock() 

243 

244 self.helm_conn._get_namespaces.return_value = ["testk8s", "kube-system"] 

245 result = await self.helm_conn._namespace_exists(self.cluster_id, self.namespace) 

246 self.helm_conn._get_namespaces.assert_called_once() 

247 self.assertEqual(result, True) 

248 

249 self.helm_conn._get_namespaces.reset_mock() 

250 result = await self.helm_conn._namespace_exists( 

251 self.cluster_id, "none-exists-namespace" 

252 ) 

253 self.helm_conn._get_namespaces.assert_called_once() 

254 self.assertEqual(result, False) 

255 

256 @asynctest.fail_on(active_handles=True) 

257 async def test_upgrade(self): 

258 kdu_model = "stable/openldap:1.2.3" 

259 kdu_instance = "stable-openldap-0005399828" 

260 db_dict = {} 

261 instance_info = { 

262 "chart": "openldap-1.2.2", 

263 "name": kdu_instance, 

264 "namespace": self.namespace, 

265 "revision": 1, 

266 "status": "DEPLOYED", 

267 } 

268 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

269 self.helm_conn._store_status = asynctest.CoroutineMock() 

270 self.helm_conn._repo_to_oci_url = Mock(return_value=None) 

271 self.helm_conn.get_instance_info = asynctest.CoroutineMock( 

272 return_value=instance_info 

273 ) 

274 # TEST-1 (--force true) 

275 await self.helm_conn.upgrade( 

276 self.cluster_uuid, 

277 kdu_instance, 

278 kdu_model, 

279 atomic=True, 

280 db_dict=db_dict, 

281 force=True, 

282 ) 

283 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id) 

284 self.helm_conn.fs.reverse_sync.assert_has_calls( 

285 [ 

286 asynctest.call(from_path=self.cluster_id), 

287 asynctest.call(from_path=self.cluster_id), 

288 ] 

289 ) 

290 self.helm_conn._store_status.assert_called_with( 

291 cluster_id=self.cluster_id, 

292 kdu_instance=kdu_instance, 

293 namespace=self.namespace, 

294 db_dict=db_dict, 

295 operation="upgrade", 

296 ) 

297 command = ( 

298 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config " 

299 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap " 

300 "--namespace testk8s --atomic --force --output yaml --timeout 300s " 

301 "--reuse-values --version 1.2.3" 

302 ) 

303 self.helm_conn._local_async_exec.assert_called_with( 

304 command=command, env=self.env, raise_exception_on_error=False 

305 ) 

306 

307 # TEST-2 (--force false) 

308 await self.helm_conn.upgrade( 

309 self.cluster_uuid, 

310 kdu_instance, 

311 kdu_model, 

312 atomic=True, 

313 db_dict=db_dict, 

314 ) 

315 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id) 

316 self.helm_conn.fs.reverse_sync.assert_has_calls( 

317 [ 

318 asynctest.call(from_path=self.cluster_id), 

319 asynctest.call(from_path=self.cluster_id), 

320 ] 

321 ) 

322 self.helm_conn._store_status.assert_called_with( 

323 cluster_id=self.cluster_id, 

324 kdu_instance=kdu_instance, 

325 namespace=self.namespace, 

326 db_dict=db_dict, 

327 operation="upgrade", 

328 ) 

329 command = ( 

330 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config " 

331 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap " 

332 "--namespace testk8s --atomic --output yaml --timeout 300s " 

333 "--reuse-values --version 1.2.3" 

334 ) 

335 self.helm_conn._local_async_exec.assert_called_with( 

336 command=command, env=self.env, raise_exception_on_error=False 

337 ) 

338 

339 @asynctest.fail_on(active_handles=True) 

340 async def test_upgrade_namespace(self): 

341 kdu_model = "stable/openldap:1.2.3" 

342 kdu_instance = "stable-openldap-0005399828" 

343 db_dict = {} 

344 instance_info = { 

345 "chart": "openldap-1.2.2", 

346 "name": kdu_instance, 

347 "namespace": self.namespace, 

348 "revision": 1, 

349 "status": "DEPLOYED", 

350 } 

351 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

352 self.helm_conn._store_status = asynctest.CoroutineMock() 

353 self.helm_conn._repo_to_oci_url = Mock(return_value=None) 

354 self.helm_conn.get_instance_info = asynctest.CoroutineMock( 

355 return_value=instance_info 

356 ) 

357 

358 await self.helm_conn.upgrade( 

359 self.cluster_uuid, 

360 kdu_instance, 

361 kdu_model, 

362 atomic=True, 

363 db_dict=db_dict, 

364 namespace="default", 

365 ) 

366 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id) 

367 self.helm_conn.fs.reverse_sync.assert_has_calls( 

368 [ 

369 asynctest.call(from_path=self.cluster_id), 

370 asynctest.call(from_path=self.cluster_id), 

371 ] 

372 ) 

373 self.helm_conn._store_status.assert_called_with( 

374 cluster_id=self.cluster_id, 

375 kdu_instance=kdu_instance, 

376 namespace="default", 

377 db_dict=db_dict, 

378 operation="upgrade", 

379 ) 

380 command = ( 

381 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config " 

382 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap " 

383 "--namespace default --atomic --output yaml --timeout 300s " 

384 "--reuse-values --version 1.2.3" 

385 ) 

386 self.helm_conn._local_async_exec.assert_called_with( 

387 command=command, env=self.env, raise_exception_on_error=False 

388 ) 

389 

390 @asynctest.fail_on(active_handles=True) 

391 async def test_scale(self): 

392 kdu_model = "stable/openldap:1.2.3" 

393 kdu_instance = "stable-openldap-0005399828" 

394 db_dict = {} 

395 instance_info = { 

396 "chart": "openldap-1.2.3", 

397 "name": kdu_instance, 

398 "namespace": self.namespace, 

399 "revision": 1, 

400 "status": "DEPLOYED", 

401 } 

402 repo_list = [ 

403 { 

404 "name": "stable", 

405 "url": "https://kubernetes-charts.storage.googleapis.com/", 

406 } 

407 ] 

408 kdu_values = """ 

409 # Default values for openldap. 

410 # This is a YAML-formatted file. 

411 # Declare variables to be passed into your templates. 

412 

413 replicaCount: 1 

414 dummy-app: 

415 replicas: 2 

416 """ 

417 

418 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list) 

419 self.helm_conn.values_kdu = asynctest.CoroutineMock(return_value=kdu_values) 

420 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

421 self.helm_conn._store_status = asynctest.CoroutineMock() 

422 self.helm_conn._repo_to_oci_url = Mock(return_value=None) 

423 self.helm_conn.get_instance_info = asynctest.CoroutineMock( 

424 return_value=instance_info 

425 ) 

426 

427 # TEST-1 

428 await self.helm_conn.scale( 

429 kdu_instance, 

430 2, 

431 "", 

432 kdu_model=kdu_model, 

433 cluster_uuid=self.cluster_uuid, 

434 atomic=True, 

435 db_dict=db_dict, 

436 ) 

437 command = ( 

438 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config " 

439 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap " 

440 "--namespace testk8s --atomic --output yaml --set replicaCount=2 --timeout 1800s " 

441 "--reuse-values --version 1.2.3" 

442 ) 

443 self.helm_conn._local_async_exec.assert_called_with( 

444 command=command, env=self.env, raise_exception_on_error=False 

445 ) 

446 # TEST-2 

447 await self.helm_conn.scale( 

448 kdu_instance, 

449 3, 

450 "dummy-app", 

451 kdu_model=kdu_model, 

452 cluster_uuid=self.cluster_uuid, 

453 atomic=True, 

454 db_dict=db_dict, 

455 ) 

456 command = ( 

457 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config " 

458 "/usr/bin/helm3 upgrade stable-openldap-0005399828 stable/openldap " 

459 "--namespace testk8s --atomic --output yaml --set dummy-app.replicas=3 --timeout 1800s " 

460 "--reuse-values --version 1.2.3" 

461 ) 

462 self.helm_conn._local_async_exec.assert_called_with( 

463 command=command, env=self.env, raise_exception_on_error=False 

464 ) 

465 self.helm_conn.fs.reverse_sync.assert_called_with(from_path=self.cluster_id) 

466 self.helm_conn._store_status.assert_called_with( 

467 cluster_id=self.cluster_id, 

468 kdu_instance=kdu_instance, 

469 namespace=self.namespace, 

470 db_dict=db_dict, 

471 operation="scale", 

472 ) 

473 

474 @asynctest.fail_on(active_handles=True) 

475 async def test_rollback(self): 

476 kdu_instance = "stable-openldap-0005399828" 

477 db_dict = {} 

478 instance_info = { 

479 "chart": "openldap-1.2.3", 

480 "name": kdu_instance, 

481 "namespace": self.namespace, 

482 "revision": 2, 

483 "status": "DEPLOYED", 

484 } 

485 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

486 self.helm_conn._store_status = asynctest.CoroutineMock() 

487 self.helm_conn.get_instance_info = asynctest.CoroutineMock( 

488 return_value=instance_info 

489 ) 

490 

491 await self.helm_conn.rollback( 

492 self.cluster_uuid, kdu_instance=kdu_instance, revision=1, db_dict=db_dict 

493 ) 

494 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id) 

495 self.helm_conn.fs.reverse_sync.assert_called_once_with( 

496 from_path=self.cluster_id 

497 ) 

498 self.helm_conn._store_status.assert_called_with( 

499 cluster_id=self.cluster_id, 

500 kdu_instance=kdu_instance, 

501 namespace=self.namespace, 

502 db_dict=db_dict, 

503 operation="rollback", 

504 ) 

505 command = ( 

506 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 " 

507 "rollback stable-openldap-0005399828 1 --namespace=testk8s --wait" 

508 ) 

509 self.helm_conn._local_async_exec.assert_called_once_with( 

510 command=command, env=self.env, raise_exception_on_error=False 

511 ) 

512 

513 @asynctest.fail_on(active_handles=True) 

514 async def test_uninstall(self): 

515 kdu_instance = "stable-openldap-0005399828" 

516 instance_info = { 

517 "chart": "openldap-1.2.2", 

518 "name": kdu_instance, 

519 "namespace": self.namespace, 

520 "revision": 3, 

521 "status": "DEPLOYED", 

522 } 

523 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

524 self.helm_conn._store_status = asynctest.CoroutineMock() 

525 self.helm_conn.get_instance_info = asynctest.CoroutineMock( 

526 return_value=instance_info 

527 ) 

528 

529 await self.helm_conn.uninstall(self.cluster_uuid, kdu_instance) 

530 self.helm_conn.fs.sync.assert_called_with(from_path=self.cluster_id) 

531 self.helm_conn.fs.reverse_sync.assert_called_once_with( 

532 from_path=self.cluster_id 

533 ) 

534 command = ( 

535 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 uninstall {} --namespace={}" 

536 ).format(kdu_instance, self.namespace) 

537 self.helm_conn._local_async_exec.assert_called_once_with( 

538 command=command, env=self.env, raise_exception_on_error=True 

539 ) 

540 

541 @asynctest.fail_on(active_handles=True) 

542 async def test_get_services(self): 

543 kdu_instance = "test_services_1" 

544 service = {"name": "testservice", "type": "LoadBalancer"} 

545 self.helm_conn._local_async_exec_pipe = asynctest.CoroutineMock( 

546 return_value=("", 0) 

547 ) 

548 self.helm_conn._parse_services = Mock(return_value=["testservice"]) 

549 self.helm_conn._get_service = asynctest.CoroutineMock(return_value=service) 

550 

551 services = await self.helm_conn.get_services( 

552 self.cluster_uuid, kdu_instance, self.namespace 

553 ) 

554 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) 

555 self.helm_conn.fs.reverse_sync.assert_called_once_with( 

556 from_path=self.cluster_id 

557 ) 

558 self.helm_conn._parse_services.assert_called_once() 

559 command1 = ( 

560 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 get manifest {} --namespace=testk8s" 

561 ).format(kdu_instance) 

562 command2 = "/usr/bin/kubectl get --namespace={} -f -".format(self.namespace) 

563 self.helm_conn._local_async_exec_pipe.assert_called_once_with( 

564 command1, command2, env=self.env, raise_exception_on_error=True 

565 ) 

566 self.assertEqual( 

567 services, [service], "Invalid service returned from get_service" 

568 ) 

569 

570 @asynctest.fail_on(active_handles=True) 

571 async def test_get_service(self): 

572 service_name = "service1" 

573 

574 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

575 await self.helm_conn.get_service( 

576 self.cluster_uuid, service_name, self.namespace 

577 ) 

578 

579 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) 

580 self.helm_conn.fs.reverse_sync.assert_called_once_with( 

581 from_path=self.cluster_id 

582 ) 

583 command = ( 

584 "/usr/bin/kubectl --kubeconfig=./tmp/helm3_cluster_id/.kube/config " 

585 "--namespace=testk8s get service service1 -o=yaml" 

586 ) 

587 self.helm_conn._local_async_exec.assert_called_once_with( 

588 command=command, env=self.env, raise_exception_on_error=True 

589 ) 

590 

591 @asynctest.fail_on(active_handles=True) 

592 async def test_inspect_kdu(self): 

593 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

594 

595 kdu_model = "stable/openldap:1.2.4" 

596 repo_url = "https://kubernetes-charts.storage.googleapis.com/" 

597 await self.helm_conn.inspect_kdu(kdu_model, repo_url) 

598 

599 command = ( 

600 "/usr/bin/helm3 show all openldap --repo " 

601 "https://kubernetes-charts.storage.googleapis.com/ " 

602 "--version 1.2.4" 

603 ) 

604 self.helm_conn._local_async_exec.assert_called_with(command=command) 

605 

606 @asynctest.fail_on(active_handles=True) 

607 async def test_help_kdu(self): 

608 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

609 

610 kdu_model = "stable/openldap:1.2.4" 

611 repo_url = "https://kubernetes-charts.storage.googleapis.com/" 

612 await self.helm_conn.help_kdu(kdu_model, repo_url) 

613 

614 command = ( 

615 "/usr/bin/helm3 show readme openldap --repo " 

616 "https://kubernetes-charts.storage.googleapis.com/ " 

617 "--version 1.2.4" 

618 ) 

619 self.helm_conn._local_async_exec.assert_called_with(command=command) 

620 

621 @asynctest.fail_on(active_handles=True) 

622 async def test_values_kdu(self): 

623 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

624 

625 kdu_model = "stable/openldap:1.2.4" 

626 repo_url = "https://kubernetes-charts.storage.googleapis.com/" 

627 await self.helm_conn.values_kdu(kdu_model, repo_url) 

628 

629 command = ( 

630 "/usr/bin/helm3 show values openldap --repo " 

631 "https://kubernetes-charts.storage.googleapis.com/ " 

632 "--version 1.2.4" 

633 ) 

634 self.helm_conn._local_async_exec.assert_called_with(command=command) 

635 

636 @asynctest.fail_on(active_handles=True) 

637 async def test_get_values_kdu(self): 

638 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

639 

640 kdu_instance = "stable-openldap-0005399828" 

641 await self.helm_conn.get_values_kdu( 

642 kdu_instance, self.namespace, self.env["KUBECONFIG"] 

643 ) 

644 

645 command = ( 

646 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 get values " 

647 "stable-openldap-0005399828 --namespace=testk8s --output yaml" 

648 ) 

649 self.helm_conn._local_async_exec.assert_called_with(command=command) 

650 

651 @asynctest.fail_on(active_handles=True) 

652 async def test_instances_list(self): 

653 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

654 

655 await self.helm_conn.instances_list(self.cluster_uuid) 

656 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) 

657 self.helm_conn.fs.reverse_sync.assert_called_once_with( 

658 from_path=self.cluster_id 

659 ) 

660 command = "/usr/bin/helm3 list --all-namespaces --output yaml" 

661 self.helm_conn._local_async_exec.assert_called_once_with( 

662 command=command, env=self.env, raise_exception_on_error=True 

663 ) 

664 

665 @asynctest.fail_on(active_handles=True) 

666 async def test_status_kdu(self): 

667 kdu_instance = "stable-openldap-0005399828" 

668 self.helm_conn._local_async_exec = asynctest.CoroutineMock(return_value=("", 0)) 

669 

670 await self.helm_conn._status_kdu( 

671 self.cluster_id, kdu_instance, self.namespace, yaml_format=True 

672 ) 

673 command = ( 

674 "env KUBECONFIG=./tmp/helm3_cluster_id/.kube/config /usr/bin/helm3 status {} --namespace={} --output yaml" 

675 ).format(kdu_instance, self.namespace) 

676 self.helm_conn._local_async_exec.assert_called_once_with( 

677 command=command, 

678 env=self.env, 

679 raise_exception_on_error=True, 

680 show_error_log=False, 

681 ) 

682 

683 @asynctest.fail_on(active_handles=True) 

684 async def test_store_status(self): 

685 kdu_instance = "stable-openldap-0005399828" 

686 db_dict = {} 

687 status = { 

688 "info": { 

689 "description": "Install complete", 

690 "status": { 

691 "code": "1", 

692 "notes": "The openldap helm chart has been installed", 

693 }, 

694 } 

695 } 

696 self.helm_conn._status_kdu = asynctest.CoroutineMock(return_value=status) 

697 self.helm_conn.write_app_status_to_db = asynctest.CoroutineMock( 

698 return_value=status 

699 ) 

700 

701 await self.helm_conn._store_status( 

702 cluster_id=self.cluster_id, 

703 kdu_instance=kdu_instance, 

704 namespace=self.namespace, 

705 db_dict=db_dict, 

706 operation="install", 

707 ) 

708 self.helm_conn._status_kdu.assert_called_once_with( 

709 cluster_id=self.cluster_id, 

710 kdu_instance=kdu_instance, 

711 namespace=self.namespace, 

712 yaml_format=False, 

713 ) 

714 self.helm_conn.write_app_status_to_db.assert_called_once_with( 

715 db_dict=db_dict, 

716 status="Install complete", 

717 detailed_status=str(status), 

718 operation="install", 

719 ) 

720 

721 @asynctest.fail_on(active_handles=True) 

722 async def test_reset_uninstall_false(self): 

723 self.helm_conn._uninstall_sw = asynctest.CoroutineMock() 

724 

725 await self.helm_conn.reset(self.cluster_uuid, force=False, uninstall_sw=False) 

726 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) 

727 self.helm_conn.fs.file_delete.assert_called_once_with( 

728 self.cluster_id, ignore_non_exist=True 

729 ) 

730 self.helm_conn._uninstall_sw.assert_not_called() 

731 

732 @asynctest.fail_on(active_handles=True) 

733 async def test_reset_uninstall(self): 

734 kdu_instance = "stable-openldap-0021099429" 

735 instances = [ 

736 { 

737 "app_version": "2.4.48", 

738 "chart": "openldap-1.2.3", 

739 "name": kdu_instance, 

740 "namespace": self.namespace, 

741 "revision": "1", 

742 "status": "deployed", 

743 "updated": "2020-10-30 11:11:20.376744191 +0000 UTC", 

744 } 

745 ] 

746 self.helm_conn._get_namespace = Mock(return_value=self.namespace) 

747 self.helm_conn._uninstall_sw = asynctest.CoroutineMock() 

748 self.helm_conn.instances_list = asynctest.CoroutineMock(return_value=instances) 

749 self.helm_conn.uninstall = asynctest.CoroutineMock() 

750 

751 await self.helm_conn.reset(self.cluster_uuid, force=True, uninstall_sw=True) 

752 self.helm_conn.fs.sync.assert_called_once_with(from_path=self.cluster_id) 

753 self.helm_conn.fs.file_delete.assert_called_once_with( 

754 self.cluster_id, ignore_non_exist=True 

755 ) 

756 self.helm_conn._get_namespace.assert_called_once_with( 

757 cluster_uuid=self.cluster_uuid 

758 ) 

759 self.helm_conn.instances_list.assert_called_once_with( 

760 cluster_uuid=self.cluster_uuid 

761 ) 

762 self.helm_conn.uninstall.assert_called_once_with( 

763 cluster_uuid=self.cluster_uuid, kdu_instance=kdu_instance 

764 ) 

765 self.helm_conn._uninstall_sw.assert_called_once_with( 

766 cluster_id=self.cluster_id, namespace=self.namespace 

767 ) 

768 

769 @asynctest.fail_on(active_handles=True) 

770 async def test_sync_repos_add(self): 

771 repo_list = [ 

772 { 

773 "name": "stable", 

774 "url": "https://kubernetes-charts.storage.googleapis.com/", 

775 } 

776 ] 

777 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list) 

778 

779 def get_one_result(*args, **kwargs): 

780 if args[0] == "k8sclusters": 

781 return { 

782 "_admin": { 

783 "helm_chart_repos": ["4b5550a9-990d-4d95-8a48-1f4614d6ac9c"] 

784 } 

785 } 

786 elif args[0] == "k8srepos": 

787 return { 

788 "_id": "4b5550a9-990d-4d95-8a48-1f4614d6ac9c", 

789 "type": "helm-chart", 

790 "name": "bitnami", 

791 "url": "https://charts.bitnami.com/bitnami", 

792 } 

793 

794 self.helm_conn.db.get_one = asynctest.Mock() 

795 self.helm_conn.db.get_one.side_effect = get_one_result 

796 

797 self.helm_conn.repo_add = asynctest.CoroutineMock() 

798 self.helm_conn.repo_remove = asynctest.CoroutineMock() 

799 

800 deleted_repo_list, added_repo_dict = await self.helm_conn.synchronize_repos( 

801 self.cluster_uuid 

802 ) 

803 self.helm_conn.repo_remove.assert_not_called() 

804 self.helm_conn.repo_add.assert_called_once_with( 

805 self.cluster_uuid, 

806 "bitnami", 

807 "https://charts.bitnami.com/bitnami", 

808 cert=None, 

809 user=None, 

810 password=None, 

811 oci=False, 

812 ) 

813 self.assertEqual(deleted_repo_list, [], "Deleted repo list should be empty") 

814 self.assertEqual( 

815 added_repo_dict, 

816 {"4b5550a9-990d-4d95-8a48-1f4614d6ac9c": "bitnami"}, 

817 "Repos added should include only one bitnami", 

818 ) 

819 

820 @asynctest.fail_on(active_handles=True) 

821 async def test_sync_repos_delete(self): 

822 repo_list = [ 

823 { 

824 "name": "stable", 

825 "url": "https://kubernetes-charts.storage.googleapis.com/", 

826 }, 

827 {"name": "bitnami", "url": "https://charts.bitnami.com/bitnami"}, 

828 ] 

829 self.helm_conn.repo_list = asynctest.CoroutineMock(return_value=repo_list) 

830 

831 def get_one_result(*args, **kwargs): 

832 if args[0] == "k8sclusters": 

833 return {"_admin": {"helm_chart_repos": []}} 

834 

835 self.helm_conn.db.get_one = asynctest.Mock() 

836 self.helm_conn.db.get_one.side_effect = get_one_result 

837 

838 self.helm_conn.repo_add = asynctest.CoroutineMock() 

839 self.helm_conn.repo_remove = asynctest.CoroutineMock() 

840 

841 deleted_repo_list, added_repo_dict = await self.helm_conn.synchronize_repos( 

842 self.cluster_uuid 

843 ) 

844 self.helm_conn.repo_add.assert_not_called() 

845 self.helm_conn.repo_remove.assert_called_once_with(self.cluster_uuid, "bitnami") 

846 self.assertEqual( 

847 deleted_repo_list, ["bitnami"], "Deleted repo list should be bitnami" 

848 ) 

849 self.assertEqual(added_repo_dict, {}, "No repos should be added")