blob: 57a6ccc69bc6fd21d00a6317b6349f490a76f6b1 [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
17import juju
18from juju.errors import JujuAPIError
19import logging
20from .utils import FakeN2VC, FakeMachine, FakeApplication
21from n2vc.libjuju import Libjuju
22from n2vc.exceptions import (
23 JujuControllerFailedConnecting,
24 JujuModelAlreadyExists,
25 JujuMachineNotFound,
26 JujuApplicationNotFound,
27 JujuActionNotFound,
28 JujuApplicationExists,
29)
30
31
32class LibjujuTestCase(asynctest.TestCase):
33 @asynctest.mock.patch("juju.controller.Controller.update_endpoints")
34 @asynctest.mock.patch("juju.client.connector.Connector.connect")
35 @asynctest.mock.patch("juju.controller.Controller.connection")
36 @asynctest.mock.patch("n2vc.libjuju.Libjuju._get_api_endpoints_db")
37 def setUp(
38 self,
39 mock__get_api_endpoints_db=None,
40 mock_connection=None,
41 mock_connect=None,
42 mock_update_endpoints=None,
43 ):
44 loop = asyncio.get_event_loop()
45 n2vc = FakeN2VC()
46 mock__get_api_endpoints_db.return_value = ["127.0.0.1:17070"]
47 endpoints = "127.0.0.1:17070"
48 username = "admin"
49 password = "secret"
50 cacert = """
51 -----BEGIN CERTIFICATE-----
52 SOMECERT
53 -----END CERTIFICATE-----"""
54 self.libjuju = Libjuju(
55 endpoints,
56 "192.168.0.155:17070",
57 username,
58 password,
59 cacert,
60 loop,
61 log=None,
62 db={"get_one": []},
63 n2vc=n2vc,
64 apt_mirror="192.168.0.100",
65 enable_os_upgrade=True,
66 )
67 logging.disable(logging.CRITICAL)
68 loop.run_until_complete(self.libjuju.disconnect())
69
70
71@asynctest.mock.patch("juju.controller.Controller.connect")
72@asynctest.mock.patch(
73 "juju.controller.Controller.api_endpoints",
74 new_callable=asynctest.CoroutineMock(return_value=["127.0.0.1:17070"]),
75)
76@asynctest.mock.patch("n2vc.libjuju.Libjuju._update_api_endpoints_db")
77class GetControllerTest(LibjujuTestCase):
78 def setUp(self):
79 super(GetControllerTest, self).setUp()
80
81 def test_diff_endpoint(
82 self, mock__update_api_endpoints_db, mock_api_endpoints, mock_connect
83 ):
84 self.libjuju.endpoints = []
85 controller = self.loop.run_until_complete(self.libjuju.get_controller())
86 mock__update_api_endpoints_db.assert_called_once_with(["127.0.0.1:17070"])
87 self.assertIsInstance(controller, juju.controller.Controller)
88
89 @asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
90 def test_exception(
91 self,
92 mock_disconnect_controller,
93 mock__update_api_endpoints_db,
94 mock_api_endpoints,
95 mock_connect,
96 ):
97 self.libjuju.endpoints = []
98 mock__update_api_endpoints_db.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +020099 controller = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200100 with self.assertRaises(JujuControllerFailedConnecting):
101 controller = self.loop.run_until_complete(self.libjuju.get_controller())
David Garcia12b29242020-09-17 16:01:48 +0200102 self.assertIsNone(controller)
103 mock_disconnect_controller.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200104
105 def test_same_endpoint_get_controller(
106 self, mock__update_api_endpoints_db, mock_api_endpoints, mock_connect
107 ):
108 self.libjuju.endpoints = ["127.0.0.1:17070"]
109 controller = self.loop.run_until_complete(self.libjuju.get_controller())
110 mock__update_api_endpoints_db.assert_not_called()
111 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
150 with self.assertRaises(JujuModelAlreadyExists):
151 self.loop.run_until_complete(
152 self.libjuju.add_model("existing_model", "cloud")
153 )
154
David Garcia12b29242020-09-17 16:01:48 +0200155 mock_disconnect_controller.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200156
157 # TODO Check two job executing at the same time and one returning without doing anything.
158
159 def test_non_existing_model(
160 self,
161 mock_disconnect_model,
162 mock_disconnect_controller,
163 mock_add_model,
164 mock_model_exists,
165 mock_get_controller,
166 ):
167 mock_model_exists.return_value = False
168 mock_get_controller.return_value = juju.controller.Controller()
169
170 self.loop.run_until_complete(
171 self.libjuju.add_model("nonexisting_model", "cloud")
172 )
173
174 mock_add_model.assert_called_once()
175 mock_disconnect_controller.assert_called()
176 mock_disconnect_model.assert_called()
177
178
179@asynctest.mock.patch("juju.controller.Controller.get_model")
180class GetModelTest(LibjujuTestCase):
181 def setUp(self):
182 super(GetModelTest, self).setUp()
183
184 def test_get_model(
185 self, mock_get_model,
186 ):
187 mock_get_model.return_value = juju.model.Model()
188 model = self.loop.run_until_complete(
189 self.libjuju.get_model(juju.controller.Controller(), "model")
190 )
191 self.assertIsInstance(model, juju.model.Model)
192
193
194@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
195@asynctest.mock.patch("juju.controller.Controller.list_models")
196class ModelExistsTest(LibjujuTestCase):
197 def setUp(self):
198 super(ModelExistsTest, self).setUp()
199
200 async def test_existing_model(
201 self, mock_list_models, mock_get_controller,
202 ):
203 mock_list_models.return_value = ["existing_model"]
204 self.assertTrue(
205 await self.libjuju.model_exists(
206 "existing_model", juju.controller.Controller()
207 )
208 )
209
210 @asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
211 async def test_no_controller(
212 self, mock_disconnect_controller, mock_list_models, mock_get_controller,
213 ):
214 mock_list_models.return_value = ["existing_model"]
215 mock_get_controller.return_value = juju.controller.Controller()
216 self.assertTrue(await self.libjuju.model_exists("existing_model"))
217 mock_disconnect_controller.assert_called_once()
218
219 async def test_non_existing_model(
220 self, mock_list_models, mock_get_controller,
221 ):
222 mock_list_models.return_value = ["existing_model"]
223 self.assertFalse(
224 await self.libjuju.model_exists(
225 "not_existing_model", juju.controller.Controller()
226 )
227 )
228
229
230@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
231@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
232@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
233@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
234@asynctest.mock.patch("juju.model.Model.get_status")
235class GetModelStatusTest(LibjujuTestCase):
236 def setUp(self):
237 super(GetModelStatusTest, self).setUp()
238
239 def test_success(
240 self,
241 mock_get_status,
242 mock_disconnect_controller,
243 mock_disconnect_model,
244 mock_get_model,
245 mock_get_controller,
246 ):
247 mock_get_model.return_value = juju.model.Model()
248 mock_get_status.return_value = {"status"}
249
250 status = self.loop.run_until_complete(self.libjuju.get_model_status("model"))
251
252 mock_get_status.assert_called_once()
253 mock_disconnect_controller.assert_called_once()
254 mock_disconnect_model.assert_called_once()
255
256 self.assertEqual(status, {"status"})
257
David Garcia12b29242020-09-17 16:01:48 +0200258 def test_exception(
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200259 self,
260 mock_get_status,
261 mock_disconnect_controller,
262 mock_disconnect_model,
263 mock_get_model,
264 mock_get_controller,
265 ):
266 mock_get_model.return_value = juju.model.Model()
267 mock_get_status.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +0200268 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200269 with self.assertRaises(Exception):
270 status = self.loop.run_until_complete(
271 self.libjuju.get_model_status("model")
272 )
273
David Garcia12b29242020-09-17 16:01:48 +0200274 mock_disconnect_controller.assert_called_once()
275 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200276
David Garcia12b29242020-09-17 16:01:48 +0200277 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200278
279
280@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
281@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
282@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
283@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
284@asynctest.mock.patch("juju.model.Model.get_machines")
285@asynctest.mock.patch("juju.model.Model.add_machine")
286@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
287class CreateMachineTest(LibjujuTestCase):
288 def setUp(self):
289 super(CreateMachineTest, self).setUp()
290
291 def test_existing_machine(
292 self,
293 mock_wait_for,
294 mock_add_machine,
295 mock_get_machines,
296 mock_disconnect_controller,
297 mock_disconnect_model,
298 mock_get_model,
299 mock_get_controller,
300 ):
301 mock_get_model.return_value = juju.model.Model()
302 mock_get_machines.return_value = {"existing_machine": FakeMachine()}
303 machine, bool_res = self.loop.run_until_complete(
304 self.libjuju.create_machine("model", "existing_machine")
305 )
306
307 self.assertIsInstance(machine, FakeMachine)
308 self.assertFalse(bool_res)
309
310 mock_disconnect_controller.assert_called()
311 mock_disconnect_model.assert_called()
312
313 def test_non_existing_machine(
314 self,
315 mock_wait_for,
316 mock_add_machine,
317 mock_get_machines,
318 mock_disconnect_controller,
319 mock_disconnect_model,
320 mock_get_model,
321 mock_get_controller,
322 ):
David Garcia12b29242020-09-17 16:01:48 +0200323 machine = None
324 bool_res = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200325 mock_get_model.return_value = juju.model.Model()
326 with self.assertRaises(JujuMachineNotFound):
327 machine, bool_res = self.loop.run_until_complete(
328 self.libjuju.create_machine("model", "non_existing_machine")
329 )
David Garcia12b29242020-09-17 16:01:48 +0200330 self.assertIsNone(machine)
331 self.assertIsNone(bool_res)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200332
David Garcia12b29242020-09-17 16:01:48 +0200333 mock_disconnect_controller.assert_called()
334 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200335
336 def test_no_machine(
337 self,
338 mock_wait_for,
339 mock_add_machine,
340 mock_get_machines,
341 mock_disconnect_controller,
342 mock_disconnect_model,
343 mock_get_model,
344 mock_get_controller,
345 ):
346 mock_get_model.return_value = juju.model.Model()
347 mock_add_machine.return_value = FakeMachine()
348
349 machine, bool_res = self.loop.run_until_complete(
350 self.libjuju.create_machine("model")
351 )
352
353 self.assertIsInstance(machine, FakeMachine)
354 self.assertTrue(bool_res)
355
356 mock_wait_for.assert_called_once()
357 mock_add_machine.assert_called_once()
358
359 mock_disconnect_controller.assert_called()
360 mock_disconnect_model.assert_called()
361
362
363# TODO test provision machine
364
365
366@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
367@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
368@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
369@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
370@asynctest.mock.patch(
371 "juju.model.Model.applications", new_callable=asynctest.PropertyMock
372)
373@asynctest.mock.patch("juju.model.Model.machines", new_callable=asynctest.PropertyMock)
374@asynctest.mock.patch("juju.model.Model.deploy")
375@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
376@asynctest.mock.patch("n2vc.libjuju.Libjuju.create_machine")
377class DeployCharmTest(LibjujuTestCase):
378 def setUp(self):
379 super(DeployCharmTest, self).setUp()
380
381 def test_existing_app(
382 self,
383 mock_create_machine,
384 mock_wait_for,
385 mock_deploy,
386 mock_machines,
387 mock_applications,
388 mock_disconnect_controller,
389 mock_disconnect_model,
390 mock_get_model,
391 mock_get_controller,
392 ):
393 mock_get_model.return_value = juju.model.Model()
394 mock_applications.return_value = {"existing_app"}
395
David Garcia12b29242020-09-17 16:01:48 +0200396 application = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200397 with self.assertRaises(JujuApplicationExists):
398 application = self.loop.run_until_complete(
399 self.libjuju.deploy_charm("existing_app", "path", "model", "machine",)
400 )
David Garcia12b29242020-09-17 16:01:48 +0200401 self.assertIsNone(application)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200402
David Garcia12b29242020-09-17 16:01:48 +0200403 mock_disconnect_controller.assert_called()
404 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200405
406 def test_non_existing_machine(
407 self,
408 mock_create_machine,
409 mock_wait_for,
410 mock_deploy,
411 mock_machines,
412 mock_applications,
413 mock_disconnect_controller,
414 mock_disconnect_model,
415 mock_get_model,
416 mock_get_controller,
417 ):
418 mock_get_model.return_value = juju.model.Model()
419 mock_machines.return_value = {"existing_machine": FakeMachine()}
David Garcia12b29242020-09-17 16:01:48 +0200420 application = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200421 with self.assertRaises(JujuMachineNotFound):
422 application = self.loop.run_until_complete(
423 self.libjuju.deploy_charm("app", "path", "model", "machine",)
424 )
425
David Garcia12b29242020-09-17 16:01:48 +0200426 self.assertIsNone(application)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200427
David Garcia12b29242020-09-17 16:01:48 +0200428 mock_disconnect_controller.assert_called()
429 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200430
431 def test_2_units(
432 self,
433 mock_create_machine,
434 mock_wait_for,
435 mock_deploy,
436 mock_machines,
437 mock_applications,
438 mock_disconnect_controller,
439 mock_disconnect_model,
440 mock_get_model,
441 mock_get_controller,
442 ):
443 mock_get_model.return_value = juju.model.Model()
444 mock_machines.return_value = {"existing_machine": FakeMachine()}
445 mock_create_machine.return_value = (FakeMachine(), "other")
446 mock_deploy.return_value = FakeApplication()
447 application = self.loop.run_until_complete(
448 self.libjuju.deploy_charm(
449 "app", "path", "model", "existing_machine", num_units=2,
450 )
451 )
452
453 self.assertIsInstance(application, FakeApplication)
454
455 mock_deploy.assert_called_once()
456 mock_wait_for.assert_called_once()
457
458 mock_create_machine.assert_called_once()
459
460 mock_disconnect_controller.assert_called()
461 mock_disconnect_model.assert_called()
462
463 def test_1_unit(
464 self,
465 mock_create_machine,
466 mock_wait_for,
467 mock_deploy,
468 mock_machines,
469 mock_applications,
470 mock_disconnect_controller,
471 mock_disconnect_model,
472 mock_get_model,
473 mock_get_controller,
474 ):
475 mock_get_model.return_value = juju.model.Model()
476 mock_machines.return_value = {"existing_machine": FakeMachine()}
477 mock_deploy.return_value = FakeApplication()
478 application = self.loop.run_until_complete(
479 self.libjuju.deploy_charm("app", "path", "model", "existing_machine")
480 )
481
482 self.assertIsInstance(application, FakeApplication)
483
484 mock_deploy.assert_called_once()
485 mock_wait_for.assert_called_once()
486
487 mock_disconnect_controller.assert_called()
488 mock_disconnect_model.assert_called()
489
490
491@asynctest.mock.patch(
492 "juju.model.Model.applications", new_callable=asynctest.PropertyMock
493)
494class GetApplicationTest(LibjujuTestCase):
495 def setUp(self):
496 super(GetApplicationTest, self).setUp()
497
498 def test_existing_application(
499 self, mock_applications,
500 ):
501 mock_applications.return_value = {"existing_app": "exists"}
502 model = juju.model.Model()
503 result = self.libjuju._get_application(model, "existing_app")
504 self.assertEqual(result, "exists")
505
506 def test_non_existing_application(
507 self, mock_applications,
508 ):
509 mock_applications.return_value = {"existing_app": "exists"}
510 model = juju.model.Model()
511 result = self.libjuju._get_application(model, "nonexisting_app")
512 self.assertIsNone(result)
513
514
515@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
516@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
517@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
518@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
519@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
520@asynctest.mock.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
521@asynctest.mock.patch("juju.model.Model.get_action_output")
522@asynctest.mock.patch("juju.model.Model.get_action_status")
523class ExecuteActionTest(LibjujuTestCase):
524 def setUp(self):
525 super(ExecuteActionTest, self).setUp()
526
527 def test_no_application(
528 self,
529 mock_get_action_status,
530 mock_get_action_output,
531 mock_wait_for,
532 mock__get_application,
533 mock_disconnect_controller,
534 mock_disconnect_model,
535 mock_get_model,
536 mock_get_controller,
537 ):
538 mock__get_application.return_value = None
539 mock_get_model.return_value = juju.model.Model()
David Garcia12b29242020-09-17 16:01:48 +0200540 output = None
541 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200542 with self.assertRaises(JujuApplicationNotFound):
543 output, status = self.loop.run_until_complete(
544 self.libjuju.execute_action("app", "model", "action",)
545 )
David Garcia12b29242020-09-17 16:01:48 +0200546 self.assertIsNone(output)
547 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200548
David Garcia12b29242020-09-17 16:01:48 +0200549 mock_disconnect_controller.assert_called()
550 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200551
552 def test_no_action(
553 self,
554 mock_get_action_status,
555 mock_get_action_output,
556 mock_wait_for,
557 mock__get_application,
558 mock_disconnect_controller,
559 mock_disconnect_model,
560 mock_get_model,
561 mock_get_controller,
562 ):
563
564 mock_get_model.return_value = juju.model.Model()
565 mock__get_application.return_value = FakeApplication()
David Garcia12b29242020-09-17 16:01:48 +0200566 output = None
567 status = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200568 with self.assertRaises(JujuActionNotFound):
569 output, status = self.loop.run_until_complete(
570 self.libjuju.execute_action("app", "model", "action",)
571 )
David Garcia12b29242020-09-17 16:01:48 +0200572 self.assertIsNone(output)
573 self.assertIsNone(status)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200574
David Garcia12b29242020-09-17 16:01:48 +0200575 mock_disconnect_controller.assert_called()
576 mock_disconnect_model.assert_called()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200577
578 # TODO no leader unit found exception
579
580 def test_succesful_exec(
581 self,
582 mock_get_action_status,
583 mock_get_action_output,
584 mock_wait_for,
585 mock__get_application,
586 mock_disconnect_controller,
587 mock_disconnect_model,
588 mock_get_model,
589 mock_get_controller,
590 ):
591 mock_get_model.return_value = juju.model.Model()
592 mock__get_application.return_value = FakeApplication()
593 mock_get_action_output.return_value = "output"
594 mock_get_action_status.return_value = {"id": "status"}
595 output, status = self.loop.run_until_complete(
596 self.libjuju.execute_action("app", "model", "existing_action")
597 )
598 self.assertEqual(output, "output")
599 self.assertEqual(status, "status")
600
601 mock_wait_for.assert_called_once()
602
603 mock_disconnect_controller.assert_called()
604 mock_disconnect_model.assert_called()
605
606
607@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
608@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
609@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
610@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
611@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
612class GetActionTest(LibjujuTestCase):
613 def setUp(self):
614 super(GetActionTest, self).setUp()
615
616 def test_exception(
617 self,
618 mock_get_application,
619 mock_disconnect_controller,
620 mock_disconnect_model,
621 mock_get_model,
622 mock_get_controller,
623 ):
624 mock_get_application.side_effect = Exception()
David Garcia12b29242020-09-17 16:01:48 +0200625 actions = None
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200626 with self.assertRaises(Exception):
627 actions = self.loop.run_until_complete(
628 self.libjuju.get_actions("app", "model")
629 )
630
David Garcia12b29242020-09-17 16:01:48 +0200631 self.assertIsNone(actions)
632 mock_disconnect_controller.assert_called_once()
633 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200634
635 def test_success(
636 self,
637 mock_get_application,
638 mock_disconnect_controller,
639 mock_disconnect_model,
640 mock_get_model,
641 mock_get_controller,
642 ):
643 mock_get_application.return_value = FakeApplication()
644
645 actions = self.loop.run_until_complete(self.libjuju.get_actions("app", "model"))
646
647 self.assertEqual(actions, ["existing_action"])
648
649 mock_get_controller.assert_called_once()
650 mock_get_model.assert_called_once()
651 mock_disconnect_controller.assert_called_once()
652 mock_disconnect_model.assert_called_once()
653
654
655@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
656@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
657@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
658@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
David Garcia85755d12020-09-21 19:51:23 +0200659@asynctest.mock.patch("juju.application.Application.get_metrics")
660@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
661class GetMetricsTest(LibjujuTestCase):
662 def setUp(self):
663 super(GetMetricsTest, self).setUp()
664
665 def test_get_metrics_success(
666 self,
667 mock_get_application,
668 mock_get_metrics,
669 mock_disconnect_controller,
670 mock_disconnect_model,
671 mock_get_model,
672 mock_get_controller,
673 ):
674 mock_get_application.return_value = FakeApplication()
675 mock_get_model.return_value = juju.model.Model()
676
677 self.loop.run_until_complete(self.libjuju.get_metrics("model", "app1"))
678
679 mock_disconnect_controller.assert_called_once()
680 mock_disconnect_model.assert_called_once()
681
682 def test_get_metrics_exception(
683 self,
684 mock_get_application,
685 mock_get_metrics,
686 mock_disconnect_controller,
687 mock_disconnect_model,
688 mock_get_model,
689 mock_get_controller,
690 ):
691 mock_get_model.return_value = juju.model.Model()
692 mock_get_metrics.side_effect = Exception()
693 with self.assertRaises(Exception):
694 self.loop.run_until_complete(self.libjuju.get_metrics("model", "app1"))
695
696 mock_disconnect_controller.assert_called_once()
697 mock_disconnect_model.assert_called_once()
698
699 def test_missing_args_exception(
700 self,
701 mock_get_application,
702 mock_get_metrics,
703 mock_disconnect_controller,
704 mock_disconnect_model,
705 mock_get_model,
706 mock_get_controller,
707 ):
708 mock_get_model.return_value = juju.model.Model()
709
710 with self.assertRaises(Exception):
711 self.loop.run_until_complete(self.libjuju.get_metrics("", ""))
712
713 mock_get_controller.assert_not_called()
714 mock_get_model.assert_not_called()
715 mock_disconnect_controller.assert_not_called()
716 mock_disconnect_model.assert_not_called()
717
718
719@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
720@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
721@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
722@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200723@asynctest.mock.patch("juju.model.Model.add_relation")
724class AddRelationTest(LibjujuTestCase):
725 def setUp(self):
726 super(AddRelationTest, self).setUp()
727
728 @asynctest.mock.patch("logging.Logger.warning")
729 def test_not_found(
730 self,
731 mock_warning,
732 mock_add_relation,
733 mock_disconnect_controller,
734 mock_disconnect_model,
735 mock_get_model,
736 mock_get_controller,
737 ):
738 # TODO in libjuju.py should this fail only with a log message?
739 result = {"error": "not found", "response": "response", "request-id": 1}
740
741 mock_get_model.return_value = juju.model.Model()
742 mock_add_relation.side_effect = JujuAPIError(result)
743
744 self.loop.run_until_complete(
David Garcia8331f7c2020-08-25 16:10:07 +0200745 self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200746 )
747
748 mock_warning.assert_called_with("Relation not found: not found")
749 mock_disconnect_controller.assert_called_once()
750 mock_disconnect_model.assert_called_once()
751
752 @asynctest.mock.patch("logging.Logger.warning")
753 def test_already_exists(
754 self,
755 mock_warning,
756 mock_add_relation,
757 mock_disconnect_controller,
758 mock_disconnect_model,
759 mock_get_model,
760 mock_get_controller,
761 ):
762 # TODO in libjuju.py should this fail silently?
763 result = {"error": "already exists", "response": "response", "request-id": 1}
764
765 mock_get_model.return_value = juju.model.Model()
766 mock_add_relation.side_effect = JujuAPIError(result)
767
768 self.loop.run_until_complete(
David Garcia8331f7c2020-08-25 16:10:07 +0200769 self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200770 )
771
772 mock_warning.assert_called_with("Relation already exists: already exists")
773 mock_disconnect_controller.assert_called_once()
774 mock_disconnect_model.assert_called_once()
775
776 def test_exception(
777 self,
778 mock_add_relation,
779 mock_disconnect_controller,
780 mock_disconnect_model,
781 mock_get_model,
782 mock_get_controller,
783 ):
784 mock_get_model.return_value = juju.model.Model()
785 result = {"error": "", "response": "response", "request-id": 1}
786 mock_add_relation.side_effect = JujuAPIError(result)
787
788 with self.assertRaises(JujuAPIError):
789 self.loop.run_until_complete(
David Garcia8331f7c2020-08-25 16:10:07 +0200790 self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200791 )
792
David Garcia12b29242020-09-17 16:01:48 +0200793 mock_disconnect_controller.assert_called_once()
794 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200795
796 def test_success(
797 self,
798 mock_add_relation,
799 mock_disconnect_controller,
800 mock_disconnect_model,
801 mock_get_model,
802 mock_get_controller,
803 ):
804 mock_get_model.return_value = juju.model.Model()
805
806 self.loop.run_until_complete(
David Garcia8331f7c2020-08-25 16:10:07 +0200807 self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",)
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200808 )
809
David Garcia12b29242020-09-17 16:01:48 +0200810 mock_add_relation.assert_called_with("app1:relation1", "app2:relation2")
David Garcia8331f7c2020-08-25 16:10:07 +0200811 mock_disconnect_controller.assert_called_once()
812 mock_disconnect_model.assert_called_once()
813
814 def test_saas(
815 self,
816 mock_add_relation,
817 mock_disconnect_controller,
818 mock_disconnect_model,
819 mock_get_model,
820 mock_get_controller,
821 ):
822 mock_get_model.return_value = juju.model.Model()
823
824 self.loop.run_until_complete(
825 self.libjuju.add_relation("model", "app1:relation1", "saas_name",)
826 )
827
David Garcia12b29242020-09-17 16:01:48 +0200828 mock_add_relation.assert_called_with("app1:relation1", "saas_name")
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200829 mock_disconnect_controller.assert_called_once()
830 mock_disconnect_model.assert_called_once()
831
832
833# TODO destroy_model testcase
834
835
836@asynctest.mock.patch("juju.model.Model.get_machines")
837@asynctest.mock.patch("logging.Logger.debug")
838class DestroyMachineTest(LibjujuTestCase):
839 def setUp(self):
840 super(DestroyMachineTest, self).setUp()
841
842 def test_success(
843 self, mock_debug, mock_get_machines,
844 ):
845 mock_get_machines.side_effect = [
846 {"machine": FakeMachine()},
847 {"machine": FakeMachine()},
848 {},
849 ]
850 self.loop.run_until_complete(
851 self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
852 )
853 calls = [
854 asynctest.call("Waiting for machine machine is destroyed"),
855 asynctest.call("Machine destroyed: machine"),
856 ]
857 mock_debug.assert_has_calls(calls)
858
859 def test_no_machine(
860 self, mock_debug, mock_get_machines,
861 ):
862 mock_get_machines.return_value = {}
863 self.loop.run_until_complete(
864 self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
865 )
866 mock_debug.assert_called_with("Machine not found: machine")
867
868
869@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
870@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_model")
871@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
872@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
873@asynctest.mock.patch("n2vc.libjuju.Libjuju._get_application")
874class ConfigureApplicationTest(LibjujuTestCase):
875 def setUp(self):
876 super(ConfigureApplicationTest, self).setUp()
877
878 def test_success(
879 self,
880 mock_get_application,
881 mock_disconnect_controller,
882 mock_disconnect_model,
883 mock_get_model,
884 mock_get_controller,
885 ):
886
887 mock_get_application.return_value = FakeApplication()
888
889 self.loop.run_until_complete(
890 self.libjuju.configure_application("model", "app", {"config"},)
891 )
892 mock_get_application.assert_called_once()
893 mock_disconnect_controller.assert_called_once()
894 mock_disconnect_model.assert_called_once()
895
896 def test_exception(
897 self,
898 mock_get_application,
899 mock_disconnect_controller,
900 mock_disconnect_model,
901 mock_get_model,
902 mock_get_controller,
903 ):
904
905 mock_get_application.side_effect = Exception()
906
907 with self.assertRaises(Exception):
908 self.loop.run_until_complete(
909 self.libjuju.configure_application("model", "app", {"config"},)
910 )
David Garcia12b29242020-09-17 16:01:48 +0200911 mock_disconnect_controller.assert_called_once()
912 mock_disconnect_model.assert_called_once()
Dominik Fleischmann7ff392f2020-07-07 13:11:19 +0200913
914
915# TODO _get_api_endpoints_db test case
916# TODO _update_api_endpoints_db test case
917# TODO healthcheck test case
918
919
920@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
921@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
922@asynctest.mock.patch("juju.controller.Controller.list_models")
923class ListModelsTest(LibjujuTestCase):
924 def setUp(self):
925 super(ListModelsTest, self).setUp()
926
927 def test_containing(
928 self, mock_list_models, mock_disconnect_controller, mock_get_controller,
929 ):
930 mock_get_controller.return_value = juju.controller.Controller()
931 mock_list_models.return_value = ["existingmodel"]
932 models = self.loop.run_until_complete(self.libjuju.list_models("existing"))
933
934 mock_disconnect_controller.assert_called_once()
935 self.assertEquals(models, ["existingmodel"])
936
937 def test_not_containing(
938 self, mock_list_models, mock_disconnect_controller, mock_get_controller,
939 ):
940 mock_get_controller.return_value = juju.controller.Controller()
941 mock_list_models.return_value = ["existingmodel", "model"]
942 models = self.loop.run_until_complete(self.libjuju.list_models("mdl"))
943
944 mock_disconnect_controller.assert_called_once()
945 self.assertEquals(models, [])
946
947 def test_no_contains_arg(
948 self, mock_list_models, mock_disconnect_controller, mock_get_controller,
949 ):
950 mock_get_controller.return_value = juju.controller.Controller()
951 mock_list_models.return_value = ["existingmodel", "model"]
952 models = self.loop.run_until_complete(self.libjuju.list_models())
953
954 mock_disconnect_controller.assert_called_once()
955 self.assertEquals(models, ["existingmodel", "model"])
David Garcia42f328a2020-08-25 15:03:01 +0200956
957
958@asynctest.mock.patch("n2vc.libjuju.Libjuju.list_models")
959class ModelsExistTest(LibjujuTestCase):
960 def setUp(self):
961 super(ModelsExistTest, self).setUp()
962
963 def test_model_names_none(self, mock_list_models):
964 mock_list_models.return_value = []
965 with self.assertRaises(Exception):
966 self.loop.run_until_complete(self.libjuju.models_exist(None))
967
968 def test_model_names_empty(self, mock_list_models):
969 mock_list_models.return_value = []
970 with self.assertRaises(Exception):
971 (exist, non_existing_models) = self.loop.run_until_complete(
972 self.libjuju.models_exist([])
973 )
974
975 def test_model_names_not_existing(self, mock_list_models):
976 mock_list_models.return_value = ["prometheus", "grafana"]
977 (exist, non_existing_models) = self.loop.run_until_complete(
978 self.libjuju.models_exist(["prometheus2", "grafana"])
979 )
980 self.assertFalse(exist)
981 self.assertEqual(non_existing_models, ["prometheus2"])
982
983 def test_model_names_exist(self, mock_list_models):
984 mock_list_models.return_value = ["prometheus", "grafana"]
985 (exist, non_existing_models) = self.loop.run_until_complete(
986 self.libjuju.models_exist(["prometheus", "grafana"])
987 )
988 self.assertTrue(exist)
989 self.assertEqual(non_existing_models, [])
David Garciabc538e42020-08-25 15:22:30 +0200990
991
992@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
993@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
994@asynctest.mock.patch("juju.controller.Controller.list_offers")
995class ListOffers(LibjujuTestCase):
996 def setUp(self):
997 super(ListOffers, self).setUp()
998
999 def test_disconnect_controller(
1000 self, mock_list_offers, mock_disconnect_controller, mock_get_controller,
1001 ):
1002 mock_get_controller.return_value = juju.controller.Controller()
1003 mock_list_offers.side_effect = Exception()
1004 with self.assertRaises(Exception):
1005 self.loop.run_until_complete(self.libjuju.list_offers("model"))
1006 mock_disconnect_controller.assert_called_once()
1007
1008 def test_empty_list(
1009 self, mock_list_offers, mock_disconnect_controller, mock_get_controller,
1010 ):
1011 mock_get_controller.return_value = juju.controller.Controller()
1012 mock_list_offers.return_value = []
1013 offers = self.loop.run_until_complete(self.libjuju.list_offers("model"))
1014 self.assertEqual(offers, [])
1015 mock_disconnect_controller.assert_called_once()
1016
1017 def test_non_empty_list(
1018 self, mock_list_offers, mock_disconnect_controller, mock_get_controller,
1019 ):
1020 mock_get_controller.return_value = juju.controller.Controller()
1021 mock_list_offers.return_value = ["offer"]
1022 offers = self.loop.run_until_complete(self.libjuju.list_offers("model"))
1023 self.assertEqual(offers, ["offer"])
1024 mock_disconnect_controller.assert_called_once()
David Garcia68b00722020-09-11 15:05:00 +02001025
1026
1027@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1028@asynctest.mock.patch("juju.controller.Controller.get_model")
1029@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_model")
1030@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1031@asynctest.mock.patch("juju.model.Model.consume")
1032class ConsumeTest(LibjujuTestCase):
1033 def setUp(self):
1034 super(ConsumeTest, self).setUp()
1035
1036 def test_consume(
1037 self,
1038 mock_consume,
1039 mock_disconnect_controller,
1040 mock_disconnect_model,
1041 mock_get_model,
1042 mock_get_controller,
1043 ):
1044 mock_get_controller.return_value = juju.controller.Controller()
1045 mock_get_model.return_value = juju.model.Model()
1046
David Garcia12b29242020-09-17 16:01:48 +02001047 self.loop.run_until_complete(self.libjuju.consume("offer_url", "model_name"))
David Garcia68b00722020-09-11 15:05:00 +02001048 mock_consume.assert_called_once()
1049 mock_disconnect_model.assert_called_once()
1050 mock_disconnect_controller.assert_called_once()
1051
1052 def test_parsing_error_exception(
1053 self,
1054 mock_consume,
1055 mock_disconnect_controller,
1056 mock_disconnect_model,
1057 mock_get_model,
1058 mock_get_controller,
1059 ):
1060 mock_get_controller.return_value = juju.controller.Controller()
1061 mock_get_model.return_value = juju.model.Model()
1062 mock_consume.side_effect = juju.offerendpoints.ParseError("")
1063
1064 with self.assertRaises(juju.offerendpoints.ParseError):
1065 self.loop.run_until_complete(
1066 self.libjuju.consume("offer_url", "model_name")
1067 )
1068 mock_consume.assert_called_once()
1069 mock_disconnect_model.assert_called_once()
1070 mock_disconnect_controller.assert_called_once()
1071
1072 def test_juju_error_exception(
1073 self,
1074 mock_consume,
1075 mock_disconnect_controller,
1076 mock_disconnect_model,
1077 mock_get_model,
1078 mock_get_controller,
1079 ):
1080 mock_get_controller.return_value = juju.controller.Controller()
1081 mock_get_model.return_value = juju.model.Model()
1082 mock_consume.side_effect = juju.errors.JujuError("")
1083
1084 with self.assertRaises(juju.errors.JujuError):
1085 self.loop.run_until_complete(
1086 self.libjuju.consume("offer_url", "model_name")
1087 )
1088 mock_consume.assert_called_once()
1089 mock_disconnect_model.assert_called_once()
1090 mock_disconnect_controller.assert_called_once()
1091
1092 def test_juju_api_error_exception(
1093 self,
1094 mock_consume,
1095 mock_disconnect_controller,
1096 mock_disconnect_model,
1097 mock_get_model,
1098 mock_get_controller,
1099 ):
1100 mock_get_controller.return_value = juju.controller.Controller()
1101 mock_get_model.return_value = juju.model.Model()
David Garcia12b29242020-09-17 16:01:48 +02001102 mock_consume.side_effect = juju.errors.JujuAPIError(
1103 {"error": "", "response": "", "request-id": ""}
1104 )
David Garcia68b00722020-09-11 15:05:00 +02001105
1106 with self.assertRaises(juju.errors.JujuAPIError):
1107 self.loop.run_until_complete(
1108 self.libjuju.consume("offer_url", "model_name")
1109 )
1110 mock_consume.assert_called_once()
1111 mock_disconnect_model.assert_called_once()
1112 mock_disconnect_controller.assert_called_once()
David Garcia12b29242020-09-17 16:01:48 +02001113
1114
1115@asynctest.mock.patch("n2vc.libjuju.Libjuju.add_cloud")
1116class AddK8sTest(LibjujuTestCase):
1117 def setUp(self):
1118 super(AddK8sTest, self).setUp()
1119 self.auth_data = {
1120 "server": "https://192.168.0.21:16443",
1121 "token": "1234",
1122 "cacert": "cacert",
1123 }
1124
1125 def test_add_k8s(self, mock_add_cloud):
1126 self.loop.run_until_complete(
1127 self.libjuju.add_k8s("cloud", self.auth_data, "storage_class")
1128 )
1129 mock_add_cloud.assert_called_once()
1130
1131 def test_add_k8s_exception(self, mock_add_cloud):
1132 mock_add_cloud.side_effect = Exception()
1133 with self.assertRaises(Exception):
1134 self.loop.run_until_complete(
1135 self.libjuju.add_k8s("cloud", self.auth_data, "storage_class")
1136 )
1137 mock_add_cloud.assert_called_once()
1138
1139 def test_add_k8s_missing_name(self, mock_add_cloud):
1140 with self.assertRaises(Exception):
1141 self.loop.run_until_complete(
1142 self.libjuju.add_k8s("", self.auth_data, "storage_class")
1143 )
1144 mock_add_cloud.assert_not_called()
1145
1146 def test_add_k8s_missing_storage_name(self, mock_add_cloud):
1147 with self.assertRaises(Exception):
1148 self.loop.run_until_complete(
1149 self.libjuju.add_k8s("cloud", self.auth_data, "")
1150 )
1151 mock_add_cloud.assert_not_called()
1152
1153 def test_add_k8s_missing_auth_data_keys(self, mock_add_cloud):
1154 with self.assertRaises(Exception):
David Garcia85755d12020-09-21 19:51:23 +02001155 self.loop.run_until_complete(self.libjuju.add_k8s("cloud", {}, ""))
David Garcia12b29242020-09-17 16:01:48 +02001156 mock_add_cloud.assert_not_called()
1157
1158
1159@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1160@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1161@asynctest.mock.patch("juju.controller.Controller.add_cloud")
1162@asynctest.mock.patch("juju.controller.Controller.add_credential")
1163class AddCloudTest(LibjujuTestCase):
1164 def setUp(self):
1165 super(AddCloudTest, self).setUp()
1166 self.cloud = juju.client.client.Cloud()
1167 self.credential = juju.client.client.CloudCredential()
1168
1169 def test_add_cloud_with_credential(
1170 self,
1171 mock_add_credential,
1172 mock_add_cloud,
1173 mock_disconnect_controller,
1174 mock_get_controller,
1175 ):
1176 mock_get_controller.return_value = juju.controller.Controller()
1177
1178 cloud = self.loop.run_until_complete(
1179 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1180 )
1181 self.assertEqual(cloud, self.cloud)
1182 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1183 mock_add_credential.assert_called_once_with(
1184 "cloud", credential=self.credential, cloud="cloud"
1185 )
1186 mock_disconnect_controller.assert_called_once()
1187
1188 def test_add_cloud_no_credential(
1189 self,
1190 mock_add_credential,
1191 mock_add_cloud,
1192 mock_disconnect_controller,
1193 mock_get_controller,
1194 ):
1195 mock_get_controller.return_value = juju.controller.Controller()
1196
1197 cloud = self.loop.run_until_complete(
1198 self.libjuju.add_cloud("cloud", self.cloud)
1199 )
1200 self.assertEqual(cloud, self.cloud)
1201 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1202 mock_add_credential.assert_not_called()
1203 mock_disconnect_controller.assert_called_once()
1204
1205 def test_add_cloud_exception(
1206 self,
1207 mock_add_credential,
1208 mock_add_cloud,
1209 mock_disconnect_controller,
1210 mock_get_controller,
1211 ):
1212 mock_get_controller.return_value = juju.controller.Controller()
1213 mock_add_cloud.side_effect = Exception()
1214 with self.assertRaises(Exception):
1215 self.loop.run_until_complete(
1216 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1217 )
1218
1219 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1220 mock_add_credential.assert_not_called()
1221 mock_disconnect_controller.assert_called_once()
1222
1223 def test_add_credential_exception(
1224 self,
1225 mock_add_credential,
1226 mock_add_cloud,
1227 mock_disconnect_controller,
1228 mock_get_controller,
1229 ):
1230 mock_get_controller.return_value = juju.controller.Controller()
1231 mock_add_credential.side_effect = Exception()
1232 with self.assertRaises(Exception):
1233 self.loop.run_until_complete(
1234 self.libjuju.add_cloud("cloud", self.cloud, credential=self.credential)
1235 )
1236
1237 mock_add_cloud.assert_called_once_with("cloud", self.cloud)
1238 mock_add_credential.assert_called_once_with(
1239 "cloud", credential=self.credential, cloud="cloud"
1240 )
1241 mock_disconnect_controller.assert_called_once()
1242
1243
1244@asynctest.mock.patch("n2vc.libjuju.Libjuju.get_controller")
1245@asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1246@asynctest.mock.patch("juju.controller.Controller.remove_cloud")
1247class RemoveCloudTest(LibjujuTestCase):
1248 def setUp(self):
1249 super(RemoveCloudTest, self).setUp()
1250
1251 def test_remove_cloud(
1252 self, mock_remove_cloud, mock_disconnect_controller, mock_get_controller,
1253 ):
1254 mock_get_controller.return_value = juju.controller.Controller()
1255
1256 self.loop.run_until_complete(self.libjuju.remove_cloud("cloud"))
1257 mock_remove_cloud.assert_called_once_with("cloud")
1258 mock_disconnect_controller.assert_called_once()
1259
1260 def test_remove_cloud_exception(
1261 self, mock_remove_cloud, mock_disconnect_controller, mock_get_controller,
1262 ):
1263 mock_get_controller.return_value = juju.controller.Controller()
1264 mock_remove_cloud.side_effect = Exception()
1265
1266 with self.assertRaises(Exception):
1267 self.loop.run_until_complete(self.libjuju.remove_cloud("cloud"))
1268 mock_remove_cloud.assert_called_once_with("cloud")
1269 mock_disconnect_controller.assert_called_once()