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
,
782 mock_get_model
.return_value
= juju
.model
.Model()
783 mock__get_application
.return_value
= FakeApplication()
786 with self
.assertRaises(JujuActionNotFound
):
787 output
, status
= self
.loop
.run_until_complete(
788 self
.libjuju
.execute_action(
794 self
.assertIsNone(output
)
795 self
.assertIsNone(status
)
797 mock_disconnect_controller
.assert_called()
798 mock_disconnect_model
.assert_called()
800 @asynctest.mock
.patch("asyncio.sleep")
801 @asynctest.mock
.patch("n2vc.tests.unit.utils.FakeUnit.is_leader_from_status")
804 mock_is_leader_from_status
,
806 mock_get_action_status
,
807 mock_get_action_output
,
809 mock__get_application
,
810 mock_disconnect_controller
,
811 mock_disconnect_model
,
815 mock_get_model
.return_value
= juju
.model
.Model()
816 mock__get_application
.return_value
= FakeApplication()
817 mock_is_leader_from_status
.return_value
= False
820 with self
.assertRaises(JujuLeaderUnitNotFound
):
821 output
, status
= self
.loop
.run_until_complete(
822 self
.libjuju
.execute_action(
828 self
.assertIsNone(output
)
829 self
.assertIsNone(status
)
831 mock_disconnect_controller
.assert_called()
832 mock_disconnect_model
.assert_called()
834 def test_successful_exec(
836 mock_get_action_status
,
837 mock_get_action_output
,
839 mock__get_application
,
840 mock_disconnect_controller
,
841 mock_disconnect_model
,
845 mock_get_model
.return_value
= juju
.model
.Model()
846 mock__get_application
.return_value
= FakeApplication()
847 mock_get_action_output
.return_value
= "output"
848 mock_get_action_status
.return_value
= {"id": "status"}
849 output
, status
= self
.loop
.run_until_complete(
850 self
.libjuju
.execute_action("app", "model", "existing_action")
852 self
.assertEqual(output
, "output")
853 self
.assertEqual(status
, "status")
855 mock_wait_for
.assert_called_once()
857 mock_disconnect_controller
.assert_called()
858 mock_disconnect_model
.assert_called()
861 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
862 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
863 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
864 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
865 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
866 class GetActionTest(LibjujuTestCase
):
868 super(GetActionTest
, self
).setUp()
872 mock_get_application
,
873 mock_disconnect_controller
,
874 mock_disconnect_model
,
878 mock_get_application
.side_effect
= Exception()
880 with self
.assertRaises(Exception):
881 actions
= self
.loop
.run_until_complete(
882 self
.libjuju
.get_actions("app", "model")
885 self
.assertIsNone(actions
)
886 mock_disconnect_controller
.assert_called_once()
887 mock_disconnect_model
.assert_called_once()
891 mock_get_application
,
892 mock_disconnect_controller
,
893 mock_disconnect_model
,
897 mock_get_application
.return_value
= FakeApplication()
899 actions
= self
.loop
.run_until_complete(self
.libjuju
.get_actions("app", "model"))
901 self
.assertEqual(actions
, ["existing_action"])
903 mock_get_controller
.assert_called_once()
904 mock_get_model
.assert_called_once()
905 mock_disconnect_controller
.assert_called_once()
906 mock_disconnect_model
.assert_called_once()
909 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
910 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
911 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
912 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
913 @asynctest.mock
.patch("juju.application.Application.get_metrics")
914 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
915 class GetMetricsTest(LibjujuTestCase
):
917 super(GetMetricsTest
, self
).setUp()
919 def test_get_metrics_success(
921 mock_get_application
,
923 mock_disconnect_controller
,
924 mock_disconnect_model
,
928 mock_get_application
.return_value
= FakeApplication()
929 mock_get_model
.return_value
= juju
.model
.Model()
931 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("model", "app1"))
933 mock_disconnect_controller
.assert_called_once()
934 mock_disconnect_model
.assert_called_once()
936 def test_get_metrics_exception(
938 mock_get_application
,
940 mock_disconnect_controller
,
941 mock_disconnect_model
,
945 mock_get_model
.return_value
= juju
.model
.Model()
946 mock_get_metrics
.side_effect
= Exception()
947 with self
.assertRaises(Exception):
948 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("model", "app1"))
950 mock_disconnect_controller
.assert_called_once()
951 mock_disconnect_model
.assert_called_once()
953 def test_missing_args_exception(
955 mock_get_application
,
957 mock_disconnect_controller
,
958 mock_disconnect_model
,
962 mock_get_model
.return_value
= juju
.model
.Model()
964 with self
.assertRaises(Exception):
965 self
.loop
.run_until_complete(self
.libjuju
.get_metrics("", ""))
967 mock_get_controller
.assert_not_called()
968 mock_get_model
.assert_not_called()
969 mock_disconnect_controller
.assert_not_called()
970 mock_disconnect_model
.assert_not_called()
973 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
974 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
975 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
976 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
977 @asynctest.mock
.patch("juju.model.Model.add_relation")
978 class AddRelationTest(LibjujuTestCase
):
980 super(AddRelationTest
, self
).setUp()
982 @asynctest.mock
.patch("logging.Logger.warning")
987 mock_disconnect_controller
,
988 mock_disconnect_model
,
992 # TODO in libjuju.py should this fail only with a log message?
993 result
= {"error": "not found", "response": "response", "request-id": 1}
995 mock_get_model
.return_value
= juju
.model
.Model()
996 mock_add_relation
.side_effect
= JujuAPIError(result
)
998 self
.loop
.run_until_complete(
999 self
.libjuju
.add_relation(
1006 mock_warning
.assert_called_with("Relation not found: not found")
1007 mock_disconnect_controller
.assert_called_once()
1008 mock_disconnect_model
.assert_called_once()
1010 @asynctest.mock
.patch("logging.Logger.warning")
1011 def test_not_found_in_error_code(
1015 mock_disconnect_controller
,
1016 mock_disconnect_model
,
1018 mock_get_controller
,
1021 "error": "relation cannot be added",
1022 "error-code": "not found",
1023 "response": "response",
1027 mock_get_model
.return_value
= juju
.model
.Model()
1028 mock_add_relation
.side_effect
= JujuAPIError(result
)
1030 self
.loop
.run_until_complete(
1031 self
.libjuju
.add_relation(
1038 mock_warning
.assert_called_with("Relation not found: relation cannot be added")
1039 mock_disconnect_controller
.assert_called_once()
1040 mock_disconnect_model
.assert_called_once()
1042 @asynctest.mock
.patch("logging.Logger.warning")
1043 def test_already_exists(
1047 mock_disconnect_controller
,
1048 mock_disconnect_model
,
1050 mock_get_controller
,
1052 # TODO in libjuju.py should this fail silently?
1053 result
= {"error": "already exists", "response": "response", "request-id": 1}
1055 mock_get_model
.return_value
= juju
.model
.Model()
1056 mock_add_relation
.side_effect
= JujuAPIError(result
)
1058 self
.loop
.run_until_complete(
1059 self
.libjuju
.add_relation(
1066 mock_warning
.assert_called_with("Relation already exists: already exists")
1067 mock_disconnect_controller
.assert_called_once()
1068 mock_disconnect_model
.assert_called_once()
1070 @asynctest.mock
.patch("logging.Logger.warning")
1071 def test_already_exists_error_code(
1075 mock_disconnect_controller
,
1076 mock_disconnect_model
,
1078 mock_get_controller
,
1081 "error": "relation cannot be added",
1082 "error-code": "already exists",
1083 "response": "response",
1087 mock_get_model
.return_value
= juju
.model
.Model()
1088 mock_add_relation
.side_effect
= JujuAPIError(result
)
1090 self
.loop
.run_until_complete(
1091 self
.libjuju
.add_relation(
1098 mock_warning
.assert_called_with(
1099 "Relation already exists: relation cannot be added"
1101 mock_disconnect_controller
.assert_called_once()
1102 mock_disconnect_model
.assert_called_once()
1107 mock_disconnect_controller
,
1108 mock_disconnect_model
,
1110 mock_get_controller
,
1112 mock_get_model
.return_value
= juju
.model
.Model()
1113 result
= {"error": "", "response": "response", "request-id": 1}
1114 mock_add_relation
.side_effect
= JujuAPIError(result
)
1116 with self
.assertRaises(JujuAPIError
):
1117 self
.loop
.run_until_complete(
1118 self
.libjuju
.add_relation(
1125 mock_disconnect_controller
.assert_called_once()
1126 mock_disconnect_model
.assert_called_once()
1131 mock_disconnect_controller
,
1132 mock_disconnect_model
,
1134 mock_get_controller
,
1136 mock_get_model
.return_value
= juju
.model
.Model()
1138 self
.loop
.run_until_complete(
1139 self
.libjuju
.add_relation(
1146 mock_add_relation
.assert_called_with("app1:relation1", "app2:relation2")
1147 mock_disconnect_controller
.assert_called_once()
1148 mock_disconnect_model
.assert_called_once()
1153 mock_disconnect_controller
,
1154 mock_disconnect_model
,
1156 mock_get_controller
,
1158 mock_get_model
.return_value
= juju
.model
.Model()
1160 self
.loop
.run_until_complete(
1161 self
.libjuju
.add_relation(
1168 mock_add_relation
.assert_called_with("app1:relation1", "saas_name")
1169 mock_disconnect_controller
.assert_called_once()
1170 mock_disconnect_model
.assert_called_once()
1173 # TODO destroy_model testcase
1176 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1177 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
1178 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1179 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
1180 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1181 class DestroyApplicationTest(LibjujuTestCase
):
1183 super(DestroyApplicationTest
, self
).setUp()
1187 mock_get_controller
,
1189 mock_disconnect_controller
,
1190 mock_get_application
,
1191 mock_disconnect_model
,
1193 mock_get_application
.return_value
= FakeApplication()
1194 mock_get_model
.return_value
= None
1195 self
.loop
.run_until_complete(
1196 self
.libjuju
.destroy_application(
1202 mock_get_application
.assert_called()
1203 mock_disconnect_controller
.assert_called_once()
1204 mock_disconnect_model
.assert_called_once()
1206 def test_no_application(
1208 mock_get_controller
,
1210 mock_disconnect_controller
,
1211 mock_get_application
,
1212 mock_disconnect_model
,
1214 mock_get_model
.return_value
= None
1215 mock_get_application
.return_value
= None
1217 self
.loop
.run_until_complete(
1218 self
.libjuju
.destroy_application(
1224 mock_get_application
.assert_called()
1228 mock_get_controller
,
1230 mock_disconnect_controller
,
1231 mock_get_application
,
1232 mock_disconnect_model
,
1234 mock_get_application
.return_value
= FakeApplication
1235 mock_get_model
.return_value
= None
1237 with self
.assertRaises(Exception):
1238 self
.loop
.run_until_complete(
1239 self
.libjuju
.destroy_application(
1245 mock_get_application
.assert_called_once()
1248 # @asynctest.mock.patch("juju.model.Model.get_machines")
1249 # @asynctest.mock.patch("logging.Logger.debug")
1250 # class DestroyMachineTest(LibjujuTestCase):
1252 # super(DestroyMachineTest, self).setUp()
1254 # def test_success_manual_machine(
1255 # self, mock_debug, mock_get_machines,
1257 # mock_get_machines.side_effect = [
1258 # {"machine": FakeManualMachine()},
1259 # {"machine": FakeManualMachine()},
1262 # self.loop.run_until_complete(
1263 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2,)
1266 # asynctest.call("Waiting for machine machine is destroyed"),
1267 # asynctest.call("Machine destroyed: machine"),
1269 # mock_debug.assert_has_calls(calls)
1271 # def test_no_machine(
1272 # self, mock_debug, mock_get_machines,
1274 # mock_get_machines.return_value = {}
1275 # self.loop.run_until_complete(
1276 # self.libjuju.destroy_machine(juju.model.Model(), "machine", 2)
1278 # mock_debug.assert_called_with("Machine not found: machine")
1281 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1282 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
1283 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1284 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1285 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
1286 class ConfigureApplicationTest(LibjujuTestCase
):
1288 super(ConfigureApplicationTest
, self
).setUp()
1292 mock_get_application
,
1293 mock_disconnect_controller
,
1294 mock_disconnect_model
,
1296 mock_get_controller
,
1299 mock_get_application
.return_value
= FakeApplication()
1301 self
.loop
.run_until_complete(
1302 self
.libjuju
.configure_application(
1308 mock_get_application
.assert_called_once()
1309 mock_disconnect_controller
.assert_called_once()
1310 mock_disconnect_model
.assert_called_once()
1314 mock_get_application
,
1315 mock_disconnect_controller
,
1316 mock_disconnect_model
,
1318 mock_get_controller
,
1321 mock_get_application
.side_effect
= Exception()
1323 with self
.assertRaises(Exception):
1324 self
.loop
.run_until_complete(
1325 self
.libjuju
.configure_application(
1331 mock_disconnect_controller
.assert_called_once()
1332 mock_disconnect_model
.assert_called_once()
1334 def test_controller_exception(
1336 mock_get_application
,
1337 mock_disconnect_controller
,
1338 mock_disconnect_model
,
1340 mock_get_controller
,
1343 result
= {"error": "not found", "response": "response", "request-id": 1}
1345 mock_get_controller
.side_effect
= JujuAPIError(result
)
1347 with self
.assertRaises(JujuAPIError
):
1348 self
.loop
.run_until_complete(
1349 self
.libjuju
.configure_application(
1355 mock_get_model
.assert_not_called()
1356 mock_disconnect_controller
.assert_not_called()
1357 mock_disconnect_model
.assert_not_called()
1359 def test_get_model_exception(
1361 mock_get_application
,
1362 mock_disconnect_controller
,
1363 mock_disconnect_model
,
1365 mock_get_controller
,
1368 result
= {"error": "not found", "response": "response", "request-id": 1}
1369 mock_get_model
.side_effect
= JujuAPIError(result
)
1371 with self
.assertRaises(JujuAPIError
):
1372 self
.loop
.run_until_complete(
1373 self
.libjuju
.configure_application(
1379 mock_get_model
.assert_called_once()
1380 mock_disconnect_controller
.assert_called_once()
1381 mock_disconnect_model
.assert_not_called()
1384 # TODO _get_api_endpoints_db test case
1385 # TODO _update_api_endpoints_db test case
1386 # TODO healthcheck test case
1389 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1390 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1391 @asynctest.mock
.patch("juju.controller.Controller.list_models")
1392 class ListModelsTest(LibjujuTestCase
):
1394 super(ListModelsTest
, self
).setUp()
1396 def test_containing(
1399 mock_disconnect_controller
,
1400 mock_get_controller
,
1402 mock_get_controller
.return_value
= juju
.controller
.Controller()
1403 mock_list_models
.return_value
= ["existingmodel"]
1404 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("existing"))
1406 mock_disconnect_controller
.assert_called_once()
1407 self
.assertEquals(models
, ["existingmodel"])
1409 def test_not_containing(
1412 mock_disconnect_controller
,
1413 mock_get_controller
,
1415 mock_get_controller
.return_value
= juju
.controller
.Controller()
1416 mock_list_models
.return_value
= ["existingmodel", "model"]
1417 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models("mdl"))
1419 mock_disconnect_controller
.assert_called_once()
1420 self
.assertEquals(models
, [])
1422 def test_no_contains_arg(
1425 mock_disconnect_controller
,
1426 mock_get_controller
,
1428 mock_get_controller
.return_value
= juju
.controller
.Controller()
1429 mock_list_models
.return_value
= ["existingmodel", "model"]
1430 models
= self
.loop
.run_until_complete(self
.libjuju
.list_models())
1432 mock_disconnect_controller
.assert_called_once()
1433 self
.assertEquals(models
, ["existingmodel", "model"])
1436 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.list_models")
1437 class ModelsExistTest(LibjujuTestCase
):
1439 super(ModelsExistTest
, self
).setUp()
1441 def test_model_names_none(self
, mock_list_models
):
1442 mock_list_models
.return_value
= []
1443 with self
.assertRaises(Exception):
1444 self
.loop
.run_until_complete(self
.libjuju
.models_exist(None))
1446 def test_model_names_empty(self
, mock_list_models
):
1447 mock_list_models
.return_value
= []
1448 with self
.assertRaises(Exception):
1449 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1450 self
.libjuju
.models_exist([])
1453 def test_model_names_not_existing(self
, mock_list_models
):
1454 mock_list_models
.return_value
= ["prometheus", "grafana"]
1455 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1456 self
.libjuju
.models_exist(["prometheus2", "grafana"])
1458 self
.assertFalse(exist
)
1459 self
.assertEqual(non_existing_models
, ["prometheus2"])
1461 def test_model_names_exist(self
, mock_list_models
):
1462 mock_list_models
.return_value
= ["prometheus", "grafana"]
1463 (exist
, non_existing_models
) = self
.loop
.run_until_complete(
1464 self
.libjuju
.models_exist(["prometheus", "grafana"])
1466 self
.assertTrue(exist
)
1467 self
.assertEqual(non_existing_models
, [])
1470 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1471 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1472 @asynctest.mock
.patch("juju.controller.Controller.list_offers")
1473 class ListOffers(LibjujuTestCase
):
1475 super(ListOffers
, self
).setUp()
1477 def test_disconnect_controller(
1480 mock_disconnect_controller
,
1481 mock_get_controller
,
1483 mock_get_controller
.return_value
= juju
.controller
.Controller()
1484 mock_list_offers
.side_effect
= Exception()
1485 with self
.assertRaises(Exception):
1486 self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1487 mock_disconnect_controller
.assert_called_once()
1489 def test_empty_list(
1492 mock_disconnect_controller
,
1493 mock_get_controller
,
1495 mock_get_controller
.return_value
= juju
.controller
.Controller()
1496 offer_results
= Mock()
1497 offer_results
.results
= []
1498 mock_list_offers
.return_value
= offer_results
1499 offers
= self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1500 self
.assertEqual(offers
, [])
1501 mock_disconnect_controller
.assert_called_once()
1503 def test_non_empty_list(
1506 mock_disconnect_controller
,
1507 mock_get_controller
,
1509 mock_get_controller
.return_value
= juju
.controller
.Controller()
1511 offer_results
= Mock()
1512 offer_results
.results
= [offer
]
1513 mock_list_offers
.return_value
= offer_results
1514 offers
= self
.loop
.run_until_complete(self
.libjuju
._list
_offers
("model"))
1515 self
.assertEqual(offers
, [offer
])
1516 mock_disconnect_controller
.assert_called_once()
1518 def test_matching_offer_name(
1521 mock_disconnect_controller
,
1522 mock_get_controller
,
1524 mock_get_controller
.return_value
= juju
.controller
.Controller()
1526 offer_1
.offer_name
= "offer1"
1528 offer_2
.offer_name
= "offer2"
1529 offer_results
= Mock()
1530 offer_results
.results
= [offer_1
, offer_2
]
1531 mock_list_offers
.return_value
= offer_results
1532 offers
= self
.loop
.run_until_complete(
1533 self
.libjuju
._list
_offers
("model", offer_name
="offer2")
1535 self
.assertEqual(offers
, [offer_2
])
1536 mock_disconnect_controller
.assert_called_once()
1538 def test_not_matching_offer_name(
1541 mock_disconnect_controller
,
1542 mock_get_controller
,
1544 mock_get_controller
.return_value
= juju
.controller
.Controller()
1546 offer_1
.offer_name
= "offer1"
1548 offer_2
.offer_name
= "offer2"
1549 offer_results
= Mock()
1550 offer_results
.results
= [offer_1
, offer_2
]
1551 mock_list_offers
.return_value
= offer_results
1552 offers
= self
.loop
.run_until_complete(
1553 self
.libjuju
._list
_offers
("model", offer_name
="offer3")
1555 self
.assertEqual(offers
, [])
1556 mock_disconnect_controller
.assert_called_once()
1559 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1560 @asynctest.mock
.patch("juju.controller.Controller.get_model")
1561 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1562 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1563 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._list_offers")
1564 @asynctest.mock
.patch("juju.model.Model.create_offer")
1565 class OfferTest(LibjujuTestCase
):
1567 super(OfferTest
, self
).setUp()
1573 mock_disconnect_controller
,
1574 mock_disconnect_model
,
1576 mock_get_controller
,
1578 controller
= juju
.controller
.Controller()
1579 model
= juju
.model
.Model()
1580 mock_get_controller
.return_value
= controller
1581 mock_get_model
.return_value
= model
1582 endpoint
= RelationEndpoint("model.app-name.0", "vca", "endpoint")
1583 self
.loop
.run_until_complete(self
.libjuju
.offer(endpoint
))
1584 mock_create_offer
.assert_called_with(
1585 "app-name:endpoint", offer_name
="app-name-endpoint"
1587 mock_disconnect_model
.assert_called_once_with(model
)
1588 mock_disconnect_controller
.assert_called_once_with(controller
)
1590 def test_offer_exception(
1594 mock_disconnect_controller
,
1595 mock_disconnect_model
,
1597 mock_get_controller
,
1599 controller
= juju
.controller
.Controller()
1600 model
= juju
.model
.Model()
1601 mock_get_controller
.return_value
= controller
1602 mock_get_model
.return_value
= model
1603 mock__list_offers
.return_value
= []
1604 endpoint
= RelationEndpoint("model.app-name.0", "vca", "endpoint")
1605 with self
.assertRaises(Exception):
1606 self
.loop
.run_until_complete(self
.libjuju
.offer(endpoint
))
1607 mock_create_offer
.assert_called_with(
1608 "app-name:endpoint", offer_name
="app-name-endpoint"
1610 mock_disconnect_model
.assert_called_once_with(model
)
1611 mock_disconnect_controller
.assert_called_once_with(controller
)
1614 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1615 @asynctest.mock
.patch("juju.controller.Controller.get_model")
1616 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
1617 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1618 @asynctest.mock
.patch("juju.model.Model.consume")
1619 class ConsumeTest(LibjujuTestCase
):
1621 self
.offer_url
= "admin/model.offer_name"
1622 super(ConsumeTest
, self
).setUp()
1623 self
.provider_libjuju
= self
.libjuju
1628 mock_disconnect_controller
,
1629 mock_disconnect_model
,
1631 mock_get_controller
,
1633 self_controller
= juju
.controller
.Controller()
1634 provider_controller
= juju
.controller
.Controller()
1635 mock_get_controller
.side_effect
= [self_controller
, provider_controller
]
1636 mock_get_model
.return_value
= juju
.model
.Model()
1638 self
.loop
.run_until_complete(
1639 self
.libjuju
.consume(
1641 Offer(self
.offer_url
, vca_id
="vca-id"),
1642 self
.provider_libjuju
,
1645 mock_consume
.assert_called_once_with(
1646 "admin/model.offer_name",
1647 application_alias
="offer_name-model-vca-id",
1648 controller
=provider_controller
,
1650 mock_disconnect_model
.assert_called_once()
1651 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1653 def test_parsing_error_exception(
1656 mock_disconnect_controller
,
1657 mock_disconnect_model
,
1659 mock_get_controller
,
1661 mock_get_controller
.return_value
= juju
.controller
.Controller()
1662 mock_get_model
.return_value
= juju
.model
.Model()
1663 mock_consume
.side_effect
= juju
.offerendpoints
.ParseError("")
1665 with self
.assertRaises(juju
.offerendpoints
.ParseError
):
1666 self
.loop
.run_until_complete(
1667 self
.libjuju
.consume(
1668 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1671 mock_consume
.assert_called_once()
1672 mock_disconnect_model
.assert_called_once()
1673 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1675 def test_juju_error_exception(
1678 mock_disconnect_controller
,
1679 mock_disconnect_model
,
1681 mock_get_controller
,
1683 mock_get_controller
.return_value
= juju
.controller
.Controller()
1684 mock_get_model
.return_value
= juju
.model
.Model()
1685 mock_consume
.side_effect
= juju
.errors
.JujuError("")
1687 with self
.assertRaises(juju
.errors
.JujuError
):
1688 self
.loop
.run_until_complete(
1689 self
.libjuju
.consume(
1690 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1693 mock_consume
.assert_called_once()
1694 mock_disconnect_model
.assert_called_once()
1695 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1697 def test_juju_api_error_exception(
1700 mock_disconnect_controller
,
1701 mock_disconnect_model
,
1703 mock_get_controller
,
1705 mock_get_controller
.return_value
= juju
.controller
.Controller()
1706 mock_get_model
.return_value
= juju
.model
.Model()
1707 mock_consume
.side_effect
= juju
.errors
.JujuAPIError(
1708 {"error": "", "response": "", "request-id": ""}
1711 with self
.assertRaises(juju
.errors
.JujuAPIError
):
1712 self
.loop
.run_until_complete(
1713 self
.libjuju
.consume(
1714 "model_name", Offer(self
.offer_url
), self
.provider_libjuju
1717 mock_consume
.assert_called_once()
1718 mock_disconnect_model
.assert_called_once()
1719 self
.assertEqual(mock_disconnect_controller
.call_count
, 2)
1722 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_k8s_cloud_credential")
1723 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.add_cloud")
1724 class AddK8sTest(LibjujuTestCase
):
1726 super(AddK8sTest
, self
).setUp()
1728 rbac_id
= generate_rbac_id()
1730 client_cert_data
= "cert"
1731 configuration
= kubernetes
.client
.configuration
.Configuration()
1732 storage_class
= "storage_class"
1733 credential_name
= name
1735 self
._add
_k
8s
_args
= {
1739 "client_cert_data": client_cert_data
,
1740 "configuration": configuration
,
1741 "storage_class": storage_class
,
1742 "credential_name": credential_name
,
1745 def test_add_k8s(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1746 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1747 mock_add_cloud
.assert_called_once()
1748 mock_get_k8s_cloud_credential
.assert_called_once()
1750 def test_add_k8s_exception(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1751 mock_add_cloud
.side_effect
= Exception()
1752 with self
.assertRaises(Exception):
1753 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1754 mock_add_cloud
.assert_called_once()
1755 mock_get_k8s_cloud_credential
.assert_called_once()
1757 def test_add_k8s_missing_name(self
, mock_add_cloud
, mock_get_k8s_cloud_credential
):
1758 self
._add
_k
8s
_args
["name"] = ""
1759 with self
.assertRaises(Exception):
1760 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1761 mock_add_cloud
.assert_not_called()
1763 def test_add_k8s_missing_storage_name(
1764 self
, mock_add_cloud
, mock_get_k8s_cloud_credential
1766 self
._add
_k
8s
_args
["storage_class"] = ""
1767 with self
.assertRaises(Exception):
1768 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1769 mock_add_cloud
.assert_not_called()
1771 def test_add_k8s_missing_configuration_keys(
1772 self
, mock_add_cloud
, mock_get_k8s_cloud_credential
1774 self
._add
_k
8s
_args
["configuration"] = None
1775 with self
.assertRaises(Exception):
1776 self
.loop
.run_until_complete(self
.libjuju
.add_k8s(**self
._add
_k
8s
_args
))
1777 mock_add_cloud
.assert_not_called()
1780 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1781 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1782 @asynctest.mock
.patch("juju.controller.Controller.add_cloud")
1783 @asynctest.mock
.patch("juju.controller.Controller.add_credential")
1784 class AddCloudTest(LibjujuTestCase
):
1786 super(AddCloudTest
, self
).setUp()
1787 self
.cloud
= juju
.client
.client
.Cloud()
1788 self
.credential
= juju
.client
.client
.CloudCredential()
1790 def test_add_cloud_with_credential(
1792 mock_add_credential
,
1794 mock_disconnect_controller
,
1795 mock_get_controller
,
1797 mock_get_controller
.return_value
= juju
.controller
.Controller()
1799 cloud
= self
.loop
.run_until_complete(
1800 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1802 self
.assertEqual(cloud
, self
.cloud
)
1803 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1804 mock_add_credential
.assert_called_once_with(
1805 "cloud", credential
=self
.credential
, cloud
="cloud"
1807 mock_disconnect_controller
.assert_called_once()
1809 def test_add_cloud_no_credential(
1811 mock_add_credential
,
1813 mock_disconnect_controller
,
1814 mock_get_controller
,
1816 mock_get_controller
.return_value
= juju
.controller
.Controller()
1818 cloud
= self
.loop
.run_until_complete(
1819 self
.libjuju
.add_cloud("cloud", self
.cloud
)
1821 self
.assertEqual(cloud
, self
.cloud
)
1822 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1823 mock_add_credential
.assert_not_called()
1824 mock_disconnect_controller
.assert_called_once()
1826 def test_add_cloud_exception(
1828 mock_add_credential
,
1830 mock_disconnect_controller
,
1831 mock_get_controller
,
1833 mock_get_controller
.return_value
= juju
.controller
.Controller()
1834 mock_add_cloud
.side_effect
= Exception()
1835 with self
.assertRaises(Exception):
1836 self
.loop
.run_until_complete(
1837 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1840 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1841 mock_add_credential
.assert_not_called()
1842 mock_disconnect_controller
.assert_called_once()
1844 def test_add_credential_exception(
1846 mock_add_credential
,
1848 mock_disconnect_controller
,
1849 mock_get_controller
,
1851 mock_get_controller
.return_value
= juju
.controller
.Controller()
1852 mock_add_credential
.side_effect
= Exception()
1853 with self
.assertRaises(Exception):
1854 self
.loop
.run_until_complete(
1855 self
.libjuju
.add_cloud("cloud", self
.cloud
, credential
=self
.credential
)
1858 mock_add_cloud
.assert_called_once_with("cloud", self
.cloud
)
1859 mock_add_credential
.assert_called_once_with(
1860 "cloud", credential
=self
.credential
, cloud
="cloud"
1862 mock_disconnect_controller
.assert_called_once()
1865 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
1866 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
1867 @asynctest.mock
.patch("juju.controller.Controller.remove_cloud")
1868 class RemoveCloudTest(LibjujuTestCase
):
1870 super(RemoveCloudTest
, self
).setUp()
1872 def test_remove_cloud(
1875 mock_disconnect_controller
,
1876 mock_get_controller
,
1878 mock_get_controller
.return_value
= juju
.controller
.Controller()
1880 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1881 mock_remove_cloud
.assert_called_once_with("cloud")
1882 mock_disconnect_controller
.assert_called_once()
1884 def test_remove_cloud_exception(
1887 mock_disconnect_controller
,
1888 mock_get_controller
,
1890 mock_get_controller
.return_value
= juju
.controller
.Controller()
1891 mock_remove_cloud
.side_effect
= Exception()
1893 with self
.assertRaises(Exception):
1894 self
.loop
.run_until_complete(self
.libjuju
.remove_cloud("cloud"))
1895 mock_remove_cloud
.assert_called_once_with("cloud")
1896 mock_disconnect_controller
.assert_called_once()
1899 @asynctest.mock
.patch("kubernetes.client.configuration.Configuration")
1900 class GetK8sCloudCredentials(LibjujuTestCase
):
1902 super(GetK8sCloudCredentials
, self
).setUp()
1903 self
.cert_data
= "cert"
1904 self
.token
= "token"
1906 @asynctest.mock
.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
1907 def test_not_supported(self
, mock_exception
, mock_configuration
):
1908 mock_configuration
.username
= ""
1909 mock_configuration
.password
= ""
1910 mock_configuration
.ssl_ca_cert
= None
1911 mock_configuration
.cert_file
= None
1912 mock_configuration
.key_file
= None
1913 exception_raised
= False
1915 self
.cert_data
= None
1917 _
= self
.libjuju
.get_k8s_cloud_credential(
1922 except JujuInvalidK8sConfiguration
as e
:
1923 exception_raised
= True
1926 "authentication method not supported",
1928 self
.assertTrue(exception_raised
)
1930 def test_user_pass(self
, mock_configuration
):
1931 mock_configuration
.username
= "admin"
1932 mock_configuration
.password
= "admin"
1933 mock_configuration
.ssl_ca_cert
= None
1934 mock_configuration
.cert_file
= None
1935 mock_configuration
.key_file
= None
1937 self
.cert_data
= None
1938 credential
= self
.libjuju
.get_k8s_cloud_credential(
1945 juju
.client
._definitions
.CloudCredential(
1946 attrs
={"username": "admin", "password": "admin"}, auth_type
="userpass"
1950 def test_user_pass_with_cert(self
, mock_configuration
):
1951 mock_configuration
.username
= "admin"
1952 mock_configuration
.password
= "admin"
1953 mock_configuration
.ssl_ca_cert
= None
1954 mock_configuration
.cert_file
= None
1955 mock_configuration
.key_file
= None
1957 credential
= self
.libjuju
.get_k8s_cloud_credential(
1964 juju
.client
._definitions
.CloudCredential(
1966 "ClientCertificateData": self
.cert_data
,
1967 "username": "admin",
1968 "password": "admin",
1970 auth_type
="userpasswithcert",
1974 def test_user_no_pass(self
, mock_configuration
):
1975 mock_configuration
.username
= "admin"
1976 mock_configuration
.password
= ""
1977 mock_configuration
.ssl_ca_cert
= None
1978 mock_configuration
.cert_file
= None
1979 mock_configuration
.key_file
= None
1981 self
.cert_data
= None
1982 with patch
.object(self
.libjuju
.log
, "debug") as mock_debug
:
1983 credential
= self
.libjuju
.get_k8s_cloud_credential(
1990 juju
.client
._definitions
.CloudCredential(
1991 attrs
={"username": "admin", "password": ""}, auth_type
="userpass"
1994 mock_debug
.assert_called_once_with(
1995 "credential for user admin has empty password"
1998 def test_cert(self
, mock_configuration
):
1999 mock_configuration
.username
= ""
2000 mock_configuration
.password
= ""
2001 mock_configuration
.api_key
= {"authorization": "Bearer Token"}
2002 ssl_ca_cert
= tempfile
.NamedTemporaryFile()
2003 with
open(ssl_ca_cert
.name
, "w") as ssl_ca_cert_file
:
2004 ssl_ca_cert_file
.write("cacert")
2005 mock_configuration
.ssl_ca_cert
= ssl_ca_cert
.name
2006 mock_configuration
.cert_file
= None
2007 mock_configuration
.key_file
= None
2008 credential
= self
.libjuju
.get_k8s_cloud_credential(
2015 juju
.client
._definitions
.CloudCredential(
2016 attrs
={"ClientCertificateData": self
.cert_data
, "Token": self
.token
},
2017 auth_type
="certificate",
2021 # TODO: Fix this test when oauth authentication is supported
2022 # def test_oauth2(self, mock_configuration):
2023 # mock_configuration.username = ""
2024 # mock_configuration.password = ""
2025 # mock_configuration.api_key = {"authorization": "Bearer Token"}
2026 # key = tempfile.NamedTemporaryFile()
2027 # with open(key.name, "w") as key_file:
2028 # key_file.write("key")
2029 # mock_configuration.ssl_ca_cert = None
2030 # mock_configuration.cert_file = None
2031 # mock_configuration.key_file = key.name
2032 # credential = self.libjuju.get_k8s_cloud_credential(
2033 # mock_configuration,
2039 # juju.client._definitions.CloudCredential(
2040 # attrs={"ClientKeyData": "key", "Token": "Token"},
2041 # auth_type="oauth2",
2045 # @asynctest.mock.patch("n2vc.exceptions.JujuInvalidK8sConfiguration")
2046 # def test_oauth2_missing_token(self, mock_exception, mock_configuration):
2047 # mock_configuration.username = ""
2048 # mock_configuration.password = ""
2049 # key = tempfile.NamedTemporaryFile()
2050 # with open(key.name, "w") as key_file:
2051 # key_file.write("key")
2052 # mock_configuration.ssl_ca_cert = None
2053 # mock_configuration.cert_file = None
2054 # mock_configuration.key_file = key.name
2055 # exception_raised = False
2057 # _ = self.libjuju.get_k8s_cloud_credential(
2058 # mock_configuration,
2062 # except JujuInvalidK8sConfiguration as e:
2063 # exception_raised = True
2066 # "missing token for auth type oauth2",
2068 # self.assertTrue(exception_raised)
2070 def test_exception_cannot_set_token_and_userpass(self
, mock_configuration
):
2071 mock_configuration
.username
= "admin"
2072 mock_configuration
.password
= "pass"
2073 mock_configuration
.api_key
= {"authorization": "No_bearer_token"}
2074 mock_configuration
.ssl_ca_cert
= None
2075 mock_configuration
.cert_file
= None
2076 mock_configuration
.key_file
= None
2077 exception_raised
= False
2079 _
= self
.libjuju
.get_k8s_cloud_credential(
2084 except JujuInvalidK8sConfiguration
as e
:
2085 exception_raised
= True
2088 "Cannot set both token and user/pass",
2090 self
.assertTrue(exception_raised
)
2093 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2094 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2095 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2096 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2097 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2098 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for_model")
2099 class ScaleApplicationTest(LibjujuTestCase
):
2101 super(ScaleApplicationTest
, self
).setUp()
2103 @asynctest.mock
.patch("asyncio.sleep")
2104 def test_scale_application(
2107 mock_wait_for_model
,
2108 mock_disconnect_controller
,
2109 mock_disconnect_model
,
2110 mock_get_application
,
2112 mock_get_controller
,
2114 mock_get_model
.return_value
= juju
.model
.Model()
2115 mock_get_application
.return_value
= FakeApplication()
2116 self
.loop
.run_until_complete(self
.libjuju
.scale_application("model", "app", 2))
2117 mock_wait_for_model
.assert_called_once()
2118 mock_disconnect_controller
.assert_called_once()
2119 mock_disconnect_model
.assert_called_once()
2121 def test_no_application(
2124 mock_disconnect_controller
,
2125 mock_disconnect_model
,
2126 mock_get_application
,
2128 mock_get_controller
,
2130 mock_get_application
.return_value
= None
2131 mock_get_model
.return_value
= juju
.model
.Model()
2132 with self
.assertRaises(JujuApplicationNotFound
):
2133 self
.loop
.run_until_complete(
2134 self
.libjuju
.scale_application("model", "app", 2)
2136 mock_disconnect_controller
.assert_called()
2137 mock_disconnect_model
.assert_called()
2142 mock_disconnect_controller
,
2143 mock_disconnect_model
,
2144 mock_get_application
,
2146 mock_get_controller
,
2148 mock_get_model
.return_value
= None
2149 mock_get_application
.return_value
= FakeApplication()
2150 with self
.assertRaises(Exception):
2151 self
.loop
.run_until_complete(
2152 self
.libjuju
.scale_application("model", "app", 2, total_timeout
=0)
2154 mock_disconnect_controller
.assert_called_once()
2157 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2158 class GetUnitNumberTest(LibjujuTestCase
):
2160 super(GetUnitNumberTest
, self
).setUp()
2162 def test_successful_get_unit_number(
2164 mock_get_applications
,
2166 mock_get_applications
.return_value
= FakeApplication()
2167 model
= juju
.model
.Model()
2168 result
= self
.libjuju
._get
_application
_count
(model
, "app")
2169 self
.assertEqual(result
, 2)
2171 def test_non_existing_application(
2173 mock_get_applications
,
2175 mock_get_applications
.return_value
= None
2176 model
= juju
.model
.Model()
2177 result
= self
.libjuju
._get
_application
_count
(model
, "app")
2178 self
.assertEqual(result
, None)
2181 @asynctest.mock
.patch("juju.model.Model.machines", new_callable
=asynctest
.PropertyMock
)
2182 class GetMachineInfoTest(LibjujuTestCase
):
2184 super(GetMachineInfoTest
, self
).setUp()
2186 def test_successful(
2190 machine_id
= "existing_machine"
2191 model
= juju
.model
.Model()
2192 mock_machines
.return_value
= {"existing_machine": FakeManualMachine()}
2193 machine
, series
= self
.libjuju
._get
_machine
_info
(
2194 machine_id
=machine_id
,
2197 self
.assertIsNotNone(machine
, series
)
2203 machine_id
= "not_existing_machine"
2204 machine
= series
= None
2205 model
= juju
.model
.Model()
2206 mock_machines
.return_value
= {"existing_machine": FakeManualMachine()}
2207 with self
.assertRaises(JujuMachineNotFound
):
2208 machine
, series
= self
.libjuju
._get
_machine
_info
(
2209 machine_id
=machine_id
,
2212 self
.assertIsNone(machine
, series
)
2215 class GetUnitTest(LibjujuTestCase
):
2217 super(GetUnitTest
, self
).setUp()
2219 def test_successful(self
):
2220 result
= self
.libjuju
._get
_unit
(FakeApplication(), "existing_machine_id")
2221 self
.assertIsInstance(result
, FakeUnit
)
2223 def test_return_none(self
):
2224 result
= self
.libjuju
._get
_unit
(FakeApplication(), "not_existing_machine_id")
2225 self
.assertIsNone(result
)
2228 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2229 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2230 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2231 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2232 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2233 class CheckApplicationExists(LibjujuTestCase
):
2235 super(CheckApplicationExists
, self
).setUp()
2237 def test_successful(
2239 mock_get_application
,
2240 mock_disconnect_controller
,
2241 mock_disconnect_model
,
2243 mock_get_controller
,
2245 mock_get_model
.return_value
= juju
.model
.Model()
2246 mock_get_application
.return_value
= FakeApplication()
2247 result
= self
.loop
.run_until_complete(
2248 self
.libjuju
.check_application_exists(
2253 self
.assertEqual(result
, True)
2255 mock_get_application
.assert_called_once()
2256 mock_get_controller
.assert_called_once()
2257 mock_get_model
.assert_called_once()
2258 mock_disconnect_controller
.assert_called_once()
2259 mock_disconnect_model
.assert_called_once()
2261 def test_no_application(
2263 mock_get_application
,
2264 mock_disconnect_controller
,
2265 mock_disconnect_model
,
2267 mock_get_controller
,
2269 mock_get_model
.return_value
= juju
.model
.Model()
2270 mock_get_application
.return_value
= None
2271 result
= self
.loop
.run_until_complete(
2272 self
.libjuju
.check_application_exists(
2277 self
.assertEqual(result
, False)
2279 mock_get_application
.assert_called_once()
2280 mock_get_controller
.assert_called_once()
2281 mock_get_model
.assert_called_once()
2282 mock_disconnect_controller
.assert_called_once()
2283 mock_disconnect_model
.assert_called_once()
2286 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2287 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2288 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2289 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2290 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2291 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_machine_info")
2292 class AddUnitTest(LibjujuTestCase
):
2294 super(AddUnitTest
, self
).setUp()
2296 @asynctest.mock
.patch("n2vc.juju_watcher.JujuModelWatcher.wait_for")
2297 @asynctest.mock
.patch("asyncio.sleep")
2298 def test_successful(
2302 mock_get_machine_info
,
2303 mock_get_application
,
2304 mock_disconnect_controller
,
2305 mock_disconnect_model
,
2307 mock_get_controller
,
2309 mock_get_model
.return_value
= juju
.model
.Model()
2310 mock_get_application
.return_value
= FakeApplication()
2311 mock_get_machine_info
.return_value
= FakeMachine(), "series"
2312 self
.loop
.run_until_complete(
2313 self
.libjuju
.add_unit(
2320 mock_wait_for
.assert_called_once()
2321 mock_get_application
.assert_called_once()
2322 mock_get_controller
.assert_called_once()
2323 mock_get_model
.assert_called_once()
2324 mock_disconnect_controller
.assert_called_once()
2325 mock_disconnect_model
.assert_called_once()
2329 mock_get_machine_info
,
2330 mock_get_application
,
2331 mock_disconnect_controller
,
2332 mock_disconnect_model
,
2334 mock_get_controller
,
2336 mock_get_model
.return_value
= juju
.model
.Model()
2337 mock_get_application
.return_value
= None
2338 with self
.assertRaises(JujuApplicationNotFound
):
2339 self
.loop
.run_until_complete(
2340 self
.libjuju
.add_unit(
2347 mock_get_application
.assert_called_once()
2348 mock_get_controller
.assert_called_once()
2349 mock_get_model
.assert_called_once()
2350 mock_disconnect_controller
.assert_called_once()
2351 mock_disconnect_model
.assert_called_once()
2353 def test_no_machine(
2355 mock_get_machine_info
,
2356 mock_get_application
,
2357 mock_disconnect_controller
,
2358 mock_disconnect_model
,
2360 mock_get_controller
,
2362 mock_get_model
.return_value
= juju
.model
.Model()
2363 mock_get_application
.return_value
= FakeApplication()
2364 mock_get_machine_info
.side_effect
= JujuMachineNotFound()
2365 with self
.assertRaises(JujuMachineNotFound
):
2366 self
.loop
.run_until_complete(
2367 self
.libjuju
.add_unit(
2374 mock_get_application
.assert_called_once()
2375 mock_get_controller
.assert_called_once()
2376 mock_get_model
.assert_called_once()
2377 mock_disconnect_controller
.assert_called_once()
2378 mock_disconnect_model
.assert_called_once()
2381 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_controller")
2382 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.get_model")
2383 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_model")
2384 @asynctest.mock
.patch("n2vc.libjuju.Libjuju.disconnect_controller")
2385 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_application")
2386 @asynctest.mock
.patch("n2vc.libjuju.Libjuju._get_unit")
2387 class DestroyUnitTest(LibjujuTestCase
):
2389 super(DestroyUnitTest
, self
).setUp()
2391 @asynctest.mock
.patch("asyncio.sleep")
2392 def test_successful(
2396 mock_get_application
,
2397 mock_disconnect_controller
,
2398 mock_disconnect_model
,
2400 mock_get_controller
,
2402 mock_get_model
.return_value
= juju
.model
.Model()
2403 mock_get_application
.return_value
= FakeApplication()
2405 self
.loop
.run_until_complete(
2406 self
.libjuju
.destroy_unit("app", "model", "machine", 0)
2409 mock_get_unit
.assert_called()
2410 mock_get_application
.assert_called_once()
2411 mock_get_controller
.assert_called_once()
2412 mock_get_model
.assert_called_once()
2413 mock_disconnect_controller
.assert_called_once()
2414 mock_disconnect_model
.assert_called_once()
2419 mock_get_application
,
2420 mock_disconnect_controller
,
2421 mock_disconnect_model
,
2423 mock_get_controller
,
2425 mock_get_model
.return_value
= juju
.model
.Model()
2426 mock_get_application
.return_value
= None
2428 with self
.assertRaises(JujuApplicationNotFound
):
2429 self
.loop
.run_until_complete(
2430 self
.libjuju
.destroy_unit("app", "model", "machine")
2433 mock_get_application
.assert_called_once()
2434 mock_get_controller
.assert_called_once()
2435 mock_get_model
.assert_called_once()
2436 mock_disconnect_controller
.assert_called_once()
2437 mock_disconnect_model
.assert_called_once()
2442 mock_get_application
,
2443 mock_disconnect_controller
,
2444 mock_disconnect_model
,
2446 mock_get_controller
,
2448 mock_get_model
.return_value
= juju
.model
.Model()
2449 mock_get_application
.return_value
= FakeApplication()
2450 mock_get_unit
.return_value
= None
2452 with self
.assertRaises(JujuError
):
2453 self
.loop
.run_until_complete(
2454 self
.libjuju
.destroy_unit("app", "model", "machine")
2457 mock_get_unit
.assert_called_once()
2458 mock_get_application
.assert_called_once()
2459 mock_get_controller
.assert_called_once()
2460 mock_get_model
.assert_called_once()
2461 mock_disconnect_controller
.assert_called_once()
2462 mock_disconnect_model
.assert_called_once()