OSM DB Update Charm
[osm/devops.git] / installers / charm / osm-update-db-operator / tests / unit / test_db_upgrade.py
1 # Copyright 2022 Canonical Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 import logging
16 import unittest
17 from unittest.mock import MagicMock, Mock, call, patch
18
19 import db_upgrade
20 from db_upgrade import (
21 MongoPatch1837,
22 MongoUpgrade,
23 MongoUpgrade910,
24 MongoUpgrade1012,
25 MysqlUpgrade,
26 )
27
28 logger = logging.getLogger(__name__)
29
30
31 class TestUpgradeMongo910(unittest.TestCase):
32 @patch("db_upgrade.MongoClient")
33 def test_upgrade_mongo_9_10(self, mock_mongo_client):
34 mock_db = MagicMock()
35 alarms = Mock()
36 alarms.find.return_value = [{"_id": "1", "alarm_status": "1"}]
37 collection_dict = {"alarms": alarms, "other": {}}
38 mock_db.list_collection_names.return_value = collection_dict
39 mock_db.__getitem__.side_effect = collection_dict.__getitem__
40 mock_mongo_client.return_value = {"osm": mock_db}
41 MongoUpgrade910.upgrade("mongo_uri")
42 alarms.update_one.assert_not_called()
43
44 @patch("db_upgrade.MongoClient")
45 def test_upgrade_mongo_9_10_no_alarms(self, mock_mongo_client):
46 mock_db = Mock()
47 mock_db.__getitem__ = Mock()
48
49 mock_db.list_collection_names.return_value = {"other": {}}
50 mock_db.alarms.return_value = None
51 mock_mongo_client.return_value = {"osm": mock_db}
52 self.assertIsNone(MongoUpgrade910.upgrade("mongo_uri"))
53
54 @patch("db_upgrade.MongoClient")
55 def test_upgrade_mongo_9_10_no_alarm_status(self, mock_mongo_client):
56 mock_db = MagicMock()
57 alarms = Mock()
58 alarms.find.return_value = [{"_id": "1"}]
59 collection_dict = {"alarms": alarms, "other": {}}
60 mock_db.list_collection_names.return_value = collection_dict
61 mock_db.__getitem__.side_effect = collection_dict.__getitem__
62 mock_db.alarms.return_value = alarms
63 mock_mongo_client.return_value = {"osm": mock_db}
64 MongoUpgrade910.upgrade("mongo_uri")
65 alarms.update_one.assert_called_once_with({"_id": "1"}, {"$set": {"alarm_status": "ok"}})
66
67
68 class TestUpgradeMongo1012(unittest.TestCase):
69 def setUp(self):
70 self.mock_db = MagicMock()
71 self.nsrs = Mock()
72 self.vnfrs = Mock()
73 self.k8s_clusters = Mock()
74
75 @patch("db_upgrade.MongoClient")
76 def test_update_nsr_empty_nsrs(self, mock_mongo_client):
77 self.nsrs.find.return_value = []
78 collection_list = {"nsrs": self.nsrs}
79 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
80 self.mock_db.list_collection_names.return_value = collection_list
81 mock_mongo_client.return_value = {"osm": self.mock_db}
82 MongoUpgrade1012.upgrade("mongo_uri")
83
84 @patch("db_upgrade.MongoClient")
85 def test_update_nsr_empty_nsr(self, mock_mongo_client):
86 nsr = MagicMock()
87 nsr_values = {"_id": "2", "_admin": {}}
88 nsr.__getitem__.side_effect = nsr_values.__getitem__
89 nsr.items.return_value = []
90 self.nsrs.find.return_value = [nsr]
91 collection_list = {"nsrs": self.nsrs}
92 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
93 self.mock_db.list_collection_names.return_value = collection_list
94 mock_mongo_client.return_value = {"osm": self.mock_db}
95 MongoUpgrade1012.upgrade("mongo_uri")
96
97 @patch("db_upgrade.MongoClient")
98 def test_update_nsr_add_vim_message(self, mock_mongo_client):
99 nsr = MagicMock()
100 vim_info1 = {"vim_info_key1": {}}
101 vim_info2 = {"vim_info_key2": {"vim_message": "Hello"}}
102 nsr_items = {"nsr_item_key": [{"vim_info": vim_info1}, {"vim_info": vim_info2}]}
103 nsr_values = {"_id": "2", "_admin": {}}
104 nsr.__getitem__.side_effect = nsr_values.__getitem__
105 nsr.items.return_value = nsr_items.items()
106 self.nsrs.find.return_value = [nsr]
107 collection_list = {"nsrs": self.nsrs}
108 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
109 self.mock_db.list_collection_names.return_value = collection_list
110 mock_mongo_client.return_value = {"osm": self.mock_db}
111 MongoUpgrade1012.upgrade("mongo_uri")
112 expected_vim_info = {"vim_info_key1": {"vim_message": None}}
113 expected_vim_info2 = {"vim_info_key2": {"vim_message": "Hello"}}
114 self.assertEqual(vim_info1, expected_vim_info)
115 self.assertEqual(vim_info2, expected_vim_info2)
116 self.nsrs.update_one.assert_called_once_with({"_id": "2"}, {"$set": nsr_items})
117
118 @patch("db_upgrade.MongoClient")
119 def test_update_nsr_admin(self, mock_mongo_client):
120 nsr = MagicMock()
121 k8s = [{"k8scluster-uuid": "namespace"}, {"k8scluster-uuid": "kube-system:k8s"}]
122 admin = {"deployed": {"K8s": k8s}}
123 nsr_values = {"_id": "2", "_admin": admin}
124 nsr.__getitem__.side_effect = nsr_values.__getitem__
125 nsr_items = {}
126 nsr.items.return_value = nsr_items.items()
127 self.nsrs.find.return_value = [nsr]
128 collection_list = {"nsrs": self.nsrs}
129 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
130 self.mock_db.list_collection_names.return_value = collection_list
131 mock_mongo_client.return_value = {"osm": self.mock_db}
132 MongoUpgrade1012.upgrade("mongo_uri")
133 expected_k8s = [{"k8scluster-uuid": "namespace"}, {"k8scluster-uuid": "k8s"}]
134 self.nsrs.update_one.assert_called_once_with(
135 {"_id": "2"}, {"$set": {"_admin.deployed.K8s": expected_k8s}}
136 )
137
138 @patch("db_upgrade.MongoClient")
139 def test_update_vnfr_empty_vnfrs(self, mock_mongo_client):
140 self.vnfrs.find.return_value = [{"_id": "10", "vdur": []}]
141 collection_list = {"vnfrs": self.vnfrs}
142 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
143 self.mock_db.list_collection_names.return_value = collection_list
144 mock_mongo_client.return_value = {"osm": self.mock_db}
145 MongoUpgrade1012.upgrade("mongo_uri")
146 self.vnfrs.update_one.assert_called_once_with({"_id": "10"}, {"$set": {"vdur": []}})
147
148 @patch("db_upgrade.MongoClient")
149 def test_update_vnfr_no_vim_info(self, mock_mongo_client):
150 vdur = {"other": {}}
151 vnfr = {"_id": "10", "vdur": [vdur]}
152 self.vnfrs.find.return_value = [vnfr]
153 collection_list = {"vnfrs": self.vnfrs}
154 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
155 self.mock_db.list_collection_names.return_value = collection_list
156 mock_mongo_client.return_value = {"osm": self.mock_db}
157 MongoUpgrade1012.upgrade("mongo_uri")
158 self.assertEqual(vdur, {"other": {}})
159 self.vnfrs.update_one.assert_called_once_with({"_id": "10"}, {"$set": {"vdur": [vdur]}})
160
161 @patch("db_upgrade.MongoClient")
162 def test_update_vnfr_vim_message_not_conditions_matched(self, mock_mongo_client):
163 vim_info = {"vim_message": "HelloWorld"}
164 vim_infos = {"key1": vim_info, "key2": "value2"}
165 vdur = {"vim_info": vim_infos, "other": {}}
166 vnfr = {"_id": "10", "vdur": [vdur]}
167 self.vnfrs.find.return_value = [vnfr]
168 collection_list = {"vnfrs": self.vnfrs}
169 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
170 self.mock_db.list_collection_names.return_value = collection_list
171 mock_mongo_client.return_value = {"osm": self.mock_db}
172 MongoUpgrade1012.upgrade("mongo_uri")
173 expected_vim_info = {"vim_message": "HelloWorld"}
174 self.assertEqual(vim_info, expected_vim_info)
175 self.vnfrs.update_one.assert_called_once_with({"_id": "10"}, {"$set": {"vdur": [vdur]}})
176
177 @patch("db_upgrade.MongoClient")
178 def test_update_vnfr_vim_message_is_missing(self, mock_mongo_client):
179 vim_info = {"interfaces_backup": "HelloWorld"}
180 vim_infos = {"key1": vim_info, "key2": "value2"}
181 vdur = {"vim_info": vim_infos, "other": {}}
182 vnfr = {"_id": "10", "vdur": [vdur]}
183 self.vnfrs.find.return_value = [vnfr]
184 collection_list = {"vnfrs": self.vnfrs}
185 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
186 self.mock_db.list_collection_names.return_value = collection_list
187 mock_mongo_client.return_value = {"osm": self.mock_db}
188 MongoUpgrade1012.upgrade("mongo_uri")
189 expected_vim_info = {"vim_message": None, "interfaces_backup": "HelloWorld"}
190 self.assertEqual(vim_info, expected_vim_info)
191 self.vnfrs.update_one.assert_called_once_with({"_id": "10"}, {"$set": {"vdur": [vdur]}})
192
193 @patch("db_upgrade.MongoClient")
194 def test_update_vnfr_interfaces_backup_is_updated(self, mock_mongo_client):
195 vim_info = {"interfaces": "HelloWorld", "vim_message": "ByeWorld"}
196 vim_infos = {"key1": vim_info, "key2": "value2"}
197 vdur = {"vim_info": vim_infos, "other": {}}
198 vnfr = {"_id": "10", "vdur": [vdur]}
199 self.vnfrs.find.return_value = [vnfr]
200 collection_list = {"vnfrs": self.vnfrs}
201 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
202 self.mock_db.list_collection_names.return_value = collection_list
203 mock_mongo_client.return_value = {"osm": self.mock_db}
204 MongoUpgrade1012.upgrade("mongo_uri")
205 expected_vim_info = {
206 "interfaces": "HelloWorld",
207 "vim_message": "ByeWorld",
208 "interfaces_backup": "HelloWorld",
209 }
210 self.assertEqual(vim_info, expected_vim_info)
211 self.vnfrs.update_one.assert_called_once_with({"_id": "10"}, {"$set": {"vdur": [vdur]}})
212
213 @patch("db_upgrade.MongoClient")
214 def test_update_k8scluster_empty_k8scluster(self, mock_mongo_client):
215 self.k8s_clusters.find.return_value = []
216 collection_list = {"k8sclusters": self.k8s_clusters}
217 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
218 self.mock_db.list_collection_names.return_value = collection_list
219 mock_mongo_client.return_value = {"osm": self.mock_db}
220 MongoUpgrade1012.upgrade("mongo_uri")
221
222 @patch("db_upgrade.MongoClient")
223 def test_update_k8scluster_replace_namespace_in_helm_chart(self, mock_mongo_client):
224 helm_chart = {"id": "kube-system:Hello", "other": {}}
225 k8s_cluster = {"_id": "8", "_admin": {"helm-chart": helm_chart}}
226 self.k8s_clusters.find.return_value = [k8s_cluster]
227 collection_list = {"k8sclusters": self.k8s_clusters}
228 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
229 self.mock_db.list_collection_names.return_value = collection_list
230 mock_mongo_client.return_value = {"osm": self.mock_db}
231 MongoUpgrade1012.upgrade("mongo_uri")
232 expected_helm_chart = {"id": "Hello", "other": {}}
233 expected_k8s_cluster = {"_id": "8", "_admin": {"helm-chart": expected_helm_chart}}
234 self.k8s_clusters.update_one.assert_called_once_with(
235 {"_id": "8"}, {"$set": expected_k8s_cluster}
236 )
237
238 @patch("db_upgrade.MongoClient")
239 def test_update_k8scluster_replace_namespace_in_helm_chart_v3(self, mock_mongo_client):
240 helm_chart_v3 = {"id": "kube-system:Hello", "other": {}}
241 k8s_cluster = {"_id": "8", "_admin": {"helm-chart-v3": helm_chart_v3}}
242 self.k8s_clusters.find.return_value = [k8s_cluster]
243 collection_list = {"k8sclusters": self.k8s_clusters}
244 self.mock_db.__getitem__.side_effect = collection_list.__getitem__
245 self.mock_db.list_collection_names.return_value = collection_list
246 mock_mongo_client.return_value = {"osm": self.mock_db}
247 MongoUpgrade1012.upgrade("mongo_uri")
248 expected_helm_chart_v3 = {"id": "Hello", "other": {}}
249 expected_k8s_cluster = {"_id": "8", "_admin": {"helm-chart-v3": expected_helm_chart_v3}}
250 self.k8s_clusters.update_one.assert_called_once_with(
251 {"_id": "8"}, {"$set": expected_k8s_cluster}
252 )
253
254
255 class TestPatch1837(unittest.TestCase):
256 def setUp(self):
257 self.mock_db = MagicMock()
258 self.vnfrs = Mock()
259 self.nslcmops = Mock()
260
261 @patch("db_upgrade.MongoClient")
262 def test_update_vnfrs_params_no_vnfrs_or_nslcmops(self, mock_mongo_client):
263 collection_dict = {"other": {}}
264 self.mock_db.list_collection_names.return_value = collection_dict
265 mock_mongo_client.return_value = {"osm": self.mock_db}
266 MongoPatch1837.patch("mongo_uri")
267
268 @patch("db_upgrade.MongoClient")
269 def test_update_vnfrs_params_no_kdur(self, mock_mongo_client):
270 self.vnfrs.find.return_value = {"_id": "1"}
271 collection_dict = {"vnfrs": self.vnfrs, "other": {}}
272 self.mock_db.list_collection_names.return_value = collection_dict
273 mock_mongo_client.return_value = {"osm": self.mock_db}
274 MongoPatch1837.patch("mongo_uri")
275
276 @patch("db_upgrade.MongoClient")
277 def test_update_vnfrs_params_kdur_without_additional_params(self, mock_mongo_client):
278 kdur = [{"other": {}}]
279 self.vnfrs.find.return_value = [{"_id": "1", "kdur": kdur}]
280 collection_dict = {"vnfrs": self.vnfrs, "other": {}}
281 self.mock_db.list_collection_names.return_value = collection_dict
282 self.mock_db.__getitem__.side_effect = collection_dict.__getitem__
283 mock_mongo_client.return_value = {"osm": self.mock_db}
284 MongoPatch1837.patch("mongo_uri")
285 self.vnfrs.update_one.assert_called_once_with({"_id": "1"}, {"$set": {"kdur": kdur}})
286
287 @patch("db_upgrade.MongoClient")
288 def test_update_vnfrs_params_kdur_two_additional_params(self, mock_mongo_client):
289 kdur1 = {"additionalParams": "additional_params", "other": {}}
290 kdur2 = {"additionalParams": 4, "other": {}}
291 kdur = [kdur1, kdur2]
292 self.vnfrs.find.return_value = [{"_id": "1", "kdur": kdur}]
293 collection_dict = {"vnfrs": self.vnfrs, "other": {}}
294 self.mock_db.list_collection_names.return_value = collection_dict
295 self.mock_db.__getitem__.side_effect = collection_dict.__getitem__
296 mock_mongo_client.return_value = {"osm": self.mock_db}
297 MongoPatch1837.patch("mongo_uri")
298 self.vnfrs.update_one.assert_called_once_with(
299 {"_id": "1"}, {"$set": {"kdur": [kdur1, {"additionalParams": "4", "other": {}}]}}
300 )
301
302 @patch("db_upgrade.MongoClient")
303 def test_update_nslcmops_params_no_nslcmops(self, mock_mongo_client):
304 self.nslcmops.find.return_value = []
305 collection_dict = {"nslcmops": self.nslcmops, "other": {}}
306 self.mock_db.list_collection_names.return_value = collection_dict
307 self.mock_db.__getitem__.side_effect = collection_dict.__getitem__
308 mock_mongo_client.return_value = {"osm": self.mock_db}
309 MongoPatch1837.patch("mongo_uri")
310
311 @patch("db_upgrade.MongoClient")
312 def test_update_nslcmops_additional_params(self, mock_mongo_client):
313 operation_params_list = {"additionalParamsForVnf": [1, 2, 3]}
314 operation_params_dict = {"primitive_params": {"dict_key": 5}}
315 nslcmops1 = {"_id": "1", "other": {}}
316 nslcmops2 = {"_id": "2", "operationParams": operation_params_list, "other": {}}
317 nslcmops3 = {"_id": "3", "operationParams": operation_params_dict, "other": {}}
318 self.nslcmops.find.return_value = [nslcmops1, nslcmops2, nslcmops3]
319 collection_dict = {"nslcmops": self.nslcmops, "other": {}}
320 self.mock_db.list_collection_names.return_value = collection_dict
321 self.mock_db.__getitem__.side_effect = collection_dict.__getitem__
322 mock_mongo_client.return_value = {"osm": self.mock_db}
323 MongoPatch1837.patch("mongo_uri")
324 call1 = call(
325 {"_id": "2"}, {"$set": {"operationParams": {"additionalParamsForVnf": "[1, 2, 3]"}}}
326 )
327 call2 = call(
328 {"_id": "3"}, {"$set": {"operationParams": {"primitive_params": '{"dict_key": 5}'}}}
329 )
330 expected_calls = [call1, call2]
331 self.nslcmops.update_one.assert_has_calls(expected_calls)
332
333
334 class TestMongoUpgrade(unittest.TestCase):
335 def setUp(self):
336 self.mongo = MongoUpgrade("http://fake_mongo:27017")
337 self.upgrade_function = Mock()
338 self.patch_function = Mock()
339 db_upgrade.MONGODB_UPGRADE_FUNCTIONS = {"9": {"10": [self.upgrade_function]}}
340 db_upgrade.BUG_FIXES = {1837: self.patch_function}
341
342 def test_validate_upgrade_fail_target(self):
343 valid_current = "9"
344 invalid_target = "7"
345 with self.assertRaises(Exception) as context:
346 self.mongo._validate_upgrade(valid_current, invalid_target)
347 self.assertEqual("cannot upgrade from version 9 to 7.", str(context.exception))
348
349 def test_validate_upgrade_fail_current(self):
350 invalid_current = "7"
351 invalid_target = "8"
352 with self.assertRaises(Exception) as context:
353 self.mongo._validate_upgrade(invalid_current, invalid_target)
354 self.assertEqual("cannot upgrade from 7 version.", str(context.exception))
355
356 def test_validate_upgrade_pass(self):
357 valid_current = "9"
358 valid_target = "10"
359 self.assertIsNone(self.mongo._validate_upgrade(valid_current, valid_target))
360
361 @patch("db_upgrade.MongoUpgrade._validate_upgrade")
362 def test_update_mongo_success(self, mock_validate):
363 valid_current = "9"
364 valid_target = "10"
365 mock_validate.return_value = ""
366 self.mongo.upgrade(valid_current, valid_target)
367 self.upgrade_function.assert_called_once()
368
369 def test_validate_apply_patch(self):
370 bug_number = 1837
371 self.mongo.apply_patch(bug_number)
372 self.patch_function.assert_called_once()
373
374 def test_validate_apply_patch_invalid_bug_fail(self):
375 bug_number = 2
376 with self.assertRaises(Exception) as context:
377 self.mongo.apply_patch(bug_number)
378 self.assertEqual("There is no patch for bug 2", str(context.exception))
379 self.patch_function.assert_not_called()
380
381
382 class TestMysqlUpgrade(unittest.TestCase):
383 def setUp(self):
384 self.mysql = MysqlUpgrade("mysql://fake_mysql:23023")
385 self.upgrade_function = Mock()
386 db_upgrade.MYSQL_UPGRADE_FUNCTIONS = {"9": {"10": [self.upgrade_function]}}
387
388 def test_validate_upgrade_mysql_fail_current(self):
389 invalid_current = "7"
390 invalid_target = "8"
391 with self.assertRaises(Exception) as context:
392 self.mysql._validate_upgrade(invalid_current, invalid_target)
393 self.assertEqual("cannot upgrade from 7 version.", str(context.exception))
394
395 def test_validate_upgrade_mysql_fail_target(self):
396 valid_current = "9"
397 invalid_target = "7"
398 with self.assertRaises(Exception) as context:
399 self.mysql._validate_upgrade(valid_current, invalid_target)
400 self.assertEqual("cannot upgrade from version 9 to 7.", str(context.exception))
401
402 def test_validate_upgrade_mysql_success(self):
403 valid_current = "9"
404 valid_target = "10"
405 self.assertIsNone(self.mysql._validate_upgrade(valid_current, valid_target))
406
407 @patch("db_upgrade.MysqlUpgrade._validate_upgrade")
408 def test_upgrade_mysql_success(self, mock_validate):
409 valid_current = "9"
410 valid_target = "10"
411 mock_validate.return_value = ""
412 self.mysql.upgrade(valid_current, valid_target)
413 self.upgrade_function.assert_called_once()