blob: fde6817a1441c8ad89388685c9bc844d3a61569e [file] [log] [blame]
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001# Copyright 2020 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
16import asynctest
David Garcia475a7222020-09-21 16:19:15 +020017import tempfile
David Garciaeb8943a2021-04-12 12:07:37 +020018from unittest.mock import Mock, patch
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020019import juju
David Garcia475a7222020-09-21 16:19:15 +020020import kubernetes
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020021from juju.errors import JujuAPIError
22import logging
David Garciaeb8943a2021-04-12 12:07:37 +020023from .utils import FakeMachine, FakeApplication
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020024from n2vc.libjuju import Libjuju
25from n2vc.exceptions import (
26 JujuControllerFailedConnecting,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020027 JujuMachineNotFound,
28 JujuApplicationNotFound,
29 JujuActionNotFound,
30 JujuApplicationExists,
David Garcia475a7222020-09-21 16:19:15 +020031 JujuInvalidK8sConfiguration,
David Garcia59f520d2020-10-15 13:16:45 +020032 JujuLeaderUnitNotFound,
ksaikiranrb84e4a72021-03-17 12:53:20 +053033 JujuError,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020034)
David Garciaf6e9b002020-11-27 15:32:02 +010035from n2vc.k8s_juju_conn import generate_rbac_id
David Garciaeb8943a2021-04-12 12:07:37 +020036from n2vc.tests.unit.utils import AsyncMock
37from n2vc.vca.connection import Connection
38from n2vc.vca.connection_data import ConnectionData
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020039
40
David Garciaeb8943a2021-04-12 12:07:37 +020041cacert = """-----BEGIN CERTIFICATE-----
42SOMECERT
43-----END CERTIFICATE-----"""
44
45
46@asynctest.mock.patch("n2vc.libjuju.Controller")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020047class LibjujuTestCase(asynctest.TestCase):
David Garciaeb8943a2021-04-12 12:07:37 +020048 @asynctest.mock.patch("n2vc.vca.connection_data.base64_to_cacert")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020049 def setUp(
50 self,
David Garciaeb8943a2021-04-12 12:07:37 +020051 mock_base64_to_cacert=None,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020052 ):
David Garciaeb8943a2021-04-12 12:07:37 +020053 self.loop = asyncio.get_event_loop()
54 self.db = Mock()
55 mock_base64_to_cacert.return_value = cacert
56 Connection._load_vca_connection_data = Mock()
57 vca_connection = Connection(AsyncMock())
58 vca_connection._data = ConnectionData(
59 **{
60 "endpoints": ["1.2.3.4:17070"],
61 "user": "user",
62 "secret": "secret",
63 "cacert": "cacert",
64 "pubkey": "pubkey",
65 "lxd-cloud": "cloud",
66 "lxd-credentials": "credentials",
67 "k8s-cloud": "k8s_cloud",
68 "k8s-credentials": "k8s_credentials",
69 "model-config": {},
70 "api-proxy": "api_proxy",
71 }
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020072 )
73 logging.disable(logging.CRITICAL)
David Garciaeb8943a2021-04-12 12:07:37 +020074 self.libjuju = Libjuju(vca_connection, self.loop)
75 self.loop.run_until_complete(self.libjuju.disconnect())
David Garciaa4f57d62020-10-22 10:50:56 +020076
77
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020078@asynctest.mock.patch("juju.controller.Controller.connect")
79@asynctest.mock.patch(
80 "juju.controller.Controller.api_endpoints",
81 new_callable=asynctest.CoroutineMock(return_value=["127.0.0.1:17070"]),
82)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020083class GetControllerTest(LibjujuTestCase):
84 def setUp(self):
85 super(GetControllerTest, self).setUp()
86
David Garciaeb8943a2021-04-12 12:07:37 +020087 def test_diff_endpoint(self, mock_api_endpoints, mock_connect):
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020088 self.libjuju.endpoints = []
89 controller = self.loop.run_until_complete(self.libjuju.get_controller())
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020090 self.assertIsInstance(controller, juju.controller.Controller)
91
92 @asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
93 def test_exception(
94 self,
95 mock_disconnect_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +020096 mock_api_endpoints,
97 mock_connect,
98 ):
99 self.libjuju.endpoints = []
David Garciaeb8943a2021-04-12 12:07:37 +0200100
101 mock_connect.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +0200102 controller = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200103 with self.assertRaises(JujuControllerFailedConnecting):
104 controller = self.loop.run_until_complete(self.libjuju.get_controller())
David Garcia12b29242020-09-17 16:01:48 +0200105 self.assertIsNone(controller)
106 mock_disconnect_controller.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200107
David Garciaeb8943a2021-04-12 12:07:37 +0200108 def test_same_endpoint_get_controller(self, mock_api_endpoints, mock_connect):
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200109 self.libjuju.endpoints = ["127.0.0.1:17070"]
110 controller = self.loop.run_until_complete(self.libjuju.get_controller())
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200111 self.assertIsInstance(controller, juju.controller.Controller)
112
113
114class DisconnectTest(LibjujuTestCase):
115 def setUp(self):
116 super(DisconnectTest, self).setUp()
117
118 @asynctest.mock.patch("juju.model.Model.disconnect")
119 def test_disconnect_model(self, mock_disconnect):
120 self.loop.run_until_complete(self.libjuju.disconnect_model(juju.model.Model()))
121 mock_disconnect.assert_called_once()
122
123 @asynctest.mock.patch("juju.controller.Controller.disconnect")
124 def test_disconnect_controller(self, mock_disconnect):
125 self.loop.run_until_complete(
126 self.libjuju.disconnect_controller(juju.controller.Controller())
127 )
128 mock_disconnect.assert_called_once()
129
130
131@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
132@asynctest.mock.patch("n2vc.libjuju.Libjuju.model_exists")
133@asynctest.mock.patch("juju.controller.Controller.add_model")
134@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
135@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
136class AddModelTest(LibjujuTestCase):
137 def setUp(self):
138 super(AddModelTest, self).setUp()
139
140 def test_existing_model(
141 self,
142 mock_disconnect_model,
143 mock_disconnect_controller,
144 mock_add_model,
145 mock_model_exists,
146 mock_get_controller,
147 ):
148 mock_model_exists.return_value = True
149
David Garciab0a8f402021-03-15 18:41:34 +0100150 # This should not raise an exception
David Garciaeb8943a2021-04-12 12:07:37 +0200151 self.loop.run_until_complete(self.libjuju.add_model("existing_model", "cloud"))
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200152
David Garcia12b29242020-09-17 16:01:48 +0200153 mock_disconnect_controller.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200154
155 # TODO Check two job executing at the same time and one returning without doing anything.
156
157 def test_non_existing_model(
158 self,
159 mock_disconnect_model,
160 mock_disconnect_controller,
161 mock_add_model,
162 mock_model_exists,
163 mock_get_controller,
164 ):
165 mock_model_exists.return_value = False
166 mock_get_controller.return_value = juju.controller.Controller()
167
168 self.loop.run_until_complete(
David Garciaeb8943a2021-04-12 12:07:37 +0200169 self.libjuju.add_model("nonexisting_model", Mock())
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200170 )
171
172 mock_add_model.assert_called_once()
173 mock_disconnect_controller.assert_called()
174 mock_disconnect_model.assert_called()
175
176
ksaikiranrb84e4a72021-03-17 12:53:20 +0530177@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
178@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
179@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
180@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
181@asynctest.mock.patch(
182 "juju.model.Model.applications", new_callable=asynctest.PropertyMock
183)
184@asynctest.mock.patch("juju.model.Model.get_action_status")
185@asynctest.mock.patch("juju.model.Model.get_action_output")
186@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_actions")
187class GetExecutedActionsTest(LibjujuTestCase):
188 def setUp(self):
189 super(GetExecutedActionsTest, self).setUp()
190
191 def test_exception(
192 self,
193 mock_get_actions,
194 mock_get_action_output,
195 mock_get_action_status,
196 mock_applications,
197 mock_disconnect_controller,
198 mock_disconnect_model,
199 mock_get_model,
200 mock_get_controller,
201 ):
202 mock_get_model.return_value = None
203 with self.assertRaises(JujuError):
204 self.loop.run_until_complete(self.libjuju.get_executed_actions("model"))
205
206 mock_get_controller.assert_called_once()
207 mock_disconnect_controller.assert_called_once()
208 mock_get_model.assert_called_once()
209 mock_disconnect_model.assert_not_called()
210
211 def test_success(
212 self,
213 mock_get_actions,
214 mock_get_action_output,
215 mock_get_action_status,
216 mock_applications,
217 mock_disconnect_controller,
218 mock_disconnect_model,
219 mock_get_model,
220 mock_get_controller,
221 ):
222 mock_get_model.return_value = juju.model.Model()
223 mock_applications.return_value = {"existing_app"}
224 mock_get_actions.return_value = {"action_name": "description"}
225 mock_get_action_status.return_value = {"id": "status"}
226 mock_get_action_output.return_value = {"output": "completed"}
227
228 executed_actions = self.loop.run_until_complete(
229 self.libjuju.get_executed_actions("model")
230 )
231 expected_result = [{'id': 'id', 'action': 'action_name',
232 'status': 'status', 'output': 'completed'}]
233 self.assertListEqual(expected_result, executed_actions)
234 self.assertIsInstance(executed_actions, list)
235
236 mock_get_controller.assert_called_once()
237 mock_get_model.assert_called_once()
238 mock_disconnect_controller.assert_called_once()
239 mock_disconnect_model.assert_called_once()
240
241
242@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
243@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
244@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
245@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
246@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
247class GetApplicationConfigsTest(LibjujuTestCase):
248 def setUp(self):
249 super(GetApplicationConfigsTest, self).setUp()
250
251 def test_exception(
252 self,
253 mock_get_application,
254 mock_disconnect_controller,
255 mock_disconnect_model,
256 mock_get_model,
257 mock_get_controller,
258 ):
259 mock_get_model.return_value = None
260 with self.assertRaises(JujuError):
261 self.loop.run_until_complete(
262 self.libjuju.get_application_configs("model", "app"))
263
264 mock_get_controller.assert_called_once()
265 mock_disconnect_controller.assert_called_once()
266 mock_get_model.assert_called_once()
267 mock_disconnect_model.assert_not_called()
268
269 def test_success(
270 self,
271 mock_get_application,
272 mock_disconnect_controller,
273 mock_disconnect_model,
274 mock_get_model,
275 mock_get_controller,
276 ):
277 mock_get_application.return_value = FakeApplication()
278 application_configs = self.loop.run_until_complete(self.libjuju
279 .get_application_configs("model", "app"))
280
281 self.assertEqual(application_configs, ["app_config"])
282
283 mock_get_controller.assert_called_once()
284 mock_get_model.assert_called_once()
285 mock_disconnect_controller.assert_called_once()
286 mock_disconnect_model.assert_called_once()
287
288
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200289@asynctest.mock.patch("juju.controller.Controller.get_model")
290class GetModelTest(LibjujuTestCase):
291 def setUp(self):
292 super(GetModelTest, self).setUp()
293
294 def test_get_model(
David Garcia5b802c92020-11-11 16:56:06 +0100295 self,
296 mock_get_model,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200297 ):
298 mock_get_model.return_value = juju.model.Model()
299 model = self.loop.run_until_complete(
300 self.libjuju.get_model(juju.controller.Controller(), "model")
301 )
302 self.assertIsInstance(model, juju.model.Model)
303
304
305@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
306@asynctest.mock.patch("juju.controller.Controller.list_models")
307class ModelExistsTest(LibjujuTestCase):
308 def setUp(self):
309 super(ModelExistsTest, self).setUp()
310
311 async def test_existing_model(
David Garcia5b802c92020-11-11 16:56:06 +0100312 self,
313 mock_list_models,
314 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200315 ):
316 mock_list_models.return_value = ["existing_model"]
317 self.assertTrue(
318 await self.libjuju.model_exists(
319 "existing_model", juju.controller.Controller()
320 )
321 )
322
323 @asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
324 async def test_no_controller(
David Garcia5b802c92020-11-11 16:56:06 +0100325 self,
326 mock_disconnect_controller,
327 mock_list_models,
328 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200329 ):
330 mock_list_models.return_value = ["existing_model"]
331 mock_get_controller.return_value = juju.controller.Controller()
332 self.assertTrue(await self.libjuju.model_exists("existing_model"))
333 mock_disconnect_controller.assert_called_once()
334
335 async def test_non_existing_model(
David Garcia5b802c92020-11-11 16:56:06 +0100336 self,
337 mock_list_models,
338 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200339 ):
340 mock_list_models.return_value = ["existing_model"]
341 self.assertFalse(
342 await self.libjuju.model_exists(
343 "not_existing_model", juju.controller.Controller()
344 )
345 )
346
347
348@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
349@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
350@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
351@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
352@asynctest.mock.patch("juju.model.Model.get_status")
353class GetModelStatusTest(LibjujuTestCase):
354 def setUp(self):
355 super(GetModelStatusTest, self).setUp()
356
357 def test_success(
358 self,
359 mock_get_status,
360 mock_disconnect_controller,
361 mock_disconnect_model,
362 mock_get_model,
363 mock_get_controller,
364 ):
365 mock_get_model.return_value = juju.model.Model()
366 mock_get_status.return_value = {"status"}
367
368 status = self.loop.run_until_complete(self.libjuju.get_model_status("model"))
369
370 mock_get_status.assert_called_once()
371 mock_disconnect_controller.assert_called_once()
372 mock_disconnect_model.assert_called_once()
373
374 self.assertEqual(status, {"status"})
375
David Garcia12b29242020-09-17 16:01:48 +0200376 def test_exception(
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200377 self,
378 mock_get_status,
379 mock_disconnect_controller,
380 mock_disconnect_model,
381 mock_get_model,
382 mock_get_controller,
383 ):
384 mock_get_model.return_value = juju.model.Model()
385 mock_get_status.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +0200386 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200387 with self.assertRaises(Exception):
388 status = self.loop.run_until_complete(
389 self.libjuju.get_model_status("model")
390 )
391
David Garcia12b29242020-09-17 16:01:48 +0200392 mock_disconnect_controller.assert_called_once()
393 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200394
David Garcia12b29242020-09-17 16:01:48 +0200395 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200396
397
398@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
399@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
400@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
401@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
402@asynctest.mock.patch("juju.model.Model.get_machines")
403@asynctest.mock.patch("juju.model.Model.add_machine")
404@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
405class CreateMachineTest(LibjujuTestCase):
406 def setUp(self):
407 super(CreateMachineTest, self).setUp()
408
409 def test_existing_machine(
410 self,
411 mock_wait_for,
412 mock_add_machine,
413 mock_get_machines,
414 mock_disconnect_controller,
415 mock_disconnect_model,
416 mock_get_model,
417 mock_get_controller,
418 ):
419 mock_get_model.return_value = juju.model.Model()
420 mock_get_machines.return_value = {"existing_machine": FakeMachine()}
421 machine, bool_res = self.loop.run_until_complete(
422 self.libjuju.create_machine("model", "existing_machine")
423 )
424
425 self.assertIsInstance(machine, FakeMachine)
426 self.assertFalse(bool_res)
427
428 mock_disconnect_controller.assert_called()
429 mock_disconnect_model.assert_called()
430
431 def test_non_existing_machine(
432 self,
433 mock_wait_for,
434 mock_add_machine,
435 mock_get_machines,
436 mock_disconnect_controller,
437 mock_disconnect_model,
438 mock_get_model,
439 mock_get_controller,
440 ):
David Garcia12b29242020-09-17 16:01:48 +0200441 machine = None
442 bool_res = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200443 mock_get_model.return_value = juju.model.Model()
444 with self.assertRaises(JujuMachineNotFound):
445 machine, bool_res = self.loop.run_until_complete(
446 self.libjuju.create_machine("model", "non_existing_machine")
447 )
David Garcia12b29242020-09-17 16:01:48 +0200448 self.assertIsNone(machine)
449 self.assertIsNone(bool_res)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200450
David Garcia12b29242020-09-17 16:01:48 +0200451 mock_disconnect_controller.assert_called()
452 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200453
454 def test_no_machine(
455 self,
456 mock_wait_for,
457 mock_add_machine,
458 mock_get_machines,
459 mock_disconnect_controller,
460 mock_disconnect_model,
461 mock_get_model,
462 mock_get_controller,
463 ):
464 mock_get_model.return_value = juju.model.Model()
465 mock_add_machine.return_value = FakeMachine()
466
467 machine, bool_res = self.loop.run_until_complete(
468 self.libjuju.create_machine("model")
469 )
470
471 self.assertIsInstance(machine, FakeMachine)
472 self.assertTrue(bool_res)
473
474 mock_wait_for.assert_called_once()
475 mock_add_machine.assert_called_once()
476
477 mock_disconnect_controller.assert_called()
478 mock_disconnect_model.assert_called()
479
480
481# TODO test provision machine
482
483
484@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
485@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
486@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
487@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
David Garcia667696e2020-09-22 14:52:32 +0200488@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for_model")
489@asynctest.mock.patch("juju.model.Model.deploy")
490class DeployTest(LibjujuTestCase):
491 def setUp(self):
492 super(DeployTest, self).setUp()
493
494 def test_deploy(
495 self,
496 mock_deploy,
497 mock_wait_for_model,
498 mock_disconnect_controller,
499 mock_disconnect_model,
500 mock_get_model,
501 mock_get_controller,
502 ):
503 mock_get_model.return_value = juju.model.Model()
504 self.loop.run_until_complete(
505 self.libjuju.deploy("cs:osm", "model", wait=True, timeout=0)
506 )
507 mock_deploy.assert_called_once()
508 mock_wait_for_model.assert_called_once()
509 mock_disconnect_controller.assert_called_once()
510 mock_disconnect_model.assert_called_once()
511
512 def test_deploy_no_wait(
513 self,
514 mock_deploy,
515 mock_wait_for_model,
516 mock_disconnect_controller,
517 mock_disconnect_model,
518 mock_get_model,
519 mock_get_controller,
520 ):
521 mock_get_model.return_value = juju.model.Model()
522 self.loop.run_until_complete(
523 self.libjuju.deploy("cs:osm", "model", wait=False, timeout=0)
524 )
525 mock_deploy.assert_called_once()
526 mock_wait_for_model.assert_not_called()
527 mock_disconnect_controller.assert_called_once()
528 mock_disconnect_model.assert_called_once()
529
530 def test_deploy_exception(
531 self,
532 mock_deploy,
533 mock_wait_for_model,
534 mock_disconnect_controller,
535 mock_disconnect_model,
536 mock_get_model,
537 mock_get_controller,
538 ):
539 mock_deploy.side_effect = Exception()
540 mock_get_model.return_value = juju.model.Model()
541 with self.assertRaises(Exception):
542 self.loop.run_until_complete(self.libjuju.deploy("cs:osm", "model"))
543 mock_deploy.assert_called_once()
544 mock_wait_for_model.assert_not_called()
545 mock_disconnect_controller.assert_called_once()
546 mock_disconnect_model.assert_called_once()
547
548
549@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
550@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
551@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
552@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200553@asynctest.mock.patch(
554 "juju.model.Model.applications", new_callable=asynctest.PropertyMock
555)
556@asynctest.mock.patch("juju.model.Model.machines", new_callable=asynctest.PropertyMock)
557@asynctest.mock.patch("juju.model.Model.deploy")
558@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
559@asynctest.mock.patch("n2vc.libjuju.Libjuju.create_machine")
560class DeployCharmTest(LibjujuTestCase):
561 def setUp(self):
562 super(DeployCharmTest, self).setUp()
563
564 def test_existing_app(
565 self,
566 mock_create_machine,
567 mock_wait_for,
568 mock_deploy,
569 mock_machines,
570 mock_applications,
571 mock_disconnect_controller,
572 mock_disconnect_model,
573 mock_get_model,
574 mock_get_controller,
575 ):
576 mock_get_model.return_value = juju.model.Model()
577 mock_applications.return_value = {"existing_app"}
578
David Garcia12b29242020-09-17 16:01:48 +0200579 application = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200580 with self.assertRaises(JujuApplicationExists):
581 application = self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100582 self.libjuju.deploy_charm(
583 "existing_app",
584 "path",
585 "model",
586 "machine",
587 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200588 )
David Garcia12b29242020-09-17 16:01:48 +0200589 self.assertIsNone(application)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200590
David Garcia12b29242020-09-17 16:01:48 +0200591 mock_disconnect_controller.assert_called()
592 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200593
594 def test_non_existing_machine(
595 self,
596 mock_create_machine,
597 mock_wait_for,
598 mock_deploy,
599 mock_machines,
600 mock_applications,
601 mock_disconnect_controller,
602 mock_disconnect_model,
603 mock_get_model,
604 mock_get_controller,
605 ):
606 mock_get_model.return_value = juju.model.Model()
607 mock_machines.return_value = {"existing_machine": FakeMachine()}
David Garcia12b29242020-09-17 16:01:48 +0200608 application = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200609 with self.assertRaises(JujuMachineNotFound):
610 application = self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100611 self.libjuju.deploy_charm(
612 "app",
613 "path",
614 "model",
615 "machine",
616 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200617 )
618
David Garcia12b29242020-09-17 16:01:48 +0200619 self.assertIsNone(application)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200620
David Garcia12b29242020-09-17 16:01:48 +0200621 mock_disconnect_controller.assert_called()
622 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200623
624 def test_2_units(
625 self,
626 mock_create_machine,
627 mock_wait_for,
628 mock_deploy,
629 mock_machines,
630 mock_applications,
631 mock_disconnect_controller,
632 mock_disconnect_model,
633 mock_get_model,
634 mock_get_controller,
635 ):
636 mock_get_model.return_value = juju.model.Model()
637 mock_machines.return_value = {"existing_machine": FakeMachine()}
638 mock_create_machine.return_value = (FakeMachine(), "other")
639 mock_deploy.return_value = FakeApplication()
640 application = self.loop.run_until_complete(
641 self.libjuju.deploy_charm(
David Garcia5b802c92020-11-11 16:56:06 +0100642 "app",
643 "path",
644 "model",
645 "existing_machine",
646 num_units=2,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200647 )
648 )
649
650 self.assertIsInstance(application, FakeApplication)
651
652 mock_deploy.assert_called_once()
653 mock_wait_for.assert_called_once()
654
655 mock_create_machine.assert_called_once()
656
657 mock_disconnect_controller.assert_called()
658 mock_disconnect_model.assert_called()
659
660 def test_1_unit(
661 self,
662 mock_create_machine,
663 mock_wait_for,
664 mock_deploy,
665 mock_machines,
666 mock_applications,
667 mock_disconnect_controller,
668 mock_disconnect_model,
669 mock_get_model,
670 mock_get_controller,
671 ):
672 mock_get_model.return_value = juju.model.Model()
673 mock_machines.return_value = {"existing_machine": FakeMachine()}
674 mock_deploy.return_value = FakeApplication()
675 application = self.loop.run_until_complete(
676 self.libjuju.deploy_charm("app", "path", "model", "existing_machine")
677 )
678
679 self.assertIsInstance(application, FakeApplication)
680
681 mock_deploy.assert_called_once()
682 mock_wait_for.assert_called_once()
683
684 mock_disconnect_controller.assert_called()
685 mock_disconnect_model.assert_called()
686
687
688@asynctest.mock.patch(
689 "juju.model.Model.applications", new_callable=asynctest.PropertyMock
690)
691class GetApplicationTest(LibjujuTestCase):
692 def setUp(self):
693 super(GetApplicationTest, self).setUp()
694
695 def test_existing_application(
David Garcia5b802c92020-11-11 16:56:06 +0100696 self,
697 mock_applications,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200698 ):
699 mock_applications.return_value = {"existing_app": "exists"}
700 model = juju.model.Model()
701 result = self.libjuju._get_application(model, "existing_app")
702 self.assertEqual(result, "exists")
703
704 def test_non_existing_application(
David Garcia5b802c92020-11-11 16:56:06 +0100705 self,
706 mock_applications,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200707 ):
708 mock_applications.return_value = {"existing_app": "exists"}
709 model = juju.model.Model()
710 result = self.libjuju._get_application(model, "nonexisting_app")
711 self.assertIsNone(result)
712
713
714@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
715@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
716@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
717@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
718@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
719@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
720@asynctest.mock.patch("juju.model.Model.get_action_output")
721@asynctest.mock.patch("juju.model.Model.get_action_status")
722class ExecuteActionTest(LibjujuTestCase):
723 def setUp(self):
724 super(ExecuteActionTest, self).setUp()
725
726 def test_no_application(
727 self,
728 mock_get_action_status,
729 mock_get_action_output,
730 mock_wait_for,
731 mock__get_application,
732 mock_disconnect_controller,
733 mock_disconnect_model,
734 mock_get_model,
735 mock_get_controller,
736 ):
737 mock__get_application.return_value = None
738 mock_get_model.return_value = juju.model.Model()
David Garcia12b29242020-09-17 16:01:48 +0200739 output = None
740 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200741 with self.assertRaises(JujuApplicationNotFound):
742 output, status = self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100743 self.libjuju.execute_action(
744 "app",
745 "model",
746 "action",
747 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200748 )
David Garcia12b29242020-09-17 16:01:48 +0200749 self.assertIsNone(output)
750 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200751
David Garcia12b29242020-09-17 16:01:48 +0200752 mock_disconnect_controller.assert_called()
753 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200754
755 def test_no_action(
756 self,
757 mock_get_action_status,
758 mock_get_action_output,
759 mock_wait_for,
760 mock__get_application,
761 mock_disconnect_controller,
762 mock_disconnect_model,
763 mock_get_model,
764 mock_get_controller,
765 ):
766
767 mock_get_model.return_value = juju.model.Model()
768 mock__get_application.return_value = FakeApplication()
David Garcia12b29242020-09-17 16:01:48 +0200769 output = None
770 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200771 with self.assertRaises(JujuActionNotFound):
772 output, status = self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100773 self.libjuju.execute_action(
774 "app",
775 "model",
776 "action",
777 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200778 )
David Garcia12b29242020-09-17 16:01:48 +0200779 self.assertIsNone(output)
780 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200781
David Garcia12b29242020-09-17 16:01:48 +0200782 mock_disconnect_controller.assert_called()
783 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200784
David Garcia59f520d2020-10-15 13:16:45 +0200785 @asynctest.mock.patch("asyncio.sleep")
786 @asynctest.mock.patch("n2vc.tests.unit.utils.FakeUnit.is_leader_from_status")
787 def test_no_leader(
788 self,
789 mock_is_leader_from_status,
790 mock_sleep,
791 mock_get_action_status,
792 mock_get_action_output,
793 mock_wait_for,
794 mock__get_application,
795 mock_disconnect_controller,
796 mock_disconnect_model,
797 mock_get_model,
798 mock_get_controller,
799 ):
800 mock_get_model.return_value = juju.model.Model()
801 mock__get_application.return_value = FakeApplication()
802 mock_is_leader_from_status.return_value = False
803 output = None
804 status = None
805 with self.assertRaises(JujuLeaderUnitNotFound):
806 output, status = self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100807 self.libjuju.execute_action(
808 "app",
809 "model",
810 "action",
811 )
David Garcia59f520d2020-10-15 13:16:45 +0200812 )
813 self.assertIsNone(output)
814 self.assertIsNone(status)
815
816 mock_disconnect_controller.assert_called()
817 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200818
819 def test_succesful_exec(
820 self,
821 mock_get_action_status,
822 mock_get_action_output,
823 mock_wait_for,
824 mock__get_application,
825 mock_disconnect_controller,
826 mock_disconnect_model,
827 mock_get_model,
828 mock_get_controller,
829 ):
830 mock_get_model.return_value = juju.model.Model()
831 mock__get_application.return_value = FakeApplication()
832 mock_get_action_output.return_value = "output"
833 mock_get_action_status.return_value = {"id": "status"}
834 output, status = self.loop.run_until_complete(
835 self.libjuju.execute_action("app", "model", "existing_action")
836 )
837 self.assertEqual(output, "output")
838 self.assertEqual(status, "status")
839
840 mock_wait_for.assert_called_once()
841
842 mock_disconnect_controller.assert_called()
843 mock_disconnect_model.assert_called()
844
845
846@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
847@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
848@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
849@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
850@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
851class GetActionTest(LibjujuTestCase):
852 def setUp(self):
853 super(GetActionTest, self).setUp()
854
855 def test_exception(
856 self,
857 mock_get_application,
858 mock_disconnect_controller,
859 mock_disconnect_model,
860 mock_get_model,
861 mock_get_controller,
862 ):
863 mock_get_application.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +0200864 actions = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200865 with self.assertRaises(Exception):
866 actions = self.loop.run_until_complete(
867 self.libjuju.get_actions("app", "model")
868 )
869
David Garcia12b29242020-09-17 16:01:48 +0200870 self.assertIsNone(actions)
871 mock_disconnect_controller.assert_called_once()
872 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200873
874 def test_success(
875 self,
876 mock_get_application,
877 mock_disconnect_controller,
878 mock_disconnect_model,
879 mock_get_model,
880 mock_get_controller,
881 ):
882 mock_get_application.return_value = FakeApplication()
883
884 actions = self.loop.run_until_complete(self.libjuju.get_actions("app", "model"))
885
886 self.assertEqual(actions, ["existing_action"])
887
888 mock_get_controller.assert_called_once()
889 mock_get_model.assert_called_once()
890 mock_disconnect_controller.assert_called_once()
891 mock_disconnect_model.assert_called_once()
892
893
894@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
895@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
896@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
897@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
David Garcia85755d12020-09-21 19:51:23 +0200898@asynctest.mock.patch("juju.application.Application.get_metrics")
899@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
900class GetMetricsTest(LibjujuTestCase):
901 def setUp(self):
902 super(GetMetricsTest, self).setUp()
903
904 def test_get_metrics_success(
905 self,
906 mock_get_application,
907 mock_get_metrics,
908 mock_disconnect_controller,
909 mock_disconnect_model,
910 mock_get_model,
911 mock_get_controller,
912 ):
913 mock_get_application.return_value = FakeApplication()
914 mock_get_model.return_value = juju.model.Model()
915
916 self.loop.run_until_complete(self.libjuju.get_metrics("model", "app1"))
917
918 mock_disconnect_controller.assert_called_once()
919 mock_disconnect_model.assert_called_once()
920
921 def test_get_metrics_exception(
922 self,
923 mock_get_application,
924 mock_get_metrics,
925 mock_disconnect_controller,
926 mock_disconnect_model,
927 mock_get_model,
928 mock_get_controller,
929 ):
930 mock_get_model.return_value = juju.model.Model()
931 mock_get_metrics.side_effect = Exception()
932 with self.assertRaises(Exception):
933 self.loop.run_until_complete(self.libjuju.get_metrics("model", "app1"))
934
935 mock_disconnect_controller.assert_called_once()
936 mock_disconnect_model.assert_called_once()
937
938 def test_missing_args_exception(
939 self,
940 mock_get_application,
941 mock_get_metrics,
942 mock_disconnect_controller,
943 mock_disconnect_model,
944 mock_get_model,
945 mock_get_controller,
946 ):
947 mock_get_model.return_value = juju.model.Model()
948
949 with self.assertRaises(Exception):
950 self.loop.run_until_complete(self.libjuju.get_metrics("", ""))
951
952 mock_get_controller.assert_not_called()
953 mock_get_model.assert_not_called()
954 mock_disconnect_controller.assert_not_called()
955 mock_disconnect_model.assert_not_called()
956
957
958@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
959@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
960@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
961@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200962@asynctest.mock.patch("juju.model.Model.add_relation")
963class AddRelationTest(LibjujuTestCase):
964 def setUp(self):
965 super(AddRelationTest, self).setUp()
966
967 @asynctest.mock.patch("logging.Logger.warning")
968 def test_not_found(
969 self,
970 mock_warning,
971 mock_add_relation,
972 mock_disconnect_controller,
973 mock_disconnect_model,
974 mock_get_model,
975 mock_get_controller,
976 ):
977 # TODO in libjuju.py should this fail only with a log message?
978 result = {"error": "not found", "response": "response", "request-id": 1}
979
980 mock_get_model.return_value = juju.model.Model()
981 mock_add_relation.side_effect = JujuAPIError(result)
982
983 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +0100984 self.libjuju.add_relation(
985 "model",
986 "app1:relation1",
987 "app2:relation2",
988 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200989 )
990
991 mock_warning.assert_called_with("Relation not found: not found")
992 mock_disconnect_controller.assert_called_once()
993 mock_disconnect_model.assert_called_once()
994
995 @asynctest.mock.patch("logging.Logger.warning")
996 def test_already_exists(
997 self,
998 mock_warning,
999 mock_add_relation,
1000 mock_disconnect_controller,
1001 mock_disconnect_model,
1002 mock_get_model,
1003 mock_get_controller,
1004 ):
1005 # TODO in libjuju.py should this fail silently?
1006 result = {"error": "already exists", "response": "response", "request-id": 1}
1007
1008 mock_get_model.return_value = juju.model.Model()
1009 mock_add_relation.side_effect = JujuAPIError(result)
1010
1011 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001012 self.libjuju.add_relation(
1013 "model",
1014 "app1:relation1",
1015 "app2:relation2",
1016 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001017 )
1018
1019 mock_warning.assert_called_with("Relation already exists: already exists")
1020 mock_disconnect_controller.assert_called_once()
1021 mock_disconnect_model.assert_called_once()
1022
1023 def test_exception(
1024 self,
1025 mock_add_relation,
1026 mock_disconnect_controller,
1027 mock_disconnect_model,
1028 mock_get_model,
1029 mock_get_controller,
1030 ):
1031 mock_get_model.return_value = juju.model.Model()
1032 result = {"error": "", "response": "response", "request-id": 1}
1033 mock_add_relation.side_effect = JujuAPIError(result)
1034
1035 with self.assertRaises(JujuAPIError):
1036 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001037 self.libjuju.add_relation(
1038 "model",
1039 "app1:relation1",
1040 "app2:relation2",
1041 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001042 )
1043
David Garcia12b29242020-09-17 16:01:48 +02001044 mock_disconnect_controller.assert_called_once()
1045 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001046
1047 def test_success(
1048 self,
1049 mock_add_relation,
1050 mock_disconnect_controller,
1051 mock_disconnect_model,
1052 mock_get_model,
1053 mock_get_controller,
1054 ):
1055 mock_get_model.return_value = juju.model.Model()
1056
1057 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001058 self.libjuju.add_relation(
1059 "model",
1060 "app1:relation1",
1061 "app2:relation2",
1062 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001063 )
1064
David Garcia12b29242020-09-17 16:01:48 +02001065 mock_add_relation.assert_called_with("app1:relation1", "app2:relation2")
David Garcia8331f7c2020-08-25 16:10:07 +02001066 mock_disconnect_controller.assert_called_once()
1067 mock_disconnect_model.assert_called_once()
1068
1069 def test_saas(
1070 self,
1071 mock_add_relation,
1072 mock_disconnect_controller,
1073 mock_disconnect_model,
1074 mock_get_model,
1075 mock_get_controller,
1076 ):
1077 mock_get_model.return_value = juju.model.Model()
1078
1079 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001080 self.libjuju.add_relation(
1081 "model",
1082 "app1:relation1",
1083 "saas_name",
1084 )
David Garcia8331f7c2020-08-25 16:10:07 +02001085 )
1086
David Garcia12b29242020-09-17 16:01:48 +02001087 mock_add_relation.assert_called_with("app1:relation1", "saas_name")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001088 mock_disconnect_controller.assert_called_once()
1089 mock_disconnect_model.assert_called_once()
1090
1091
1092# TODO destroy_model testcase
1093
1094
aktas56120292021-02-26 15:32:39 +03001095@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1096@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
1097@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1098@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
1099@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
1100class DestroyApplicationTest(LibjujuTestCase):
1101 def setUp(self):
1102 super(DestroyApplicationTest, self).setUp()
1103
1104 def test_success(
1105 self,
1106 mock_get_controller,
1107 mock_get_model,
1108 mock_disconnect_controller,
1109 mock_get_application,
1110 mock_disconnect_model,
1111 ):
1112 mock_get_application.return_value = FakeApplication()
1113 mock_get_model.return_value = None
1114 self.loop.run_until_complete(
1115 self.libjuju.destroy_application(
1116 "existing_model",
1117 "existing_app",
1118 3600,
1119 )
1120 )
1121 mock_get_application.assert_called()
1122 mock_disconnect_controller.assert_called_once()
1123 mock_disconnect_model.assert_called_once()
1124
1125 def test_no_application(
1126 self,
1127 mock_get_controller,
1128 mock_get_model,
1129 mock_disconnect_controller,
1130 mock_get_application,
1131 mock_disconnect_model,
1132 ):
1133 mock_get_model.return_value = None
1134 mock_get_application.return_value = None
1135
1136 self.loop.run_until_complete(
1137 self.libjuju.destroy_application(
1138 "existing_model",
1139 "existing_app",
1140 3600,
1141 )
1142 )
1143 mock_get_application.assert_called()
1144
1145 def test_exception(
1146 self,
1147 mock_get_controller,
1148 mock_get_model,
1149 mock_disconnect_controller,
1150 mock_get_application,
1151 mock_disconnect_model,
1152 ):
1153 mock_get_application.return_value = FakeApplication
1154 mock_get_model.return_value = None
1155
1156 with self.assertRaises(Exception):
1157 self.loop.run_until_complete(
1158 self.libjuju.destroy_application(
1159 "existing_model",
1160 "existing_app",
1161 0,
1162 )
1163 )
1164 mock_get_application.assert_called_once()
1165
1166
David Garcia5ef42a12020-09-29 19:48:13 +02001167# @asynctest.mock.patch("juju.model.Model.get_machines")
1168# @asynctest.mock.patch("logging.Logger.debug")
1169# class DestroyMachineTest(LibjujuTestCase):
1170# def setUp(self):
1171# super(DestroyMachineTest, self).setUp()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001172
David Garcia5ef42a12020-09-29 19:48:13 +02001173# def test_success_manual_machine(
1174# self, mock_debug, mock_get_machines,
1175# ):
1176# mock_get_machines.side_effect = [
1177# {"machine": FakeManualMachine()},
1178# {"machine": FakeManualMachine()},
1179# {},
1180# ]
1181# self.loop.run_until_complete(
1182# self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
1183# )
1184# calls = [
1185# asynctest.call("Waiting for machine machine is destroyed"),
1186# asynctest.call("Machine destroyed: machine"),
1187# ]
1188# mock_debug.assert_has_calls(calls)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001189
David Garcia5ef42a12020-09-29 19:48:13 +02001190# def test_no_machine(
1191# self, mock_debug, mock_get_machines,
1192# ):
1193# mock_get_machines.return_value = {}
1194# self.loop.run_until_complete(
1195# self.libjuju.destroy_machine(juju.model.Model(), "machine", 2)
1196# )
1197# mock_debug.assert_called_with("Machine not found: machine")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001198
1199
1200@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1201@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
1202@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
1203@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1204@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
1205class ConfigureApplicationTest(LibjujuTestCase):
1206 def setUp(self):
1207 super(ConfigureApplicationTest, self).setUp()
1208
1209 def test_success(
1210 self,
1211 mock_get_application,
1212 mock_disconnect_controller,
1213 mock_disconnect_model,
1214 mock_get_model,
1215 mock_get_controller,
1216 ):
1217
1218 mock_get_application.return_value = FakeApplication()
1219
1220 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001221 self.libjuju.configure_application(
1222 "model",
1223 "app",
1224 {"config"},
1225 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001226 )
1227 mock_get_application.assert_called_once()
1228 mock_disconnect_controller.assert_called_once()
1229 mock_disconnect_model.assert_called_once()
1230
1231 def test_exception(
1232 self,
1233 mock_get_application,
1234 mock_disconnect_controller,
1235 mock_disconnect_model,
1236 mock_get_model,
1237 mock_get_controller,
1238 ):
1239
1240 mock_get_application.side_effect = Exception()
1241
1242 with self.assertRaises(Exception):
1243 self.loop.run_until_complete(
David Garcia5b802c92020-11-11 16:56:06 +01001244 self.libjuju.configure_application(
1245 "model",
1246 "app",
1247 {"config"},
1248 )
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001249 )
David Garcia12b29242020-09-17 16:01:48 +02001250 mock_disconnect_controller.assert_called_once()
1251 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001252
David Garcia5b802c92020-11-11 16:56:06 +01001253 def test_controller_exception(
1254 self,
1255 mock_get_application,
1256 mock_disconnect_controller,
1257 mock_disconnect_model,
1258 mock_get_model,
1259 mock_get_controller,
1260 ):
1261
1262 result = {"error": "not found", "response": "response", "request-id": 1}
1263
1264 mock_get_controller.side_effect = JujuAPIError(result)
1265
1266 with self.assertRaises(JujuAPIError):
1267 self.loop.run_until_complete(
1268 self.libjuju.configure_application(
1269 "model",
1270 "app",
1271 {"config"},
1272 )
1273 )
1274 mock_get_model.assert_not_called()
1275 mock_disconnect_controller.assert_not_called()
1276 mock_disconnect_model.assert_not_called()
1277
1278 def test_get_model_exception(
1279 self,
1280 mock_get_application,
1281 mock_disconnect_controller,
1282 mock_disconnect_model,
1283 mock_get_model,
1284 mock_get_controller,
1285 ):
1286
1287 result = {"error": "not found", "response": "response", "request-id": 1}
1288 mock_get_model.side_effect = JujuAPIError(result)
1289
1290 with self.assertRaises(JujuAPIError):
1291 self.loop.run_until_complete(
1292 self.libjuju.configure_application(
1293 "model",
1294 "app",
1295 {"config"},
1296 )
1297 )
1298 mock_get_model.assert_called_once()
1299 mock_disconnect_controller.assert_called_once()
1300 mock_disconnect_model.assert_not_called()
1301
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001302
1303# TODO _get_api_endpoints_db test case
1304# TODO _update_api_endpoints_db test case
1305# TODO healthcheck test case
1306
1307
1308@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1309@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1310@asynctest.mock.patch("juju.controller.Controller.list_models")
1311class ListModelsTest(LibjujuTestCase):
1312 def setUp(self):
1313 super(ListModelsTest, self).setUp()
1314
1315 def test_containing(
David Garcia5b802c92020-11-11 16:56:06 +01001316 self,
1317 mock_list_models,
1318 mock_disconnect_controller,
1319 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001320 ):
1321 mock_get_controller.return_value = juju.controller.Controller()
1322 mock_list_models.return_value = ["existingmodel"]
1323 models = self.loop.run_until_complete(self.libjuju.list_models("existing"))
1324
1325 mock_disconnect_controller.assert_called_once()
1326 self.assertEquals(models, ["existingmodel"])
1327
1328 def test_not_containing(
David Garcia5b802c92020-11-11 16:56:06 +01001329 self,
1330 mock_list_models,
1331 mock_disconnect_controller,
1332 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001333 ):
1334 mock_get_controller.return_value = juju.controller.Controller()
1335 mock_list_models.return_value = ["existingmodel", "model"]
1336 models = self.loop.run_until_complete(self.libjuju.list_models("mdl"))
1337
1338 mock_disconnect_controller.assert_called_once()
1339 self.assertEquals(models, [])
1340
1341 def test_no_contains_arg(
David Garcia5b802c92020-11-11 16:56:06 +01001342 self,
1343 mock_list_models,
1344 mock_disconnect_controller,
1345 mock_get_controller,
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +02001346 ):
1347 mock_get_controller.return_value = juju.controller.Controller()
1348 mock_list_models.return_value = ["existingmodel", "model"]
1349 models = self.loop.run_until_complete(self.libjuju.list_models())
1350
1351 mock_disconnect_controller.assert_called_once()
1352 self.assertEquals(models, ["existingmodel", "model"])
David Garcia42f328a2020-08-25 15:03:01 +02001353
1354
1355@asynctest.mock.patch("n2vc.libjuju.Libjuju.list_models")
1356class ModelsExistTest(LibjujuTestCase):
1357 def setUp(self):
1358 super(ModelsExistTest, self).setUp()
1359
1360 def test_model_names_none(self, mock_list_models):
1361 mock_list_models.return_value = []
1362 with self.assertRaises(Exception):
1363 self.loop.run_until_complete(self.libjuju.models_exist(None))
1364
1365 def test_model_names_empty(self, mock_list_models):
1366 mock_list_models.return_value = []
1367 with self.assertRaises(Exception):
1368 (exist, non_existing_models) = self.loop.run_until_complete(
1369 self.libjuju.models_exist([])
1370 )
1371
1372 def test_model_names_not_existing(self, mock_list_models):
1373 mock_list_models.return_value = ["prometheus", "grafana"]
1374 (exist, non_existing_models) = self.loop.run_until_complete(
1375 self.libjuju.models_exist(["prometheus2", "grafana"])
1376 )
1377 self.assertFalse(exist)
1378 self.assertEqual(non_existing_models, ["prometheus2"])
1379
1380 def test_model_names_exist(self, mock_list_models):
1381 mock_list_models.return_value = ["prometheus", "grafana"]
1382 (exist, non_existing_models) = self.loop.run_until_complete(
1383 self.libjuju.models_exist(["prometheus", "grafana"])
1384 )
1385 self.assertTrue(exist)
1386 self.assertEqual(non_existing_models, [])
David Garciabc538e42020-08-25 15:22:30 +02001387
1388
1389@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1390@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1391@asynctest.mock.patch("juju.controller.Controller.list_offers")
1392class ListOffers(LibjujuTestCase):
1393 def setUp(self):
1394 super(ListOffers, self).setUp()
1395
1396 def test_disconnect_controller(
David Garcia5b802c92020-11-11 16:56:06 +01001397 self,
1398 mock_list_offers,
1399 mock_disconnect_controller,
1400 mock_get_controller,
David Garciabc538e42020-08-25 15:22:30 +02001401 ):
1402 mock_get_controller.return_value = juju.controller.Controller()
1403 mock_list_offers.side_effect = Exception()
1404 with self.assertRaises(Exception):
1405 self.loop.run_until_complete(self.libjuju.list_offers("model"))
1406 mock_disconnect_controller.assert_called_once()
1407
1408 def test_empty_list(
David Garcia5b802c92020-11-11 16:56:06 +01001409 self,
1410 mock_list_offers,
1411 mock_disconnect_controller,
1412 mock_get_controller,
David Garciabc538e42020-08-25 15:22:30 +02001413 ):
1414 mock_get_controller.return_value = juju.controller.Controller()
1415 mock_list_offers.return_value = []
1416 offers = self.loop.run_until_complete(self.libjuju.list_offers("model"))
1417 self.assertEqual(offers, [])
1418 mock_disconnect_controller.assert_called_once()
1419
1420 def test_non_empty_list(
David Garcia5b802c92020-11-11 16:56:06 +01001421 self,
1422 mock_list_offers,
1423 mock_disconnect_controller,
1424 mock_get_controller,
David Garciabc538e42020-08-25 15:22:30 +02001425 ):
1426 mock_get_controller.return_value = juju.controller.Controller()
1427 mock_list_offers.return_value = ["offer"]
1428 offers = self.loop.run_until_complete(self.libjuju.list_offers("model"))
1429 self.assertEqual(offers, ["offer"])
1430 mock_disconnect_controller.assert_called_once()
David Garcia68b00722020-09-11 15:05:00 +02001431
1432
1433@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1434@asynctest.mock.patch("juju.controller.Controller.get_model")
1435@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
1436@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1437@asynctest.mock.patch("juju.model.Model.consume")
1438class ConsumeTest(LibjujuTestCase):
1439 def setUp(self):
1440 super(ConsumeTest, self).setUp()
1441
1442 def test_consume(
1443 self,
1444 mock_consume,
1445 mock_disconnect_controller,
1446 mock_disconnect_model,
1447 mock_get_model,
1448 mock_get_controller,
1449 ):
1450 mock_get_controller.return_value = juju.controller.Controller()
1451 mock_get_model.return_value = juju.model.Model()
1452
David Garcia12b29242020-09-17 16:01:48 +02001453 self.loop.run_until_complete(self.libjuju.consume("offer_url", "model_name"))
David Garcia68b00722020-09-11 15:05:00 +02001454 mock_consume.assert_called_once()
1455 mock_disconnect_model.assert_called_once()
1456 mock_disconnect_controller.assert_called_once()
1457
1458 def test_parsing_error_exception(
1459 self,
1460 mock_consume,
1461 mock_disconnect_controller,
1462 mock_disconnect_model,
1463 mock_get_model,
1464 mock_get_controller,
1465 ):
1466 mock_get_controller.return_value = juju.controller.Controller()
1467 mock_get_model.return_value = juju.model.Model()
1468 mock_consume.side_effect = juju.offerendpoints.ParseError("")
1469
1470 with self.assertRaises(juju.offerendpoints.ParseError):
1471 self.loop.run_until_complete(
1472 self.libjuju.consume("offer_url", "model_name")
1473 )
1474 mock_consume.assert_called_once()
1475 mock_disconnect_model.assert_called_once()
1476 mock_disconnect_controller.assert_called_once()
1477
1478 def test_juju_error_exception(
1479 self,
1480 mock_consume,
1481 mock_disconnect_controller,
1482 mock_disconnect_model,
1483 mock_get_model,
1484 mock_get_controller,
1485 ):
1486 mock_get_controller.return_value = juju.controller.Controller()
1487 mock_get_model.return_value = juju.model.Model()
1488 mock_consume.side_effect = juju.errors.JujuError("")
1489
1490 with self.assertRaises(juju.errors.JujuError):
1491 self.loop.run_until_complete(
1492 self.libjuju.consume("offer_url", "model_name")
1493 )
1494 mock_consume.assert_called_once()
1495 mock_disconnect_model.assert_called_once()
1496 mock_disconnect_controller.assert_called_once()
1497
1498 def test_juju_api_error_exception(
1499 self,
1500 mock_consume,
1501 mock_disconnect_controller,
1502 mock_disconnect_model,
1503 mock_get_model,
1504 mock_get_controller,
1505 ):
1506 mock_get_controller.return_value = juju.controller.Controller()
1507 mock_get_model.return_value = juju.model.Model()
David Garcia12b29242020-09-17 16:01:48 +02001508 mock_consume.side_effect = juju.errors.JujuAPIError(
1509 {"error": "", "response": "", "request-id": ""}
1510 )
David Garcia68b00722020-09-11 15:05:00 +02001511
1512 with self.assertRaises(juju.errors.JujuAPIError):
1513 self.loop.run_until_complete(
1514 self.libjuju.consume("offer_url", "model_name")
1515 )
1516 mock_consume.assert_called_once()
1517 mock_disconnect_model.assert_called_once()
1518 mock_disconnect_controller.assert_called_once()
David Garcia12b29242020-09-17 16:01:48 +02001519
1520
David Garcia475a7222020-09-21 16:19:15 +02001521@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_k8s_cloud_credential")
David Garcia12b29242020-09-17 16:01:48 +02001522@asynctest.mock.patch("n2vc.libjuju.Libjuju.add_cloud")
1523class AddK8sTest(LibjujuTestCase):
1524 def setUp(self):
1525 super(AddK8sTest, self).setUp()
David Garciaf6e9b002020-11-27 15:32:02 +01001526 name = "cloud"
1527 rbac_id = generate_rbac_id()
1528 token = "token"
1529 client_cert_data = "cert"
1530 configuration = kubernetes.client.configuration.Configuration()
1531 storage_class = "storage_class"
1532 credential_name = name
1533
1534 self._add_k8s_args = {
1535 "name": name,
1536 "rbac_id": rbac_id,
1537 "token": token,
1538 "client_cert_data": client_cert_data,
1539 "configuration": configuration,
1540 "storage_class": storage_class,
1541 "credential_name": credential_name,
1542 }
David Garcia12b29242020-09-17 16:01:48 +02001543
David Garcia475a7222020-09-21 16:19:15 +02001544 def test_add_k8s(self, mock_add_cloud, mock_get_k8s_cloud_credential):
David Garciaf6e9b002020-11-27 15:32:02 +01001545 self.loop.run_until_complete(self.libjuju.add_k8s(**self._add_k8s_args))
David Garcia12b29242020-09-17 16:01:48 +02001546 mock_add_cloud.assert_called_once()
David Garcia475a7222020-09-21 16:19:15 +02001547 mock_get_k8s_cloud_credential.assert_called_once()
David Garcia12b29242020-09-17 16:01:48 +02001548
David Garcia475a7222020-09-21 16:19:15 +02001549 def test_add_k8s_exception(self, mock_add_cloud, mock_get_k8s_cloud_credential):
David Garcia12b29242020-09-17 16:01:48 +02001550 mock_add_cloud.side_effect = Exception()
1551 with self.assertRaises(Exception):
David Garciaf6e9b002020-11-27 15:32:02 +01001552 self.loop.run_until_complete(self.libjuju.add_k8s(**self._add_k8s_args))
David Garcia12b29242020-09-17 16:01:48 +02001553 mock_add_cloud.assert_called_once()
David Garcia475a7222020-09-21 16:19:15 +02001554 mock_get_k8s_cloud_credential.assert_called_once()
David Garcia12b29242020-09-17 16:01:48 +02001555
David Garcia475a7222020-09-21 16:19:15 +02001556 def test_add_k8s_missing_name(self, mock_add_cloud, mock_get_k8s_cloud_credential):
David Garciaf6e9b002020-11-27 15:32:02 +01001557 self._add_k8s_args["name"] = ""
David Garcia12b29242020-09-17 16:01:48 +02001558 with self.assertRaises(Exception):
David Garciaf6e9b002020-11-27 15:32:02 +01001559 self.loop.run_until_complete(self.libjuju.add_k8s(**self._add_k8s_args))
David Garcia12b29242020-09-17 16:01:48 +02001560 mock_add_cloud.assert_not_called()
1561
David Garcia475a7222020-09-21 16:19:15 +02001562 def test_add_k8s_missing_storage_name(
1563 self, mock_add_cloud, mock_get_k8s_cloud_credential
1564 ):
David Garciaf6e9b002020-11-27 15:32:02 +01001565 self._add_k8s_args["storage_class"] = ""
David Garcia12b29242020-09-17 16:01:48 +02001566 with self.assertRaises(Exception):
David Garciaf6e9b002020-11-27 15:32:02 +01001567 self.loop.run_until_complete(self.libjuju.add_k8s(**self._add_k8s_args))
David Garcia12b29242020-09-17 16:01:48 +02001568 mock_add_cloud.assert_not_called()
1569
David Garcia475a7222020-09-21 16:19:15 +02001570 def test_add_k8s_missing_configuration_keys(
1571 self, mock_add_cloud, mock_get_k8s_cloud_credential
1572 ):
David Garciaf6e9b002020-11-27 15:32:02 +01001573 self._add_k8s_args["configuration"] = None
David Garcia12b29242020-09-17 16:01:48 +02001574 with self.assertRaises(Exception):
David Garciaf6e9b002020-11-27 15:32:02 +01001575 self.loop.run_until_complete(self.libjuju.add_k8s(**self._add_k8s_args))
David Garcia12b29242020-09-17 16:01:48 +02001576 mock_add_cloud.assert_not_called()
1577
1578
1579@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1580@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1581@asynctest.mock.patch("juju.controller.Controller.add_cloud")
1582@asynctest.mock.patch("juju.controller.Controller.add_credential")
1583class AddCloudTest(LibjujuTestCase):
1584 def setUp(self):
1585 super(AddCloudTest, self).setUp()
1586 self.cloud = juju.client.client.Cloud()
1587 self.credential = juju.client.client.CloudCredential()
1588
1589 def test_add_cloud_with_credential(
1590 self,
1591 mock_add_credential,
1592 mock_add_cloud,
1593 mock_disconnect_controller,
1594 mock_get_controller,
1595 ):
1596 mock_get_controller.return_value = juju.controller.Controller()
1597
1598 cloud = self.loop.run_until_complete(
1599 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1600 )
1601 self.assertEqual(cloud, self.cloud)
1602 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1603 mock_add_credential.assert_called_once_with(
1604 "cloud", credential=self.credential, cloud="cloud"
1605 )
1606 mock_disconnect_controller.assert_called_once()
1607
1608 def test_add_cloud_no_credential(
1609 self,
1610 mock_add_credential,
1611 mock_add_cloud,
1612 mock_disconnect_controller,
1613 mock_get_controller,
1614 ):
1615 mock_get_controller.return_value = juju.controller.Controller()
1616
1617 cloud = self.loop.run_until_complete(
1618 self.libjuju.add_cloud("cloud", self.cloud)
1619 )
1620 self.assertEqual(cloud, self.cloud)
1621 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1622 mock_add_credential.assert_not_called()
1623 mock_disconnect_controller.assert_called_once()
1624
1625 def test_add_cloud_exception(
1626 self,
1627 mock_add_credential,
1628 mock_add_cloud,
1629 mock_disconnect_controller,
1630 mock_get_controller,
1631 ):
1632 mock_get_controller.return_value = juju.controller.Controller()
1633 mock_add_cloud.side_effect = Exception()
1634 with self.assertRaises(Exception):
1635 self.loop.run_until_complete(
1636 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1637 )
1638
1639 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1640 mock_add_credential.assert_not_called()
1641 mock_disconnect_controller.assert_called_once()
1642
1643 def test_add_credential_exception(
1644 self,
1645 mock_add_credential,
1646 mock_add_cloud,
1647 mock_disconnect_controller,
1648 mock_get_controller,
1649 ):
1650 mock_get_controller.return_value = juju.controller.Controller()
1651 mock_add_credential.side_effect = Exception()
1652 with self.assertRaises(Exception):
1653 self.loop.run_until_complete(
1654 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1655 )
1656
1657 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1658 mock_add_credential.assert_called_once_with(
1659 "cloud", credential=self.credential, cloud="cloud"
1660 )
1661 mock_disconnect_controller.assert_called_once()
1662
1663
1664@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1665@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1666@asynctest.mock.patch("juju.controller.Controller.remove_cloud")
1667class RemoveCloudTest(LibjujuTestCase):
1668 def setUp(self):
1669 super(RemoveCloudTest, self).setUp()
1670
1671 def test_remove_cloud(
David Garcia5b802c92020-11-11 16:56:06 +01001672 self,
1673 mock_remove_cloud,
1674 mock_disconnect_controller,
1675 mock_get_controller,
David Garcia12b29242020-09-17 16:01:48 +02001676 ):
1677 mock_get_controller.return_value = juju.controller.Controller()
1678
1679 self.loop.run_until_complete(self.libjuju.remove_cloud("cloud"))
1680 mock_remove_cloud.assert_called_once_with("cloud")
1681 mock_disconnect_controller.assert_called_once()
1682
1683 def test_remove_cloud_exception(
David Garcia5b802c92020-11-11 16:56:06 +01001684 self,
1685 mock_remove_cloud,
1686 mock_disconnect_controller,
1687 mock_get_controller,
David Garcia12b29242020-09-17 16:01:48 +02001688 ):
1689 mock_get_controller.return_value = juju.controller.Controller()
1690 mock_remove_cloud.side_effect = Exception()
1691
1692 with self.assertRaises(Exception):
1693 self.loop.run_until_complete(self.libjuju.remove_cloud("cloud"))
1694 mock_remove_cloud.assert_called_once_with("cloud")
1695 mock_disconnect_controller.assert_called_once()
David Garcia475a7222020-09-21 16:19:15 +02001696
1697
1698@asynctest.mock.patch("kubernetes.client.configuration.Configuration")
1699class GetK8sCloudCredentials(LibjujuTestCase):
1700 def setUp(self):
1701 super(GetK8sCloudCredentials, self).setUp()
David Garciaf6e9b002020-11-27 15:32:02 +01001702 self.cert_data = "cert"
1703 self.token = "token"
David Garcia475a7222020-09-21 16:19:15 +02001704
1705 @asynctest.mock.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
1706 def test_not_supported(self, mock_exception, mock_configuration):
1707 mock_configuration.username = ""
1708 mock_configuration.password = ""
1709 mock_configuration.ssl_ca_cert = None
1710 mock_configuration.cert_file = None
1711 mock_configuration.key_file = None
1712 exception_raised = False
David Garciaf6e9b002020-11-27 15:32:02 +01001713 self.token = None
1714 self.cert_data = None
David Garcia475a7222020-09-21 16:19:15 +02001715 try:
David Garciaf6e9b002020-11-27 15:32:02 +01001716 _ = self.libjuju.get_k8s_cloud_credential(
1717 mock_configuration,
1718 self.cert_data,
1719 self.token,
1720 )
David Garcia475a7222020-09-21 16:19:15 +02001721 except JujuInvalidK8sConfiguration as e:
1722 exception_raised = True
1723 self.assertEqual(
David Garcia5b802c92020-11-11 16:56:06 +01001724 e.message,
1725 "authentication method not supported",
David Garcia475a7222020-09-21 16:19:15 +02001726 )
1727 self.assertTrue(exception_raised)
1728
1729 def test_user_pass(self, mock_configuration):
1730 mock_configuration.username = "admin"
1731 mock_configuration.password = "admin"
1732 mock_configuration.ssl_ca_cert = None
1733 mock_configuration.cert_file = None
1734 mock_configuration.key_file = None
David Garciaf6e9b002020-11-27 15:32:02 +01001735 self.token = None
1736 self.cert_data = None
1737 credential = self.libjuju.get_k8s_cloud_credential(
1738 mock_configuration,
1739 self.cert_data,
1740 self.token,
1741 )
David Garcia475a7222020-09-21 16:19:15 +02001742 self.assertEqual(
1743 credential,
1744 juju.client._definitions.CloudCredential(
1745 attrs={"username": "admin", "password": "admin"}, auth_type="userpass"
1746 ),
1747 )
1748
David Garciaf6e9b002020-11-27 15:32:02 +01001749 def test_user_pass_with_cert(self, mock_configuration):
1750 mock_configuration.username = "admin"
1751 mock_configuration.password = "admin"
1752 mock_configuration.ssl_ca_cert = None
1753 mock_configuration.cert_file = None
1754 mock_configuration.key_file = None
1755 self.token = None
1756 credential = self.libjuju.get_k8s_cloud_credential(
1757 mock_configuration,
1758 self.cert_data,
1759 self.token,
1760 )
1761 self.assertEqual(
1762 credential,
1763 juju.client._definitions.CloudCredential(
1764 attrs={
1765 "ClientCertificateData": self.cert_data,
1766 "username": "admin",
1767 "password": "admin",
1768 },
1769 auth_type="userpasswithcert",
1770 ),
1771 )
1772
David Garcia475a7222020-09-21 16:19:15 +02001773 def test_user_no_pass(self, mock_configuration):
1774 mock_configuration.username = "admin"
1775 mock_configuration.password = ""
1776 mock_configuration.ssl_ca_cert = None
1777 mock_configuration.cert_file = None
1778 mock_configuration.key_file = None
David Garciaf6e9b002020-11-27 15:32:02 +01001779 self.token = None
1780 self.cert_data = None
David Garciaeb8943a2021-04-12 12:07:37 +02001781 with patch.object(self.libjuju.log, "debug") as mock_debug:
David Garciaf6e9b002020-11-27 15:32:02 +01001782 credential = self.libjuju.get_k8s_cloud_credential(
1783 mock_configuration,
1784 self.cert_data,
1785 self.token,
1786 )
David Garcia475a7222020-09-21 16:19:15 +02001787 self.assertEqual(
1788 credential,
1789 juju.client._definitions.CloudCredential(
1790 attrs={"username": "admin", "password": ""}, auth_type="userpass"
1791 ),
1792 )
1793 mock_debug.assert_called_once_with(
1794 "credential for user admin has empty password"
1795 )
1796
David Garcia475a7222020-09-21 16:19:15 +02001797 def test_cert(self, mock_configuration):
1798 mock_configuration.username = ""
1799 mock_configuration.password = ""
1800 mock_configuration.api_key = {"authorization": "Bearer Token"}
1801 ssl_ca_cert = tempfile.NamedTemporaryFile()
1802 with open(ssl_ca_cert.name, "w") as ssl_ca_cert_file:
1803 ssl_ca_cert_file.write("cacert")
1804 mock_configuration.ssl_ca_cert = ssl_ca_cert.name
1805 mock_configuration.cert_file = None
1806 mock_configuration.key_file = None
David Garciaf6e9b002020-11-27 15:32:02 +01001807 credential = self.libjuju.get_k8s_cloud_credential(
1808 mock_configuration,
1809 self.cert_data,
1810 self.token,
1811 )
David Garcia475a7222020-09-21 16:19:15 +02001812 self.assertEqual(
1813 credential,
1814 juju.client._definitions.CloudCredential(
David Garciaf6e9b002020-11-27 15:32:02 +01001815 attrs={"ClientCertificateData": self.cert_data, "Token": self.token},
David Garcia475a7222020-09-21 16:19:15 +02001816 auth_type="certificate",
1817 ),
1818 )
1819
David Garciaf6e9b002020-11-27 15:32:02 +01001820 # TODO: Fix this test when oauth authentication is supported
1821 # def test_oauth2(self, mock_configuration):
1822 # mock_configuration.username = ""
1823 # mock_configuration.password = ""
1824 # mock_configuration.api_key = {"authorization": "Bearer Token"}
1825 # key = tempfile.NamedTemporaryFile()
1826 # with open(key.name, "w") as key_file:
1827 # key_file.write("key")
1828 # mock_configuration.ssl_ca_cert = None
1829 # mock_configuration.cert_file = None
1830 # mock_configuration.key_file = key.name
1831 # credential = self.libjuju.get_k8s_cloud_credential(
1832 # mock_configuration,
1833 # self.cert_data,
1834 # self.token,
1835 # )
1836 # self.assertEqual(
1837 # credential,
1838 # juju.client._definitions.CloudCredential(
1839 # attrs={"ClientKeyData": "key", "Token": "Token"},
1840 # auth_type="oauth2",
1841 # ),
1842 # )
David Garcia475a7222020-09-21 16:19:15 +02001843
David Garciaf6e9b002020-11-27 15:32:02 +01001844 # @asynctest.mock.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
1845 # def test_oauth2_missing_token(self, mock_exception, mock_configuration):
1846 # mock_configuration.username = ""
1847 # mock_configuration.password = ""
1848 # key = tempfile.NamedTemporaryFile()
1849 # with open(key.name, "w") as key_file:
1850 # key_file.write("key")
1851 # mock_configuration.ssl_ca_cert = None
1852 # mock_configuration.cert_file = None
1853 # mock_configuration.key_file = key.name
1854 # exception_raised = False
1855 # try:
1856 # _ = self.libjuju.get_k8s_cloud_credential(
1857 # mock_configuration,
1858 # self.cert_data,
1859 # self.token,
1860 # )
1861 # except JujuInvalidK8sConfiguration as e:
1862 # exception_raised = True
1863 # self.assertEqual(
1864 # e.message,
1865 # "missing token for auth type oauth2",
1866 # )
1867 # self.assertTrue(exception_raised)
David Garcia475a7222020-09-21 16:19:15 +02001868
1869 def test_exception_cannot_set_token_and_userpass(self, mock_configuration):
1870 mock_configuration.username = "admin"
1871 mock_configuration.password = "pass"
1872 mock_configuration.api_key = {"authorization": "No_bearer_token"}
1873 mock_configuration.ssl_ca_cert = None
1874 mock_configuration.cert_file = None
1875 mock_configuration.key_file = None
1876 exception_raised = False
1877 try:
David Garciaf6e9b002020-11-27 15:32:02 +01001878 _ = self.libjuju.get_k8s_cloud_credential(
1879 mock_configuration,
1880 self.cert_data,
1881 self.token,
1882 )
David Garcia475a7222020-09-21 16:19:15 +02001883 except JujuInvalidK8sConfiguration as e:
1884 exception_raised = True
1885 self.assertEqual(
David Garcia5b802c92020-11-11 16:56:06 +01001886 e.message,
1887 "Cannot set both token and user/pass",
David Garcia475a7222020-09-21 16:19:15 +02001888 )
1889 self.assertTrue(exception_raised)