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