fc50b4999f8073d27d8e469d80521871f32dc6e4
[osm/devops.git] / installers / charm / kafka-exporter / tests / test_charm.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 from ops.model import BlockedStatus
27 from ops.testing import Harness
28
29 from charm import KafkaExporterCharm
30
31
32 class TestCharm(unittest.TestCase):
33 """Kafka Exporter Charm unit tests."""
34
35 def setUp(self) -> NoReturn:
36 """Test setup"""
37 self.harness = Harness(KafkaExporterCharm)
38 self.harness.set_leader(is_leader=True)
39 self.harness.begin()
40
41 def test_on_start_without_relations(self) -> NoReturn:
42 """Test installation without any relation."""
43 self.harness.charm.on.start.emit()
44
45 # Verifying status
46 self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
47
48 # Verifying status message
49 self.assertGreater(len(self.harness.charm.unit.status.message), 0)
50 self.assertTrue(
51 self.harness.charm.unit.status.message.startswith("Waiting for ")
52 )
53 self.assertIn("kafka", self.harness.charm.unit.status.message)
54 self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
55
56 def test_on_start_with_relations_without_http(self) -> NoReturn:
57 """Test deployment."""
58 expected_result = {
59 "version": 3,
60 "containers": [
61 {
62 "name": "kafka-exporter",
63 "imageDetails": self.harness.charm.image.fetch(),
64 "imagePullPolicy": "Always",
65 "ports": [
66 {
67 "name": "kafka-exporter",
68 "containerPort": 9308,
69 "protocol": "TCP",
70 }
71 ],
72 "envConfig": {},
73 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
74 "kubernetes": {
75 "readinessProbe": {
76 "httpGet": {
77 "path": "/api/health",
78 "port": 9308,
79 },
80 "initialDelaySeconds": 10,
81 "periodSeconds": 10,
82 "timeoutSeconds": 5,
83 "successThreshold": 1,
84 "failureThreshold": 3,
85 },
86 "livenessProbe": {
87 "httpGet": {
88 "path": "/api/health",
89 "port": 9308,
90 },
91 "initialDelaySeconds": 60,
92 "timeoutSeconds": 30,
93 "failureThreshold": 10,
94 },
95 },
96 },
97 ],
98 "kubernetesResources": {"ingressResources": []},
99 }
100
101 self.harness.charm.on.start.emit()
102
103 # Initializing the kafka relation
104 relation_id = self.harness.add_relation("kafka", "kafka")
105 self.harness.add_relation_unit(relation_id, "kafka/0")
106 self.harness.update_relation_data(
107 relation_id,
108 "kafka/0",
109 {
110 "host": "kafka",
111 "port": "9090",
112 },
113 )
114
115 # Verifying status
116 self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
117
118 pod_spec, _ = self.harness.get_pod_spec()
119
120 self.assertDictEqual(expected_result, pod_spec)
121
122 def test_ingress_resources_with_http(self) -> NoReturn:
123 """Test ingress resources with HTTP."""
124 expected_result = {
125 "version": 3,
126 "containers": [
127 {
128 "name": "kafka-exporter",
129 "imageDetails": self.harness.charm.image.fetch(),
130 "imagePullPolicy": "Always",
131 "ports": [
132 {
133 "name": "kafka-exporter",
134 "containerPort": 9308,
135 "protocol": "TCP",
136 }
137 ],
138 "envConfig": {},
139 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
140 "kubernetes": {
141 "readinessProbe": {
142 "httpGet": {
143 "path": "/api/health",
144 "port": 9308,
145 },
146 "initialDelaySeconds": 10,
147 "periodSeconds": 10,
148 "timeoutSeconds": 5,
149 "successThreshold": 1,
150 "failureThreshold": 3,
151 },
152 "livenessProbe": {
153 "httpGet": {
154 "path": "/api/health",
155 "port": 9308,
156 },
157 "initialDelaySeconds": 60,
158 "timeoutSeconds": 30,
159 "failureThreshold": 10,
160 },
161 },
162 },
163 ],
164 "kubernetesResources": {
165 "ingressResources": [
166 {
167 "name": "kafka-exporter-ingress",
168 "annotations": {
169 "nginx.ingress.kubernetes.io/ssl-redirect": "false",
170 },
171 "spec": {
172 "rules": [
173 {
174 "host": "kafka-exporter",
175 "http": {
176 "paths": [
177 {
178 "path": "/",
179 "backend": {
180 "serviceName": "kafka-exporter",
181 "servicePort": 9308,
182 },
183 }
184 ]
185 },
186 }
187 ]
188 },
189 }
190 ],
191 },
192 }
193
194 self.harness.charm.on.start.emit()
195
196 # Initializing the kafka relation
197 relation_id = self.harness.add_relation("kafka", "kafka")
198 self.harness.add_relation_unit(relation_id, "kafka/0")
199 self.harness.update_relation_data(
200 relation_id,
201 "kafka/0",
202 {
203 "host": "kafka",
204 "port": "9090",
205 },
206 )
207
208 self.harness.update_config({"site_url": "http://kafka-exporter"})
209
210 pod_spec, _ = self.harness.get_pod_spec()
211
212 self.assertDictEqual(expected_result, pod_spec)
213
214 def test_ingress_resources_with_https(self) -> NoReturn:
215 """Test ingress resources with HTTPS."""
216 expected_result = {
217 "version": 3,
218 "containers": [
219 {
220 "name": "kafka-exporter",
221 "imageDetails": self.harness.charm.image.fetch(),
222 "imagePullPolicy": "Always",
223 "ports": [
224 {
225 "name": "kafka-exporter",
226 "containerPort": 9308,
227 "protocol": "TCP",
228 }
229 ],
230 "envConfig": {},
231 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
232 "kubernetes": {
233 "readinessProbe": {
234 "httpGet": {
235 "path": "/api/health",
236 "port": 9308,
237 },
238 "initialDelaySeconds": 10,
239 "periodSeconds": 10,
240 "timeoutSeconds": 5,
241 "successThreshold": 1,
242 "failureThreshold": 3,
243 },
244 "livenessProbe": {
245 "httpGet": {
246 "path": "/api/health",
247 "port": 9308,
248 },
249 "initialDelaySeconds": 60,
250 "timeoutSeconds": 30,
251 "failureThreshold": 10,
252 },
253 },
254 },
255 ],
256 "kubernetesResources": {
257 "ingressResources": [
258 {
259 "name": "kafka-exporter-ingress",
260 "annotations": {},
261 "spec": {
262 "rules": [
263 {
264 "host": "kafka-exporter",
265 "http": {
266 "paths": [
267 {
268 "path": "/",
269 "backend": {
270 "serviceName": "kafka-exporter",
271 "servicePort": 9308,
272 },
273 }
274 ]
275 },
276 }
277 ],
278 "tls": [
279 {
280 "hosts": ["kafka-exporter"],
281 "secretName": "kafka-exporter",
282 }
283 ],
284 },
285 }
286 ],
287 },
288 }
289
290 self.harness.charm.on.start.emit()
291
292 # Initializing the kafka relation
293 relation_id = self.harness.add_relation("kafka", "kafka")
294 self.harness.add_relation_unit(relation_id, "kafka/0")
295 self.harness.update_relation_data(
296 relation_id,
297 "kafka/0",
298 {
299 "host": "kafka",
300 "port": "9090",
301 },
302 )
303
304 self.harness.update_config(
305 {
306 "site_url": "https://kafka-exporter",
307 "tls_secret_name": "kafka-exporter",
308 }
309 )
310
311 pod_spec, _ = self.harness.get_pod_spec()
312
313 self.assertDictEqual(expected_result, pod_spec)
314
315 def test_ingress_resources_with_https_and_ingress_whitelist(self) -> NoReturn:
316 """Test ingress resources with HTTPS and ingress whitelist."""
317 expected_result = {
318 "version": 3,
319 "containers": [
320 {
321 "name": "kafka-exporter",
322 "imageDetails": self.harness.charm.image.fetch(),
323 "imagePullPolicy": "Always",
324 "ports": [
325 {
326 "name": "kafka-exporter",
327 "containerPort": 9308,
328 "protocol": "TCP",
329 }
330 ],
331 "envConfig": {},
332 "command": ["kafka_exporter", "--kafka.server=kafka:9090"],
333 "kubernetes": {
334 "readinessProbe": {
335 "httpGet": {
336 "path": "/api/health",
337 "port": 9308,
338 },
339 "initialDelaySeconds": 10,
340 "periodSeconds": 10,
341 "timeoutSeconds": 5,
342 "successThreshold": 1,
343 "failureThreshold": 3,
344 },
345 "livenessProbe": {
346 "httpGet": {
347 "path": "/api/health",
348 "port": 9308,
349 },
350 "initialDelaySeconds": 60,
351 "timeoutSeconds": 30,
352 "failureThreshold": 10,
353 },
354 },
355 },
356 ],
357 "kubernetesResources": {
358 "ingressResources": [
359 {
360 "name": "kafka-exporter-ingress",
361 "annotations": {
362 "nginx.ingress.kubernetes.io/whitelist-source-range": "0.0.0.0/0",
363 },
364 "spec": {
365 "rules": [
366 {
367 "host": "kafka-exporter",
368 "http": {
369 "paths": [
370 {
371 "path": "/",
372 "backend": {
373 "serviceName": "kafka-exporter",
374 "servicePort": 9308,
375 },
376 }
377 ]
378 },
379 }
380 ],
381 "tls": [
382 {
383 "hosts": ["kafka-exporter"],
384 "secretName": "kafka-exporter",
385 }
386 ],
387 },
388 }
389 ],
390 },
391 }
392
393 self.harness.charm.on.start.emit()
394
395 # Initializing the kafka relation
396 relation_id = self.harness.add_relation("kafka", "kafka")
397 self.harness.add_relation_unit(relation_id, "kafka/0")
398 self.harness.update_relation_data(
399 relation_id,
400 "kafka/0",
401 {
402 "host": "kafka",
403 "port": "9090",
404 },
405 )
406
407 self.harness.update_config(
408 {
409 "site_url": "https://kafka-exporter",
410 "tls_secret_name": "kafka-exporter",
411 "ingress_whitelist_source_range": "0.0.0.0/0",
412 }
413 )
414
415 pod_spec, _ = self.harness.get_pod_spec()
416
417 self.assertDictEqual(expected_result, pod_spec)
418
419 def test_on_kafka_unit_relation_changed(self) -> NoReturn:
420 """Test to see if kafka relation is updated."""
421 self.harness.charm.on.start.emit()
422
423 relation_id = self.harness.add_relation("kafka", "kafka")
424 self.harness.add_relation_unit(relation_id, "kafka/0")
425 self.harness.update_relation_data(
426 relation_id,
427 "kafka/0",
428 {
429 "host": "kafka",
430 "port": "9090",
431 },
432 )
433
434 # Verifying status
435 self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
436
437 def test_publish_target_info(self) -> NoReturn:
438 """Test to see if target relation is updated."""
439 expected_result = {
440 "hostname": "kafka-exporter",
441 "port": "9308",
442 "metrics_path": "/metrics",
443 "scrape_interval": "30s",
444 "scrape_timeout": "15s",
445 }
446
447 self.harness.charm.on.start.emit()
448
449 relation_id = self.harness.add_relation("prometheus-scrape", "prometheus")
450 self.harness.add_relation_unit(relation_id, "prometheus/0")
451 relation_data = self.harness.get_relation_data(relation_id, "kafka-exporter/0")
452
453 self.assertDictEqual(expected_result, relation_data)
454
455 def test_publish_target_info_with_site_url(self) -> NoReturn:
456 """Test to see if target relation is updated."""
457 expected_result = {
458 "hostname": "kafka-exporter-osm",
459 "port": "80",
460 "metrics_path": "/metrics",
461 "scrape_interval": "30s",
462 "scrape_timeout": "15s",
463 }
464
465 self.harness.charm.on.start.emit()
466
467 self.harness.update_config({"site_url": "http://kafka-exporter-osm"})
468
469 relation_id = self.harness.add_relation("prometheus-scrape", "prometheus")
470 self.harness.add_relation_unit(relation_id, "prometheus/0")
471 relation_data = self.harness.get_relation_data(relation_id, "kafka-exporter/0")
472
473 self.assertDictEqual(expected_result, relation_data)
474
475 def test_publish_dashboard_info(self) -> NoReturn:
476 """Test to see if dashboard relation is updated."""
477 self.harness.charm.on.start.emit()
478
479 relation_id = self.harness.add_relation("grafana-dashboard", "grafana")
480 self.harness.add_relation_unit(relation_id, "grafana/0")
481 relation_data = self.harness.get_relation_data(relation_id, "kafka-exporter/0")
482
483 self.assertTrue("dashboard" in relation_data)
484 self.assertTrue(len(relation_data["dashboard"]) > 0)
485
486
487 if __name__ == "__main__":
488 unittest.main()