1 # Copyright 2020 Canonical Ltd.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
18 from unittest
.mock
import Mock
19 from unittest
.mock
import patch
23 from n2vc
.definitions
import Offer
, RelationEndpoint
24 from n2vc
.n2vc_juju_conn
import N2VCJujuConnector
25 from osm_common
import fslocal
26 from n2vc
.exceptions
import (
27 N2VCBadArgumentsException
,
29 JujuApplicationNotFound
,
31 from n2vc
.tests
.unit
.utils
import AsyncMock
32 from n2vc
.vca
.connection_data
import ConnectionData
35 class N2VCJujuConnTestCase(asynctest
.TestCase
):
36 @asynctest.mock
.patch("n2vc.n2vc_juju_conn.MotorStore")
37 @asynctest.mock
.patch("n2vc.n2vc_juju_conn.get_connection")
38 @asynctest.mock
.patch("n2vc.vca.connection_data.base64_to_cacert")
41 mock_base64_to_cacert
=None,
42 mock_get_connection
=None,
45 self
.loop
= asyncio
.get_event_loop()
47 mock_base64_to_cacert
.return_value
= """
48 -----BEGIN CERTIFICATE-----
50 -----END CERTIFICATE-----"""
51 mock_store
.return_value
= AsyncMock()
52 mock_vca_connection
= Mock()
53 mock_get_connection
.return_value
= mock_vca_connection
54 mock_vca_connection
.data
.return_value
= ConnectionData(
56 "endpoints": ["1.2.3.4:17070"],
62 "lxd-credentials": "credentials",
63 "k8s-cloud": "k8s_cloud",
64 "k8s-credentials": "k8s_credentials",
66 "api-proxy": "api_proxy",
69 logging
.disable(logging
.CRITICAL
)
71 N2VCJujuConnector
.get_public_key
= Mock()
72 self
.n2vc
= N2VCJujuConnector(
79 N2VCJujuConnector
.get_public_key
.assert_not_called()
80 self
.n2vc
.libjuju
= Mock()
83 class GetMetricssTest(N2VCJujuConnTestCase
):
85 super(GetMetricssTest
, self
).setUp()
86 self
.n2vc
.libjuju
.get_metrics
= AsyncMock()
88 def test_success(self
):
89 _
= self
.loop
.run_until_complete(self
.n2vc
.get_metrics("model", "application"))
90 self
.n2vc
.libjuju
.get_metrics
.assert_called_once()
92 def test_except(self
):
93 self
.n2vc
.libjuju
.get_metrics
.side_effect
= Exception()
94 with self
.assertRaises(Exception):
95 _
= self
.loop
.run_until_complete(
96 self
.n2vc
.get_metrics("model", "application")
98 self
.n2vc
.libjuju
.get_metrics
.assert_called_once()
101 class UpdateVcaStatusTest(N2VCJujuConnTestCase
):
103 super(UpdateVcaStatusTest
, self
).setUp()
104 self
.n2vc
.libjuju
.get_controller
= AsyncMock()
105 self
.n2vc
.libjuju
.get_model
= AsyncMock()
106 self
.n2vc
.libjuju
.get_executed_actions
= AsyncMock()
107 self
.n2vc
.libjuju
.get_actions
= AsyncMock()
108 self
.n2vc
.libjuju
.get_application_configs
= AsyncMock()
109 self
.n2vc
.libjuju
._get
_application
= AsyncMock()
114 self
.loop
.run_until_complete(
115 self
.n2vc
.update_vca_status(
116 {"model": {"applications": {"app": {"actions": {}}}}}
119 self
.n2vc
.libjuju
.get_executed_actions
.assert_called_once()
120 self
.n2vc
.libjuju
.get_actions
.assert_called_once()
121 self
.n2vc
.libjuju
.get_application_configs
.assert_called_once()
123 def test_exception(self
):
124 self
.n2vc
.libjuju
.get_model
.return_value
= None
125 self
.n2vc
.libjuju
.get_executed_actions
.side_effect
= Exception()
126 with self
.assertRaises(Exception):
127 self
.loop
.run_until_complete(
128 self
.n2vc
.update_vca_status(
129 {"model": {"applications": {"app": {"actions": {}}}}}
132 self
.n2vc
.libjuju
.get_executed_actions
.assert_not_called()
133 self
.n2vc
.libjuju
.get_actions
.assert_not_called_once()
134 self
.n2vc
.libjuju
.get_application_configs
.assert_not_called_once()
137 @asynctest.mock
.patch("osm_common.fslocal.FsLocal.file_exists")
138 @asynctest.mock
.patch(
139 "osm_common.fslocal.FsLocal.path", new_callable
=asynctest
.PropertyMock
, create
=True
141 class K8sProxyCharmsTest(N2VCJujuConnTestCase
):
143 super(K8sProxyCharmsTest
, self
).setUp()
144 self
.n2vc
.libjuju
.model_exists
= AsyncMock()
145 self
.n2vc
.libjuju
.add_model
= AsyncMock()
146 self
.n2vc
.libjuju
.deploy_charm
= AsyncMock()
147 self
.n2vc
.libjuju
.model_exists
.return_value
= False
150 "n2vc.n2vc_juju_conn.generate_random_alfanum_string",
151 **{"return_value": "random"}
155 mock_generate_random_alfanum_string
,
159 mock_file_exists
.return_value
= True
160 mock_path
.return_value
= "/path"
161 ee_id
= self
.loop
.run_until_complete(
162 self
.n2vc
.install_k8s_proxy_charm(
164 "nsi-id.ns-id.vnf-id.vdu",
170 self
.n2vc
.libjuju
.add_model
.assert_called_once()
171 self
.n2vc
.libjuju
.deploy_charm
.assert_called_once_with(
172 model_name
="ns-id-k8s",
173 application_name
="app-vnf-vnf-id-vdu-vdu-random",
177 progress_timeout
=None,
181 self
.assertEqual(ee_id
, "ns-id-k8s.app-vnf-vnf-id-vdu-vdu-random.k8s")
183 def test_no_artifact_path(
188 with self
.assertRaises(N2VCBadArgumentsException
):
189 ee_id
= self
.loop
.run_until_complete(
190 self
.n2vc
.install_k8s_proxy_charm(
192 "nsi-id.ns-id.vnf-id.vdu",
197 self
.assertIsNone(ee_id
)
204 with self
.assertRaises(N2VCBadArgumentsException
):
205 ee_id
= self
.loop
.run_until_complete(
206 self
.n2vc
.install_k8s_proxy_charm(
208 "nsi-id.ns-id.vnf-id.vdu",
213 self
.assertIsNone(ee_id
)
215 def test_file_not_exists(
220 mock_file_exists
.return_value
= False
221 with self
.assertRaises(N2VCBadArgumentsException
):
222 ee_id
= self
.loop
.run_until_complete(
223 self
.n2vc
.install_k8s_proxy_charm(
225 "nsi-id.ns-id.vnf-id.vdu",
230 self
.assertIsNone(ee_id
)
237 mock_file_exists
.return_value
= True
238 mock_path
.return_value
= "/path"
239 self
.n2vc
.libjuju
.deploy_charm
.side_effect
= Exception()
240 with self
.assertRaises(N2VCException
):
241 ee_id
= self
.loop
.run_until_complete(
242 self
.n2vc
.install_k8s_proxy_charm(
244 "nsi-id.ns-id.vnf-id.vdu",
249 self
.assertIsNone(ee_id
)
252 class AddRelationTest(N2VCJujuConnTestCase
):
254 super(AddRelationTest
, self
).setUp()
255 self
.n2vc
.libjuju
.add_relation
= AsyncMock()
256 self
.n2vc
.libjuju
.offer
= AsyncMock()
257 self
.n2vc
.libjuju
.get_controller
= AsyncMock()
258 self
.n2vc
.libjuju
.consume
= AsyncMock()
260 def test_standard_relation(self
):
261 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
262 relation_endpoint_2
= RelationEndpoint("model-1.app2.1", None, "endpoint")
263 self
.loop
.run_until_complete(
264 self
.n2vc
.add_relation(relation_endpoint_1
, relation_endpoint_2
)
266 self
.n2vc
.libjuju
.add_relation
.assert_called_once_with(
267 model_name
="model-1", endpoint_1
="app1:endpoint", endpoint_2
="app2:endpoint"
269 self
.n2vc
.libjuju
.offer
.assert_not_called()
270 self
.n2vc
.libjuju
.consume
.assert_not_called()
272 def test_cmr_relation_same_controller(self
):
273 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
274 relation_endpoint_2
= RelationEndpoint("model-2.app2.1", None, "endpoint")
275 offer
= Offer("admin/model-1.app1")
276 self
.n2vc
.libjuju
.offer
.return_value
= offer
277 self
.n2vc
.libjuju
.consume
.return_value
= "saas"
278 self
.loop
.run_until_complete(
279 self
.n2vc
.add_relation(relation_endpoint_1
, relation_endpoint_2
)
281 self
.n2vc
.libjuju
.offer
.assert_called_once_with(relation_endpoint_1
)
282 self
.n2vc
.libjuju
.consume
.assert_called_once()
283 self
.n2vc
.libjuju
.add_relation
.assert_called_once_with(
284 "model-2", "app2:endpoint", "saas"
287 def test_relation_exception(self
):
288 relation_endpoint_1
= RelationEndpoint("model-1.app1.0", None, "endpoint")
289 relation_endpoint_2
= RelationEndpoint("model-2.app2.1", None, "endpoint")
290 self
.n2vc
.libjuju
.offer
.side_effect
= Exception()
291 with self
.assertRaises(N2VCException
):
292 self
.loop
.run_until_complete(
293 self
.n2vc
.add_relation(relation_endpoint_1
, relation_endpoint_2
)
297 class UpgradeCharmTest(N2VCJujuConnTestCase
):
299 super(UpgradeCharmTest
, self
).setUp()
300 self
.n2vc
._get
_libjuju
= AsyncMock(return_value
=self
.n2vc
.libjuju
)
301 N2VCJujuConnector
._get
_ee
_id
_components
= Mock()
302 self
.n2vc
.libjuju
.upgrade_charm
= AsyncMock()
304 def test_empty_ee_id(self
):
305 with self
.assertRaises(N2VCBadArgumentsException
):
306 self
.loop
.run_until_complete(
307 self
.n2vc
.upgrade_charm(
308 "", "/sample_charm_path", "sample_charm_id", "native-charm", None
311 self
.n2vc
._get
_libjuju
.assert_called()
312 self
.n2vc
._get
_ee
_id
_components
.assert_not_called()
313 self
.n2vc
.libjuju
.upgrade_charm
.assert_not_called()
315 def test_wrong_ee_id(self
):
316 N2VCJujuConnector
._get
_ee
_id
_components
.side_effect
= Exception
317 with self
.assertRaises(N2VCBadArgumentsException
):
318 self
.loop
.run_until_complete(
319 self
.n2vc
.upgrade_charm(
320 "ns-id-k8s.app-vnf-vnf-id-vdu-vdu-random.k8s",
321 "/sample_charm_path",
327 self
.n2vc
._get
_libjuju
.assert_called()
328 self
.n2vc
._get
_ee
_id
_components
.assert_called()
329 self
.n2vc
.libjuju
.upgrade_charm
.assert_not_called()
331 def test_charm_upgrade_succeded(self
):
332 N2VCJujuConnector
._get
_ee
_id
_components
.return_value
= (
337 self
.loop
.run_until_complete(
338 self
.n2vc
.upgrade_charm(
339 "ns-id-k8s.app-vnf-vnf-id-vdu-vdu-random.k8s",
340 "/sample_charm_path",
346 self
.n2vc
._get
_libjuju
.assert_called()
347 self
.n2vc
._get
_ee
_id
_components
.assert_called()
348 self
.n2vc
.libjuju
.upgrade_charm
.assert_called_with(
349 application_name
="sample_app",
350 path
="/sample_charm_path",
351 model_name
="sample_model",
355 def test_charm_upgrade_failed(self
):
356 N2VCJujuConnector
._get
_ee
_id
_components
.return_value
= (
361 self
.n2vc
.libjuju
.upgrade_charm
.side_effect
= JujuApplicationNotFound
362 with self
.assertRaises(N2VCException
):
363 self
.loop
.run_until_complete(
364 self
.n2vc
.upgrade_charm(
365 "ns-id-k8s.app-vnf-vnf-id-vdu-vdu-random.k8s",
366 "/sample_charm_path",
372 self
.n2vc
._get
_libjuju
.assert_called()
373 self
.n2vc
._get
_ee
_id
_components
.assert_called()
374 self
.n2vc
.libjuju
.upgrade_charm
.assert_called_with(
375 application_name
="sample_app",
376 path
="/sample_charm_path",
377 model_name
="sample_model",