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