360895f0be70eb41544248f9aa9cbfcd1b01df84
[osm/devops.git] / installers / charm / nbi / tests / test_pod_spec.py
1 #!/usr/bin/env python3
2 # Copyright 2020 Canonical Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15 #
16 # For those usages not covered by the Apache License, Version 2.0 please
17 # contact: legal@canonical.com
18 #
19 # To get in touch with the maintainers, please contact:
20 # osm-charmers@lists.launchpad.net
21 ##
22
23 from typing import NoReturn
24 import unittest
25
26 import pod_spec
27
28
29 class TestPodSpec(unittest.TestCase):
30 """Pod spec unit tests."""
31
32 def test_make_pod_ports(self) -> NoReturn:
33 """Testing make pod ports."""
34 port = 9999
35
36 expected_result = [
37 {
38 "name": "nbi",
39 "containerPort": port,
40 "protocol": "TCP",
41 }
42 ]
43
44 pod_ports = pod_spec._make_pod_ports(port)
45
46 self.assertListEqual(expected_result, pod_ports)
47
48 def test_make_pod_envconfig_without_keystone(self) -> NoReturn:
49 """Teting make pod envconfig without Keystone."""
50 config = {
51 "enable_test": False,
52 "database_commonkey": "commonkey",
53 "log_level": "DEBUG",
54 "auth_backend": "internal",
55 }
56 relation_state = {
57 "message_host": "kafka",
58 "message_port": 9090,
59 "database_uri": "mongodb://mongo",
60 "prometheus_host": "prometheus",
61 "prometheus_port": 9082,
62 }
63
64 expected_result = {
65 "ALLOW_ANONYMOUS_LOGIN": "yes",
66 "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
67 "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
68 "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
69 "OSMNBI_MESSAGE_DRIVER": "kafka",
70 "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
71 "OSMNBI_DATABASE_DRIVER": "mongo",
72 "OSMNBI_DATABASE_URI": relation_state["database_uri"],
73 "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
74 "OSMNBI_STORAGE_DRIVER": "mongo",
75 "OSMNBI_STORAGE_PATH": "/app/storage",
76 "OSMNBI_STORAGE_COLLECTION": "files",
77 "OSMNBI_STORAGE_URI": relation_state["database_uri"],
78 "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
79 "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
80 "OSMNBI_LOG_LEVEL": config["log_level"],
81 "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
82 }
83
84 pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
85
86 self.assertDictEqual(expected_result, pod_envconfig)
87
88 def test_make_pod_envconfig_with_keystone(self) -> NoReturn:
89 """Teting make pod envconfig with Keystone."""
90 config = {
91 "enable_test": False,
92 "database_commonkey": "commonkey",
93 "log_level": "DEBUG",
94 "auth_backend": "keystone",
95 }
96 relation_state = {
97 "message_host": "kafka",
98 "message_port": 9090,
99 "database_uri": "mongodb://mongo",
100 "prometheus_host": "prometheus",
101 "prometheus_port": 9082,
102 "keystone_host": "keystone",
103 "keystone_port": 5000,
104 "keystone_user_domain_name": "user_domain",
105 "keystone_project_domain_name": "project_domain",
106 "keystone_username": "username",
107 "keystone_password": "password",
108 "keystone_service": "service",
109 }
110
111 expected_result = {
112 "ALLOW_ANONYMOUS_LOGIN": "yes",
113 "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
114 "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
115 "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
116 "OSMNBI_MESSAGE_DRIVER": "kafka",
117 "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
118 "OSMNBI_DATABASE_DRIVER": "mongo",
119 "OSMNBI_DATABASE_URI": relation_state["database_uri"],
120 "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
121 "OSMNBI_STORAGE_DRIVER": "mongo",
122 "OSMNBI_STORAGE_PATH": "/app/storage",
123 "OSMNBI_STORAGE_COLLECTION": "files",
124 "OSMNBI_STORAGE_URI": relation_state["database_uri"],
125 "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
126 "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
127 "OSMNBI_LOG_LEVEL": config["log_level"],
128 "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
129 "OSMNBI_AUTHENTICATION_AUTH_URL": relation_state["keystone_host"],
130 "OSMNBI_AUTHENTICATION_AUTH_PORT": relation_state["keystone_port"],
131 "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": relation_state[
132 "keystone_user_domain_name"
133 ],
134 "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": relation_state[
135 "keystone_project_domain_name"
136 ],
137 "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": relation_state[
138 "keystone_username"
139 ],
140 "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": relation_state[
141 "keystone_password"
142 ],
143 "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": relation_state["keystone_service"],
144 }
145
146 pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
147
148 self.assertDictEqual(expected_result, pod_envconfig)
149
150 def test_make_pod_envconfig_wrong_auth_backend(self) -> NoReturn:
151 """Teting make pod envconfig with wrong auth_backend."""
152 config = {
153 "enable_test": False,
154 "database_commonkey": "commonkey",
155 "log_level": "DEBUG",
156 "auth_backend": "kerberos",
157 }
158 relation_state = {
159 "message_host": "kafka",
160 "message_port": 9090,
161 "database_uri": "mongodb://mongo",
162 "prometheus_host": "prometheus",
163 "prometheus_port": 9082,
164 "keystone_host": "keystone",
165 "keystone_port": 5000,
166 "keystone_user_domain_name": "user_domain",
167 "keystone_project_domain_name": "project_domain",
168 "keystone_username": "username",
169 "keystone_password": "password",
170 "keystone_service": "service",
171 }
172
173 with self.assertRaises(ValueError) as exc:
174 pod_spec._make_pod_envconfig(config, relation_state)
175
176 self.assertTrue(
177 "auth_backend needs to be either internal or keystone" in str(exc.exception)
178 )
179
180 def test_make_pod_ingress_resources_without_site_url(self) -> NoReturn:
181 """Testing make pod ingress resources without site_url."""
182 config = {"site_url": ""}
183 app_name = "nbi"
184 port = 9999
185
186 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
187 config, app_name, port
188 )
189
190 self.assertIsNone(pod_ingress_resources)
191
192 def test_make_pod_ingress_resources(self) -> NoReturn:
193 """Testing make pod ingress resources."""
194 config = {
195 "site_url": "http://nbi",
196 "max_file_size": 0,
197 "ingress_whitelist_source_range": "",
198 }
199 app_name = "nbi"
200 port = 9999
201
202 expected_result = [
203 {
204 "name": f"{app_name}-ingress",
205 "annotations": {
206 "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
207 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
208 "nginx.ingress.kubernetes.io/ssl-redirect": "false",
209 },
210 "spec": {
211 "rules": [
212 {
213 "host": app_name,
214 "http": {
215 "paths": [
216 {
217 "path": "/",
218 "backend": {
219 "serviceName": app_name,
220 "servicePort": port,
221 },
222 }
223 ]
224 },
225 }
226 ]
227 },
228 }
229 ]
230
231 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
232 config, app_name, port
233 )
234
235 self.assertListEqual(expected_result, pod_ingress_resources)
236
237 def test_make_pod_ingress_resources_with_whitelist_source_range(self) -> NoReturn:
238 """Testing make pod ingress resources with whitelist_source_range."""
239 config = {
240 "site_url": "http://nbi",
241 "max_file_size": 0,
242 "ingress_whitelist_source_range": "0.0.0.0/0",
243 }
244 app_name = "nbi"
245 port = 9999
246
247 expected_result = [
248 {
249 "name": f"{app_name}-ingress",
250 "annotations": {
251 "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
252 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
253 "nginx.ingress.kubernetes.io/ssl-redirect": "false",
254 "nginx.ingress.kubernetes.io/whitelist-source-range": config[
255 "ingress_whitelist_source_range"
256 ],
257 },
258 "spec": {
259 "rules": [
260 {
261 "host": app_name,
262 "http": {
263 "paths": [
264 {
265 "path": "/",
266 "backend": {
267 "serviceName": app_name,
268 "servicePort": port,
269 },
270 }
271 ]
272 },
273 }
274 ]
275 },
276 }
277 ]
278
279 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
280 config, app_name, port
281 )
282
283 self.assertListEqual(expected_result, pod_ingress_resources)
284
285 def test_make_pod_ingress_resources_with_https(self) -> NoReturn:
286 """Testing make pod ingress resources with HTTPs."""
287 config = {
288 "site_url": "https://nbi",
289 "max_file_size": 0,
290 "ingress_whitelist_source_range": "",
291 "tls_secret_name": "",
292 }
293 app_name = "nbi"
294 port = 9999
295
296 expected_result = [
297 {
298 "name": f"{app_name}-ingress",
299 "annotations": {
300 "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
301 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
302 },
303 "spec": {
304 "rules": [
305 {
306 "host": app_name,
307 "http": {
308 "paths": [
309 {
310 "path": "/",
311 "backend": {
312 "serviceName": app_name,
313 "servicePort": port,
314 },
315 }
316 ]
317 },
318 }
319 ],
320 "tls": [{"hosts": [app_name]}],
321 },
322 }
323 ]
324
325 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
326 config, app_name, port
327 )
328
329 self.assertListEqual(expected_result, pod_ingress_resources)
330
331 def test_make_pod_ingress_resources_with_https_tls_secret_name(self) -> NoReturn:
332 """Testing make pod ingress resources with HTTPs and TLS secret name."""
333 config = {
334 "site_url": "https://nbi",
335 "max_file_size": 0,
336 "ingress_whitelist_source_range": "",
337 "tls_secret_name": "secret_name",
338 }
339 app_name = "nbi"
340 port = 9999
341
342 expected_result = [
343 {
344 "name": f"{app_name}-ingress",
345 "annotations": {
346 "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
347 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
348 },
349 "spec": {
350 "rules": [
351 {
352 "host": app_name,
353 "http": {
354 "paths": [
355 {
356 "path": "/",
357 "backend": {
358 "serviceName": app_name,
359 "servicePort": port,
360 },
361 }
362 ]
363 },
364 }
365 ],
366 "tls": [
367 {"hosts": [app_name], "secretName": config["tls_secret_name"]}
368 ],
369 },
370 }
371 ]
372
373 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
374 config, app_name, port
375 )
376
377 self.assertListEqual(expected_result, pod_ingress_resources)
378
379 def test_make_startup_probe(self) -> NoReturn:
380 """Testing make startup probe."""
381 expected_result = {
382 "exec": {"command": ["/usr/bin/pgrep python3"]},
383 "initialDelaySeconds": 60,
384 "timeoutSeconds": 5,
385 }
386
387 startup_probe = pod_spec._make_startup_probe()
388
389 self.assertDictEqual(expected_result, startup_probe)
390
391 def test_make_readiness_probe(self) -> NoReturn:
392 """Testing make readiness probe."""
393 port = 9999
394
395 expected_result = {
396 "httpGet": {
397 "path": "/osm/",
398 "port": port,
399 },
400 "initialDelaySeconds": 45,
401 "timeoutSeconds": 5,
402 }
403
404 readiness_probe = pod_spec._make_readiness_probe(port)
405
406 self.assertDictEqual(expected_result, readiness_probe)
407
408 def test_make_liveness_probe(self) -> NoReturn:
409 """Testing make liveness probe."""
410 port = 9999
411
412 expected_result = {
413 "httpGet": {
414 "path": "/osm/",
415 "port": port,
416 },
417 "initialDelaySeconds": 45,
418 "timeoutSeconds": 5,
419 }
420
421 liveness_probe = pod_spec._make_liveness_probe(port)
422
423 self.assertDictEqual(expected_result, liveness_probe)
424
425 def test_make_pod_spec_without_image_info(self) -> NoReturn:
426 """Testing make pod spec without image_info."""
427 image_info = None
428 config = {
429 "enable_test": False,
430 "database_commonkey": "commonkey",
431 "log_level": "DEBUG",
432 "auth_backend": "internal",
433 "site_url": "",
434 }
435 relation_state = {
436 "message_host": "kafka",
437 "message_port": 9090,
438 "database_uri": "mongodb://mongo",
439 "prometheus_host": "prometheus",
440 "prometheus_port": 9082,
441 }
442 app_name = "nbi"
443 port = 9999
444
445 spec = pod_spec.make_pod_spec(
446 image_info, config, relation_state, app_name, port
447 )
448
449 self.assertIsNone(spec)
450
451 def test_make_pod_spec_without_config(self) -> NoReturn:
452 """Testing make pod spec without config."""
453 image_info = {"upstream-source": "opensourcemano/nbi:8"}
454 config = {}
455 relation_state = {
456 "message_host": "kafka",
457 "message_port": 9090,
458 "database_uri": "mongodb://mongo",
459 "prometheus_host": "prometheus",
460 "prometheus_port": 9082,
461 }
462 app_name = "nbi"
463 port = 9999
464
465 with self.assertRaises(ValueError):
466 pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
467
468 def test_make_pod_spec_without_relation_state(self) -> NoReturn:
469 """Testing make pod spec without relation_state."""
470 image_info = {"upstream-source": "opensourcemano/nbi:8"}
471 config = {
472 "enable_test": False,
473 "database_commonkey": "commonkey",
474 "log_level": "DEBUG",
475 "auth_backend": "internal",
476 "site_url": "",
477 }
478 relation_state = {}
479 app_name = "nbi"
480 port = 9999
481
482 with self.assertRaises(ValueError):
483 pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
484
485 def test_make_pod_spec(self) -> NoReturn:
486 """Testing make pod spec."""
487 image_info = {"upstream-source": "opensourcemano/nbi:8"}
488 config = {
489 "enable_test": False,
490 "database_commonkey": "commonkey",
491 "log_level": "DEBUG",
492 "auth_backend": "internal",
493 "site_url": "",
494 }
495 relation_state = {
496 "message_host": "kafka",
497 "message_port": 9090,
498 "database_uri": "mongodb://mongo",
499 "prometheus_host": "prometheus",
500 "prometheus_port": 9082,
501 }
502 app_name = "nbi"
503 port = 9999
504
505 expected_result = {
506 "version": 3,
507 "containers": [
508 {
509 "name": app_name,
510 "imageDetails": image_info,
511 "imagePullPolicy": "Always",
512 "ports": [
513 {
514 "name": "nbi",
515 "containerPort": port,
516 "protocol": "TCP",
517 }
518 ],
519 "envConfig": {
520 "ALLOW_ANONYMOUS_LOGIN": "yes",
521 "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
522 "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
523 "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
524 "OSMNBI_MESSAGE_DRIVER": "kafka",
525 "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
526 "OSMNBI_DATABASE_DRIVER": "mongo",
527 "OSMNBI_DATABASE_URI": relation_state["database_uri"],
528 "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
529 "OSMNBI_STORAGE_DRIVER": "mongo",
530 "OSMNBI_STORAGE_PATH": "/app/storage",
531 "OSMNBI_STORAGE_COLLECTION": "files",
532 "OSMNBI_STORAGE_URI": relation_state["database_uri"],
533 "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
534 "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
535 "OSMNBI_LOG_LEVEL": config["log_level"],
536 "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
537 },
538 }
539 ],
540 "kubernetesResources": {
541 "ingressResources": [],
542 },
543 }
544
545 spec = pod_spec.make_pod_spec(
546 image_info, config, relation_state, app_name, port
547 )
548
549 self.assertDictEqual(expected_result, spec)
550
551 def test_make_pod_spec_with_keystone(self) -> NoReturn:
552 """Testing make pod spec with keystone."""
553 image_info = {"upstream-source": "opensourcemano/nbi:8"}
554 config = {
555 "enable_test": False,
556 "database_commonkey": "commonkey",
557 "log_level": "DEBUG",
558 "auth_backend": "keystone",
559 "site_url": "",
560 }
561 relation_state = {
562 "message_host": "kafka",
563 "message_port": 9090,
564 "database_uri": "mongodb://mongo",
565 "prometheus_host": "prometheus",
566 "prometheus_port": 9082,
567 "keystone_host": "keystone",
568 "keystone_port": 5000,
569 "keystone_user_domain_name": "user_domain",
570 "keystone_project_domain_name": "project_domain",
571 "keystone_username": "username",
572 "keystone_password": "password",
573 "keystone_service": "service",
574 }
575 app_name = "nbi"
576 port = 9999
577
578 expected_result = {
579 "version": 3,
580 "containers": [
581 {
582 "name": app_name,
583 "imageDetails": image_info,
584 "imagePullPolicy": "Always",
585 "ports": [
586 {
587 "name": "nbi",
588 "containerPort": port,
589 "protocol": "TCP",
590 }
591 ],
592 "envConfig": {
593 "ALLOW_ANONYMOUS_LOGIN": "yes",
594 "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
595 "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
596 "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
597 "OSMNBI_MESSAGE_DRIVER": "kafka",
598 "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
599 "OSMNBI_DATABASE_DRIVER": "mongo",
600 "OSMNBI_DATABASE_URI": relation_state["database_uri"],
601 "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
602 "OSMNBI_STORAGE_DRIVER": "mongo",
603 "OSMNBI_STORAGE_PATH": "/app/storage",
604 "OSMNBI_STORAGE_COLLECTION": "files",
605 "OSMNBI_STORAGE_URI": relation_state["database_uri"],
606 "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
607 "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
608 "OSMNBI_LOG_LEVEL": config["log_level"],
609 "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
610 "OSMNBI_AUTHENTICATION_AUTH_URL": relation_state[
611 "keystone_host"
612 ],
613 "OSMNBI_AUTHENTICATION_AUTH_PORT": relation_state[
614 "keystone_port"
615 ],
616 "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": relation_state[
617 "keystone_user_domain_name"
618 ],
619 "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": relation_state[
620 "keystone_project_domain_name"
621 ],
622 "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": relation_state[
623 "keystone_username"
624 ],
625 "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": relation_state[
626 "keystone_password"
627 ],
628 "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": relation_state[
629 "keystone_service"
630 ],
631 },
632 }
633 ],
634 "kubernetesResources": {
635 "ingressResources": [],
636 },
637 }
638
639 spec = pod_spec.make_pod_spec(
640 image_info, config, relation_state, app_name, port
641 )
642
643 self.assertDictEqual(expected_result, spec)
644
645
646 if __name__ == "__main__":
647 unittest.main()