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