7bd6c655f8656fb5998fd949485f18f99bd88b57
[osm/LCM.git] / osm_lcm / tests / test_vim_sdn.py
1 # Copyright 2021 Canonical Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain 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,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import asyncio
16 from unittest import TestCase
17 from unittest.mock import Mock, patch, MagicMock
18
19
20 from osm_common import msgbase
21 from osm_common.dbbase import DbException
22 from osm_lcm.vim_sdn import K8sClusterLcm, VcaLcm
23
24
25 class AsyncMock(MagicMock):
26 async def __call__(self, *args, **kwargs):
27 return super(AsyncMock, self).__call__(*args, **kwargs)
28
29
30 class TestVcaLcm(TestCase):
31 @patch("osm_lcm.lcm_utils.Database")
32 @patch("osm_lcm.lcm_utils.Filesystem")
33 def setUp(self, mock_filesystem, mock_database):
34 self.loop = asyncio.get_event_loop()
35 self.msg = Mock(msgbase.MsgBase())
36 self.lcm_tasks = Mock()
37 self.config = {"database": {"driver": "mongo"}}
38 self.vca_lcm = VcaLcm(self.msg, self.lcm_tasks, self.config)
39 self.vca_lcm.db = Mock()
40 self.vca_lcm.fs = Mock()
41
42 def test_vca_lcm_create(self):
43 vca_content = {"op_id": "order-id", "_id": "id"}
44 db_vca = {
45 "_id": "vca-id",
46 "secret": "secret",
47 "cacert": "cacert",
48 "schema_version": "1.11",
49 }
50 order_id = "order-id"
51 self.lcm_tasks.lock_HA.return_value = True
52 self.vca_lcm.db.get_one.return_value = db_vca
53 self.vca_lcm.n2vc.validate_vca = AsyncMock()
54 self.vca_lcm.update_db_2 = Mock()
55
56 self.loop.run_until_complete(self.vca_lcm.create(vca_content, order_id))
57
58 self.lcm_tasks.lock_HA.assert_called_with("vca", "create", "order-id")
59 self.vca_lcm.db.encrypt_decrypt_fields.assert_called_with(
60 db_vca,
61 "decrypt",
62 ["secret", "cacert"],
63 schema_version="1.11",
64 salt="vca-id",
65 )
66 self.vca_lcm.update_db_2.assert_called_with(
67 "vca",
68 "id",
69 {
70 "_admin.operationalState": "ENABLED",
71 "_admin.detailed-status": "Connectivity: ok",
72 },
73 )
74 self.lcm_tasks.unlock_HA.assert_called_with(
75 "vca",
76 "create",
77 "order-id",
78 operationState="COMPLETED",
79 detailed_status="VCA validated",
80 )
81 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
82
83 def test_vca_lcm_create_exception(self):
84 vca_content = {"op_id": "order-id", "_id": "id"}
85 db_vca = {
86 "_id": "vca-id",
87 "secret": "secret",
88 "cacert": "cacert",
89 "schema_version": "1.11",
90 }
91 order_id = "order-id"
92 self.lcm_tasks.lock_HA.return_value = True
93 self.vca_lcm.db.get_one.return_value = db_vca
94 self.vca_lcm.n2vc.validate_vca = AsyncMock()
95 self.vca_lcm.n2vc.validate_vca.side_effect = Exception("failed")
96 self.vca_lcm.update_db_2 = Mock()
97 self.vca_lcm.update_db_2.side_effect = DbException("failed")
98 self.loop.run_until_complete(self.vca_lcm.create(vca_content, order_id))
99
100 self.lcm_tasks.lock_HA.assert_called_with("vca", "create", "order-id")
101 self.vca_lcm.db.encrypt_decrypt_fields.assert_called_with(
102 db_vca,
103 "decrypt",
104 ["secret", "cacert"],
105 schema_version="1.11",
106 salt="vca-id",
107 )
108 self.vca_lcm.update_db_2.assert_called_with(
109 "vca",
110 "id",
111 {
112 "_admin.operationalState": "ERROR",
113 "_admin.detailed-status": "Failed with exception: failed",
114 },
115 )
116 self.lcm_tasks.unlock_HA.assert_not_called()
117 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
118
119 def test_vca_lcm_edit_success_no_config(self):
120 vca_content = {
121 "op_id": "order-id",
122 "_id": "id",
123 "description": "test-description",
124 }
125 db_vca = {
126 "_id": "vca-id",
127 "secret": "secret",
128 "cacert": "cacert",
129 "schema_version": "1.11",
130 }
131 order_id = "order-id"
132 self.lcm_tasks.lock_HA.return_value = True
133 self.vca_lcm.db.get_one.return_value = db_vca
134 self.vca_lcm.n2vc.validate_vca = AsyncMock()
135 self.vca_lcm.update_db_2 = Mock()
136 self.loop.run_until_complete(self.vca_lcm.edit(vca_content, order_id))
137 self.vca_lcm.n2vc.validate_vca.assert_not_called()
138 self.lcm_tasks.unlock_HA.assert_called_with(
139 "vca",
140 "edit",
141 "order-id",
142 operationState="COMPLETED",
143 detailed_status="Edited",
144 )
145 self.vca_lcm.update_db_2.assert_called_with(
146 "vca",
147 "id",
148 {},
149 )
150 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
151
152 def test_vca_lcm_edit_success_config(self):
153 vca_content = {"op_id": "order-id", "_id": "id", "cacert": "editcacert"}
154 db_vca = {
155 "_id": "vca-id",
156 "secret": "secret",
157 "cacert": "cacert",
158 "schema_version": "1.11",
159 }
160 order_id = "order-id"
161 self.lcm_tasks.lock_HA.return_value = True
162 self.vca_lcm.db.get_one.return_value = db_vca
163 self.vca_lcm.n2vc.validate_vca = AsyncMock()
164 self.vca_lcm.update_db_2 = Mock()
165 self.loop.run_until_complete(self.vca_lcm.edit(vca_content, order_id))
166 self.vca_lcm.n2vc.validate_vca.assert_called()
167 self.lcm_tasks.unlock_HA.assert_called_with(
168 "vca",
169 "edit",
170 "order-id",
171 operationState="COMPLETED",
172 detailed_status="Edited",
173 )
174 self.vca_lcm.update_db_2.assert_called_with(
175 "vca",
176 "id",
177 {
178 "_admin.operationalState": "ENABLED",
179 "_admin.detailed-status": "Connectivity: ok",
180 },
181 )
182 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
183
184 def test_vca_lcm_edit_exception_no_config(self):
185 vca_content = {
186 "op_id": "order-id",
187 "_id": "id",
188 "description": "new-description",
189 }
190 db_vca = {
191 "_id": "vca-id",
192 "secret": "secret",
193 "cacert": "cacert",
194 "schema_version": "1.11",
195 }
196 order_id = "order-id"
197 self.lcm_tasks.lock_HA.return_value = True
198 self.vca_lcm.db.get_one.return_value = db_vca
199 self.vca_lcm.n2vc.validate_vca = AsyncMock()
200 # validate_vca should not be called in this case
201 self.vca_lcm.n2vc.validate_vca.side_effect = Exception("failed")
202 self.vca_lcm.update_db_2 = Mock()
203 self.loop.run_until_complete(self.vca_lcm.edit(vca_content, order_id))
204 self.lcm_tasks.lock_HA.assert_called_with("vca", "edit", "order-id")
205 self.lcm_tasks.unlock_HA.assert_called_with(
206 "vca",
207 "edit",
208 "order-id",
209 operationState="COMPLETED",
210 detailed_status="Edited",
211 )
212 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
213
214 def test_vca_lcm_edit_exception_config(self):
215 vca_content = {"op_id": "order-id", "_id": "id", "user": "new-user"}
216 db_vca = {
217 "_id": "vca-id",
218 "secret": "secret",
219 "cacert": "cacert",
220 "schema_version": "1.11",
221 }
222 order_id = "order-id"
223 self.lcm_tasks.lock_HA.return_value = True
224 self.vca_lcm.db.get_one.return_value = db_vca
225 self.vca_lcm.n2vc.validate_vca = AsyncMock()
226 # validate_vca should be called in this case
227 self.vca_lcm.n2vc.validate_vca.side_effect = Exception("failed")
228 self.vca_lcm.update_db_2 = Mock()
229 self.loop.run_until_complete(self.vca_lcm.edit(vca_content, order_id))
230 self.lcm_tasks.lock_HA.assert_called_with("vca", "edit", "order-id")
231 self.lcm_tasks.unlock_HA.assert_called_with(
232 "vca",
233 "edit",
234 "order-id",
235 operationState="FAILED",
236 detailed_status="Failed with exception: failed",
237 )
238 self.vca_lcm.update_db_2.assert_called_with(
239 "vca",
240 "id",
241 {
242 "_admin.operationalState": "ERROR",
243 "_admin.detailed-status": "Failed with exception: failed",
244 },
245 )
246 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
247
248 def test_vca_lcm_edit_db_exception(self):
249 vca_content = {
250 "op_id": "order-id",
251 "_id": "id",
252 "description": "new-description",
253 }
254 db_vca = {
255 "_id": "vca-id",
256 "secret": "secret",
257 "cacert": "cacert",
258 "schema_version": "1.11",
259 }
260 order_id = "order-id"
261 self.lcm_tasks.lock_HA.return_value = True
262 self.vca_lcm.db.get_one.return_value = db_vca
263 self.vca_lcm.n2vc.validate_vca = AsyncMock()
264 self.vca_lcm.update_db_2 = Mock()
265 self.vca_lcm.update_db_2.side_effect = DbException("failed")
266 self.loop.run_until_complete(self.vca_lcm.edit(vca_content, order_id))
267 self.vca_lcm.n2vc.validate_vca.assert_not_called()
268 self.lcm_tasks.lock_HA.assert_called_with("vca", "edit", "order-id")
269 self.vca_lcm.update_db_2.assert_called_with(
270 "vca",
271 "id",
272 {},
273 )
274 self.lcm_tasks.unlock_HA.assert_not_called()
275 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
276
277 def test_vca_lcm_delete(self):
278 vca_content = {"op_id": "order-id", "_id": "id"}
279 order_id = "order-id"
280 self.lcm_tasks.lock_HA.return_value = True
281 self.vca_lcm.update_db_2 = Mock()
282
283 self.loop.run_until_complete(self.vca_lcm.delete(vca_content, order_id))
284
285 self.lcm_tasks.lock_HA.assert_called_with("vca", "delete", "order-id")
286 self.vca_lcm.db.del_one.assert_called_with("vca", {"_id": "id"})
287 self.vca_lcm.update_db_2.assert_called_with("vca", "id", None)
288 self.lcm_tasks.unlock_HA.assert_called_with(
289 "vca",
290 "delete",
291 "order-id",
292 operationState="COMPLETED",
293 detailed_status="deleted",
294 )
295 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
296
297 def test_vca_lcm_delete_exception(self):
298 vca_content = {"op_id": "order-id", "_id": "id"}
299 order_id = "order-id"
300 self.lcm_tasks.lock_HA.return_value = True
301 self.vca_lcm.update_db_2 = Mock()
302 self.vca_lcm.db.del_one.side_effect = Exception("failed deleting")
303 self.vca_lcm.update_db_2.side_effect = DbException("failed")
304
305 self.loop.run_until_complete(self.vca_lcm.delete(vca_content, order_id))
306
307 self.lcm_tasks.lock_HA.assert_called_with("vca", "delete", "order-id")
308 self.vca_lcm.db.del_one.assert_called_with("vca", {"_id": "id"})
309 self.vca_lcm.update_db_2.assert_called_with(
310 "vca",
311 "id",
312 {
313 "_admin.operationalState": "ERROR",
314 "_admin.detailed-status": "Failed with exception: failed deleting",
315 },
316 )
317 self.lcm_tasks.unlock_HA.not_called()
318 self.lcm_tasks.remove.assert_called_with("vca", "id", "order-id")
319
320
321 class TestK8SClusterLcm(TestCase):
322 @patch("osm_lcm.vim_sdn.K8sHelmConnector")
323 @patch("osm_lcm.vim_sdn.K8sHelm3Connector")
324 @patch("osm_lcm.vim_sdn.K8sJujuConnector")
325 @patch("osm_lcm.lcm_utils.Database")
326 @patch("osm_lcm.lcm_utils.Filesystem")
327 def setUp(
328 self,
329 mock_filesystem,
330 mock_database,
331 juju_connector,
332 helm3_connector,
333 helm_connector,
334 ):
335 self.loop = asyncio.get_event_loop()
336 self.msg = Mock(msgbase.MsgBase())
337 self.lcm_tasks = Mock()
338 self.config = {"database": {"driver": "mongo"}}
339 self.vca_config = {
340 "VCA": {
341 "helmpath": "/usr/local/bin/helm",
342 "helm3path": "/usr/local/bin/helm3",
343 "kubectlpath": "/usr/bin/kubectl",
344 }
345 }
346 self.k8scluster_lcm = K8sClusterLcm(self.msg, self.lcm_tasks, self.vca_config)
347 self.k8scluster_lcm.db = Mock()
348 self.k8scluster_lcm.fs = Mock()
349
350 def test_k8scluster_edit(self):
351 k8scluster_content = {"op_id": "op-id", "_id": "id"}
352 order_id = "order-id"
353 self.lcm_tasks.lock_HA.return_value = True
354 self.loop.run_until_complete(
355 self.k8scluster_lcm.edit(k8scluster_content, order_id)
356 )
357 self.lcm_tasks.unlock_HA.assert_called_with(
358 "k8scluster",
359 "edit",
360 "op-id",
361 operationState="COMPLETED",
362 detailed_status="Not implemented",
363 )
364 self.lcm_tasks.remove.assert_called_with("k8scluster", "id", order_id)
365
366 def test_k8scluster_edit_lock_false(self):
367 k8scluster_content = {"op_id": "op-id", "_id": "id"}
368 order_id = "order-id"
369 self.lcm_tasks.lock_HA.return_value = False
370 self.loop.run_until_complete(
371 self.k8scluster_lcm.edit(k8scluster_content, order_id)
372 )
373 self.lcm_tasks.unlock_HA.assert_not_called()
374 self.lcm_tasks.remove.assert_not_called()
375
376 def test_k8scluster_edit_no_opid(self):
377 k8scluster_content = {"_id": "id"}
378 order_id = "order-id"
379 self.lcm_tasks.lock_HA.return_value = True
380 self.loop.run_until_complete(
381 self.k8scluster_lcm.edit(k8scluster_content, order_id)
382 )
383 self.lcm_tasks.unlock_HA.assert_called_with(
384 "k8scluster",
385 "edit",
386 None,
387 operationState="COMPLETED",
388 detailed_status="Not implemented",
389 )
390 self.lcm_tasks.remove.assert_called_with("k8scluster", "id", order_id)
391
392 def test_k8scluster_edit_no_orderid(self):
393 k8scluster_content = {"op_id": "op-id", "_id": "id"}
394 order_id = None
395 self.lcm_tasks.lock_HA.return_value = True
396 self.loop.run_until_complete(
397 self.k8scluster_lcm.edit(k8scluster_content, order_id)
398 )
399 self.lcm_tasks.unlock_HA.assert_called_with(
400 "k8scluster",
401 "edit",
402 "op-id",
403 operationState="COMPLETED",
404 detailed_status="Not implemented",
405 )
406 self.lcm_tasks.remove.assert_called_with("k8scluster", "id", order_id)