1 # Copyright 2020 Canonical Ltd.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 from juju
.errors
import JujuAPIError
20 from .utils
import FakeN2VC
, FakeMachine
, FakeApplication
21 from n2vc
.libjuju
import Libjuju
22 from n2vc
.exceptions
import (
23 JujuControllerFailedConnecting
,
24 JujuModelAlreadyExists
,
26 JujuApplicationNotFound
,
28 JujuApplicationExists
,
33 class LibjujuTestCase(asynctest
.TestCase
):
34 @asynctest.mock
.patch("juju.controller.Controller.update_endpoints")
35 @asynctest.mock
.patch("juju.client.connector.Connector.connect")
36 @asynctest.mock
.patch("juju.controller.Controller.connection")
37 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_api_endpoints_db")
40 mock__get_api_endpoints_db
=None,
43 mock_update_endpoints
=None,
45 loop
= asyncio
.get_event_loop()
47 mock__get_api_endpoints_db
.return_value
= ["127.0.0.1:17070"]
48 endpoints
= "127.0.0.1:17070"
52 -----BEGIN CERTIFICATE-----
54 -----END CERTIFICATE-----"""
55 self
.libjuju
= Libjuju(
57 "192.168.0.155:17070",
65 apt_mirror
="192.168.0.100",
66 enable_os_upgrade
=True,
68 logging
.disable(logging
.CRITICAL
)
69 loop
.run_until_complete(self
.libjuju
.disconnect())
72 @asynctest.mock
.patch("juju.controller.Controller.connect")
73 @asynctest.mock
.patch(
74 "juju.controller.Controller.api_endpoints",
75 new_callable
=asynctest
.CoroutineMock(return_value
=["127.0.0.1:17070"]),
77 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._update_api_endpoints_db")
78 class GetControllerTest(LibjujuTestCase
):
80 super(GetControllerTest
, self
).setUp()
82 def test_diff_endpoint(
83 self
, mock__update_api_endpoints_db
, mock_api_endpoints
, mock_connect
85 self
.libjuju
.endpoints
= []
86 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
87 mock__update_api_endpoints_db
.assert_called_once_with(["127.0.0.1:17070"])
88 self
.assertIsInstance(controller
, juju
.controller
.Controller
)
90 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
93 mock_disconnect_controller
,
94 mock__update_api_endpoints_db
,
98 self
.libjuju
.endpoints
= []
99 mock__update_api_endpoints_db
.side_effect
= Exception()
100 with self
.assertRaises(JujuControllerFailedConnecting
):
101 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
102 self
.assertIsNone(controller
)
103 mock_disconnect_controller
.assert_called_once()
105 def test_same_endpoint_get_controller(
106 self
, mock__update_api_endpoints_db
, mock_api_endpoints
, mock_connect
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
)
114 class DisconnectTest(LibjujuTestCase
):
116 super(DisconnectTest
, self
).setUp()
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()
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())
128 mock_disconnect
.assert_called_once()
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")
136 class AddModelTest(LibjujuTestCase
):
138 super(AddModelTest
, self
).setUp()
140 def test_existing_model(
142 mock_disconnect_model
,
143 mock_disconnect_controller
,
148 mock_model_exists
.return_value
= True
150 with self
.assertRaises(JujuModelAlreadyExists
):
151 self
.loop
.run_until_complete(
152 self
.libjuju
.add_model("existing_model", "cloud")
155 mock_disconnect_controller
.assert_called()
157 # TODO Check two job executing at the same time and one returning without doing anything.
159 def test_non_existing_model(
161 mock_disconnect_model
,
162 mock_disconnect_controller
,
167 mock_model_exists
.return_value
= False
168 mock_get_controller
.return_value
= juju
.controller
.Controller()
170 self
.loop
.run_until_complete(
171 self
.libjuju
.add_model("nonexisting_model", "cloud")
174 mock_add_model
.assert_called_once()
175 mock_disconnect_controller
.assert_called()
176 mock_disconnect_model
.assert_called()
179 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
180 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
181 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
182 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
183 @asynctest.mock
.patch(
184 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
186 @asynctest.mock
.patch("juju.model.Model.get_action_status")
187 @asynctest.mock
.patch("juju.model.Model.get_action_output")
188 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_actions")
189 class GetExecutedActionsTest(LibjujuTestCase
):
191 super(GetExecutedActionsTest
, self
).setUp()
196 mock_get_action_output
,
197 mock_get_action_status
,
199 mock_disconnect_controller
,
200 mock_disconnect_model
,
204 mock_get_model
.return_value
= None
205 with self
.assertRaises(JujuError
):
206 self
.loop
.run_until_complete(self
.libjuju
.get_executed_actions("model"))
208 mock_get_controller
.assert_called_once()
209 mock_disconnect_controller
.assert_called_once()
210 mock_get_model
.assert_called_once()
211 mock_disconnect_model
.assert_not_called()
216 mock_get_action_output
,
217 mock_get_action_status
,
219 mock_disconnect_controller
,
220 mock_disconnect_model
,
224 mock_get_model
.return_value
= juju
.model
.Model()
225 mock_applications
.return_value
= {"existing_app"}
226 mock_get_actions
.return_value
= {"action_name": "description"}
227 mock_get_action_status
.return_value
= {"id": "status"}
228 mock_get_action_output
.return_value
= {"output": "completed"}
230 executed_actions
= self
.loop
.run_until_complete(
231 self
.libjuju
.get_executed_actions("model")
233 expected_result
= [{'id': 'id', 'action': 'action_name',
234 'status': 'status', 'output': 'completed'}]
235 self
.assertListEqual(expected_result
, executed_actions
)
236 self
.assertIsInstance(executed_actions
, list)
238 mock_get_controller
.assert_called_once()
239 mock_get_model
.assert_called_once()
240 mock_disconnect_controller
.assert_called_once()
241 mock_disconnect_model
.assert_called_once()
244 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
245 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
246 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
247 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
248 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
249 class GetApplicationConfigsTest(LibjujuTestCase
):
251 super(GetApplicationConfigsTest
, self
).setUp()
255 mock_get_application
,
256 mock_disconnect_controller
,
257 mock_disconnect_model
,
261 mock_get_model
.return_value
= None
262 with self
.assertRaises(JujuError
):
263 self
.loop
.run_until_complete(
264 self
.libjuju
.get_application_configs("model", "app"))
266 mock_get_controller
.assert_called_once()
267 mock_disconnect_controller
.assert_called_once()
268 mock_get_model
.assert_called_once()
269 mock_disconnect_model
.assert_not_called()
273 mock_get_application
,
274 mock_disconnect_controller
,
275 mock_disconnect_model
,
279 mock_get_application
.return_value
= FakeApplication()
280 application_configs
= self
.loop
.run_until_complete(self
.libjuju
281 .get_application_configs("model", "app"))
283 self
.assertEqual(application_configs
, ["app_config"])
285 mock_get_controller
.assert_called_once()
286 mock_get_model
.assert_called_once()
287 mock_disconnect_controller
.assert_called_once()
288 mock_disconnect_model
.assert_called_once()
291 @asynctest.mock
.patch("juju.controller.Controller.get_model")
292 class GetModelTest(LibjujuTestCase
):
294 super(GetModelTest
, self
).setUp()
297 self
, mock_get_model
,
299 mock_get_model
.return_value
= juju
.model
.Model()
300 model
= self
.loop
.run_until_complete(
301 self
.libjuju
.get_model(juju
.controller
.Controller(), "model")
303 self
.assertIsInstance(model
, juju
.model
.Model
)
306 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
307 @asynctest.mock
.patch("juju.controller.Controller.list_models")
308 class ModelExistsTest(LibjujuTestCase
):
310 super(ModelExistsTest
, self
).setUp()
312 async def test_existing_model(
313 self
, mock_list_models
, mock_get_controller
,
315 mock_list_models
.return_value
= ["existing_model"]
317 await self
.libjuju
.model_exists(
318 "existing_model", juju
.controller
.Controller()
322 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
323 async def test_no_controller(
324 self
, mock_disconnect_controller
, mock_list_models
, mock_get_controller
,
326 mock_list_models
.return_value
= ["existing_model"]
327 mock_get_controller
.return_value
= juju
.controller
.Controller()
328 self
.assertTrue(await self
.libjuju
.model_exists("existing_model"))
329 mock_disconnect_controller
.assert_called_once()
331 async def test_non_existing_model(
332 self
, mock_list_models
, mock_get_controller
,
334 mock_list_models
.return_value
= ["existing_model"]
336 await self
.libjuju
.model_exists(
337 "not_existing_model", juju
.controller
.Controller()
342 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
343 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
344 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
345 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
346 @asynctest.mock
.patch("juju.model.Model.get_status")
347 class GetModelStatusTest(LibjujuTestCase
):
349 super(GetModelStatusTest
, self
).setUp()
354 mock_disconnect_controller
,
355 mock_disconnect_model
,
359 mock_get_model
.return_value
= juju
.model
.Model()
360 mock_get_status
.return_value
= {"status"}
362 status
= self
.loop
.run_until_complete(self
.libjuju
.get_model_status("model"))
364 mock_get_status
.assert_called_once()
365 mock_disconnect_controller
.assert_called_once()
366 mock_disconnect_model
.assert_called_once()
368 self
.assertEqual(status
, {"status"})
373 mock_disconnect_controller
,
374 mock_disconnect_model
,
378 mock_get_model
.return_value
= juju
.model
.Model()
379 mock_get_status
.side_effect
= Exception()
381 with self
.assertRaises(Exception):
382 status
= self
.loop
.run_until_complete(
383 self
.libjuju
.get_model_status("model")
386 mock_disconnect_controller
.assert_called_once()
387 mock_disconnect_model
.assert_called_once()
389 self
.assertIsNone(status
)
392 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
393 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
394 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
395 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
396 @asynctest.mock
.patch("juju.model.Model.get_machines")
397 @asynctest.mock
.patch("juju.model.Model.add_machine")
398 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
399 class CreateMachineTest(LibjujuTestCase
):
401 super(CreateMachineTest
, self
).setUp()
403 def test_existing_machine(
408 mock_disconnect_controller
,
409 mock_disconnect_model
,
413 mock_get_model
.return_value
= juju
.model
.Model()
414 mock_get_machines
.return_value
= {"existing_machine": FakeMachine()}
415 machine
, bool_res
= self
.loop
.run_until_complete(
416 self
.libjuju
.create_machine("model", "existing_machine")
419 self
.assertIsInstance(machine
, FakeMachine
)
420 self
.assertFalse(bool_res
)
422 mock_disconnect_controller
.assert_called()
423 mock_disconnect_model
.assert_called()
425 def test_non_existing_machine(
430 mock_disconnect_controller
,
431 mock_disconnect_model
,
435 mock_get_model
.return_value
= juju
.model
.Model()
436 with self
.assertRaises(JujuMachineNotFound
):
437 machine
, bool_res
= self
.loop
.run_until_complete(
438 self
.libjuju
.create_machine("model", "non_existing_machine")
440 self
.assertIsNone(machine
)
441 self
.assertIsNone(bool_res
)
443 mock_disconnect_controller
.assert_called()
444 mock_disconnect_model
.assert_called()
451 mock_disconnect_controller
,
452 mock_disconnect_model
,
456 mock_get_model
.return_value
= juju
.model
.Model()
457 mock_add_machine
.return_value
= FakeMachine()
459 machine
, bool_res
= self
.loop
.run_until_complete(
460 self
.libjuju
.create_machine("model")
463 self
.assertIsInstance(machine
, FakeMachine
)
464 self
.assertTrue(bool_res
)
466 mock_wait_for
.assert_called_once()
467 mock_add_machine
.assert_called_once()
469 mock_disconnect_controller
.assert_called()
470 mock_disconnect_model
.assert_called()
473 # TODO test provision machine
476 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
477 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
478 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
479 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
480 @asynctest.mock
.patch(
481 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
483 @asynctest.mock
.patch("juju.model.Model.machines", new_callable
=asynctest
.PropertyMock
)
484 @asynctest.mock
.patch("juju.model.Model.deploy")
485 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
486 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.create_machine")
487 class DeployCharmTest(LibjujuTestCase
):
489 super(DeployCharmTest
, self
).setUp()
491 def test_existing_app(
498 mock_disconnect_controller
,
499 mock_disconnect_model
,
503 mock_get_model
.return_value
= juju
.model
.Model()
504 mock_applications
.return_value
= {"existing_app"}
506 with self
.assertRaises(JujuApplicationExists
):
507 application
= self
.loop
.run_until_complete(
508 self
.libjuju
.deploy_charm("existing_app", "path", "model", "machine",)
510 self
.assertIsNone(application
)
512 mock_disconnect_controller
.assert_called()
513 mock_disconnect_model
.assert_called()
515 def test_non_existing_machine(
522 mock_disconnect_controller
,
523 mock_disconnect_model
,
527 mock_get_model
.return_value
= juju
.model
.Model()
528 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
529 with self
.assertRaises(JujuMachineNotFound
):
530 application
= self
.loop
.run_until_complete(
531 self
.libjuju
.deploy_charm("app", "path", "model", "machine",)
534 self
.assertIsNone(application
)
536 mock_disconnect_controller
.assert_called()
537 mock_disconnect_model
.assert_called()
546 mock_disconnect_controller
,
547 mock_disconnect_model
,
551 mock_get_model
.return_value
= juju
.model
.Model()
552 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
553 mock_create_machine
.return_value
= (FakeMachine(), "other")
554 mock_deploy
.return_value
= FakeApplication()
555 application
= self
.loop
.run_until_complete(
556 self
.libjuju
.deploy_charm(
557 "app", "path", "model", "existing_machine", num_units
=2,
561 self
.assertIsInstance(application
, FakeApplication
)
563 mock_deploy
.assert_called_once()
564 mock_wait_for
.assert_called_once()
566 mock_create_machine
.assert_called_once()
568 mock_disconnect_controller
.assert_called()
569 mock_disconnect_model
.assert_called()
578 mock_disconnect_controller
,
579 mock_disconnect_model
,
583 mock_get_model
.return_value
= juju
.model
.Model()
584 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
585 mock_deploy
.return_value
= FakeApplication()
586 application
= self
.loop
.run_until_complete(
587 self
.libjuju
.deploy_charm("app", "path", "model", "existing_machine")
590 self
.assertIsInstance(application
, FakeApplication
)
592 mock_deploy
.assert_called_once()
593 mock_wait_for
.assert_called_once()
595 mock_disconnect_controller
.assert_called()
596 mock_disconnect_model
.assert_called()
599 @asynctest.mock
.patch(
600 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
602 class GetApplicationTest(LibjujuTestCase
):
604 super(GetApplicationTest
, self
).setUp()
606 def test_existing_application(
607 self
, mock_applications
,
609 mock_applications
.return_value
= {"existing_app": "exists"}
610 model
= juju
.model
.Model()
611 result
= self
.libjuju
._get
_application
(model
, "existing_app")
612 self
.assertEqual(result
, "exists")
614 def test_non_existing_application(
615 self
, mock_applications
,
617 mock_applications
.return_value
= {"existing_app": "exists"}
618 model
= juju
.model
.Model()
619 result
= self
.libjuju
._get
_application
(model
, "nonexisting_app")
620 self
.assertIsNone(result
)
623 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
624 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
625 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
626 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
627 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
628 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
629 @asynctest.mock
.patch("juju.model.Model.get_action_output")
630 @asynctest.mock
.patch("juju.model.Model.get_action_status")
631 class ExecuteActionTest(LibjujuTestCase
):
633 super(ExecuteActionTest
, self
).setUp()
635 def test_no_application(
637 mock_get_action_status
,
638 mock_get_action_output
,
640 mock__get_application
,
641 mock_disconnect_controller
,
642 mock_disconnect_model
,
646 mock__get_application
.return_value
= None
647 mock_get_model
.return_value
= juju
.model
.Model()
649 with self
.assertRaises(JujuApplicationNotFound
):
650 output
, status
= self
.loop
.run_until_complete(
651 self
.libjuju
.execute_action("app", "model", "action",)
653 self
.assertIsNone(output
)
654 self
.assertIsNone(status
)
656 mock_disconnect_controller
.assert_called()
657 mock_disconnect_model
.assert_called()
661 mock_get_action_status
,
662 mock_get_action_output
,
664 mock__get_application
,
665 mock_disconnect_controller
,
666 mock_disconnect_model
,
671 mock_get_model
.return_value
= juju
.model
.Model()
672 mock__get_application
.return_value
= FakeApplication()
673 with self
.assertRaises(JujuActionNotFound
):
674 output
, status
= self
.loop
.run_until_complete(
675 self
.libjuju
.execute_action("app", "model", "action",)
677 self
.assertIsNone(output
)
678 self
.assertIsNone(status
)
680 mock_disconnect_controller
.assert_called()
681 mock_disconnect_model
.assert_called()
683 # TODO no leader unit found exception
685 def test_succesful_exec(
687 mock_get_action_status
,
688 mock_get_action_output
,
690 mock__get_application
,
691 mock_disconnect_controller
,
692 mock_disconnect_model
,
696 mock_get_model
.return_value
= juju
.model
.Model()
697 mock__get_application
.return_value
= FakeApplication()
698 mock_get_action_output
.return_value
= "output"
699 mock_get_action_status
.return_value
= {"id": "status"}
700 output
, status
= self
.loop
.run_until_complete(
701 self
.libjuju
.execute_action("app", "model", "existing_action")
703 self
.assertEqual(output
, "output")
704 self
.assertEqual(status
, "status")
706 mock_wait_for
.assert_called_once()
708 mock_disconnect_controller
.assert_called()
709 mock_disconnect_model
.assert_called()
712 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
713 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
714 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
715 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
716 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
717 class GetActionTest(LibjujuTestCase
):
719 super(GetActionTest
, self
).setUp()
723 mock_get_application
,
724 mock_disconnect_controller
,
725 mock_disconnect_model
,
729 mock_get_application
.side_effect
= Exception()
731 with self
.assertRaises(Exception):
732 actions
= self
.loop
.run_until_complete(
733 self
.libjuju
.get_actions("app", "model")
736 self
.assertIsNone(actions
)
737 mock_disconnect_controller
.assert_called_once()
738 mock_disconnect_model
.assert_called_once()
742 mock_get_application
,
743 mock_disconnect_controller
,
744 mock_disconnect_model
,
748 mock_get_application
.return_value
= FakeApplication()
750 actions
= self
.loop
.run_until_complete(self
.libjuju
.get_actions("app", "model"))
752 self
.assertEqual(actions
, ["existing_action"])
754 mock_get_controller
.assert_called_once()
755 mock_get_model
.assert_called_once()
756 mock_disconnect_controller
.assert_called_once()
757 mock_disconnect_model
.assert_called_once()
760 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
761 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
762 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
763 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
764 @asynctest.mock
.patch("juju.model.Model.add_relation")
765 class AddRelationTest(LibjujuTestCase
):
767 super(AddRelationTest
, self
).setUp()
769 @asynctest.mock
.patch("logging.Logger.warning")
774 mock_disconnect_controller
,
775 mock_disconnect_model
,
779 # TODO in libjuju.py should this fail only with a log message?
780 result
= {"error": "not found", "response": "response", "request-id": 1}
782 mock_get_model
.return_value
= juju
.model
.Model()
783 mock_add_relation
.side_effect
= JujuAPIError(result
)
785 self
.loop
.run_until_complete(
786 self
.libjuju
.add_relation(
787 "model", "app1", "app2", "relation1", "relation2",
791 mock_warning
.assert_called_with("Relation not found: not found")
792 mock_disconnect_controller
.assert_called_once()
793 mock_disconnect_model
.assert_called_once()
795 @asynctest.mock
.patch("logging.Logger.warning")
796 def test_already_exists(
800 mock_disconnect_controller
,
801 mock_disconnect_model
,
805 # TODO in libjuju.py should this fail silently?
806 result
= {"error": "already exists", "response": "response", "request-id": 1}
808 mock_get_model
.return_value
= juju
.model
.Model()
809 mock_add_relation
.side_effect
= JujuAPIError(result
)
811 self
.loop
.run_until_complete(
812 self
.libjuju
.add_relation(
813 "model", "app1", "app2", "relation1", "relation2",
817 mock_warning
.assert_called_with("Relation already exists: already exists")
818 mock_disconnect_controller
.assert_called_once()
819 mock_disconnect_model
.assert_called_once()
824 mock_disconnect_controller
,
825 mock_disconnect_model
,
829 mock_get_model
.return_value
= juju
.model
.Model()
830 result
= {"error": "", "response": "response", "request-id": 1}
831 mock_add_relation
.side_effect
= JujuAPIError(result
)
833 with self
.assertRaises(JujuAPIError
):
834 self
.loop
.run_until_complete(
835 self
.libjuju
.add_relation(
836 "model", "app1", "app2", "relation1", "relation2",
840 mock_disconnect_controller
.assert_called_once()
841 mock_disconnect_model
.assert_called_once()
846 mock_disconnect_controller
,
847 mock_disconnect_model
,
851 mock_get_model
.return_value
= juju
.model
.Model()
853 self
.loop
.run_until_complete(
854 self
.libjuju
.add_relation(
855 "model", "app1", "app2", "relation1", "relation2",
859 mock_add_relation
.assert_called_with(
860 relation1
="app1:relation1", relation2
="app2:relation2"
862 mock_disconnect_controller
.assert_called_once()
863 mock_disconnect_model
.assert_called_once()
866 # TODO destroy_model testcase
869 # @asynctest.mock.patch("juju.model.Model.get_machines")
870 # @asynctest.mock.patch("logging.Logger.debug")
871 # class DestroyMachineTest(LibjujuTestCase):
873 # super(DestroyMachineTest, self).setUp()
875 # def test_success_manual_machine(
876 # self, mock_debug, mock_get_machines,
878 # mock_get_machines.side_effect = [
879 # {"machine": FakeManualMachine()},
880 # {"machine": FakeManualMachine()},
883 # self.loop.run_until_complete(
884 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
887 # asynctest.call("Waiting for machine machine is destroyed"),
888 # asynctest.call("Machine destroyed: machine"),
890 # mock_debug.assert_has_calls(calls)
892 # def test_no_machine(
893 # self, mock_debug, mock_get_machines,
895 # mock_get_machines.return_value = {}
896 # self.loop.run_until_complete(
897 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2)
899 # mock_debug.assert_called_with("Machine not found: machine")
902 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
903 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
904 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
905 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
906 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
907 class ConfigureApplicationTest(LibjujuTestCase
):
909 super(ConfigureApplicationTest
, self
).setUp()
913 mock_get_application
,
914 mock_disconnect_controller
,
915 mock_disconnect_model
,
920 mock_get_application
.return_value
= FakeApplication()
922 self
.loop
.run_until_complete(
923 self
.libjuju
.configure_application("model", "app", {"config"},)
925 mock_get_application
.assert_called_once()
926 mock_disconnect_controller
.assert_called_once()
927 mock_disconnect_model
.assert_called_once()
931 mock_get_application
,
932 mock_disconnect_controller
,
933 mock_disconnect_model
,
938 mock_get_application
.side_effect
= Exception()
940 with self
.assertRaises(Exception):
941 self
.loop
.run_until_complete(
942 self
.libjuju
.configure_application("model", "app", {"config"},)
944 mock_disconnect_controller
.assert_called_once()
945 mock_disconnect_model
.assert_called_once()
948 # TODO _get_api_endpoints_db test case
949 # TODO _update_api_endpoints_db test case
950 # TODO healthcheck test case
953 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
954 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
955 @asynctest.mock
.patch("juju.controller.Controller.list_models")
956 class ListModelsTest(LibjujuTestCase
):
958 super(ListModelsTest
, self
).setUp()
961 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
963 mock_get_controller
.return_value
= juju
.controller
.Controller()
964 mock_list_models
.return_value
= ["existingmodel"]
965 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("existing"))
967 mock_disconnect_controller
.assert_called_once()
968 self
.assertEquals(models
, ["existingmodel"])
970 def test_not_containing(
971 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
973 mock_get_controller
.return_value
= juju
.controller
.Controller()
974 mock_list_models
.return_value
= ["existingmodel", "model"]
975 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("mdl"))
977 mock_disconnect_controller
.assert_called_once()
978 self
.assertEquals(models
, [])
980 def test_no_contains_arg(
981 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
983 mock_get_controller
.return_value
= juju
.controller
.Controller()
984 mock_list_models
.return_value
= ["existingmodel", "model"]
985 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models())
987 mock_disconnect_controller
.assert_called_once()
988 self
.assertEquals(models
, ["existingmodel", "model"])