831e1762a0eda634827d35c9587924bee6da20b3
[osm/devops.git] / installers / charm / lcm / 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 import sys
24 from typing import NoReturn
25 import unittest
26
27 from charm import LcmCharm
28 import mock
29 from ops.model import ActiveStatus, BlockedStatus
30 from ops.testing import Harness
31
32
33 class TestCharm(unittest.TestCase):
34 """Prometheus Charm unit tests."""
35
36 def setUp(self) -> NoReturn:
37 """Test setup"""
38 self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
39 self.harness = Harness(LcmCharm)
40 self.harness.set_leader(is_leader=True)
41 self.harness.begin()
42 self.config = {
43 "vca_host": "192.168.0.13",
44 "vca_port": 17070,
45 "vca_user": "admin",
46 "vca_secret": "admin",
47 "vca_pubkey": "key",
48 "vca_cacert": "cacert",
49 "vca_cloud": "cloud",
50 "vca_k8s_cloud": "k8scloud",
51 "database_commonkey": "commonkey",
52 "log_level": "INFO",
53 }
54 self.harness.update_config(self.config)
55
56 def test_config_changed_no_relations(
57 self,
58 ) -> NoReturn:
59 """Test ingress resources without HTTP."""
60
61 self.harness.charm.on.config_changed.emit()
62
63 # Assertions
64 self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
65 self.assertTrue(
66 all(
67 relation in self.harness.charm.unit.status.message
68 for relation in ["mongodb", "kafka", "ro"]
69 )
70 )
71
72 def test_config_changed_non_leader(
73 self,
74 ) -> NoReturn:
75 """Test ingress resources without HTTP."""
76 self.harness.set_leader(is_leader=False)
77 self.harness.charm.on.config_changed.emit()
78
79 # Assertions
80 self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
81
82 def test_with_relations(
83 self,
84 ) -> NoReturn:
85 "Test with relations (internal)"
86 self.initialize_kafka_relation()
87 self.initialize_mongo_relation()
88 self.initialize_ro_relation()
89 # Verifying status
90 self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
91
92 def test_build_pod_spec(
93 self,
94 ) -> NoReturn:
95 expected_config = {
96 "OSMLCM_GLOBAL_LOGLEVEL": self.config["log_level"],
97 "OSMLCM_DATABASE_COMMONKEY": self.config["database_commonkey"],
98 }
99 expected_config.update(
100 {
101 f"OSMLCM_{k.upper()}": v
102 for k, v in self.config.items()
103 if k.startswith("vca_")
104 }
105 )
106 self.harness.charm._check_missing_dependencies = mock.Mock()
107 pod_spec = self.harness.charm.build_pod_spec(
108 {"imageDetails": {"imagePath": "lcm-image"}}
109 )
110 actual_config = pod_spec["containers"][0]["envConfig"]
111
112 self.assertDictContainsSubset(
113 expected_config,
114 actual_config,
115 )
116 for config_key in actual_config:
117 self.assertNotIn("VCA_MODEL_CONFIG", config_key)
118
119 def test_build_pod_spec_with_model_config(
120 self,
121 ) -> NoReturn:
122 self.harness.update_config(
123 {
124 "vca_model_config_agent_metadata_url": "string",
125 "vca_model_config_agent_stream": "string",
126 "vca_model_config_apt_ftp_proxy": "string",
127 "vca_model_config_apt_http_proxy": "string",
128 "vca_model_config_apt_https_proxy": "string",
129 "vca_model_config_apt_mirror": "string",
130 "vca_model_config_apt_no_proxy": "string",
131 "vca_model_config_automatically_retry_hooks": False,
132 "vca_model_config_backup_dir": "string",
133 "vca_model_config_cloudinit_userdata": "string",
134 "vca_model_config_container_image_metadata_url": "string",
135 "vca_model_config_container_image_stream": "string",
136 "vca_model_config_container_inherit_properties": "string",
137 "vca_model_config_container_networking_method": "string",
138 "vca_model_config_default_series": "string",
139 "vca_model_config_default_space": "string",
140 "vca_model_config_development": False,
141 "vca_model_config_disable_network_management": False,
142 "vca_model_config_egress_subnets": "string",
143 "vca_model_config_enable_os_refresh_update": False,
144 "vca_model_config_enable_os_upgrade": False,
145 "vca_model_config_fan_config": "string",
146 "vca_model_config_firewall_mode": "string",
147 "vca_model_config_ftp_proxy": "string",
148 "vca_model_config_http_proxy": "string",
149 "vca_model_config_https_proxy": "string",
150 "vca_model_config_ignore_machine_addresses": False,
151 "vca_model_config_image_metadata_url": "string",
152 "vca_model_config_image_stream": "string",
153 "vca_model_config_juju_ftp_proxy": "string",
154 "vca_model_config_juju_http_proxy": "string",
155 "vca_model_config_juju_https_proxy": "string",
156 "vca_model_config_juju_no_proxy": "string",
157 "vca_model_config_logforward_enabled": False,
158 "vca_model_config_logging_config": "string",
159 "vca_model_config_lxd_snap_channel": "string",
160 "vca_model_config_max_action_results_age": "string",
161 "vca_model_config_max_action_results_size": "string",
162 "vca_model_config_max_status_history_age": "string",
163 "vca_model_config_max_status_history_size": "string",
164 "vca_model_config_net_bond_reconfigure_delay": "string",
165 "vca_model_config_no_proxy": "string",
166 "vca_model_config_provisioner_harvest_mode": "string",
167 "vca_model_config_proxy_ssh": False,
168 "vca_model_config_snap_http_proxy": "string",
169 "vca_model_config_snap_https_proxy": "string",
170 "vca_model_config_snap_store_assertions": "string",
171 "vca_model_config_snap_store_proxy": "string",
172 "vca_model_config_snap_store_proxy_url": "string",
173 "vca_model_config_ssl_hostname_verification": False,
174 "vca_model_config_test_mode": False,
175 "vca_model_config_transmit_vendor_metrics": False,
176 "vca_model_config_update_status_hook_interval": "string",
177 }
178 )
179 expected_config = {
180 f"OSMLCM_{k.upper()}": v
181 for k, v in self.config.items()
182 if k.startswith("vca_model_config_")
183 }
184
185 self.harness.charm._check_missing_dependencies = mock.Mock()
186 pod_spec = self.harness.charm.build_pod_spec(
187 {"imageDetails": {"imagePath": "lcm-image"}}
188 )
189 actual_config = pod_spec["containers"][0]["envConfig"]
190
191 self.assertDictContainsSubset(
192 expected_config,
193 actual_config,
194 )
195
196 def initialize_kafka_relation(self):
197 kafka_relation_id = self.harness.add_relation("kafka", "kafka")
198 self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
199 self.harness.update_relation_data(
200 kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
201 )
202
203 def initialize_mongo_relation(self):
204 mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
205 self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
206 self.harness.update_relation_data(
207 mongodb_relation_id,
208 "mongodb/0",
209 {"connection_string": "mongodb://mongo:27017"},
210 )
211
212 def initialize_ro_relation(self):
213 http_relation_id = self.harness.add_relation("ro", "ro")
214 self.harness.add_relation_unit(http_relation_id, "ro")
215 self.harness.update_relation_data(
216 http_relation_id,
217 "ro",
218 {"host": "ro", "port": 9090},
219 )
220
221
222 if __name__ == "__main__":
223 unittest.main()
224
225
226 # class TestCharm(unittest.TestCase):
227 # """LCM Charm unit tests."""
228
229 # def setUp(self) -> NoReturn:
230 # """Test setup"""
231 # self.harness = Harness(LcmCharm)
232 # self.harness.set_leader(is_leader=True)
233 # self.harness.begin()
234
235 # def test_on_start_without_relations(self) -> NoReturn:
236 # """Test installation without any relation."""
237 # self.harness.charm.on.start.emit()
238
239 # # Verifying status
240 # self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
241
242 # # Verifying status message
243 # self.assertGreater(len(self.harness.charm.unit.status.message), 0)
244 # self.assertTrue(
245 # self.harness.charm.unit.status.message.startswith("Waiting for ")
246 # )
247 # self.assertIn("kafka", self.harness.charm.unit.status.message)
248 # self.assertIn("mongodb", self.harness.charm.unit.status.message)
249 # self.assertIn("ro", self.harness.charm.unit.status.message)
250 # self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
251
252 # def test_on_start_with_relations(self) -> NoReturn:
253 # """Test deployment without keystone."""
254 # expected_result = {
255 # "version": 3,
256 # "containers": [
257 # {
258 # "name": "lcm",
259 # "imageDetails": self.harness.charm.image.fetch(),
260 # "imagePullPolicy": "Always",
261 # "ports": [
262 # {
263 # "name": "lcm",
264 # "containerPort": 9999,
265 # "protocol": "TCP",
266 # }
267 # ],
268 # "envConfig": {
269 # "ALLOW_ANONYMOUS_LOGIN": "yes",
270 # "OSMLCM_GLOBAL_LOGLEVEL": "INFO",
271 # "OSMLCM_RO_HOST": "ro",
272 # "OSMLCM_RO_PORT": 9090,
273 # "OSMLCM_RO_TENANT": "osm",
274 # "OSMLCM_MESSAGE_DRIVER": "kafka",
275 # "OSMLCM_MESSAGE_HOST": "kafka",
276 # "OSMLCM_MESSAGE_PORT": 9092,
277 # "OSMLCM_DATABASE_DRIVER": "mongo",
278 # "OSMLCM_DATABASE_URI": "mongodb://mongo:27017",
279 # "OSMLCM_DATABASE_COMMONKEY": "osm",
280 # "OSMLCM_STORAGE_DRIVER": "mongo",
281 # "OSMLCM_STORAGE_PATH": "/app/storage",
282 # "OSMLCM_STORAGE_COLLECTION": "files",
283 # "OSMLCM_STORAGE_URI": "mongodb://mongo:27017",
284 # "OSMLCM_VCA_HOST": "admin",
285 # "OSMLCM_VCA_PORT": 17070,
286 # "OSMLCM_VCA_USER": "admin",
287 # "OSMLCM_VCA_PUBKEY": "secret",
288 # "OSMLCM_VCA_SECRET": "secret",
289 # "OSMLCM_VCA_CACERT": "",
290 # "OSMLCM_VCA_CLOUD": "localhost",
291 # "OSMLCM_VCA_K8S_CLOUD": "k8scloud",
292 # },
293 # }
294 # ],
295 # "kubernetesResources": {"ingressResources": []},
296 # }
297
298 # self.harness.charm.on.start.emit()
299
300 # # Check if kafka datastore is initialized
301 # self.assertIsNone(self.harness.charm.state.message_host)
302 # self.assertIsNone(self.harness.charm.state.message_port)
303
304 # # Check if mongodb datastore is initialized
305 # self.assertIsNone(self.harness.charm.state.database_uri)
306
307 # # Check if RO datastore is initialized
308 # self.assertIsNone(self.harness.charm.state.ro_host)
309 # self.assertIsNone(self.harness.charm.state.ro_port)
310
311 # # Initializing the kafka relation
312 # kafka_relation_id = self.harness.add_relation("kafka", "kafka")
313 # self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
314 # self.harness.update_relation_data(
315 # kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
316 # )
317
318 # # Initializing the mongo relation
319 # mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
320 # self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
321 # self.harness.update_relation_data(
322 # mongodb_relation_id,
323 # "mongodb/0",
324 # {"connection_string": "mongodb://mongo:27017"},
325 # )
326
327 # # Initializing the RO relation
328 # ro_relation_id = self.harness.add_relation("ro", "ro")
329 # self.harness.add_relation_unit(ro_relation_id, "ro/0")
330 # self.harness.update_relation_data(
331 # ro_relation_id, "ro/0", {"host": "ro", "port": 9090}
332 # )
333
334 # # Checking if kafka data is stored
335 # self.assertEqual(self.harness.charm.state.message_host, "kafka")
336 # self.assertEqual(self.harness.charm.state.message_port, 9092)
337
338 # # Checking if mongodb data is stored
339 # self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
340
341 # # Checking if RO data is stored
342 # self.assertEqual(self.harness.charm.state.ro_host, "ro")
343 # self.assertEqual(self.harness.charm.state.ro_port, 9090)
344
345 # # Verifying status
346 # self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
347
348 # pod_spec, _ = self.harness.get_pod_spec()
349
350 # self.assertDictEqual(expected_result, pod_spec)
351
352 # def test_on_kafka_relation_unit_changed(self) -> NoReturn:
353 # """Test to see if kafka relation is updated."""
354 # self.harness.charm.on.start.emit()
355
356 # self.assertIsNone(self.harness.charm.state.message_host)
357 # self.assertIsNone(self.harness.charm.state.message_port)
358
359 # relation_id = self.harness.add_relation("kafka", "kafka")
360 # self.harness.add_relation_unit(relation_id, "kafka/0")
361 # self.harness.update_relation_data(
362 # relation_id, "kafka/0", {"host": "kafka", "port": 9092}
363 # )
364
365 # self.assertEqual(self.harness.charm.state.message_host, "kafka")
366 # self.assertEqual(self.harness.charm.state.message_port, 9092)
367
368 # # Verifying status
369 # self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
370
371 # # Verifying status message
372 # self.assertGreater(len(self.harness.charm.unit.status.message), 0)
373 # self.assertTrue(
374 # self.harness.charm.unit.status.message.startswith("Waiting for ")
375 # )
376 # self.assertNotIn("kafka", self.harness.charm.unit.status.message)
377 # self.assertIn("mongodb", self.harness.charm.unit.status.message)
378 # self.assertIn("ro", self.harness.charm.unit.status.message)
379 # self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
380
381 # def test_on_mongodb_unit_relation_changed(self) -> NoReturn:
382 # """Test to see if mongodb relation is updated."""
383 # self.harness.charm.on.start.emit()
384
385 # self.assertIsNone(self.harness.charm.state.database_uri)
386
387 # relation_id = self.harness.add_relation("mongodb", "mongodb")
388 # self.harness.add_relation_unit(relation_id, "mongodb/0")
389 # self.harness.update_relation_data(
390 # relation_id, "mongodb/0", {"connection_string": "mongodb://mongo:27017"}
391 # )
392
393 # self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
394
395 # # Verifying status
396 # self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
397
398 # # Verifying status message
399 # self.assertGreater(len(self.harness.charm.unit.status.message), 0)
400 # self.assertTrue(
401 # self.harness.charm.unit.status.message.startswith("Waiting for ")
402 # )
403 # self.assertIn("kafka", self.harness.charm.unit.status.message)
404 # self.assertNotIn("mongodb", self.harness.charm.unit.status.message)
405 # self.assertIn("ro", self.harness.charm.unit.status.message)
406 # self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
407
408 # def test_on_ro_unit_relation_changed(self) -> NoReturn:
409 # """Test to see if RO relation is updated."""
410 # self.harness.charm.on.start.emit()
411
412 # self.assertIsNone(self.harness.charm.state.ro_host)
413 # self.assertIsNone(self.harness.charm.state.ro_port)
414
415 # relation_id = self.harness.add_relation("ro", "ro")
416 # self.harness.add_relation_unit(relation_id, "ro/0")
417 # self.harness.update_relation_data(
418 # relation_id, "ro/0", {"host": "ro", "port": 9090}
419 # )
420
421 # self.assertEqual(self.harness.charm.state.ro_host, "ro")
422 # self.assertEqual(self.harness.charm.state.ro_port, 9090)
423
424 # # Verifying status
425 # self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
426
427 # # Verifying status message
428 # self.assertGreater(len(self.harness.charm.unit.status.message), 0)
429 # self.assertTrue(
430 # self.harness.charm.unit.status.message.startswith("Waiting for ")
431 # )
432 # self.assertIn("kafka", self.harness.charm.unit.status.message)
433 # self.assertIn("mongodb", self.harness.charm.unit.status.message)
434 # self.assertNotIn("ro", self.harness.charm.unit.status.message)
435 # self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
436
437
438 # if __name__ == "__main__":
439 # unittest.main()