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
,
32 class 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")
39 mock__get_api_endpoints_db
=None,
42 mock_update_endpoints
=None,
44 loop
= asyncio
.get_event_loop()
46 mock__get_api_endpoints_db
.return_value
= ["127.0.0.1:17070"]
47 endpoints
= "127.0.0.1:17070"
51 -----BEGIN CERTIFICATE-----
53 -----END CERTIFICATE-----"""
54 self
.libjuju
= Libjuju(
56 "192.168.0.155:17070",
64 apt_mirror
="192.168.0.100",
65 enable_os_upgrade
=True,
67 logging
.disable(logging
.CRITICAL
)
68 loop
.run_until_complete(self
.libjuju
.disconnect())
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"]),
76 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._update_api_endpoints_db")
77 class GetControllerTest(LibjujuTestCase
):
79 super(GetControllerTest
, self
).setUp()
81 def test_diff_endpoint(
82 self
, mock__update_api_endpoints_db
, mock_api_endpoints
, mock_connect
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
)
89 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
92 mock_disconnect_controller
,
93 mock__update_api_endpoints_db
,
97 self
.libjuju
.endpoints
= []
98 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("juju.controller.Controller.get_model")
180 class GetModelTest(LibjujuTestCase
):
182 super(GetModelTest
, self
).setUp()
185 self
, mock_get_model
,
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")
191 self
.assertIsInstance(model
, juju
.model
.Model
)
194 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
195 @asynctest.mock
.patch("juju.controller.Controller.list_models")
196 class ModelExistsTest(LibjujuTestCase
):
198 super(ModelExistsTest
, self
).setUp()
200 async def test_existing_model(
201 self
, mock_list_models
, mock_get_controller
,
203 mock_list_models
.return_value
= ["existing_model"]
205 await self
.libjuju
.model_exists(
206 "existing_model", juju
.controller
.Controller()
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
,
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()
219 async def test_non_existing_model(
220 self
, mock_list_models
, mock_get_controller
,
222 mock_list_models
.return_value
= ["existing_model"]
224 await self
.libjuju
.model_exists(
225 "not_existing_model", juju
.controller
.Controller()
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")
235 class GetModelStatusTest(LibjujuTestCase
):
237 super(GetModelStatusTest
, self
).setUp()
242 mock_disconnect_controller
,
243 mock_disconnect_model
,
247 mock_get_model
.return_value
= juju
.model
.Model()
248 mock_get_status
.return_value
= {"status"}
250 status
= self
.loop
.run_until_complete(self
.libjuju
.get_model_status("model"))
252 mock_get_status
.assert_called_once()
253 mock_disconnect_controller
.assert_called_once()
254 mock_disconnect_model
.assert_called_once()
256 self
.assertEqual(status
, {"status"})
261 mock_disconnect_controller
,
262 mock_disconnect_model
,
266 mock_get_model
.return_value
= juju
.model
.Model()
267 mock_get_status
.side_effect
= Exception()
269 with self
.assertRaises(Exception):
270 status
= self
.loop
.run_until_complete(
271 self
.libjuju
.get_model_status("model")
274 mock_disconnect_controller
.assert_called_once()
275 mock_disconnect_model
.assert_called_once()
277 self
.assertIsNone(status
)
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")
287 class CreateMachineTest(LibjujuTestCase
):
289 super(CreateMachineTest
, self
).setUp()
291 def test_existing_machine(
296 mock_disconnect_controller
,
297 mock_disconnect_model
,
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")
307 self
.assertIsInstance(machine
, FakeMachine
)
308 self
.assertFalse(bool_res
)
310 mock_disconnect_controller
.assert_called()
311 mock_disconnect_model
.assert_called()
313 def test_non_existing_machine(
318 mock_disconnect_controller
,
319 mock_disconnect_model
,
325 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")
330 self
.assertIsNone(machine
)
331 self
.assertIsNone(bool_res
)
333 mock_disconnect_controller
.assert_called()
334 mock_disconnect_model
.assert_called()
341 mock_disconnect_controller
,
342 mock_disconnect_model
,
346 mock_get_model
.return_value
= juju
.model
.Model()
347 mock_add_machine
.return_value
= FakeMachine()
349 machine
, bool_res
= self
.loop
.run_until_complete(
350 self
.libjuju
.create_machine("model")
353 self
.assertIsInstance(machine
, FakeMachine
)
354 self
.assertTrue(bool_res
)
356 mock_wait_for
.assert_called_once()
357 mock_add_machine
.assert_called_once()
359 mock_disconnect_controller
.assert_called()
360 mock_disconnect_model
.assert_called()
363 # TODO test provision machine
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
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")
377 class DeployCharmTest(LibjujuTestCase
):
379 super(DeployCharmTest
, self
).setUp()
381 def test_existing_app(
388 mock_disconnect_controller
,
389 mock_disconnect_model
,
393 mock_get_model
.return_value
= juju
.model
.Model()
394 mock_applications
.return_value
= {"existing_app"}
397 with self
.assertRaises(JujuApplicationExists
):
398 application
= self
.loop
.run_until_complete(
399 self
.libjuju
.deploy_charm("existing_app", "path", "model", "machine",)
401 self
.assertIsNone(application
)
403 mock_disconnect_controller
.assert_called()
404 mock_disconnect_model
.assert_called()
406 def test_non_existing_machine(
413 mock_disconnect_controller
,
414 mock_disconnect_model
,
418 mock_get_model
.return_value
= juju
.model
.Model()
419 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
421 with self
.assertRaises(JujuMachineNotFound
):
422 application
= self
.loop
.run_until_complete(
423 self
.libjuju
.deploy_charm("app", "path", "model", "machine",)
426 self
.assertIsNone(application
)
428 mock_disconnect_controller
.assert_called()
429 mock_disconnect_model
.assert_called()
438 mock_disconnect_controller
,
439 mock_disconnect_model
,
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,
453 self
.assertIsInstance(application
, FakeApplication
)
455 mock_deploy
.assert_called_once()
456 mock_wait_for
.assert_called_once()
458 mock_create_machine
.assert_called_once()
460 mock_disconnect_controller
.assert_called()
461 mock_disconnect_model
.assert_called()
470 mock_disconnect_controller
,
471 mock_disconnect_model
,
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")
482 self
.assertIsInstance(application
, FakeApplication
)
484 mock_deploy
.assert_called_once()
485 mock_wait_for
.assert_called_once()
487 mock_disconnect_controller
.assert_called()
488 mock_disconnect_model
.assert_called()
491 @asynctest.mock
.patch(
492 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
494 class GetApplicationTest(LibjujuTestCase
):
496 super(GetApplicationTest
, self
).setUp()
498 def test_existing_application(
499 self
, mock_applications
,
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")
506 def test_non_existing_application(
507 self
, mock_applications
,
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
)
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")
523 class ExecuteActionTest(LibjujuTestCase
):
525 super(ExecuteActionTest
, self
).setUp()
527 def test_no_application(
529 mock_get_action_status
,
530 mock_get_action_output
,
532 mock__get_application
,
533 mock_disconnect_controller
,
534 mock_disconnect_model
,
538 mock__get_application
.return_value
= None
539 mock_get_model
.return_value
= juju
.model
.Model()
542 with self
.assertRaises(JujuApplicationNotFound
):
543 output
, status
= self
.loop
.run_until_complete(
544 self
.libjuju
.execute_action("app", "model", "action",)
546 self
.assertIsNone(output
)
547 self
.assertIsNone(status
)
549 mock_disconnect_controller
.assert_called()
550 mock_disconnect_model
.assert_called()
554 mock_get_action_status
,
555 mock_get_action_output
,
557 mock__get_application
,
558 mock_disconnect_controller
,
559 mock_disconnect_model
,
564 mock_get_model
.return_value
= juju
.model
.Model()
565 mock__get_application
.return_value
= FakeApplication()
568 with self
.assertRaises(JujuActionNotFound
):
569 output
, status
= self
.loop
.run_until_complete(
570 self
.libjuju
.execute_action("app", "model", "action",)
572 self
.assertIsNone(output
)
573 self
.assertIsNone(status
)
575 mock_disconnect_controller
.assert_called()
576 mock_disconnect_model
.assert_called()
578 # TODO no leader unit found exception
580 def test_succesful_exec(
582 mock_get_action_status
,
583 mock_get_action_output
,
585 mock__get_application
,
586 mock_disconnect_controller
,
587 mock_disconnect_model
,
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")
598 self
.assertEqual(output
, "output")
599 self
.assertEqual(status
, "status")
601 mock_wait_for
.assert_called_once()
603 mock_disconnect_controller
.assert_called()
604 mock_disconnect_model
.assert_called()
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")
612 class GetActionTest(LibjujuTestCase
):
614 super(GetActionTest
, self
).setUp()
618 mock_get_application
,
619 mock_disconnect_controller
,
620 mock_disconnect_model
,
624 mock_get_application
.side_effect
= Exception()
626 with self
.assertRaises(Exception):
627 actions
= self
.loop
.run_until_complete(
628 self
.libjuju
.get_actions("app", "model")
631 self
.assertIsNone(actions
)
632 mock_disconnect_controller
.assert_called_once()
633 mock_disconnect_model
.assert_called_once()
637 mock_get_application
,
638 mock_disconnect_controller
,
639 mock_disconnect_model
,
643 mock_get_application
.return_value
= FakeApplication()
645 actions
= self
.loop
.run_until_complete(self
.libjuju
.get_actions("app", "model"))
647 self
.assertEqual(actions
, ["existing_action"])
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()
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")
659 @asynctest.mock
.patch("juju.model.Model.add_relation")
660 class AddRelationTest(LibjujuTestCase
):
662 super(AddRelationTest
, self
).setUp()
664 @asynctest.mock
.patch("logging.Logger.warning")
669 mock_disconnect_controller
,
670 mock_disconnect_model
,
674 # TODO in libjuju.py should this fail only with a log message?
675 result
= {"error": "not found", "response": "response", "request-id": 1}
677 mock_get_model
.return_value
= juju
.model
.Model()
678 mock_add_relation
.side_effect
= JujuAPIError(result
)
680 self
.loop
.run_until_complete(
681 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
684 mock_warning
.assert_called_with("Relation not found: not found")
685 mock_disconnect_controller
.assert_called_once()
686 mock_disconnect_model
.assert_called_once()
688 @asynctest.mock
.patch("logging.Logger.warning")
689 def test_already_exists(
693 mock_disconnect_controller
,
694 mock_disconnect_model
,
698 # TODO in libjuju.py should this fail silently?
699 result
= {"error": "already exists", "response": "response", "request-id": 1}
701 mock_get_model
.return_value
= juju
.model
.Model()
702 mock_add_relation
.side_effect
= JujuAPIError(result
)
704 self
.loop
.run_until_complete(
705 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
708 mock_warning
.assert_called_with("Relation already exists: already exists")
709 mock_disconnect_controller
.assert_called_once()
710 mock_disconnect_model
.assert_called_once()
715 mock_disconnect_controller
,
716 mock_disconnect_model
,
720 mock_get_model
.return_value
= juju
.model
.Model()
721 result
= {"error": "", "response": "response", "request-id": 1}
722 mock_add_relation
.side_effect
= JujuAPIError(result
)
724 with self
.assertRaises(JujuAPIError
):
725 self
.loop
.run_until_complete(
726 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
729 mock_disconnect_controller
.assert_called_once()
730 mock_disconnect_model
.assert_called_once()
735 mock_disconnect_controller
,
736 mock_disconnect_model
,
740 mock_get_model
.return_value
= juju
.model
.Model()
742 self
.loop
.run_until_complete(
743 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
746 mock_add_relation
.assert_called_with("app1:relation1", "app2:relation2")
747 mock_disconnect_controller
.assert_called_once()
748 mock_disconnect_model
.assert_called_once()
753 mock_disconnect_controller
,
754 mock_disconnect_model
,
758 mock_get_model
.return_value
= juju
.model
.Model()
760 self
.loop
.run_until_complete(
761 self
.libjuju
.add_relation("model", "app1:relation1", "saas_name",)
764 mock_add_relation
.assert_called_with("app1:relation1", "saas_name")
765 mock_disconnect_controller
.assert_called_once()
766 mock_disconnect_model
.assert_called_once()
769 # TODO destroy_model testcase
772 @asynctest.mock
.patch("juju.model.Model.get_machines")
773 @asynctest.mock
.patch("logging.Logger.debug")
774 class DestroyMachineTest(LibjujuTestCase
):
776 super(DestroyMachineTest
, self
).setUp()
779 self
, mock_debug
, mock_get_machines
,
781 mock_get_machines
.side_effect
= [
782 {"machine": FakeMachine()},
783 {"machine": FakeMachine()},
786 self
.loop
.run_until_complete(
787 self
.libjuju
.destroy_machine(juju
.model
.Model(), "machine", 2,)
790 asynctest
.call("Waiting for machine machine is destroyed"),
791 asynctest
.call("Machine destroyed: machine"),
793 mock_debug
.assert_has_calls(calls
)
796 self
, mock_debug
, mock_get_machines
,
798 mock_get_machines
.return_value
= {}
799 self
.loop
.run_until_complete(
800 self
.libjuju
.destroy_machine(juju
.model
.Model(), "machine", 2,)
802 mock_debug
.assert_called_with("Machine not found: machine")
805 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
806 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
807 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
808 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
809 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
810 class ConfigureApplicationTest(LibjujuTestCase
):
812 super(ConfigureApplicationTest
, self
).setUp()
816 mock_get_application
,
817 mock_disconnect_controller
,
818 mock_disconnect_model
,
823 mock_get_application
.return_value
= FakeApplication()
825 self
.loop
.run_until_complete(
826 self
.libjuju
.configure_application("model", "app", {"config"},)
828 mock_get_application
.assert_called_once()
829 mock_disconnect_controller
.assert_called_once()
830 mock_disconnect_model
.assert_called_once()
834 mock_get_application
,
835 mock_disconnect_controller
,
836 mock_disconnect_model
,
841 mock_get_application
.side_effect
= Exception()
843 with self
.assertRaises(Exception):
844 self
.loop
.run_until_complete(
845 self
.libjuju
.configure_application("model", "app", {"config"},)
847 mock_disconnect_controller
.assert_called_once()
848 mock_disconnect_model
.assert_called_once()
851 # TODO _get_api_endpoints_db test case
852 # TODO _update_api_endpoints_db test case
853 # TODO healthcheck test case
856 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
857 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
858 @asynctest.mock
.patch("juju.controller.Controller.list_models")
859 class ListModelsTest(LibjujuTestCase
):
861 super(ListModelsTest
, self
).setUp()
864 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
866 mock_get_controller
.return_value
= juju
.controller
.Controller()
867 mock_list_models
.return_value
= ["existingmodel"]
868 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("existing"))
870 mock_disconnect_controller
.assert_called_once()
871 self
.assertEquals(models
, ["existingmodel"])
873 def test_not_containing(
874 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
876 mock_get_controller
.return_value
= juju
.controller
.Controller()
877 mock_list_models
.return_value
= ["existingmodel", "model"]
878 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("mdl"))
880 mock_disconnect_controller
.assert_called_once()
881 self
.assertEquals(models
, [])
883 def test_no_contains_arg(
884 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
886 mock_get_controller
.return_value
= juju
.controller
.Controller()
887 mock_list_models
.return_value
= ["existingmodel", "model"]
888 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models())
890 mock_disconnect_controller
.assert_called_once()
891 self
.assertEquals(models
, ["existingmodel", "model"])
894 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.list_models")
895 class ModelsExistTest(LibjujuTestCase
):
897 super(ModelsExistTest
, self
).setUp()
899 def test_model_names_none(self
, mock_list_models
):
900 mock_list_models
.return_value
= []
901 with self
.assertRaises(Exception):
902 self
.loop
.run_until_complete(self
.libjuju
.models_exist(None))
904 def test_model_names_empty(self
, mock_list_models
):
905 mock_list_models
.return_value
= []
906 with self
.assertRaises(Exception):
907 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
908 self
.libjuju
.models_exist([])
911 def test_model_names_not_existing(self
, mock_list_models
):
912 mock_list_models
.return_value
= ["prometheus", "grafana"]
913 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
914 self
.libjuju
.models_exist(["prometheus2", "grafana"])
916 self
.assertFalse(exist
)
917 self
.assertEqual(non_existing_models
, ["prometheus2"])
919 def test_model_names_exist(self
, mock_list_models
):
920 mock_list_models
.return_value
= ["prometheus", "grafana"]
921 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
922 self
.libjuju
.models_exist(["prometheus", "grafana"])
924 self
.assertTrue(exist
)
925 self
.assertEqual(non_existing_models
, [])
928 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
929 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
930 @asynctest.mock
.patch("juju.controller.Controller.list_offers")
931 class ListOffers(LibjujuTestCase
):
933 super(ListOffers
, self
).setUp()
935 def test_disconnect_controller(
936 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
938 mock_get_controller
.return_value
= juju
.controller
.Controller()
939 mock_list_offers
.side_effect
= Exception()
940 with self
.assertRaises(Exception):
941 self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
942 mock_disconnect_controller
.assert_called_once()
945 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
947 mock_get_controller
.return_value
= juju
.controller
.Controller()
948 mock_list_offers
.return_value
= []
949 offers
= self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
950 self
.assertEqual(offers
, [])
951 mock_disconnect_controller
.assert_called_once()
953 def test_non_empty_list(
954 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
956 mock_get_controller
.return_value
= juju
.controller
.Controller()
957 mock_list_offers
.return_value
= ["offer"]
958 offers
= self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
959 self
.assertEqual(offers
, ["offer"])
960 mock_disconnect_controller
.assert_called_once()
963 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
964 @asynctest.mock
.patch("juju.controller.Controller.get_model")
965 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
966 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
967 @asynctest.mock
.patch("juju.model.Model.consume")
968 class ConsumeTest(LibjujuTestCase
):
970 super(ConsumeTest
, self
).setUp()
975 mock_disconnect_controller
,
976 mock_disconnect_model
,
980 mock_get_controller
.return_value
= juju
.controller
.Controller()
981 mock_get_model
.return_value
= juju
.model
.Model()
983 self
.loop
.run_until_complete(self
.libjuju
.consume("offer_url", "model_name"))
984 mock_consume
.assert_called_once()
985 mock_disconnect_model
.assert_called_once()
986 mock_disconnect_controller
.assert_called_once()
988 def test_parsing_error_exception(
991 mock_disconnect_controller
,
992 mock_disconnect_model
,
996 mock_get_controller
.return_value
= juju
.controller
.Controller()
997 mock_get_model
.return_value
= juju
.model
.Model()
998 mock_consume
.side_effect
= juju
.offerendpoints
.ParseError("")
1000 with self
.assertRaises(juju
.offerendpoints
.ParseError
):
1001 self
.loop
.run_until_complete(
1002 self
.libjuju
.consume("offer_url", "model_name")
1004 mock_consume
.assert_called_once()
1005 mock_disconnect_model
.assert_called_once()
1006 mock_disconnect_controller
.assert_called_once()
1008 def test_juju_error_exception(
1011 mock_disconnect_controller
,
1012 mock_disconnect_model
,
1014 mock_get_controller
,
1016 mock_get_controller
.return_value
= juju
.controller
.Controller()
1017 mock_get_model
.return_value
= juju
.model
.Model()
1018 mock_consume
.side_effect
= juju
.errors
.JujuError("")
1020 with self
.assertRaises(juju
.errors
.JujuError
):
1021 self
.loop
.run_until_complete(
1022 self
.libjuju
.consume("offer_url", "model_name")
1024 mock_consume
.assert_called_once()
1025 mock_disconnect_model
.assert_called_once()
1026 mock_disconnect_controller
.assert_called_once()
1028 def test_juju_api_error_exception(
1031 mock_disconnect_controller
,
1032 mock_disconnect_model
,
1034 mock_get_controller
,
1036 mock_get_controller
.return_value
= juju
.controller
.Controller()
1037 mock_get_model
.return_value
= juju
.model
.Model()
1038 mock_consume
.side_effect
= juju
.errors
.JujuAPIError(
1039 {"error": "", "response": "", "request-id": ""}
1042 with self
.assertRaises(juju
.errors
.JujuAPIError
):
1043 self
.loop
.run_until_complete(
1044 self
.libjuju
.consume("offer_url", "model_name")
1046 mock_consume
.assert_called_once()
1047 mock_disconnect_model
.assert_called_once()
1048 mock_disconnect_controller
.assert_called_once()
1051 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.add_cloud")
1052 class AddK8sTest(LibjujuTestCase
):
1054 super(AddK8sTest
, self
).setUp()
1056 "server": "https://192.168.0.21:16443",
1061 def test_add_k8s(self
, mock_add_cloud
):
1062 self
.loop
.run_until_complete(
1063 self
.libjuju
.add_k8s("cloud", self
.auth_data
, "storage_class")
1065 mock_add_cloud
.assert_called_once()
1067 def test_add_k8s_exception(self
, mock_add_cloud
):
1068 mock_add_cloud
.side_effect
= Exception()
1069 with self
.assertRaises(Exception):
1070 self
.loop
.run_until_complete(
1071 self
.libjuju
.add_k8s("cloud", self
.auth_data
, "storage_class")
1073 mock_add_cloud
.assert_called_once()
1075 def test_add_k8s_missing_name(self
, mock_add_cloud
):
1076 with self
.assertRaises(Exception):
1077 self
.loop
.run_until_complete(
1078 self
.libjuju
.add_k8s("", self
.auth_data
, "storage_class")
1080 mock_add_cloud
.assert_not_called()
1082 def test_add_k8s_missing_storage_name(self
, mock_add_cloud
):
1083 with self
.assertRaises(Exception):
1084 self
.loop
.run_until_complete(
1085 self
.libjuju
.add_k8s("cloud", self
.auth_data
, "")
1087 mock_add_cloud
.assert_not_called()
1089 def test_add_k8s_missing_auth_data_keys(self
, mock_add_cloud
):
1090 with self
.assertRaises(Exception):
1091 self
.loop
.run_until_complete(
1092 self
.libjuju
.add_k8s("cloud", {}, "")
1094 mock_add_cloud
.assert_not_called()
1097 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1098 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1099 @asynctest.mock
.patch("juju.controller.Controller.add_cloud")
1100 @asynctest.mock
.patch("juju.controller.Controller.add_credential")
1101 class AddCloudTest(LibjujuTestCase
):
1103 super(AddCloudTest
, self
).setUp()
1104 self
.cloud
= juju
.client
.client
.Cloud()
1105 self
.credential
= juju
.client
.client
.CloudCredential()
1107 def test_add_cloud_with_credential(
1109 mock_add_credential
,
1111 mock_disconnect_controller
,
1112 mock_get_controller
,
1114 mock_get_controller
.return_value
= juju
.controller
.Controller()
1116 cloud
= self
.loop
.run_until_complete(
1117 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1119 self
.assertEqual(cloud
, self
.cloud
)
1120 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1121 mock_add_credential
.assert_called_once_with(
1122 "cloud", credential
=self
.credential
, cloud
="cloud"
1124 mock_disconnect_controller
.assert_called_once()
1126 def test_add_cloud_no_credential(
1128 mock_add_credential
,
1130 mock_disconnect_controller
,
1131 mock_get_controller
,
1133 mock_get_controller
.return_value
= juju
.controller
.Controller()
1135 cloud
= self
.loop
.run_until_complete(
1136 self
.libjuju
.add_cloud("cloud", self
.cloud
)
1138 self
.assertEqual(cloud
, self
.cloud
)
1139 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1140 mock_add_credential
.assert_not_called()
1141 mock_disconnect_controller
.assert_called_once()
1143 def test_add_cloud_exception(
1145 mock_add_credential
,
1147 mock_disconnect_controller
,
1148 mock_get_controller
,
1150 mock_get_controller
.return_value
= juju
.controller
.Controller()
1151 mock_add_cloud
.side_effect
= Exception()
1152 with self
.assertRaises(Exception):
1153 self
.loop
.run_until_complete(
1154 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1157 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1158 mock_add_credential
.assert_not_called()
1159 mock_disconnect_controller
.assert_called_once()
1161 def test_add_credential_exception(
1163 mock_add_credential
,
1165 mock_disconnect_controller
,
1166 mock_get_controller
,
1168 mock_get_controller
.return_value
= juju
.controller
.Controller()
1169 mock_add_credential
.side_effect
= Exception()
1170 with self
.assertRaises(Exception):
1171 self
.loop
.run_until_complete(
1172 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1175 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1176 mock_add_credential
.assert_called_once_with(
1177 "cloud", credential
=self
.credential
, cloud
="cloud"
1179 mock_disconnect_controller
.assert_called_once()
1182 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1183 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1184 @asynctest.mock
.patch("juju.controller.Controller.remove_cloud")
1185 class RemoveCloudTest(LibjujuTestCase
):
1187 super(RemoveCloudTest
, self
).setUp()
1189 def test_remove_cloud(
1190 self
, mock_remove_cloud
, mock_disconnect_controller
, mock_get_controller
,
1192 mock_get_controller
.return_value
= juju
.controller
.Controller()
1194 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1195 mock_remove_cloud
.assert_called_once_with("cloud")
1196 mock_disconnect_controller
.assert_called_once()
1198 def test_remove_cloud_exception(
1199 self
, mock_remove_cloud
, mock_disconnect_controller
, mock_get_controller
,
1201 mock_get_controller
.return_value
= juju
.controller
.Controller()
1202 mock_remove_cloud
.side_effect
= Exception()
1204 with self
.assertRaises(Exception):
1205 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1206 mock_remove_cloud
.assert_called_once_with("cloud")
1207 mock_disconnect_controller
.assert_called_once()