From 5b802c9d0ee35b529cdac7e6db237aab2fe409d8 Mon Sep 17 00:00:00 2001 From: David Garcia Date: Wed, 11 Nov 2020 16:56:06 +0100 Subject: [PATCH] Fix minor bug in configure application Variable model was unassigned if the connection to the controller was failing Change-Id: I14764079f505c46ff7c9af7adec8079b43eca14e Signed-off-by: David Garcia --- n2vc/libjuju.py | 6 +- n2vc/tests/unit/test_libjuju.py | 206 +++++++++++++++++++++++++++----- 2 files changed, 178 insertions(+), 34 deletions(-) diff --git a/n2vc/libjuju.py b/n2vc/libjuju.py index aa7afa1..5a3ddbb 100644 --- a/n2vc/libjuju.py +++ b/n2vc/libjuju.py @@ -953,15 +953,17 @@ class Libjuju: self.log.debug("Configuring application {}".format(application_name)) if config: + controller = await self.get_controller() + model = None try: - controller = await self.get_controller() model = await self.get_model(controller, model_name) application = self._get_application( model, application_name=application_name, ) await application.set_config(config) finally: - await self.disconnect_model(model) + if model: + await self.disconnect_model(model) await self.disconnect_controller(controller) def _get_api_endpoints_db(self) -> [str]: diff --git a/n2vc/tests/unit/test_libjuju.py b/n2vc/tests/unit/test_libjuju.py index 454b87f..7bea6b3 100644 --- a/n2vc/tests/unit/test_libjuju.py +++ b/n2vc/tests/unit/test_libjuju.py @@ -272,7 +272,8 @@ class GetModelTest(LibjujuTestCase): super(GetModelTest, self).setUp() def test_get_model( - self, mock_get_model, + self, + mock_get_model, ): mock_get_model.return_value = juju.model.Model() model = self.loop.run_until_complete( @@ -288,7 +289,9 @@ class ModelExistsTest(LibjujuTestCase): super(ModelExistsTest, self).setUp() async def test_existing_model( - self, mock_list_models, mock_get_controller, + self, + mock_list_models, + mock_get_controller, ): mock_list_models.return_value = ["existing_model"] self.assertTrue( @@ -299,7 +302,10 @@ class ModelExistsTest(LibjujuTestCase): @asynctest.mock.patch("n2vc.libjuju.Libjuju.disconnect_controller") async def test_no_controller( - self, mock_disconnect_controller, mock_list_models, mock_get_controller, + self, + mock_disconnect_controller, + mock_list_models, + mock_get_controller, ): mock_list_models.return_value = ["existing_model"] mock_get_controller.return_value = juju.controller.Controller() @@ -307,7 +313,9 @@ class ModelExistsTest(LibjujuTestCase): mock_disconnect_controller.assert_called_once() async def test_non_existing_model( - self, mock_list_models, mock_get_controller, + self, + mock_list_models, + mock_get_controller, ): mock_list_models.return_value = ["existing_model"] self.assertFalse( @@ -551,7 +559,12 @@ class DeployCharmTest(LibjujuTestCase): application = None with self.assertRaises(JujuApplicationExists): application = self.loop.run_until_complete( - self.libjuju.deploy_charm("existing_app", "path", "model", "machine",) + self.libjuju.deploy_charm( + "existing_app", + "path", + "model", + "machine", + ) ) self.assertIsNone(application) @@ -575,7 +588,12 @@ class DeployCharmTest(LibjujuTestCase): application = None with self.assertRaises(JujuMachineNotFound): application = self.loop.run_until_complete( - self.libjuju.deploy_charm("app", "path", "model", "machine",) + self.libjuju.deploy_charm( + "app", + "path", + "model", + "machine", + ) ) self.assertIsNone(application) @@ -601,7 +619,11 @@ class DeployCharmTest(LibjujuTestCase): mock_deploy.return_value = FakeApplication() application = self.loop.run_until_complete( self.libjuju.deploy_charm( - "app", "path", "model", "existing_machine", num_units=2, + "app", + "path", + "model", + "existing_machine", + num_units=2, ) ) @@ -651,7 +673,8 @@ class GetApplicationTest(LibjujuTestCase): super(GetApplicationTest, self).setUp() def test_existing_application( - self, mock_applications, + self, + mock_applications, ): mock_applications.return_value = {"existing_app": "exists"} model = juju.model.Model() @@ -659,7 +682,8 @@ class GetApplicationTest(LibjujuTestCase): self.assertEqual(result, "exists") def test_non_existing_application( - self, mock_applications, + self, + mock_applications, ): mock_applications.return_value = {"existing_app": "exists"} model = juju.model.Model() @@ -696,7 +720,11 @@ class ExecuteActionTest(LibjujuTestCase): status = None with self.assertRaises(JujuApplicationNotFound): output, status = self.loop.run_until_complete( - self.libjuju.execute_action("app", "model", "action",) + self.libjuju.execute_action( + "app", + "model", + "action", + ) ) self.assertIsNone(output) self.assertIsNone(status) @@ -722,7 +750,11 @@ class ExecuteActionTest(LibjujuTestCase): status = None with self.assertRaises(JujuActionNotFound): output, status = self.loop.run_until_complete( - self.libjuju.execute_action("app", "model", "action",) + self.libjuju.execute_action( + "app", + "model", + "action", + ) ) self.assertIsNone(output) self.assertIsNone(status) @@ -752,7 +784,11 @@ class ExecuteActionTest(LibjujuTestCase): status = None with self.assertRaises(JujuLeaderUnitNotFound): output, status = self.loop.run_until_complete( - self.libjuju.execute_action("app", "model", "action",) + self.libjuju.execute_action( + "app", + "model", + "action", + ) ) self.assertIsNone(output) self.assertIsNone(status) @@ -925,7 +961,11 @@ class AddRelationTest(LibjujuTestCase): mock_add_relation.side_effect = JujuAPIError(result) self.loop.run_until_complete( - self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",) + self.libjuju.add_relation( + "model", + "app1:relation1", + "app2:relation2", + ) ) mock_warning.assert_called_with("Relation not found: not found") @@ -949,7 +989,11 @@ class AddRelationTest(LibjujuTestCase): mock_add_relation.side_effect = JujuAPIError(result) self.loop.run_until_complete( - self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",) + self.libjuju.add_relation( + "model", + "app1:relation1", + "app2:relation2", + ) ) mock_warning.assert_called_with("Relation already exists: already exists") @@ -970,7 +1014,11 @@ class AddRelationTest(LibjujuTestCase): with self.assertRaises(JujuAPIError): self.loop.run_until_complete( - self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",) + self.libjuju.add_relation( + "model", + "app1:relation1", + "app2:relation2", + ) ) mock_disconnect_controller.assert_called_once() @@ -987,7 +1035,11 @@ class AddRelationTest(LibjujuTestCase): mock_get_model.return_value = juju.model.Model() self.loop.run_until_complete( - self.libjuju.add_relation("model", "app1:relation1", "app2:relation2",) + self.libjuju.add_relation( + "model", + "app1:relation1", + "app2:relation2", + ) ) mock_add_relation.assert_called_with("app1:relation1", "app2:relation2") @@ -1005,7 +1057,11 @@ class AddRelationTest(LibjujuTestCase): mock_get_model.return_value = juju.model.Model() self.loop.run_until_complete( - self.libjuju.add_relation("model", "app1:relation1", "saas_name",) + self.libjuju.add_relation( + "model", + "app1:relation1", + "saas_name", + ) ) mock_add_relation.assert_called_with("app1:relation1", "saas_name") @@ -1070,7 +1126,11 @@ class ConfigureApplicationTest(LibjujuTestCase): mock_get_application.return_value = FakeApplication() self.loop.run_until_complete( - self.libjuju.configure_application("model", "app", {"config"},) + self.libjuju.configure_application( + "model", + "app", + {"config"}, + ) ) mock_get_application.assert_called_once() mock_disconnect_controller.assert_called_once() @@ -1089,11 +1149,64 @@ class ConfigureApplicationTest(LibjujuTestCase): with self.assertRaises(Exception): self.loop.run_until_complete( - self.libjuju.configure_application("model", "app", {"config"},) + self.libjuju.configure_application( + "model", + "app", + {"config"}, + ) ) mock_disconnect_controller.assert_called_once() mock_disconnect_model.assert_called_once() + def test_controller_exception( + self, + mock_get_application, + mock_disconnect_controller, + mock_disconnect_model, + mock_get_model, + mock_get_controller, + ): + + result = {"error": "not found", "response": "response", "request-id": 1} + + mock_get_controller.side_effect = JujuAPIError(result) + + with self.assertRaises(JujuAPIError): + self.loop.run_until_complete( + self.libjuju.configure_application( + "model", + "app", + {"config"}, + ) + ) + mock_get_model.assert_not_called() + mock_disconnect_controller.assert_not_called() + mock_disconnect_model.assert_not_called() + + def test_get_model_exception( + self, + mock_get_application, + mock_disconnect_controller, + mock_disconnect_model, + mock_get_model, + mock_get_controller, + ): + + result = {"error": "not found", "response": "response", "request-id": 1} + mock_get_model.side_effect = JujuAPIError(result) + + with self.assertRaises(JujuAPIError): + self.loop.run_until_complete( + self.libjuju.configure_application( + "model", + "app", + {"config"}, + ) + ) + mock_get_model.assert_called_once() + mock_disconnect_controller.assert_called_once() + mock_disconnect_model.assert_not_called() + # TODO _get_api_endpoints_db test case # TODO _update_api_endpoints_db test case @@ -1108,7 +1221,10 @@ class ListModelsTest(LibjujuTestCase): super(ListModelsTest, self).setUp() def test_containing( - self, mock_list_models, mock_disconnect_controller, mock_get_controller, + self, + mock_list_models, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_models.return_value = ["existingmodel"] @@ -1118,7 +1234,10 @@ class ListModelsTest(LibjujuTestCase): self.assertEquals(models, ["existingmodel"]) def test_not_containing( - self, mock_list_models, mock_disconnect_controller, mock_get_controller, + self, + mock_list_models, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_models.return_value = ["existingmodel", "model"] @@ -1128,7 +1247,10 @@ class ListModelsTest(LibjujuTestCase): self.assertEquals(models, []) def test_no_contains_arg( - self, mock_list_models, mock_disconnect_controller, mock_get_controller, + self, + mock_list_models, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_models.return_value = ["existingmodel", "model"] @@ -1180,7 +1302,10 @@ class ListOffers(LibjujuTestCase): super(ListOffers, self).setUp() def test_disconnect_controller( - self, mock_list_offers, mock_disconnect_controller, mock_get_controller, + self, + mock_list_offers, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_offers.side_effect = Exception() @@ -1189,7 +1314,10 @@ class ListOffers(LibjujuTestCase): mock_disconnect_controller.assert_called_once() def test_empty_list( - self, mock_list_offers, mock_disconnect_controller, mock_get_controller, + self, + mock_list_offers, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_offers.return_value = [] @@ -1198,7 +1326,10 @@ class ListOffers(LibjujuTestCase): mock_disconnect_controller.assert_called_once() def test_non_empty_list( - self, mock_list_offers, mock_disconnect_controller, mock_get_controller, + self, + mock_list_offers, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_list_offers.return_value = ["offer"] @@ -1435,7 +1566,10 @@ class RemoveCloudTest(LibjujuTestCase): super(RemoveCloudTest, self).setUp() def test_remove_cloud( - self, mock_remove_cloud, mock_disconnect_controller, mock_get_controller, + self, + mock_remove_cloud, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() @@ -1444,7 +1578,10 @@ class RemoveCloudTest(LibjujuTestCase): mock_disconnect_controller.assert_called_once() def test_remove_cloud_exception( - self, mock_remove_cloud, mock_disconnect_controller, mock_get_controller, + self, + mock_remove_cloud, + mock_disconnect_controller, + mock_get_controller, ): mock_get_controller.return_value = juju.controller.Controller() mock_remove_cloud.side_effect = Exception() @@ -1473,7 +1610,8 @@ class GetK8sCloudCredentials(LibjujuTestCase): except JujuInvalidK8sConfiguration as e: exception_raised = True self.assertEqual( - e.message, "authentication method not supported", + e.message, + "authentication method not supported", ) self.assertTrue(exception_raised) @@ -1564,7 +1702,8 @@ class GetK8sCloudCredentials(LibjujuTestCase): self.assertEqual( credential, juju.client._definitions.CloudCredential( - attrs={"ClientKeyData": "key", "Token": "Token"}, auth_type="oauth2", + attrs={"ClientKeyData": "key", "Token": "Token"}, + auth_type="oauth2", ), ) @@ -1584,7 +1723,8 @@ class GetK8sCloudCredentials(LibjujuTestCase): except JujuInvalidK8sConfiguration as e: exception_raised = True self.assertEqual( - e.message, "missing token for auth type oauth2", + e.message, + "missing token for auth type oauth2", ) self.assertTrue(exception_raised) @@ -1601,7 +1741,8 @@ class GetK8sCloudCredentials(LibjujuTestCase): except JujuInvalidK8sConfiguration as e: exception_raised = True self.assertEqual( - e.message, "unknown format of api_key", + e.message, + "unknown format of api_key", ) self.assertTrue(exception_raised) @@ -1618,6 +1759,7 @@ class GetK8sCloudCredentials(LibjujuTestCase): except JujuInvalidK8sConfiguration as e: exception_raised = True self.assertEqual( - e.message, "Cannot set both token and user/pass", + e.message, + "Cannot set both token and user/pass", ) self.assertTrue(exception_raised) -- 2.25.1