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