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()
99 with self
.assertRaises(JujuControllerFailedConnecting
):
100 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
101 self
.assertIsNone(controller
)
102 mock_disconnect_controller
.assert_called_once()
104 def test_same_endpoint_get_controller(
105 self
, mock__update_api_endpoints_db
, mock_api_endpoints
, mock_connect
107 self
.libjuju
.endpoints
= ["127.0.0.1:17070"]
108 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
109 mock__update_api_endpoints_db
.assert_not_called()
110 self
.assertIsInstance(controller
, juju
.controller
.Controller
)
113 class DisconnectTest(LibjujuTestCase
):
115 super(DisconnectTest
, self
).setUp()
117 @asynctest.mock
.patch("juju.model.Model.disconnect")
118 def test_disconnect_model(self
, mock_disconnect
):
119 self
.loop
.run_until_complete(self
.libjuju
.disconnect_model(juju
.model
.Model()))
120 mock_disconnect
.assert_called_once()
122 @asynctest.mock
.patch("juju.controller.Controller.disconnect")
123 def test_disconnect_controller(self
, mock_disconnect
):
124 self
.loop
.run_until_complete(
125 self
.libjuju
.disconnect_controller(juju
.controller
.Controller())
127 mock_disconnect
.assert_called_once()
130 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
131 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.model_exists")
132 @asynctest.mock
.patch("juju.controller.Controller.add_model")
133 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
134 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
135 class AddModelTest(LibjujuTestCase
):
137 super(AddModelTest
, self
).setUp()
139 def test_existing_model(
141 mock_disconnect_model
,
142 mock_disconnect_controller
,
147 mock_model_exists
.return_value
= True
149 with self
.assertRaises(JujuModelAlreadyExists
):
150 self
.loop
.run_until_complete(
151 self
.libjuju
.add_model("existing_model", "cloud")
154 mock_disconnect_controller
.assert_called()
156 # TODO Check two job executing at the same time and one returning without doing anything.
158 def test_non_existing_model(
160 mock_disconnect_model
,
161 mock_disconnect_controller
,
166 mock_model_exists
.return_value
= False
167 mock_get_controller
.return_value
= juju
.controller
.Controller()
169 self
.loop
.run_until_complete(
170 self
.libjuju
.add_model("nonexisting_model", "cloud")
173 mock_add_model
.assert_called_once()
174 mock_disconnect_controller
.assert_called()
175 mock_disconnect_model
.assert_called()
178 @asynctest.mock
.patch("juju.controller.Controller.get_model")
179 class GetModelTest(LibjujuTestCase
):
181 super(GetModelTest
, self
).setUp()
184 self
, mock_get_model
,
186 mock_get_model
.return_value
= juju
.model
.Model()
187 model
= self
.loop
.run_until_complete(
188 self
.libjuju
.get_model(juju
.controller
.Controller(), "model")
190 self
.assertIsInstance(model
, juju
.model
.Model
)
193 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
194 @asynctest.mock
.patch("juju.controller.Controller.list_models")
195 class ModelExistsTest(LibjujuTestCase
):
197 super(ModelExistsTest
, self
).setUp()
199 async def test_existing_model(
200 self
, mock_list_models
, mock_get_controller
,
202 mock_list_models
.return_value
= ["existing_model"]
204 await self
.libjuju
.model_exists(
205 "existing_model", juju
.controller
.Controller()
209 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
210 async def test_no_controller(
211 self
, mock_disconnect_controller
, mock_list_models
, mock_get_controller
,
213 mock_list_models
.return_value
= ["existing_model"]
214 mock_get_controller
.return_value
= juju
.controller
.Controller()
215 self
.assertTrue(await self
.libjuju
.model_exists("existing_model"))
216 mock_disconnect_controller
.assert_called_once()
218 async def test_non_existing_model(
219 self
, mock_list_models
, mock_get_controller
,
221 mock_list_models
.return_value
= ["existing_model"]
223 await self
.libjuju
.model_exists(
224 "not_existing_model", juju
.controller
.Controller()
229 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
230 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
231 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
232 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
233 @asynctest.mock
.patch("juju.model.Model.get_status")
234 class GetModelStatusTest(LibjujuTestCase
):
236 super(GetModelStatusTest
, self
).setUp()
241 mock_disconnect_controller
,
242 mock_disconnect_model
,
246 mock_get_model
.return_value
= juju
.model
.Model()
247 mock_get_status
.return_value
= {"status"}
249 status
= self
.loop
.run_until_complete(self
.libjuju
.get_model_status("model"))
251 mock_get_status
.assert_called_once()
252 mock_disconnect_controller
.assert_called_once()
253 mock_disconnect_model
.assert_called_once()
255 self
.assertEqual(status
, {"status"})
260 mock_disconnect_controller
,
261 mock_disconnect_model
,
265 mock_get_model
.return_value
= juju
.model
.Model()
266 mock_get_status
.side_effect
= Exception()
268 with self
.assertRaises(Exception):
269 status
= self
.loop
.run_until_complete(
270 self
.libjuju
.get_model_status("model")
273 mock_disconnect_controller
.assert_called_once()
274 mock_disconnect_model
.assert_called_once()
276 self
.assertIsNone(status
)
279 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
280 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
281 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
282 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
283 @asynctest.mock
.patch("juju.model.Model.get_machines")
284 @asynctest.mock
.patch("juju.model.Model.add_machine")
285 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
286 class CreateMachineTest(LibjujuTestCase
):
288 super(CreateMachineTest
, self
).setUp()
290 def test_existing_machine(
295 mock_disconnect_controller
,
296 mock_disconnect_model
,
300 mock_get_model
.return_value
= juju
.model
.Model()
301 mock_get_machines
.return_value
= {"existing_machine": FakeMachine()}
302 machine
, bool_res
= self
.loop
.run_until_complete(
303 self
.libjuju
.create_machine("model", "existing_machine")
306 self
.assertIsInstance(machine
, FakeMachine
)
307 self
.assertFalse(bool_res
)
309 mock_disconnect_controller
.assert_called()
310 mock_disconnect_model
.assert_called()
312 def test_non_existing_machine(
317 mock_disconnect_controller
,
318 mock_disconnect_model
,
322 mock_get_model
.return_value
= juju
.model
.Model()
323 with self
.assertRaises(JujuMachineNotFound
):
324 machine
, bool_res
= self
.loop
.run_until_complete(
325 self
.libjuju
.create_machine("model", "non_existing_machine")
327 self
.assertIsNone(machine
)
328 self
.assertIsNone(bool_res
)
330 mock_disconnect_controller
.assert_called()
331 mock_disconnect_model
.assert_called()
338 mock_disconnect_controller
,
339 mock_disconnect_model
,
343 mock_get_model
.return_value
= juju
.model
.Model()
344 mock_add_machine
.return_value
= FakeMachine()
346 machine
, bool_res
= self
.loop
.run_until_complete(
347 self
.libjuju
.create_machine("model")
350 self
.assertIsInstance(machine
, FakeMachine
)
351 self
.assertTrue(bool_res
)
353 mock_wait_for
.assert_called_once()
354 mock_add_machine
.assert_called_once()
356 mock_disconnect_controller
.assert_called()
357 mock_disconnect_model
.assert_called()
360 # TODO test provision machine
363 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
364 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
365 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
366 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
367 @asynctest.mock
.patch(
368 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
370 @asynctest.mock
.patch("juju.model.Model.machines", new_callable
=asynctest
.PropertyMock
)
371 @asynctest.mock
.patch("juju.model.Model.deploy")
372 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
373 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.create_machine")
374 class DeployCharmTest(LibjujuTestCase
):
376 super(DeployCharmTest
, self
).setUp()
378 def test_existing_app(
385 mock_disconnect_controller
,
386 mock_disconnect_model
,
390 mock_get_model
.return_value
= juju
.model
.Model()
391 mock_applications
.return_value
= {"existing_app"}
393 with self
.assertRaises(JujuApplicationExists
):
394 application
= self
.loop
.run_until_complete(
395 self
.libjuju
.deploy_charm("existing_app", "path", "model", "machine",)
397 self
.assertIsNone(application
)
399 mock_disconnect_controller
.assert_called()
400 mock_disconnect_model
.assert_called()
402 def test_non_existing_machine(
409 mock_disconnect_controller
,
410 mock_disconnect_model
,
414 mock_get_model
.return_value
= juju
.model
.Model()
415 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
416 with self
.assertRaises(JujuMachineNotFound
):
417 application
= self
.loop
.run_until_complete(
418 self
.libjuju
.deploy_charm("app", "path", "model", "machine",)
421 self
.assertIsNone(application
)
423 mock_disconnect_controller
.assert_called()
424 mock_disconnect_model
.assert_called()
433 mock_disconnect_controller
,
434 mock_disconnect_model
,
438 mock_get_model
.return_value
= juju
.model
.Model()
439 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
440 mock_create_machine
.return_value
= (FakeMachine(), "other")
441 mock_deploy
.return_value
= FakeApplication()
442 application
= self
.loop
.run_until_complete(
443 self
.libjuju
.deploy_charm(
444 "app", "path", "model", "existing_machine", num_units
=2,
448 self
.assertIsInstance(application
, FakeApplication
)
450 mock_deploy
.assert_called_once()
451 mock_wait_for
.assert_called_once()
453 mock_create_machine
.assert_called_once()
455 mock_disconnect_controller
.assert_called()
456 mock_disconnect_model
.assert_called()
465 mock_disconnect_controller
,
466 mock_disconnect_model
,
470 mock_get_model
.return_value
= juju
.model
.Model()
471 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
472 mock_deploy
.return_value
= FakeApplication()
473 application
= self
.loop
.run_until_complete(
474 self
.libjuju
.deploy_charm("app", "path", "model", "existing_machine")
477 self
.assertIsInstance(application
, FakeApplication
)
479 mock_deploy
.assert_called_once()
480 mock_wait_for
.assert_called_once()
482 mock_disconnect_controller
.assert_called()
483 mock_disconnect_model
.assert_called()
486 @asynctest.mock
.patch(
487 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
489 class GetApplicationTest(LibjujuTestCase
):
491 super(GetApplicationTest
, self
).setUp()
493 def test_existing_application(
494 self
, mock_applications
,
496 mock_applications
.return_value
= {"existing_app": "exists"}
497 model
= juju
.model
.Model()
498 result
= self
.libjuju
._get
_application
(model
, "existing_app")
499 self
.assertEqual(result
, "exists")
501 def test_non_existing_application(
502 self
, mock_applications
,
504 mock_applications
.return_value
= {"existing_app": "exists"}
505 model
= juju
.model
.Model()
506 result
= self
.libjuju
._get
_application
(model
, "nonexisting_app")
507 self
.assertIsNone(result
)
510 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
511 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
512 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
513 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
514 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
515 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
516 @asynctest.mock
.patch("juju.model.Model.get_action_output")
517 @asynctest.mock
.patch("juju.model.Model.get_action_status")
518 class ExecuteActionTest(LibjujuTestCase
):
520 super(ExecuteActionTest
, self
).setUp()
522 def test_no_application(
524 mock_get_action_status
,
525 mock_get_action_output
,
527 mock__get_application
,
528 mock_disconnect_controller
,
529 mock_disconnect_model
,
533 mock__get_application
.return_value
= None
534 mock_get_model
.return_value
= juju
.model
.Model()
536 with self
.assertRaises(JujuApplicationNotFound
):
537 output
, status
= self
.loop
.run_until_complete(
538 self
.libjuju
.execute_action("app", "model", "action",)
540 self
.assertIsNone(output
)
541 self
.assertIsNone(status
)
543 mock_disconnect_controller
.assert_called()
544 mock_disconnect_model
.assert_called()
548 mock_get_action_status
,
549 mock_get_action_output
,
551 mock__get_application
,
552 mock_disconnect_controller
,
553 mock_disconnect_model
,
558 mock_get_model
.return_value
= juju
.model
.Model()
559 mock__get_application
.return_value
= FakeApplication()
560 with self
.assertRaises(JujuActionNotFound
):
561 output
, status
= self
.loop
.run_until_complete(
562 self
.libjuju
.execute_action("app", "model", "action",)
564 self
.assertIsNone(output
)
565 self
.assertIsNone(status
)
567 mock_disconnect_controller
.assert_called()
568 mock_disconnect_model
.assert_called()
570 # TODO no leader unit found exception
572 def test_succesful_exec(
574 mock_get_action_status
,
575 mock_get_action_output
,
577 mock__get_application
,
578 mock_disconnect_controller
,
579 mock_disconnect_model
,
583 mock_get_model
.return_value
= juju
.model
.Model()
584 mock__get_application
.return_value
= FakeApplication()
585 mock_get_action_output
.return_value
= "output"
586 mock_get_action_status
.return_value
= {"id": "status"}
587 output
, status
= self
.loop
.run_until_complete(
588 self
.libjuju
.execute_action("app", "model", "existing_action")
590 self
.assertEqual(output
, "output")
591 self
.assertEqual(status
, "status")
593 mock_wait_for
.assert_called_once()
595 mock_disconnect_controller
.assert_called()
596 mock_disconnect_model
.assert_called()
599 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
600 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
601 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
602 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
603 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
604 class GetActionTest(LibjujuTestCase
):
606 super(GetActionTest
, self
).setUp()
610 mock_get_application
,
611 mock_disconnect_controller
,
612 mock_disconnect_model
,
616 mock_get_application
.side_effect
= Exception()
618 with self
.assertRaises(Exception):
619 actions
= self
.loop
.run_until_complete(
620 self
.libjuju
.get_actions("app", "model")
623 self
.assertIsNone(actions
)
624 mock_disconnect_controller
.assert_called_once()
625 mock_disconnect_model
.assert_called_once()
629 mock_get_application
,
630 mock_disconnect_controller
,
631 mock_disconnect_model
,
635 mock_get_application
.return_value
= FakeApplication()
637 actions
= self
.loop
.run_until_complete(self
.libjuju
.get_actions("app", "model"))
639 self
.assertEqual(actions
, ["existing_action"])
641 mock_get_controller
.assert_called_once()
642 mock_get_model
.assert_called_once()
643 mock_disconnect_controller
.assert_called_once()
644 mock_disconnect_model
.assert_called_once()
647 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
648 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
649 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
650 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
651 @asynctest.mock
.patch("juju.model.Model.add_relation")
652 class AddRelationTest(LibjujuTestCase
):
654 super(AddRelationTest
, self
).setUp()
656 @asynctest.mock
.patch("logging.Logger.warning")
661 mock_disconnect_controller
,
662 mock_disconnect_model
,
666 # TODO in libjuju.py should this fail only with a log message?
667 result
= {"error": "not found", "response": "response", "request-id": 1}
669 mock_get_model
.return_value
= juju
.model
.Model()
670 mock_add_relation
.side_effect
= JujuAPIError(result
)
672 self
.loop
.run_until_complete(
673 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
676 mock_warning
.assert_called_with("Relation not found: not found")
677 mock_disconnect_controller
.assert_called_once()
678 mock_disconnect_model
.assert_called_once()
680 @asynctest.mock
.patch("logging.Logger.warning")
681 def test_already_exists(
685 mock_disconnect_controller
,
686 mock_disconnect_model
,
690 # TODO in libjuju.py should this fail silently?
691 result
= {"error": "already exists", "response": "response", "request-id": 1}
693 mock_get_model
.return_value
= juju
.model
.Model()
694 mock_add_relation
.side_effect
= JujuAPIError(result
)
696 self
.loop
.run_until_complete(
697 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
700 mock_warning
.assert_called_with("Relation already exists: already exists")
701 mock_disconnect_controller
.assert_called_once()
702 mock_disconnect_model
.assert_called_once()
707 mock_disconnect_controller
,
708 mock_disconnect_model
,
712 mock_get_model
.return_value
= juju
.model
.Model()
713 result
= {"error": "", "response": "response", "request-id": 1}
714 mock_add_relation
.side_effect
= JujuAPIError(result
)
716 with self
.assertRaises(JujuAPIError
):
717 self
.loop
.run_until_complete(
718 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
721 mock_disconnect_controller
.assert_called_once()
722 mock_disconnect_model
.assert_called_once()
727 mock_disconnect_controller
,
728 mock_disconnect_model
,
732 mock_get_model
.return_value
= juju
.model
.Model()
734 self
.loop
.run_until_complete(
735 self
.libjuju
.add_relation("model", "app1:relation1", "app2:relation2",)
738 mock_add_relation
.assert_called_with(
739 "app1:relation1", "app2:relation2"
741 mock_disconnect_controller
.assert_called_once()
742 mock_disconnect_model
.assert_called_once()
747 mock_disconnect_controller
,
748 mock_disconnect_model
,
752 mock_get_model
.return_value
= juju
.model
.Model()
754 self
.loop
.run_until_complete(
755 self
.libjuju
.add_relation("model", "app1:relation1", "saas_name",)
758 mock_add_relation
.assert_called_with(
759 "app1:relation1", "saas_name"
761 mock_disconnect_controller
.assert_called_once()
762 mock_disconnect_model
.assert_called_once()
765 # TODO destroy_model testcase
768 @asynctest.mock
.patch("juju.model.Model.get_machines")
769 @asynctest.mock
.patch("logging.Logger.debug")
770 class DestroyMachineTest(LibjujuTestCase
):
772 super(DestroyMachineTest
, self
).setUp()
775 self
, mock_debug
, mock_get_machines
,
777 mock_get_machines
.side_effect
= [
778 {"machine": FakeMachine()},
779 {"machine": FakeMachine()},
782 self
.loop
.run_until_complete(
783 self
.libjuju
.destroy_machine(juju
.model
.Model(), "machine", 2,)
786 asynctest
.call("Waiting for machine machine is destroyed"),
787 asynctest
.call("Machine destroyed: machine"),
789 mock_debug
.assert_has_calls(calls
)
792 self
, mock_debug
, mock_get_machines
,
794 mock_get_machines
.return_value
= {}
795 self
.loop
.run_until_complete(
796 self
.libjuju
.destroy_machine(juju
.model
.Model(), "machine", 2,)
798 mock_debug
.assert_called_with("Machine not found: machine")
801 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
802 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
803 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
804 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
805 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
806 class ConfigureApplicationTest(LibjujuTestCase
):
808 super(ConfigureApplicationTest
, self
).setUp()
812 mock_get_application
,
813 mock_disconnect_controller
,
814 mock_disconnect_model
,
819 mock_get_application
.return_value
= FakeApplication()
821 self
.loop
.run_until_complete(
822 self
.libjuju
.configure_application("model", "app", {"config"},)
824 mock_get_application
.assert_called_once()
825 mock_disconnect_controller
.assert_called_once()
826 mock_disconnect_model
.assert_called_once()
830 mock_get_application
,
831 mock_disconnect_controller
,
832 mock_disconnect_model
,
837 mock_get_application
.side_effect
= Exception()
839 with self
.assertRaises(Exception):
840 self
.loop
.run_until_complete(
841 self
.libjuju
.configure_application("model", "app", {"config"},)
843 mock_disconnect_controller
.assert_called_once()
844 mock_disconnect_model
.assert_called_once()
847 # TODO _get_api_endpoints_db test case
848 # TODO _update_api_endpoints_db test case
849 # TODO healthcheck test case
852 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
853 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
854 @asynctest.mock
.patch("juju.controller.Controller.list_models")
855 class ListModelsTest(LibjujuTestCase
):
857 super(ListModelsTest
, self
).setUp()
860 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
862 mock_get_controller
.return_value
= juju
.controller
.Controller()
863 mock_list_models
.return_value
= ["existingmodel"]
864 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("existing"))
866 mock_disconnect_controller
.assert_called_once()
867 self
.assertEquals(models
, ["existingmodel"])
869 def test_not_containing(
870 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
872 mock_get_controller
.return_value
= juju
.controller
.Controller()
873 mock_list_models
.return_value
= ["existingmodel", "model"]
874 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("mdl"))
876 mock_disconnect_controller
.assert_called_once()
877 self
.assertEquals(models
, [])
879 def test_no_contains_arg(
880 self
, mock_list_models
, mock_disconnect_controller
, mock_get_controller
,
882 mock_get_controller
.return_value
= juju
.controller
.Controller()
883 mock_list_models
.return_value
= ["existingmodel", "model"]
884 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models())
886 mock_disconnect_controller
.assert_called_once()
887 self
.assertEquals(models
, ["existingmodel", "model"])
890 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.list_models")
891 class ModelsExistTest(LibjujuTestCase
):
893 super(ModelsExistTest
, self
).setUp()
895 def test_model_names_none(self
, mock_list_models
):
896 mock_list_models
.return_value
= []
897 with self
.assertRaises(Exception):
898 self
.loop
.run_until_complete(self
.libjuju
.models_exist(None))
900 def test_model_names_empty(self
, mock_list_models
):
901 mock_list_models
.return_value
= []
902 with self
.assertRaises(Exception):
903 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
904 self
.libjuju
.models_exist([])
907 def test_model_names_not_existing(self
, mock_list_models
):
908 mock_list_models
.return_value
= ["prometheus", "grafana"]
909 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
910 self
.libjuju
.models_exist(["prometheus2", "grafana"])
912 self
.assertFalse(exist
)
913 self
.assertEqual(non_existing_models
, ["prometheus2"])
915 def test_model_names_exist(self
, mock_list_models
):
916 mock_list_models
.return_value
= ["prometheus", "grafana"]
917 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
918 self
.libjuju
.models_exist(["prometheus", "grafana"])
920 self
.assertTrue(exist
)
921 self
.assertEqual(non_existing_models
, [])
924 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
925 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
926 @asynctest.mock
.patch("juju.controller.Controller.list_offers")
927 class ListOffers(LibjujuTestCase
):
929 super(ListOffers
, self
).setUp()
931 def test_disconnect_controller(
932 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
934 mock_get_controller
.return_value
= juju
.controller
.Controller()
935 mock_list_offers
.side_effect
= Exception()
936 with self
.assertRaises(Exception):
937 self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
938 mock_disconnect_controller
.assert_called_once()
941 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
943 mock_get_controller
.return_value
= juju
.controller
.Controller()
944 mock_list_offers
.return_value
= []
945 offers
= self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
946 self
.assertEqual(offers
, [])
947 mock_disconnect_controller
.assert_called_once()
949 def test_non_empty_list(
950 self
, mock_list_offers
, mock_disconnect_controller
, mock_get_controller
,
952 mock_get_controller
.return_value
= juju
.controller
.Controller()
953 mock_list_offers
.return_value
= ["offer"]
954 offers
= self
.loop
.run_until_complete(self
.libjuju
.list_offers("model"))
955 self
.assertEqual(offers
, ["offer"])
956 mock_disconnect_controller
.assert_called_once()
959 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
960 @asynctest.mock
.patch("juju.controller.Controller.get_model")
961 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
962 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
963 @asynctest.mock
.patch("juju.model.Model.consume")
964 class ConsumeTest(LibjujuTestCase
):
966 super(ConsumeTest
, self
).setUp()
971 mock_disconnect_controller
,
972 mock_disconnect_model
,
976 mock_get_controller
.return_value
= juju
.controller
.Controller()
977 mock_get_model
.return_value
= juju
.model
.Model()
979 self
.loop
.run_until_complete(
980 self
.libjuju
.consume("offer_url", "model_name")
982 mock_consume
.assert_called_once()
983 mock_disconnect_model
.assert_called_once()
984 mock_disconnect_controller
.assert_called_once()
986 def test_parsing_error_exception(
989 mock_disconnect_controller
,
990 mock_disconnect_model
,
994 mock_get_controller
.return_value
= juju
.controller
.Controller()
995 mock_get_model
.return_value
= juju
.model
.Model()
996 mock_consume
.side_effect
= juju
.offerendpoints
.ParseError("")
998 with self
.assertRaises(juju
.offerendpoints
.ParseError
):
999 self
.loop
.run_until_complete(
1000 self
.libjuju
.consume("offer_url", "model_name")
1002 mock_consume
.assert_called_once()
1003 mock_disconnect_model
.assert_called_once()
1004 mock_disconnect_controller
.assert_called_once()
1006 def test_juju_error_exception(
1009 mock_disconnect_controller
,
1010 mock_disconnect_model
,
1012 mock_get_controller
,
1014 mock_get_controller
.return_value
= juju
.controller
.Controller()
1015 mock_get_model
.return_value
= juju
.model
.Model()
1016 mock_consume
.side_effect
= juju
.errors
.JujuError("")
1018 with self
.assertRaises(juju
.errors
.JujuError
):
1019 self
.loop
.run_until_complete(
1020 self
.libjuju
.consume("offer_url", "model_name")
1022 mock_consume
.assert_called_once()
1023 mock_disconnect_model
.assert_called_once()
1024 mock_disconnect_controller
.assert_called_once()
1026 def test_juju_api_error_exception(
1029 mock_disconnect_controller
,
1030 mock_disconnect_model
,
1032 mock_get_controller
,
1034 mock_get_controller
.return_value
= juju
.controller
.Controller()
1035 mock_get_model
.return_value
= juju
.model
.Model()
1036 mock_consume
.side_effect
= juju
.errors
.JujuAPIError({
1043 with self
.assertRaises(juju
.errors
.JujuAPIError
):
1044 self
.loop
.run_until_complete(
1045 self
.libjuju
.consume("offer_url", "model_name")
1047 mock_consume
.assert_called_once()
1048 mock_disconnect_model
.assert_called_once()
1049 mock_disconnect_controller
.assert_called_once()