Adding cluster-issuer annotation for TLS provisioning
[osm/devops.git] / installers / charm / kafka-exporter / tests / test_pod_spec.py
1 #!/usr/bin/env python3
2 # Copyright 2021 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 = 9308
35
36 expected_result = [
37 {
38 "name": "kafka-exporter",
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(self) -> NoReturn:
49 """Teting make pod envconfig."""
50 config = {}
51 relation_state = {}
52
53 expected_result = {}
54
55 pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
56
57 self.assertDictEqual(expected_result, pod_envconfig)
58
59 def test_make_pod_ingress_resources_without_site_url(self) -> NoReturn:
60 """Testing make pod ingress resources without site_url."""
61 config = {
62 "cluster_issuer": "",
63 "site_url": "",
64 }
65 app_name = "kafka-exporter"
66 port = 9308
67
68 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
69 config, app_name, port
70 )
71
72 self.assertIsNone(pod_ingress_resources)
73
74 def test_make_pod_ingress_resources(self) -> NoReturn:
75 """Testing make pod ingress resources."""
76 config = {
77 "cluster_issuer": "",
78 "site_url": "http://kafka-exporter",
79 "ingress_whitelist_source_range": "",
80 }
81 app_name = "kafka-exporter"
82 port = 9308
83
84 expected_result = [
85 {
86 "name": f"{app_name}-ingress",
87 "annotations": {
88 "nginx.ingress.kubernetes.io/ssl-redirect": "false",
89 },
90 "spec": {
91 "rules": [
92 {
93 "host": app_name,
94 "http": {
95 "paths": [
96 {
97 "path": "/",
98 "backend": {
99 "serviceName": app_name,
100 "servicePort": port,
101 },
102 }
103 ]
104 },
105 }
106 ]
107 },
108 }
109 ]
110
111 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
112 config, app_name, port
113 )
114
115 self.assertListEqual(expected_result, pod_ingress_resources)
116
117 def test_make_pod_ingress_resources_with_whitelist_source_range(self) -> NoReturn:
118 """Testing make pod ingress resources with whitelist_source_range."""
119 config = {
120 "site_url": "http://kafka-exporter",
121 "cluster_issuer": "",
122 "ingress_whitelist_source_range": "0.0.0.0/0",
123 }
124 app_name = "kafka-exporter"
125 port = 9308
126
127 expected_result = [
128 {
129 "name": f"{app_name}-ingress",
130 "annotations": {
131 "nginx.ingress.kubernetes.io/ssl-redirect": "false",
132 "nginx.ingress.kubernetes.io/whitelist-source-range": config[
133 "ingress_whitelist_source_range"
134 ],
135 },
136 "spec": {
137 "rules": [
138 {
139 "host": app_name,
140 "http": {
141 "paths": [
142 {
143 "path": "/",
144 "backend": {
145 "serviceName": app_name,
146 "servicePort": port,
147 },
148 }
149 ]
150 },
151 }
152 ]
153 },
154 }
155 ]
156
157 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
158 config, app_name, port
159 )
160
161 self.assertListEqual(expected_result, pod_ingress_resources)
162
163 def test_make_pod_ingress_resources_with_https(self) -> NoReturn:
164 """Testing make pod ingress resources with HTTPs."""
165 config = {
166 "site_url": "https://kafka-exporter",
167 "max_file_size": 0,
168 "cluster_issuer": "",
169 "ingress_whitelist_source_range": "",
170 "tls_secret_name": "",
171 }
172 app_name = "kafka-exporter"
173 port = 9308
174
175 expected_result = [
176 {
177 "name": f"{app_name}-ingress",
178 "annotations": {},
179 "spec": {
180 "rules": [
181 {
182 "host": app_name,
183 "http": {
184 "paths": [
185 {
186 "path": "/",
187 "backend": {
188 "serviceName": app_name,
189 "servicePort": port,
190 },
191 }
192 ]
193 },
194 }
195 ],
196 "tls": [{"hosts": [app_name]}],
197 },
198 }
199 ]
200
201 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
202 config, app_name, port
203 )
204
205 self.assertListEqual(expected_result, pod_ingress_resources)
206
207 def test_make_pod_ingress_resources_with_https_tls_secret_name(self) -> NoReturn:
208 """Testing make pod ingress resources with HTTPs and TLS secret name."""
209 config = {
210 "site_url": "https://kafka-exporter",
211 "max_file_size": 0,
212 "cluster_issuer": "",
213 "ingress_whitelist_source_range": "",
214 "tls_secret_name": "secret_name",
215 }
216 app_name = "kafka-exporter"
217 port = 9308
218
219 expected_result = [
220 {
221 "name": f"{app_name}-ingress",
222 "annotations": {},
223 "spec": {
224 "rules": [
225 {
226 "host": app_name,
227 "http": {
228 "paths": [
229 {
230 "path": "/",
231 "backend": {
232 "serviceName": app_name,
233 "servicePort": port,
234 },
235 }
236 ]
237 },
238 }
239 ],
240 "tls": [
241 {"hosts": [app_name], "secretName": config["tls_secret_name"]}
242 ],
243 },
244 }
245 ]
246
247 pod_ingress_resources = pod_spec._make_pod_ingress_resources(
248 config, app_name, port
249 )
250
251 self.assertListEqual(expected_result, pod_ingress_resources)
252
253 def test_make_readiness_probe(self) -> NoReturn:
254 """Testing make readiness probe."""
255 port = 9308
256
257 expected_result = {
258 "httpGet": {
259 "path": "/api/health",
260 "port": port,
261 },
262 "initialDelaySeconds": 10,
263 "periodSeconds": 10,
264 "timeoutSeconds": 5,
265 "successThreshold": 1,
266 "failureThreshold": 3,
267 }
268
269 readiness_probe = pod_spec._make_readiness_probe(port)
270
271 self.assertDictEqual(expected_result, readiness_probe)
272
273 def test_make_liveness_probe(self) -> NoReturn:
274 """Testing make liveness probe."""
275 port = 9308
276
277 expected_result = {
278 "httpGet": {
279 "path": "/api/health",
280 "port": port,
281 },
282 "initialDelaySeconds": 60,
283 "timeoutSeconds": 30,
284 "failureThreshold": 10,
285 }
286
287 liveness_probe = pod_spec._make_liveness_probe(port)
288
289 self.assertDictEqual(expected_result, liveness_probe)
290
291 def test_make_pod_command(self) -> NoReturn:
292 """Testing make pod command."""
293 relation = {
294 "kakfa_host": "kafka",
295 "kafka_port": "9090",
296 }
297
298 expected_result = [
299 "kafka_exporter",
300 "--kafka.server={}:{}".format(
301 relation.get("kafka_host"), relation.get("kafka_port")
302 ),
303 ]
304
305 pod_envconfig = pod_spec._make_pod_command(relation)
306
307 self.assertListEqual(expected_result, pod_envconfig)
308
309 def test_make_pod_spec(self) -> NoReturn:
310 """Testing make pod spec."""
311 image_info = {"upstream-source": "bitnami/kafka-exporter:latest"}
312 config = {
313 "site_url": "",
314 "cluster_issuer": "",
315 }
316 relation_state = {
317 "kafka_host": "kafka",
318 "kafka_port": "9090",
319 }
320 app_name = "kafka-exporter"
321 port = 9308
322
323 expected_result = {
324 "version": 3,
325 "containers": [
326 {
327 "name": app_name,
328 "imageDetails": image_info,
329 "imagePullPolicy": "Always",
330 "ports": [
331 {
332 "name": app_name,
333 "containerPort": port,
334 "protocol": "TCP",
335 }
336 ],
337 "envConfig": {},
338 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
339 "kubernetes": {
340 "readinessProbe": {
341 "httpGet": {
342 "path": "/api/health",
343 "port": port,
344 },
345 "initialDelaySeconds": 10,
346 "periodSeconds": 10,
347 "timeoutSeconds": 5,
348 "successThreshold": 1,
349 "failureThreshold": 3,
350 },
351 "livenessProbe": {
352 "httpGet": {
353 "path": "/api/health",
354 "port": port,
355 },
356 "initialDelaySeconds": 60,
357 "timeoutSeconds": 30,
358 "failureThreshold": 10,
359 },
360 },
361 }
362 ],
363 "kubernetesResources": {"ingressResources": []},
364 }
365
366 spec = pod_spec.make_pod_spec(
367 image_info, config, relation_state, app_name, port
368 )
369
370 self.assertDictEqual(expected_result, spec)
371
372 def test_make_pod_spec_with_ingress(self) -> NoReturn:
373 """Testing make pod spec."""
374 image_info = {"upstream-source": "bitnami/kafka-exporter:latest"}
375 config = {
376 "site_url": "https://kafka-exporter",
377 "cluster_issuer": "",
378 "tls_secret_name": "kafka-exporter",
379 "max_file_size": 0,
380 "ingress_whitelist_source_range": "0.0.0.0/0",
381 }
382 relation_state = {
383 "kafka_host": "kafka",
384 "kafka_port": "9090",
385 }
386 app_name = "kafka-exporter"
387 port = 9308
388
389 expected_result = {
390 "version": 3,
391 "containers": [
392 {
393 "name": app_name,
394 "imageDetails": image_info,
395 "imagePullPolicy": "Always",
396 "ports": [
397 {
398 "name": app_name,
399 "containerPort": port,
400 "protocol": "TCP",
401 }
402 ],
403 "envConfig": {},
404 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
405 "kubernetes": {
406 "readinessProbe": {
407 "httpGet": {
408 "path": "/api/health",
409 "port": port,
410 },
411 "initialDelaySeconds": 10,
412 "periodSeconds": 10,
413 "timeoutSeconds": 5,
414 "successThreshold": 1,
415 "failureThreshold": 3,
416 },
417 "livenessProbe": {
418 "httpGet": {
419 "path": "/api/health",
420 "port": port,
421 },
422 "initialDelaySeconds": 60,
423 "timeoutSeconds": 30,
424 "failureThreshold": 10,
425 },
426 },
427 }
428 ],
429 "kubernetesResources": {
430 "ingressResources": [
431 {
432 "name": "{}-ingress".format(app_name),
433 "annotations": {
434 "nginx.ingress.kubernetes.io/whitelist-source-range": config.get(
435 "ingress_whitelist_source_range"
436 ),
437 },
438 "spec": {
439 "rules": [
440 {
441 "host": app_name,
442 "http": {
443 "paths": [
444 {
445 "path": "/",
446 "backend": {
447 "serviceName": app_name,
448 "servicePort": port,
449 },
450 }
451 ]
452 },
453 }
454 ],
455 "tls": [
456 {
457 "hosts": [app_name],
458 "secretName": config.get("tls_secret_name"),
459 }
460 ],
461 },
462 }
463 ],
464 },
465 }
466
467 spec = pod_spec.make_pod_spec(
468 image_info, config, relation_state, app_name, port
469 )
470
471 self.assertDictEqual(expected_result, spec)
472
473 def test_make_pod_spec_without_image_info(self) -> NoReturn:
474 """Testing make pod spec without image_info."""
475 image_info = None
476 config = {
477 "site_url": "",
478 "cluster_issuer": "",
479 }
480 relation_state = {
481 "kafka_host": "kafka",
482 "kafka_port": "9090",
483 }
484 app_name = "kafka-exporter"
485 port = 9308
486
487 spec = pod_spec.make_pod_spec(
488 image_info, config, relation_state, app_name, port
489 )
490
491 self.assertIsNone(spec)
492
493 def test_make_pod_spec_without_relation_state(self) -> NoReturn:
494 """Testing make pod spec without relation_state."""
495 image_info = {"upstream-source": "bitnami/kafka-exporter:latest"}
496 config = {
497 "site_url": "",
498 "cluster_issuer": "",
499 }
500 relation_state = {}
501 app_name = "kafka-exporter"
502 port = 9308
503
504 with self.assertRaises(ValueError):
505 pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
506
507
508 if __name__ == "__main__":
509 unittest.main()