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 unittest
.mock
import Mock
, patch
21 from juju
.errors
import JujuAPIError
24 from n2vc
.definitions
import Offer
, RelationEndpoint
31 from n2vc
.libjuju
import Libjuju
32 from n2vc
.exceptions
import (
33 JujuControllerFailedConnecting
,
35 JujuApplicationNotFound
,
37 JujuApplicationExists
,
38 JujuInvalidK8sConfiguration
,
39 JujuLeaderUnitNotFound
,
42 from n2vc
.k8s_juju_conn
import generate_rbac_id
43 from n2vc
.tests
.unit
.utils
import AsyncMock
44 from n2vc
.vca
.connection
import Connection
45 from n2vc
.vca
.connection_data
import ConnectionData
48 cacert
= """-----BEGIN CERTIFICATE-----
50 -----END CERTIFICATE-----"""
53 @asynctest.mock
.patch("n2vc.libjuju.Controller")
54 class LibjujuTestCase(asynctest
.TestCase
):
55 @asynctest.mock
.patch("n2vc.vca.connection_data.base64_to_cacert")
58 mock_base64_to_cacert
=None,
60 self
.loop
= asyncio
.get_event_loop()
62 mock_base64_to_cacert
.return_value
= cacert
63 # Connection._load_vca_connection_data = Mock()
64 vca_connection
= Connection(AsyncMock())
65 vca_connection
._data
= ConnectionData(
67 "endpoints": ["1.2.3.4:17070"],
73 "lxd-credentials": "credentials",
74 "k8s-cloud": "k8s_cloud",
75 "k8s-credentials": "k8s_credentials",
77 "api-proxy": "api_proxy",
80 logging
.disable(logging
.CRITICAL
)
81 self
.libjuju
= Libjuju(vca_connection
, self
.loop
)
82 self
.loop
.run_until_complete(self
.libjuju
.disconnect())
85 @asynctest.mock
.patch("juju.controller.Controller.connect")
86 @asynctest.mock
.patch(
87 "juju.controller.Controller.api_endpoints",
88 new_callable
=asynctest
.CoroutineMock(return_value
=["127.0.0.1:17070"]),
90 class GetControllerTest(LibjujuTestCase
):
92 super(GetControllerTest
, self
).setUp()
94 def test_diff_endpoint(self
, mock_api_endpoints
, mock_connect
):
95 self
.libjuju
.endpoints
= []
96 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
97 self
.assertIsInstance(controller
, juju
.controller
.Controller
)
99 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
102 mock_disconnect_controller
,
106 self
.libjuju
.endpoints
= []
108 mock_connect
.side_effect
= Exception()
110 with self
.assertRaises(JujuControllerFailedConnecting
):
111 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
112 self
.assertIsNone(controller
)
113 mock_disconnect_controller
.assert_called()
115 def test_same_endpoint_get_controller(self
, mock_api_endpoints
, mock_connect
):
116 self
.libjuju
.endpoints
= ["127.0.0.1:17070"]
117 controller
= self
.loop
.run_until_complete(self
.libjuju
.get_controller())
118 self
.assertIsInstance(controller
, juju
.controller
.Controller
)
121 class DisconnectTest(LibjujuTestCase
):
123 super(DisconnectTest
, self
).setUp()
125 @asynctest.mock
.patch("juju.model.Model.disconnect")
126 def test_disconnect_model(self
, mock_disconnect
):
127 self
.loop
.run_until_complete(self
.libjuju
.disconnect_model(juju
.model
.Model()))
128 mock_disconnect
.assert_called_once()
130 @asynctest.mock
.patch("juju.controller.Controller.disconnect")
131 def test_disconnect_controller(self
, mock_disconnect
):
132 self
.loop
.run_until_complete(
133 self
.libjuju
.disconnect_controller(juju
.controller
.Controller())
135 mock_disconnect
.assert_called_once()
138 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
139 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.model_exists")
140 @asynctest.mock
.patch("juju.controller.Controller.add_model")
141 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
142 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
143 class AddModelTest(LibjujuTestCase
):
145 super(AddModelTest
, self
).setUp()
147 def test_existing_model(
149 mock_disconnect_model
,
150 mock_disconnect_controller
,
155 mock_model_exists
.return_value
= True
157 # This should not raise an exception
158 self
.loop
.run_until_complete(self
.libjuju
.add_model("existing_model", "cloud"))
160 mock_disconnect_controller
.assert_called()
162 # TODO Check two job executing at the same time and one returning without doing anything.
164 def test_non_existing_model(
166 mock_disconnect_model
,
167 mock_disconnect_controller
,
172 mock_model_exists
.return_value
= False
173 mock_get_controller
.return_value
= juju
.controller
.Controller()
175 self
.loop
.run_until_complete(
176 self
.libjuju
.add_model("nonexisting_model", Mock())
179 mock_add_model
.assert_called_once()
180 mock_disconnect_controller
.assert_called()
181 mock_disconnect_model
.assert_called()
184 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
185 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
186 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
187 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
188 @asynctest.mock
.patch(
189 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
191 @asynctest.mock
.patch("juju.model.Model.get_action_status")
192 @asynctest.mock
.patch("juju.model.Model.get_action_output")
193 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_actions")
194 class GetExecutedActionsTest(LibjujuTestCase
):
196 super(GetExecutedActionsTest
, self
).setUp()
201 mock_get_action_output
,
202 mock_get_action_status
,
204 mock_disconnect_controller
,
205 mock_disconnect_model
,
209 mock_get_model
.return_value
= None
210 with self
.assertRaises(JujuError
):
211 self
.loop
.run_until_complete(self
.libjuju
.get_executed_actions("model"))
213 mock_get_controller
.assert_called_once()
214 mock_disconnect_controller
.assert_called_once()
215 mock_get_model
.assert_called_once()
216 mock_disconnect_model
.assert_not_called()
221 mock_get_action_output
,
222 mock_get_action_status
,
224 mock_disconnect_controller
,
225 mock_disconnect_model
,
229 mock_get_model
.return_value
= juju
.model
.Model()
230 mock_applications
.return_value
= {"existing_app"}
231 mock_get_actions
.return_value
= {"action_name": "description"}
232 mock_get_action_status
.return_value
= {"id": "status"}
233 mock_get_action_output
.return_value
= {"output": "completed"}
235 executed_actions
= self
.loop
.run_until_complete(
236 self
.libjuju
.get_executed_actions("model")
241 "action": "action_name",
243 "output": "completed",
246 self
.assertListEqual(expected_result
, executed_actions
)
247 self
.assertIsInstance(executed_actions
, list)
249 mock_get_controller
.assert_called_once()
250 mock_get_model
.assert_called_once()
251 mock_disconnect_controller
.assert_called_once()
252 mock_disconnect_model
.assert_called_once()
255 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
256 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
257 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
258 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
259 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
260 class GetApplicationConfigsTest(LibjujuTestCase
):
262 super(GetApplicationConfigsTest
, self
).setUp()
266 mock_get_application
,
267 mock_disconnect_controller
,
268 mock_disconnect_model
,
272 mock_get_model
.return_value
= None
273 with self
.assertRaises(JujuError
):
274 self
.loop
.run_until_complete(
275 self
.libjuju
.get_application_configs("model", "app")
278 mock_get_controller
.assert_called_once()
279 mock_disconnect_controller
.assert_called_once()
280 mock_get_model
.assert_called_once()
281 mock_disconnect_model
.assert_not_called()
285 mock_get_application
,
286 mock_disconnect_controller
,
287 mock_disconnect_model
,
291 mock_get_application
.return_value
= FakeApplication()
292 application_configs
= self
.loop
.run_until_complete(
293 self
.libjuju
.get_application_configs("model", "app")
296 self
.assertEqual(application_configs
, ["app_config"])
298 mock_get_controller
.assert_called_once()
299 mock_get_model
.assert_called_once()
300 mock_disconnect_controller
.assert_called_once()
301 mock_disconnect_model
.assert_called_once()
304 @asynctest.mock
.patch("juju.controller.Controller.get_model")
305 class GetModelTest(LibjujuTestCase
):
307 super(GetModelTest
, self
).setUp()
313 mock_get_model
.return_value
= juju
.model
.Model()
314 model
= self
.loop
.run_until_complete(
315 self
.libjuju
.get_model(juju
.controller
.Controller(), "model")
317 self
.assertIsInstance(model
, juju
.model
.Model
)
320 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
321 @asynctest.mock
.patch("juju.controller.Controller.list_models")
322 class ModelExistsTest(LibjujuTestCase
):
324 super(ModelExistsTest
, self
).setUp()
326 async def test_existing_model(
331 mock_list_models
.return_value
= ["existing_model"]
333 await self
.libjuju
.model_exists(
334 "existing_model", juju
.controller
.Controller()
338 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
339 async def test_no_controller(
341 mock_disconnect_controller
,
345 mock_list_models
.return_value
= ["existing_model"]
346 mock_get_controller
.return_value
= juju
.controller
.Controller()
347 self
.assertTrue(await self
.libjuju
.model_exists("existing_model"))
348 mock_disconnect_controller
.assert_called_once()
350 async def test_non_existing_model(
355 mock_list_models
.return_value
= ["existing_model"]
357 await self
.libjuju
.model_exists(
358 "not_existing_model", juju
.controller
.Controller()
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("juju.model.Model.get_status")
368 class GetModelStatusTest(LibjujuTestCase
):
370 super(GetModelStatusTest
, self
).setUp()
375 mock_disconnect_controller
,
376 mock_disconnect_model
,
380 mock_get_model
.return_value
= juju
.model
.Model()
381 mock_get_status
.return_value
= {"status"}
383 status
= self
.loop
.run_until_complete(self
.libjuju
.get_model_status("model"))
385 mock_get_status
.assert_called_once()
386 mock_disconnect_controller
.assert_called_once()
387 mock_disconnect_model
.assert_called_once()
389 self
.assertEqual(status
, {"status"})
394 mock_disconnect_controller
,
395 mock_disconnect_model
,
399 mock_get_model
.return_value
= juju
.model
.Model()
400 mock_get_status
.side_effect
= Exception()
402 with self
.assertRaises(Exception):
403 status
= self
.loop
.run_until_complete(
404 self
.libjuju
.get_model_status("model")
407 mock_disconnect_controller
.assert_called_once()
408 mock_disconnect_model
.assert_called_once()
410 self
.assertIsNone(status
)
413 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
414 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
415 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
416 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
417 @asynctest.mock
.patch("juju.model.Model.get_machines")
418 @asynctest.mock
.patch("juju.model.Model.add_machine")
419 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
420 class CreateMachineTest(LibjujuTestCase
):
422 super(CreateMachineTest
, self
).setUp()
424 def test_existing_machine(
429 mock_disconnect_controller
,
430 mock_disconnect_model
,
434 mock_get_model
.return_value
= juju
.model
.Model()
435 mock_get_machines
.return_value
= {"existing_machine": FakeMachine()}
436 machine
, bool_res
= self
.loop
.run_until_complete(
437 self
.libjuju
.create_machine("model", "existing_machine")
440 self
.assertIsInstance(machine
, FakeMachine
)
441 self
.assertFalse(bool_res
)
443 mock_disconnect_controller
.assert_called()
444 mock_disconnect_model
.assert_called()
446 def test_non_existing_machine(
451 mock_disconnect_controller
,
452 mock_disconnect_model
,
458 mock_get_model
.return_value
= juju
.model
.Model()
459 with self
.assertRaises(JujuMachineNotFound
):
460 machine
, bool_res
= self
.loop
.run_until_complete(
461 self
.libjuju
.create_machine("model", "non_existing_machine")
463 self
.assertIsNone(machine
)
464 self
.assertIsNone(bool_res
)
466 mock_disconnect_controller
.assert_called()
467 mock_disconnect_model
.assert_called()
474 mock_disconnect_controller
,
475 mock_disconnect_model
,
479 mock_get_model
.return_value
= juju
.model
.Model()
480 mock_add_machine
.return_value
= FakeMachine()
482 machine
, bool_res
= self
.loop
.run_until_complete(
483 self
.libjuju
.create_machine("model")
486 self
.assertIsInstance(machine
, FakeMachine
)
487 self
.assertTrue(bool_res
)
489 mock_wait_for
.assert_called_once()
490 mock_add_machine
.assert_called_once()
492 mock_disconnect_controller
.assert_called()
493 mock_disconnect_model
.assert_called()
496 # TODO test provision machine
499 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
500 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
501 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
502 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
503 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for_model")
504 @asynctest.mock
.patch("juju.model.Model.deploy")
505 class DeployTest(LibjujuTestCase
):
507 super(DeployTest
, self
).setUp()
513 mock_disconnect_controller
,
514 mock_disconnect_model
,
518 mock_get_model
.return_value
= juju
.model
.Model()
519 self
.loop
.run_until_complete(
520 self
.libjuju
.deploy("cs:osm", "model", wait
=True, timeout
=0)
522 mock_deploy
.assert_called_once()
523 mock_wait_for_model
.assert_called_once()
524 mock_disconnect_controller
.assert_called_once()
525 mock_disconnect_model
.assert_called_once()
527 def test_deploy_no_wait(
531 mock_disconnect_controller
,
532 mock_disconnect_model
,
536 mock_get_model
.return_value
= juju
.model
.Model()
537 self
.loop
.run_until_complete(
538 self
.libjuju
.deploy("cs:osm", "model", wait
=False, timeout
=0)
540 mock_deploy
.assert_called_once()
541 mock_wait_for_model
.assert_not_called()
542 mock_disconnect_controller
.assert_called_once()
543 mock_disconnect_model
.assert_called_once()
545 def test_deploy_exception(
549 mock_disconnect_controller
,
550 mock_disconnect_model
,
554 mock_deploy
.side_effect
= Exception()
555 mock_get_model
.return_value
= juju
.model
.Model()
556 with self
.assertRaises(Exception):
557 self
.loop
.run_until_complete(self
.libjuju
.deploy("cs:osm", "model"))
558 mock_deploy
.assert_called_once()
559 mock_wait_for_model
.assert_not_called()
560 mock_disconnect_controller
.assert_called_once()
561 mock_disconnect_model
.assert_called_once()
564 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
565 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
566 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
567 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
568 @asynctest.mock
.patch(
569 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
571 @asynctest.mock
.patch("juju.model.Model.machines", new_callable
=asynctest
.PropertyMock
)
572 @asynctest.mock
.patch("juju.model.Model.deploy")
573 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
574 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.create_machine")
575 class DeployCharmTest(LibjujuTestCase
):
577 super(DeployCharmTest
, self
).setUp()
579 def test_existing_app(
586 mock_disconnect_controller
,
587 mock_disconnect_model
,
591 mock_get_model
.return_value
= juju
.model
.Model()
592 mock_applications
.return_value
= {"existing_app"}
595 with self
.assertRaises(JujuApplicationExists
):
596 application
= self
.loop
.run_until_complete(
597 self
.libjuju
.deploy_charm(
604 self
.assertIsNone(application
)
606 mock_disconnect_controller
.assert_called()
607 mock_disconnect_model
.assert_called()
609 def test_non_existing_machine(
616 mock_disconnect_controller
,
617 mock_disconnect_model
,
621 mock_get_model
.return_value
= juju
.model
.Model()
622 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
624 with self
.assertRaises(JujuMachineNotFound
):
625 application
= self
.loop
.run_until_complete(
626 self
.libjuju
.deploy_charm(
634 self
.assertIsNone(application
)
636 mock_disconnect_controller
.assert_called()
637 mock_disconnect_model
.assert_called()
646 mock_disconnect_controller
,
647 mock_disconnect_model
,
651 mock_get_model
.return_value
= juju
.model
.Model()
652 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
653 mock_create_machine
.return_value
= (FakeMachine(), "other")
654 mock_deploy
.return_value
= FakeApplication()
655 application
= self
.loop
.run_until_complete(
656 self
.libjuju
.deploy_charm(
665 self
.assertIsInstance(application
, FakeApplication
)
667 mock_deploy
.assert_called_once()
668 mock_wait_for
.assert_called_once()
670 mock_create_machine
.assert_called_once()
672 mock_disconnect_controller
.assert_called()
673 mock_disconnect_model
.assert_called()
682 mock_disconnect_controller
,
683 mock_disconnect_model
,
687 mock_get_model
.return_value
= juju
.model
.Model()
688 mock_machines
.return_value
= {"existing_machine": FakeMachine()}
689 mock_deploy
.return_value
= FakeApplication()
690 application
= self
.loop
.run_until_complete(
691 self
.libjuju
.deploy_charm("app", "path", "model", "existing_machine")
694 self
.assertIsInstance(application
, FakeApplication
)
696 mock_deploy
.assert_called_once()
697 mock_wait_for
.assert_called_once()
699 mock_disconnect_controller
.assert_called()
700 mock_disconnect_model
.assert_called()
703 @asynctest.mock
.patch(
704 "juju.model.Model.applications", new_callable
=asynctest
.PropertyMock
706 class GetApplicationTest(LibjujuTestCase
):
708 super(GetApplicationTest
, self
).setUp()
710 def test_existing_application(
714 mock_applications
.return_value
= {"existing_app": "exists"}
715 model
= juju
.model
.Model()
716 result
= self
.libjuju
._get
_application
(model
, "existing_app")
717 self
.assertEqual(result
, "exists")
719 def test_non_existing_application(
723 mock_applications
.return_value
= {"existing_app": "exists"}
724 model
= juju
.model
.Model()
725 result
= self
.libjuju
._get
_application
(model
, "nonexisting_app")
726 self
.assertIsNone(result
)
729 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
730 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
731 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
732 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
733 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
734 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
735 @asynctest.mock
.patch("juju.model.Model.get_action_output")
736 @asynctest.mock
.patch("juju.model.Model.get_action_status")
737 class ExecuteActionTest(LibjujuTestCase
):
739 super(ExecuteActionTest
, self
).setUp()
741 def test_no_application(
743 mock_get_action_status
,
744 mock_get_action_output
,
746 mock__get_application
,
747 mock_disconnect_controller
,
748 mock_disconnect_model
,
752 mock__get_application
.return_value
= None
753 mock_get_model
.return_value
= juju
.model
.Model()
756 with self
.assertRaises(JujuApplicationNotFound
):
757 output
, status
= self
.loop
.run_until_complete(
758 self
.libjuju
.execute_action(
764 self
.assertIsNone(output
)
765 self
.assertIsNone(status
)
767 mock_disconnect_controller
.assert_called()
768 mock_disconnect_model
.assert_called()
772 mock_get_action_status
,
773 mock_get_action_output
,
775 mock__get_application
,
776 mock_disconnect_controller
,
777 mock_disconnect_model
,
781 mock_get_model
.return_value
= juju
.model
.Model()
782 mock__get_application
.return_value
= FakeApplication()
785 with self
.assertRaises(JujuActionNotFound
):
786 output
, status
= self
.loop
.run_until_complete(
787 self
.libjuju
.execute_action(
793 self
.assertIsNone(output
)
794 self
.assertIsNone(status
)
796 mock_disconnect_controller
.assert_called()
797 mock_disconnect_model
.assert_called()
799 @asynctest.mock
.patch("asyncio.sleep")
800 @asynctest.mock
.patch("n2vc.tests.unit.utils.FakeUnit.is_leader_from_status")
803 mock_is_leader_from_status
,
805 mock_get_action_status
,
806 mock_get_action_output
,
808 mock__get_application
,
809 mock_disconnect_controller
,
810 mock_disconnect_model
,
814 mock_get_model
.return_value
= juju
.model
.Model()
815 mock__get_application
.return_value
= FakeApplication()
816 mock_is_leader_from_status
.return_value
= False
819 with self
.assertRaises(JujuLeaderUnitNotFound
):
820 output
, status
= self
.loop
.run_until_complete(
821 self
.libjuju
.execute_action(
827 self
.assertIsNone(output
)
828 self
.assertIsNone(status
)
830 mock_disconnect_controller
.assert_called()
831 mock_disconnect_model
.assert_called()
833 def test_successful_exec(
835 mock_get_action_status
,
836 mock_get_action_output
,
838 mock__get_application
,
839 mock_disconnect_controller
,
840 mock_disconnect_model
,
844 mock_get_model
.return_value
= juju
.model
.Model()
845 mock__get_application
.return_value
= FakeApplication()
846 mock_get_action_output
.return_value
= "output"
847 mock_get_action_status
.return_value
= {"id": "status"}
848 output
, status
= self
.loop
.run_until_complete(
849 self
.libjuju
.execute_action("app", "model", "existing_action")
851 self
.assertEqual(output
, "output")
852 self
.assertEqual(status
, "status")
854 mock_wait_for
.assert_called_once()
856 mock_disconnect_controller
.assert_called()
857 mock_disconnect_model
.assert_called()
860 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
861 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
862 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
863 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
864 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
865 class GetActionTest(LibjujuTestCase
):
867 super(GetActionTest
, self
).setUp()
871 mock_get_application
,
872 mock_disconnect_controller
,
873 mock_disconnect_model
,
877 mock_get_application
.side_effect
= Exception()
879 with self
.assertRaises(Exception):
880 actions
= self
.loop
.run_until_complete(
881 self
.libjuju
.get_actions("app", "model")
884 self
.assertIsNone(actions
)
885 mock_disconnect_controller
.assert_called_once()
886 mock_disconnect_model
.assert_called_once()
890 mock_get_application
,
891 mock_disconnect_controller
,
892 mock_disconnect_model
,
896 mock_get_application
.return_value
= FakeApplication()
898 actions
= self
.loop
.run_until_complete(self
.libjuju
.get_actions("app", "model"))
900 self
.assertEqual(actions
, ["existing_action"])
902 mock_get_controller
.assert_called_once()
903 mock_get_model
.assert_called_once()
904 mock_disconnect_controller
.assert_called_once()
905 mock_disconnect_model
.assert_called_once()
908 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
909 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
910 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
911 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
912 @asynctest.mock
.patch("juju.application.Application.get_metrics")
913 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
914 class GetMetricsTest(LibjujuTestCase
):
916 super(GetMetricsTest
, self
).setUp()
918 def test_get_metrics_success(
920 mock_get_application
,
922 mock_disconnect_controller
,
923 mock_disconnect_model
,
927 mock_get_application
.return_value
= FakeApplication()
928 mock_get_model
.return_value
= juju
.model
.Model()
930 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("model", "app1"))
932 mock_disconnect_controller
.assert_called_once()
933 mock_disconnect_model
.assert_called_once()
935 def test_get_metrics_exception(
937 mock_get_application
,
939 mock_disconnect_controller
,
940 mock_disconnect_model
,
944 mock_get_model
.return_value
= juju
.model
.Model()
945 mock_get_metrics
.side_effect
= Exception()
946 with self
.assertRaises(Exception):
947 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("model", "app1"))
949 mock_disconnect_controller
.assert_called_once()
950 mock_disconnect_model
.assert_called_once()
952 def test_missing_args_exception(
954 mock_get_application
,
956 mock_disconnect_controller
,
957 mock_disconnect_model
,
961 mock_get_model
.return_value
= juju
.model
.Model()
963 with self
.assertRaises(Exception):
964 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("", ""))
966 mock_get_controller
.assert_not_called()
967 mock_get_model
.assert_not_called()
968 mock_disconnect_controller
.assert_not_called()
969 mock_disconnect_model
.assert_not_called()
972 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
973 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
974 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
975 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
976 @asynctest.mock
.patch("juju.model.Model.add_relation")
977 class AddRelationTest(LibjujuTestCase
):
979 super(AddRelationTest
, self
).setUp()
981 @asynctest.mock
.patch("logging.Logger.warning")
986 mock_disconnect_controller
,
987 mock_disconnect_model
,
991 # TODO in libjuju.py should this fail only with a log message?
992 result
= {"error": "not found", "response": "response", "request-id": 1}
994 mock_get_model
.return_value
= juju
.model
.Model()
995 mock_add_relation
.side_effect
= JujuAPIError(result
)
997 self
.loop
.run_until_complete(
998 self
.libjuju
.add_relation(
1005 mock_warning
.assert_called_with("Relation not found: not found")
1006 mock_disconnect_controller
.assert_called_once()
1007 mock_disconnect_model
.assert_called_once()
1009 @asynctest.mock
.patch("logging.Logger.warning")
1010 def test_not_found_in_error_code(
1014 mock_disconnect_controller
,
1015 mock_disconnect_model
,
1017 mock_get_controller
,
1020 "error": "relation cannot be added",
1021 "error-code": "not found",
1022 "response": "response",
1026 mock_get_model
.return_value
= juju
.model
.Model()
1027 mock_add_relation
.side_effect
= JujuAPIError(result
)
1029 self
.loop
.run_until_complete(
1030 self
.libjuju
.add_relation(
1037 mock_warning
.assert_called_with("Relation not found: relation cannot be added")
1038 mock_disconnect_controller
.assert_called_once()
1039 mock_disconnect_model
.assert_called_once()
1041 @asynctest.mock
.patch("logging.Logger.warning")
1042 def test_already_exists(
1046 mock_disconnect_controller
,
1047 mock_disconnect_model
,
1049 mock_get_controller
,
1051 # TODO in libjuju.py should this fail silently?
1052 result
= {"error": "already exists", "response": "response", "request-id": 1}
1054 mock_get_model
.return_value
= juju
.model
.Model()
1055 mock_add_relation
.side_effect
= JujuAPIError(result
)
1057 self
.loop
.run_until_complete(
1058 self
.libjuju
.add_relation(
1065 mock_warning
.assert_called_with("Relation already exists: already exists")
1066 mock_disconnect_controller
.assert_called_once()
1067 mock_disconnect_model
.assert_called_once()
1069 @asynctest.mock
.patch("logging.Logger.warning")
1070 def test_already_exists_error_code(
1074 mock_disconnect_controller
,
1075 mock_disconnect_model
,
1077 mock_get_controller
,
1080 "error": "relation cannot be added",
1081 "error-code": "already exists",
1082 "response": "response",
1086 mock_get_model
.return_value
= juju
.model
.Model()
1087 mock_add_relation
.side_effect
= JujuAPIError(result
)
1089 self
.loop
.run_until_complete(
1090 self
.libjuju
.add_relation(
1097 mock_warning
.assert_called_with(
1098 "Relation already exists: relation cannot be added"
1100 mock_disconnect_controller
.assert_called_once()
1101 mock_disconnect_model
.assert_called_once()
1106 mock_disconnect_controller
,
1107 mock_disconnect_model
,
1109 mock_get_controller
,
1111 mock_get_model
.return_value
= juju
.model
.Model()
1112 result
= {"error": "", "response": "response", "request-id": 1}
1113 mock_add_relation
.side_effect
= JujuAPIError(result
)
1115 with self
.assertRaises(JujuAPIError
):
1116 self
.loop
.run_until_complete(
1117 self
.libjuju
.add_relation(
1124 mock_disconnect_controller
.assert_called_once()
1125 mock_disconnect_model
.assert_called_once()
1130 mock_disconnect_controller
,
1131 mock_disconnect_model
,
1133 mock_get_controller
,
1135 mock_get_model
.return_value
= juju
.model
.Model()
1137 self
.loop
.run_until_complete(
1138 self
.libjuju
.add_relation(
1145 mock_add_relation
.assert_called_with("app1:relation1", "app2:relation2")
1146 mock_disconnect_controller
.assert_called_once()
1147 mock_disconnect_model
.assert_called_once()
1152 mock_disconnect_controller
,
1153 mock_disconnect_model
,
1155 mock_get_controller
,
1157 mock_get_model
.return_value
= juju
.model
.Model()
1159 self
.loop
.run_until_complete(
1160 self
.libjuju
.add_relation(
1167 mock_add_relation
.assert_called_with("app1:relation1", "saas_name")
1168 mock_disconnect_controller
.assert_called_once()
1169 mock_disconnect_model
.assert_called_once()
1172 # TODO destroy_model testcase
1175 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1176 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
1177 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1178 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
1179 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1180 class DestroyApplicationTest(LibjujuTestCase
):
1182 super(DestroyApplicationTest
, self
).setUp()
1186 mock_get_controller
,
1188 mock_disconnect_controller
,
1189 mock_get_application
,
1190 mock_disconnect_model
,
1192 mock_get_application
.return_value
= FakeApplication()
1193 mock_get_model
.return_value
= None
1194 self
.loop
.run_until_complete(
1195 self
.libjuju
.destroy_application(
1201 mock_get_application
.assert_called()
1202 mock_disconnect_controller
.assert_called_once()
1203 mock_disconnect_model
.assert_called_once()
1205 def test_no_application(
1207 mock_get_controller
,
1209 mock_disconnect_controller
,
1210 mock_get_application
,
1211 mock_disconnect_model
,
1213 mock_get_model
.return_value
= None
1214 mock_get_application
.return_value
= None
1216 self
.loop
.run_until_complete(
1217 self
.libjuju
.destroy_application(
1223 mock_get_application
.assert_called()
1227 mock_get_controller
,
1229 mock_disconnect_controller
,
1230 mock_get_application
,
1231 mock_disconnect_model
,
1233 mock_get_application
.return_value
= FakeApplication
1234 mock_get_model
.return_value
= None
1236 with self
.assertRaises(Exception):
1237 self
.loop
.run_until_complete(
1238 self
.libjuju
.destroy_application(
1244 mock_get_application
.assert_called_once()
1247 # @asynctest.mock.patch("juju.model.Model.get_machines")
1248 # @asynctest.mock.patch("logging.Logger.debug")
1249 # class DestroyMachineTest(LibjujuTestCase):
1251 # super(DestroyMachineTest, self).setUp()
1253 # def test_success_manual_machine(
1254 # self, mock_debug, mock_get_machines,
1256 # mock_get_machines.side_effect = [
1257 # {"machine": FakeManualMachine()},
1258 # {"machine": FakeManualMachine()},
1261 # self.loop.run_until_complete(
1262 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
1265 # asynctest.call("Waiting for machine machine is destroyed"),
1266 # asynctest.call("Machine destroyed: machine"),
1268 # mock_debug.assert_has_calls(calls)
1270 # def test_no_machine(
1271 # self, mock_debug, mock_get_machines,
1273 # mock_get_machines.return_value = {}
1274 # self.loop.run_until_complete(
1275 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2)
1277 # mock_debug.assert_called_with("Machine not found: machine")
1280 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1281 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
1282 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1283 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1284 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
1285 class ConfigureApplicationTest(LibjujuTestCase
):
1287 super(ConfigureApplicationTest
, self
).setUp()
1291 mock_get_application
,
1292 mock_disconnect_controller
,
1293 mock_disconnect_model
,
1295 mock_get_controller
,
1297 mock_get_application
.return_value
= FakeApplication()
1299 self
.loop
.run_until_complete(
1300 self
.libjuju
.configure_application(
1306 mock_get_application
.assert_called_once()
1307 mock_disconnect_controller
.assert_called_once()
1308 mock_disconnect_model
.assert_called_once()
1312 mock_get_application
,
1313 mock_disconnect_controller
,
1314 mock_disconnect_model
,
1316 mock_get_controller
,
1318 mock_get_application
.side_effect
= Exception()
1320 with self
.assertRaises(Exception):
1321 self
.loop
.run_until_complete(
1322 self
.libjuju
.configure_application(
1328 mock_disconnect_controller
.assert_called_once()
1329 mock_disconnect_model
.assert_called_once()
1331 def test_controller_exception(
1333 mock_get_application
,
1334 mock_disconnect_controller
,
1335 mock_disconnect_model
,
1337 mock_get_controller
,
1339 result
= {"error": "not found", "response": "response", "request-id": 1}
1341 mock_get_controller
.side_effect
= JujuAPIError(result
)
1343 with self
.assertRaises(JujuAPIError
):
1344 self
.loop
.run_until_complete(
1345 self
.libjuju
.configure_application(
1351 mock_get_model
.assert_not_called()
1352 mock_disconnect_controller
.assert_not_called()
1353 mock_disconnect_model
.assert_not_called()
1355 def test_get_model_exception(
1357 mock_get_application
,
1358 mock_disconnect_controller
,
1359 mock_disconnect_model
,
1361 mock_get_controller
,
1363 result
= {"error": "not found", "response": "response", "request-id": 1}
1364 mock_get_model
.side_effect
= JujuAPIError(result
)
1366 with self
.assertRaises(JujuAPIError
):
1367 self
.loop
.run_until_complete(
1368 self
.libjuju
.configure_application(
1374 mock_get_model
.assert_called_once()
1375 mock_disconnect_controller
.assert_called_once()
1376 mock_disconnect_model
.assert_not_called()
1379 # TODO _get_api_endpoints_db test case
1380 # TODO _update_api_endpoints_db test case
1381 # TODO healthcheck test case
1384 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1385 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1386 @asynctest.mock
.patch("juju.controller.Controller.list_models")
1387 class ListModelsTest(LibjujuTestCase
):
1389 super(ListModelsTest
, self
).setUp()
1391 def test_containing(
1394 mock_disconnect_controller
,
1395 mock_get_controller
,
1397 mock_get_controller
.return_value
= juju
.controller
.Controller()
1398 mock_list_models
.return_value
= ["existingmodel"]
1399 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("existing"))
1401 mock_disconnect_controller
.assert_called_once()
1402 self
.assertEquals(models
, ["existingmodel"])
1404 def test_not_containing(
1407 mock_disconnect_controller
,
1408 mock_get_controller
,
1410 mock_get_controller
.return_value
= juju
.controller
.Controller()
1411 mock_list_models
.return_value
= ["existingmodel", "model"]
1412 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("mdl"))
1414 mock_disconnect_controller
.assert_called_once()
1415 self
.assertEquals(models
, [])
1417 def test_no_contains_arg(
1420 mock_disconnect_controller
,
1421 mock_get_controller
,
1423 mock_get_controller
.return_value
= juju
.controller
.Controller()
1424 mock_list_models
.return_value
= ["existingmodel", "model"]
1425 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models())
1427 mock_disconnect_controller
.assert_called_once()
1428 self
.assertEquals(models
, ["existingmodel", "model"])
1431 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.list_models")
1432 class ModelsExistTest(LibjujuTestCase
):
1434 super(ModelsExistTest
, self
).setUp()
1436 def test_model_names_none(self
, mock_list_models
):
1437 mock_list_models
.return_value
= []
1438 with self
.assertRaises(Exception):
1439 self
.loop
.run_until_complete(self
.libjuju
.models_exist(None))
1441 def test_model_names_empty(self
, mock_list_models
):
1442 mock_list_models
.return_value
= []
1443 with self
.assertRaises(Exception):
1444 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1445 self
.libjuju
.models_exist([])
1448 def test_model_names_not_existing(self
, mock_list_models
):
1449 mock_list_models
.return_value
= ["prometheus", "grafana"]
1450 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1451 self
.libjuju
.models_exist(["prometheus2", "grafana"])
1453 self
.assertFalse(exist
)
1454 self
.assertEqual(non_existing_models
, ["prometheus2"])
1456 def test_model_names_exist(self
, mock_list_models
):
1457 mock_list_models
.return_value
= ["prometheus", "grafana"]
1458 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1459 self
.libjuju
.models_exist(["prometheus", "grafana"])
1461 self
.assertTrue(exist
)
1462 self
.assertEqual(non_existing_models
, [])
1465 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1466 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1467 @asynctest.mock
.patch("juju.controller.Controller.list_offers")
1468 class ListOffers(LibjujuTestCase
):
1470 super(ListOffers
, self
).setUp()
1472 def test_disconnect_controller(
1475 mock_disconnect_controller
,
1476 mock_get_controller
,
1478 mock_get_controller
.return_value
= juju
.controller
.Controller()
1479 mock_list_offers
.side_effect
= Exception()
1480 with self
.assertRaises(Exception):
1481 self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1482 mock_disconnect_controller
.assert_called_once()
1484 def test_empty_list(
1487 mock_disconnect_controller
,
1488 mock_get_controller
,
1490 mock_get_controller
.return_value
= juju
.controller
.Controller()
1491 offer_results
= Mock()
1492 offer_results
.results
= []
1493 mock_list_offers
.return_value
= offer_results
1494 offers
= self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1495 self
.assertEqual(offers
, [])
1496 mock_disconnect_controller
.assert_called_once()
1498 def test_non_empty_list(
1501 mock_disconnect_controller
,
1502 mock_get_controller
,
1504 mock_get_controller
.return_value
= juju
.controller
.Controller()
1506 offer_results
= Mock()
1507 offer_results
.results
= [offer
]
1508 mock_list_offers
.return_value
= offer_results
1509 offers
= self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1510 self
.assertEqual(offers
, [offer
])
1511 mock_disconnect_controller
.assert_called_once()
1513 def test_matching_offer_name(
1516 mock_disconnect_controller
,
1517 mock_get_controller
,
1519 mock_get_controller
.return_value
= juju
.controller
.Controller()
1521 offer_1
.offer_name
= "offer1"
1523 offer_2
.offer_name
= "offer2"
1524 offer_results
= Mock()
1525 offer_results
.results
= [offer_1
, offer_2
]
1526 mock_list_offers
.return_value
= offer_results
1527 offers
= self
.loop
.run_until_complete(
1528 self
.libjuju
._list
_offers
("model", offer_name
="offer2")
1530 self
.assertEqual(offers
, [offer_2
])
1531 mock_disconnect_controller
.assert_called_once()
1533 def test_not_matching_offer_name(
1536 mock_disconnect_controller
,
1537 mock_get_controller
,
1539 mock_get_controller
.return_value
= juju
.controller
.Controller()
1541 offer_1
.offer_name
= "offer1"
1543 offer_2
.offer_name
= "offer2"
1544 offer_results
= Mock()
1545 offer_results
.results
= [offer_1
, offer_2
]
1546 mock_list_offers
.return_value
= offer_results
1547 offers
= self
.loop
.run_until_complete(
1548 self
.libjuju
._list
_offers
("model", offer_name
="offer3")
1550 self
.assertEqual(offers
, [])
1551 mock_disconnect_controller
.assert_called_once()
1554 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1555 @asynctest.mock
.patch("juju.controller.Controller.get_model")
1556 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1557 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1558 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._list_offers")
1559 @asynctest.mock
.patch("juju.model.Model.create_offer")
1560 class OfferTest(LibjujuTestCase
):
1562 super(OfferTest
, self
).setUp()
1568 mock_disconnect_controller
,
1569 mock_disconnect_model
,
1571 mock_get_controller
,
1573 controller
= juju
.controller
.Controller()
1574 model
= juju
.model
.Model()
1575 mock_get_controller
.return_value
= controller
1576 mock_get_model
.return_value
= model
1577 endpoint
= RelationEndpoint("model.app-name.0", "vca", "endpoint")
1578 self
.loop
.run_until_complete(self
.libjuju
.offer(endpoint
))
1579 mock_create_offer
.assert_called_with(
1580 "app-name:endpoint", offer_name
="app-name-endpoint"
1582 mock_disconnect_model
.assert_called_once_with(model
)
1583 mock_disconnect_controller
.assert_called_once_with(controller
)
1585 def test_offer_exception(
1589 mock_disconnect_controller
,
1590 mock_disconnect_model
,
1592 mock_get_controller
,
1594 controller
= juju
.controller
.Controller()
1595 model
= juju
.model
.Model()
1596 mock_get_controller
.return_value
= controller
1597 mock_get_model
.return_value
= model
1598 mock__list_offers
.return_value
= []
1599 endpoint
= RelationEndpoint("model.app-name.0", "vca", "endpoint")
1600 with self
.assertRaises(Exception):
1601 self
.loop
.run_until_complete(self
.libjuju
.offer(endpoint
))
1602 mock_create_offer
.assert_called_with(
1603 "app-name:endpoint", offer_name
="app-name-endpoint"
1605 mock_disconnect_model
.assert_called_once_with(model
)
1606 mock_disconnect_controller
.assert_called_once_with(controller
)
1609 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1610 @asynctest.mock
.patch("juju.controller.Controller.get_model")
1611 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1612 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1613 @asynctest.mock
.patch("juju.model.Model.consume")
1614 class ConsumeTest(LibjujuTestCase
):
1616 self
.offer_url
= "admin/model.offer_name"
1617 super(ConsumeTest
, self
).setUp()
1618 self
.provider_libjuju
= self
.libjuju
1623 mock_disconnect_controller
,
1624 mock_disconnect_model
,
1626 mock_get_controller
,
1628 self_controller
= juju
.controller
.Controller()
1629 provider_controller
= juju
.controller
.Controller()
1630 mock_get_controller
.side_effect
= [self_controller
, provider_controller
]
1631 mock_get_model
.return_value
= juju
.model
.Model()
1633 self
.loop
.run_until_complete(
1634 self
.libjuju
.consume(
1636 Offer(self
.offer_url
, vca_id
="vca-id"),
1637 self
.provider_libjuju
,
1640 mock_consume
.assert_called_once_with(
1641 "admin/model.offer_name",
1642 application_alias
="offer_name-model-vca-id",
1643 controller
=provider_controller
,
1645 mock_disconnect_model
.assert_called_once()
1646 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1648 def test_parsing_error_exception(
1651 mock_disconnect_controller
,
1652 mock_disconnect_model
,
1654 mock_get_controller
,
1656 mock_get_controller
.return_value
= juju
.controller
.Controller()
1657 mock_get_model
.return_value
= juju
.model
.Model()
1658 mock_consume
.side_effect
= juju
.offerendpoints
.ParseError("")
1660 with self
.assertRaises(juju
.offerendpoints
.ParseError
):
1661 self
.loop
.run_until_complete(
1662 self
.libjuju
.consume(
1663 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1666 mock_consume
.assert_called_once()
1667 mock_disconnect_model
.assert_called_once()
1668 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1670 def test_juju_error_exception(
1673 mock_disconnect_controller
,
1674 mock_disconnect_model
,
1676 mock_get_controller
,
1678 mock_get_controller
.return_value
= juju
.controller
.Controller()
1679 mock_get_model
.return_value
= juju
.model
.Model()
1680 mock_consume
.side_effect
= juju
.errors
.JujuError("")
1682 with self
.assertRaises(juju
.errors
.JujuError
):
1683 self
.loop
.run_until_complete(
1684 self
.libjuju
.consume(
1685 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1688 mock_consume
.assert_called_once()
1689 mock_disconnect_model
.assert_called_once()
1690 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1692 def test_juju_api_error_exception(
1695 mock_disconnect_controller
,
1696 mock_disconnect_model
,
1698 mock_get_controller
,
1700 mock_get_controller
.return_value
= juju
.controller
.Controller()
1701 mock_get_model
.return_value
= juju
.model
.Model()
1702 mock_consume
.side_effect
= juju
.errors
.JujuAPIError(
1703 {"error": "", "response": "", "request-id": ""}
1706 with self
.assertRaises(juju
.errors
.JujuAPIError
):
1707 self
.loop
.run_until_complete(
1708 self
.libjuju
.consume(
1709 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1712 mock_consume
.assert_called_once()
1713 mock_disconnect_model
.assert_called_once()
1714 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1717 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_k8s_cloud_credential")
1718 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.add_cloud")
1719 class AddK8sTest(LibjujuTestCase
):
1721 super(AddK8sTest
, self
).setUp()
1723 rbac_id
= generate_rbac_id()
1725 client_cert_data
= "cert"
1726 configuration
= kubernetes
.client
.configuration
.Configuration()
1727 storage_class
= "storage_class"
1728 credential_name
= name
1730 self
._add
_k
8s
_args
= {
1734 "client_cert_data": client_cert_data
,
1735 "configuration": configuration
,
1736 "storage_class": storage_class
,
1737 "credential_name": credential_name
,
1740 def test_add_k8s(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1741 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1742 mock_add_cloud
.assert_called_once()
1743 mock_get_k8s_cloud_credential
.assert_called_once()
1745 def test_add_k8s_exception(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1746 mock_add_cloud
.side_effect
= Exception()
1747 with self
.assertRaises(Exception):
1748 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1749 mock_add_cloud
.assert_called_once()
1750 mock_get_k8s_cloud_credential
.assert_called_once()
1752 def test_add_k8s_missing_name(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1753 self
._add
_k
8s
_args
["name"] = ""
1754 with self
.assertRaises(Exception):
1755 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1756 mock_add_cloud
.assert_not_called()
1758 def test_add_k8s_missing_storage_name(
1759 self
, mock_add_cloud
, mock_get_k8s_cloud_credential
1761 self
._add
_k
8s
_args
["storage_class"] = ""
1762 with self
.assertRaises(Exception):
1763 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1764 mock_add_cloud
.assert_not_called()
1766 def test_add_k8s_missing_configuration_keys(
1767 self
, mock_add_cloud
, mock_get_k8s_cloud_credential
1769 self
._add
_k
8s
_args
["configuration"] = None
1770 with self
.assertRaises(Exception):
1771 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1772 mock_add_cloud
.assert_not_called()
1775 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1776 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1777 @asynctest.mock
.patch("juju.controller.Controller.add_cloud")
1778 @asynctest.mock
.patch("juju.controller.Controller.add_credential")
1779 class AddCloudTest(LibjujuTestCase
):
1781 super(AddCloudTest
, self
).setUp()
1782 self
.cloud
= juju
.client
.client
.Cloud()
1783 self
.credential
= juju
.client
.client
.CloudCredential()
1785 def test_add_cloud_with_credential(
1787 mock_add_credential
,
1789 mock_disconnect_controller
,
1790 mock_get_controller
,
1792 mock_get_controller
.return_value
= juju
.controller
.Controller()
1794 cloud
= self
.loop
.run_until_complete(
1795 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1797 self
.assertEqual(cloud
, self
.cloud
)
1798 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1799 mock_add_credential
.assert_called_once_with(
1800 "cloud", credential
=self
.credential
, cloud
="cloud"
1802 mock_disconnect_controller
.assert_called_once()
1804 def test_add_cloud_no_credential(
1806 mock_add_credential
,
1808 mock_disconnect_controller
,
1809 mock_get_controller
,
1811 mock_get_controller
.return_value
= juju
.controller
.Controller()
1813 cloud
= self
.loop
.run_until_complete(
1814 self
.libjuju
.add_cloud("cloud", self
.cloud
)
1816 self
.assertEqual(cloud
, self
.cloud
)
1817 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1818 mock_add_credential
.assert_not_called()
1819 mock_disconnect_controller
.assert_called_once()
1821 def test_add_cloud_exception(
1823 mock_add_credential
,
1825 mock_disconnect_controller
,
1826 mock_get_controller
,
1828 mock_get_controller
.return_value
= juju
.controller
.Controller()
1829 mock_add_cloud
.side_effect
= Exception()
1830 with self
.assertRaises(Exception):
1831 self
.loop
.run_until_complete(
1832 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1835 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1836 mock_add_credential
.assert_not_called()
1837 mock_disconnect_controller
.assert_called_once()
1839 def test_add_credential_exception(
1841 mock_add_credential
,
1843 mock_disconnect_controller
,
1844 mock_get_controller
,
1846 mock_get_controller
.return_value
= juju
.controller
.Controller()
1847 mock_add_credential
.side_effect
= Exception()
1848 with self
.assertRaises(Exception):
1849 self
.loop
.run_until_complete(
1850 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1853 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1854 mock_add_credential
.assert_called_once_with(
1855 "cloud", credential
=self
.credential
, cloud
="cloud"
1857 mock_disconnect_controller
.assert_called_once()
1860 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1861 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1862 @asynctest.mock
.patch("juju.controller.Controller.remove_cloud")
1863 class RemoveCloudTest(LibjujuTestCase
):
1865 super(RemoveCloudTest
, self
).setUp()
1867 def test_remove_cloud(
1870 mock_disconnect_controller
,
1871 mock_get_controller
,
1873 mock_get_controller
.return_value
= juju
.controller
.Controller()
1875 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1876 mock_remove_cloud
.assert_called_once_with("cloud")
1877 mock_disconnect_controller
.assert_called_once()
1879 def test_remove_cloud_exception(
1882 mock_disconnect_controller
,
1883 mock_get_controller
,
1885 mock_get_controller
.return_value
= juju
.controller
.Controller()
1886 mock_remove_cloud
.side_effect
= Exception()
1888 with self
.assertRaises(Exception):
1889 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1890 mock_remove_cloud
.assert_called_once_with("cloud")
1891 mock_disconnect_controller
.assert_called_once()
1894 @asynctest.mock
.patch("kubernetes.client.configuration.Configuration")
1895 class GetK8sCloudCredentials(LibjujuTestCase
):
1897 super(GetK8sCloudCredentials
, self
).setUp()
1898 self
.cert_data
= "cert"
1899 self
.token
= "token"
1901 @asynctest.mock
.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
1902 def test_not_supported(self
, mock_exception
, mock_configuration
):
1903 mock_configuration
.username
= ""
1904 mock_configuration
.password
= ""
1905 mock_configuration
.ssl_ca_cert
= None
1906 mock_configuration
.cert_file
= None
1907 mock_configuration
.key_file
= None
1908 exception_raised
= False
1910 self
.cert_data
= None
1912 _
= self
.libjuju
.get_k8s_cloud_credential(
1917 except JujuInvalidK8sConfiguration
as e
:
1918 exception_raised
= True
1921 "authentication method not supported",
1923 self
.assertTrue(exception_raised
)
1925 def test_user_pass(self
, mock_configuration
):
1926 mock_configuration
.username
= "admin"
1927 mock_configuration
.password
= "admin"
1928 mock_configuration
.ssl_ca_cert
= None
1929 mock_configuration
.cert_file
= None
1930 mock_configuration
.key_file
= None
1932 self
.cert_data
= None
1933 credential
= self
.libjuju
.get_k8s_cloud_credential(
1940 juju
.client
._definitions
.CloudCredential(
1941 attrs
={"username": "admin", "password": "admin"}, auth_type
="userpass"
1945 def test_user_pass_with_cert(self
, mock_configuration
):
1946 mock_configuration
.username
= "admin"
1947 mock_configuration
.password
= "admin"
1948 mock_configuration
.ssl_ca_cert
= None
1949 mock_configuration
.cert_file
= None
1950 mock_configuration
.key_file
= None
1952 credential
= self
.libjuju
.get_k8s_cloud_credential(
1959 juju
.client
._definitions
.CloudCredential(
1961 "ClientCertificateData": self
.cert_data
,
1962 "username": "admin",
1963 "password": "admin",
1965 auth_type
="userpasswithcert",
1969 def test_user_no_pass(self
, mock_configuration
):
1970 mock_configuration
.username
= "admin"
1971 mock_configuration
.password
= ""
1972 mock_configuration
.ssl_ca_cert
= None
1973 mock_configuration
.cert_file
= None
1974 mock_configuration
.key_file
= None
1976 self
.cert_data
= None
1977 with patch
.object(self
.libjuju
.log
, "debug") as mock_debug
:
1978 credential
= self
.libjuju
.get_k8s_cloud_credential(
1985 juju
.client
._definitions
.CloudCredential(
1986 attrs
={"username": "admin", "password": ""}, auth_type
="userpass"
1989 mock_debug
.assert_called_once_with(
1990 "credential for user admin has empty password"
1993 def test_cert(self
, mock_configuration
):
1994 mock_configuration
.username
= ""
1995 mock_configuration
.password
= ""
1996 mock_configuration
.api_key
= {"authorization": "Bearer Token"}
1997 ssl_ca_cert
= tempfile
.NamedTemporaryFile()
1998 with
open(ssl_ca_cert
.name
, "w") as ssl_ca_cert_file
:
1999 ssl_ca_cert_file
.write("cacert")
2000 mock_configuration
.ssl_ca_cert
= ssl_ca_cert
.name
2001 mock_configuration
.cert_file
= None
2002 mock_configuration
.key_file
= None
2003 credential
= self
.libjuju
.get_k8s_cloud_credential(
2010 juju
.client
._definitions
.CloudCredential(
2011 attrs
={"ClientCertificateData": self
.cert_data
, "Token": self
.token
},
2012 auth_type
="certificate",
2016 # TODO: Fix this test when oauth authentication is supported
2017 # def test_oauth2(self, mock_configuration):
2018 # mock_configuration.username = ""
2019 # mock_configuration.password = ""
2020 # mock_configuration.api_key = {"authorization": "Bearer Token"}
2021 # key = tempfile.NamedTemporaryFile()
2022 # with open(key.name, "w") as key_file:
2023 # key_file.write("key")
2024 # mock_configuration.ssl_ca_cert = None
2025 # mock_configuration.cert_file = None
2026 # mock_configuration.key_file = key.name
2027 # credential = self.libjuju.get_k8s_cloud_credential(
2028 # mock_configuration,
2034 # juju.client._definitions.CloudCredential(
2035 # attrs={"ClientKeyData": "key", "Token": "Token"},
2036 # auth_type="oauth2",
2040 # @asynctest.mock.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
2041 # def test_oauth2_missing_token(self, mock_exception, mock_configuration):
2042 # mock_configuration.username = ""
2043 # mock_configuration.password = ""
2044 # key = tempfile.NamedTemporaryFile()
2045 # with open(key.name, "w") as key_file:
2046 # key_file.write("key")
2047 # mock_configuration.ssl_ca_cert = None
2048 # mock_configuration.cert_file = None
2049 # mock_configuration.key_file = key.name
2050 # exception_raised = False
2052 # _ = self.libjuju.get_k8s_cloud_credential(
2053 # mock_configuration,
2057 # except JujuInvalidK8sConfiguration as e:
2058 # exception_raised = True
2061 # "missing token for auth type oauth2",
2063 # self.assertTrue(exception_raised)
2065 def test_exception_cannot_set_token_and_userpass(self
, mock_configuration
):
2066 mock_configuration
.username
= "admin"
2067 mock_configuration
.password
= "pass"
2068 mock_configuration
.api_key
= {"authorization": "No_bearer_token"}
2069 mock_configuration
.ssl_ca_cert
= None
2070 mock_configuration
.cert_file
= None
2071 mock_configuration
.key_file
= None
2072 exception_raised
= False
2074 _
= self
.libjuju
.get_k8s_cloud_credential(
2079 except JujuInvalidK8sConfiguration
as e
:
2080 exception_raised
= True
2083 "Cannot set both token and user/pass",
2085 self
.assertTrue(exception_raised
)
2088 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2089 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2090 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2091 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2092 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2093 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for_model")
2094 class ScaleApplicationTest(LibjujuTestCase
):
2096 super(ScaleApplicationTest
, self
).setUp()
2098 @asynctest.mock
.patch("asyncio.sleep")
2099 def test_scale_application(
2102 mock_wait_for_model
,
2103 mock_disconnect_controller
,
2104 mock_disconnect_model
,
2105 mock_get_application
,
2107 mock_get_controller
,
2109 mock_get_model
.return_value
= juju
.model
.Model()
2110 mock_get_application
.return_value
= FakeApplication()
2111 self
.loop
.run_until_complete(self
.libjuju
.scale_application("model", "app", 2))
2112 mock_wait_for_model
.assert_called_once()
2113 mock_disconnect_controller
.assert_called_once()
2114 mock_disconnect_model
.assert_called_once()
2116 def test_no_application(
2119 mock_disconnect_controller
,
2120 mock_disconnect_model
,
2121 mock_get_application
,
2123 mock_get_controller
,
2125 mock_get_application
.return_value
= None
2126 mock_get_model
.return_value
= juju
.model
.Model()
2127 with self
.assertRaises(JujuApplicationNotFound
):
2128 self
.loop
.run_until_complete(
2129 self
.libjuju
.scale_application("model", "app", 2)
2131 mock_disconnect_controller
.assert_called()
2132 mock_disconnect_model
.assert_called()
2137 mock_disconnect_controller
,
2138 mock_disconnect_model
,
2139 mock_get_application
,
2141 mock_get_controller
,
2143 mock_get_model
.return_value
= None
2144 mock_get_application
.return_value
= FakeApplication()
2145 with self
.assertRaises(Exception):
2146 self
.loop
.run_until_complete(
2147 self
.libjuju
.scale_application("model", "app", 2, total_timeout
=0)
2149 mock_disconnect_controller
.assert_called_once()
2152 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2153 class GetUnitNumberTest(LibjujuTestCase
):
2155 super(GetUnitNumberTest
, self
).setUp()
2157 def test_successful_get_unit_number(
2159 mock_get_applications
,
2161 mock_get_applications
.return_value
= FakeApplication()
2162 model
= juju
.model
.Model()
2163 result
= self
.libjuju
._get
_application
_count
(model
, "app")
2164 self
.assertEqual(result
, 2)
2166 def test_non_existing_application(
2168 mock_get_applications
,
2170 mock_get_applications
.return_value
= None
2171 model
= juju
.model
.Model()
2172 result
= self
.libjuju
._get
_application
_count
(model
, "app")
2173 self
.assertEqual(result
, None)
2176 @asynctest.mock
.patch("juju.model.Model.machines", new_callable
=asynctest
.PropertyMock
)
2177 class GetMachineInfoTest(LibjujuTestCase
):
2179 super(GetMachineInfoTest
, self
).setUp()
2181 def test_successful(
2185 machine_id
= "existing_machine"
2186 model
= juju
.model
.Model()
2187 mock_machines
.return_value
= {"existing_machine": FakeManualMachine()}
2188 machine
, series
= self
.libjuju
._get
_machine
_info
(
2189 machine_id
=machine_id
,
2192 self
.assertIsNotNone(machine
, series
)
2198 machine_id
= "not_existing_machine"
2199 machine
= series
= None
2200 model
= juju
.model
.Model()
2201 mock_machines
.return_value
= {"existing_machine": FakeManualMachine()}
2202 with self
.assertRaises(JujuMachineNotFound
):
2203 machine
, series
= self
.libjuju
._get
_machine
_info
(
2204 machine_id
=machine_id
,
2207 self
.assertIsNone(machine
, series
)
2210 class GetUnitTest(LibjujuTestCase
):
2212 super(GetUnitTest
, self
).setUp()
2214 def test_successful(self
):
2215 result
= self
.libjuju
._get
_unit
(FakeApplication(), "existing_machine_id")
2216 self
.assertIsInstance(result
, FakeUnit
)
2218 def test_return_none(self
):
2219 result
= self
.libjuju
._get
_unit
(FakeApplication(), "not_existing_machine_id")
2220 self
.assertIsNone(result
)
2223 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2224 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2225 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2226 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2227 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2228 class CheckApplicationExists(LibjujuTestCase
):
2230 super(CheckApplicationExists
, self
).setUp()
2232 def test_successful(
2234 mock_get_application
,
2235 mock_disconnect_controller
,
2236 mock_disconnect_model
,
2238 mock_get_controller
,
2240 mock_get_model
.return_value
= juju
.model
.Model()
2241 mock_get_application
.return_value
= FakeApplication()
2242 result
= self
.loop
.run_until_complete(
2243 self
.libjuju
.check_application_exists(
2248 self
.assertEqual(result
, True)
2250 mock_get_application
.assert_called_once()
2251 mock_get_controller
.assert_called_once()
2252 mock_get_model
.assert_called_once()
2253 mock_disconnect_controller
.assert_called_once()
2254 mock_disconnect_model
.assert_called_once()
2256 def test_no_application(
2258 mock_get_application
,
2259 mock_disconnect_controller
,
2260 mock_disconnect_model
,
2262 mock_get_controller
,
2264 mock_get_model
.return_value
= juju
.model
.Model()
2265 mock_get_application
.return_value
= None
2266 result
= self
.loop
.run_until_complete(
2267 self
.libjuju
.check_application_exists(
2272 self
.assertEqual(result
, False)
2274 mock_get_application
.assert_called_once()
2275 mock_get_controller
.assert_called_once()
2276 mock_get_model
.assert_called_once()
2277 mock_disconnect_controller
.assert_called_once()
2278 mock_disconnect_model
.assert_called_once()
2281 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2282 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2283 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2284 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2285 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2286 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_machine_info")
2287 class AddUnitTest(LibjujuTestCase
):
2289 super(AddUnitTest
, self
).setUp()
2291 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
2292 @asynctest.mock
.patch("asyncio.sleep")
2293 def test_successful(
2297 mock_get_machine_info
,
2298 mock_get_application
,
2299 mock_disconnect_controller
,
2300 mock_disconnect_model
,
2302 mock_get_controller
,
2304 mock_get_model
.return_value
= juju
.model
.Model()
2305 mock_get_application
.return_value
= FakeApplication()
2306 mock_get_machine_info
.return_value
= FakeMachine(), "series"
2307 self
.loop
.run_until_complete(
2308 self
.libjuju
.add_unit(
2315 mock_wait_for
.assert_called_once()
2316 mock_get_application
.assert_called_once()
2317 mock_get_controller
.assert_called_once()
2318 mock_get_model
.assert_called_once()
2319 mock_disconnect_controller
.assert_called_once()
2320 mock_disconnect_model
.assert_called_once()
2324 mock_get_machine_info
,
2325 mock_get_application
,
2326 mock_disconnect_controller
,
2327 mock_disconnect_model
,
2329 mock_get_controller
,
2331 mock_get_model
.return_value
= juju
.model
.Model()
2332 mock_get_application
.return_value
= None
2333 with self
.assertRaises(JujuApplicationNotFound
):
2334 self
.loop
.run_until_complete(
2335 self
.libjuju
.add_unit(
2342 mock_get_application
.assert_called_once()
2343 mock_get_controller
.assert_called_once()
2344 mock_get_model
.assert_called_once()
2345 mock_disconnect_controller
.assert_called_once()
2346 mock_disconnect_model
.assert_called_once()
2348 def test_no_machine(
2350 mock_get_machine_info
,
2351 mock_get_application
,
2352 mock_disconnect_controller
,
2353 mock_disconnect_model
,
2355 mock_get_controller
,
2357 mock_get_model
.return_value
= juju
.model
.Model()
2358 mock_get_application
.return_value
= FakeApplication()
2359 mock_get_machine_info
.side_effect
= JujuMachineNotFound()
2360 with self
.assertRaises(JujuMachineNotFound
):
2361 self
.loop
.run_until_complete(
2362 self
.libjuju
.add_unit(
2369 mock_get_application
.assert_called_once()
2370 mock_get_controller
.assert_called_once()
2371 mock_get_model
.assert_called_once()
2372 mock_disconnect_controller
.assert_called_once()
2373 mock_disconnect_model
.assert_called_once()
2376 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2377 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2378 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2379 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2380 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2381 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_unit")
2382 class DestroyUnitTest(LibjujuTestCase
):
2384 super(DestroyUnitTest
, self
).setUp()
2386 @asynctest.mock
.patch("asyncio.sleep")
2387 def test_successful(
2391 mock_get_application
,
2392 mock_disconnect_controller
,
2393 mock_disconnect_model
,
2395 mock_get_controller
,
2397 mock_get_model
.return_value
= juju
.model
.Model()
2398 mock_get_application
.return_value
= FakeApplication()
2400 self
.loop
.run_until_complete(
2401 self
.libjuju
.destroy_unit("app", "model", "machine", 0)
2404 mock_get_unit
.assert_called()
2405 mock_get_application
.assert_called_once()
2406 mock_get_controller
.assert_called_once()
2407 mock_get_model
.assert_called_once()
2408 mock_disconnect_controller
.assert_called_once()
2409 mock_disconnect_model
.assert_called_once()
2414 mock_get_application
,
2415 mock_disconnect_controller
,
2416 mock_disconnect_model
,
2418 mock_get_controller
,
2420 mock_get_model
.return_value
= juju
.model
.Model()
2421 mock_get_application
.return_value
= None
2423 with self
.assertRaises(JujuApplicationNotFound
):
2424 self
.loop
.run_until_complete(
2425 self
.libjuju
.destroy_unit("app", "model", "machine")
2428 mock_get_application
.assert_called_once()
2429 mock_get_controller
.assert_called_once()
2430 mock_get_model
.assert_called_once()
2431 mock_disconnect_controller
.assert_called_once()
2432 mock_disconnect_model
.assert_called_once()
2437 mock_get_application
,
2438 mock_disconnect_controller
,
2439 mock_disconnect_model
,
2441 mock_get_controller
,
2443 mock_get_model
.return_value
= juju
.model
.Model()
2444 mock_get_application
.return_value
= FakeApplication()
2445 mock_get_unit
.return_value
= None
2447 with self
.assertRaises(JujuError
):
2448 self
.loop
.run_until_complete(
2449 self
.libjuju
.destroy_unit("app", "model", "machine")
2452 mock_get_unit
.assert_called_once()
2453 mock_get_application
.assert_called_once()
2454 mock_get_controller
.assert_called_once()
2455 mock_get_model
.assert_called_once()
2456 mock_disconnect_controller
.assert_called_once()
2457 mock_disconnect_model
.assert_called_once()