diff --git a/unit_tests/test_zaza_charm_lifecycle_utils.py b/unit_tests/test_zaza_charm_lifecycle_utils.py index edf3647..0bd1594 100644 --- a/unit_tests/test_zaza_charm_lifecycle_utils.py +++ b/unit_tests/test_zaza_charm_lifecycle_utils.py @@ -1,6 +1,4 @@ -import os -import tempfile -import yaml +import mock import zaza.charm_lifecycle.utils as lc_utils import unit_tests.utils as ut_utils @@ -9,12 +7,22 @@ import unit_tests.utils as ut_utils class TestCharmLifecycleUtils(ut_utils.BaseTestCase): def test_get_charm_config(self): - f = tempfile.NamedTemporaryFile(delete=False, mode='w') - f.write(yaml.dump({'test_config': 'someconfig'})) - f.close() - charm_config = lc_utils.get_charm_config(yaml_file=f.name) - os.unlink(f.name) - self.assertEqual(charm_config, {'test_config': 'someconfig'}) + self.patch("builtins.open", + new_callable=mock.mock_open(), + name="_open") + self.patch_object(lc_utils, 'yaml') + _yaml = "testconfig: someconfig" + _yaml_dict = {'test_config': 'someconfig'} + self.yaml.load.return_value = _yaml_dict + _filename = "filename" + _fileobj = mock.MagicMock() + _fileobj.__enter__.return_value = _yaml + self._open.return_value = _fileobj + + self.assertEqual(lc_utils.get_charm_config(yaml_file=_filename), + _yaml_dict) + self._open.assert_called_once_with(_filename, "r") + self.yaml.load.assert_called_once_with(_yaml) def test_get_class(self): self.assertEqual( @@ -22,3 +30,22 @@ class TestCharmLifecycleUtils(ut_utils.BaseTestCase): 'test_zaza_charm_lifecycle_utils.' 'TestCharmLifecycleUtils')()), type(self)) + + def test_get_juju_model(self): + self.patch_object(lc_utils.os, 'environ') + self.patch_object(lc_utils.model, 'get_current_model') + self.get_current_model.return_value = 'modelsmodel' + + def _get_env(key): + return _env.get(key) + self.environ.__getitem__.side_effect = _get_env + _env = {"JUJU_MODEL": 'envmodel'} + + # JUJU_ENV environment variable set + self.assertEqual(lc_utils.get_juju_model(), 'envmodel') + self.get_current_model.assert_not_called() + + # No envirnment variable + self.environ.__getitem__.side_effect = KeyError + self.assertEqual(lc_utils.get_juju_model(), 'modelsmodel') + self.get_current_model.assert_called_once() diff --git a/unit_tests/test_zaza_model.py b/unit_tests/test_zaza_model.py index 26ee41a..7b78f39 100644 --- a/unit_tests/test_zaza_model.py +++ b/unit_tests/test_zaza_model.py @@ -80,12 +80,18 @@ class TestModel(ut_utils.BaseTestCase): async def _disconnect(): return + async def _connect(): + return + + self.Model_mock.connect.side_effect = _connect self.Model_mock.connect_model.side_effect = _connect_model self.Model_mock.disconnect.side_effect = _disconnect self.Model_mock.applications = self.mymodel.applications self.Model_mock.units = { 'app/2': self.unit1, 'app/4': self.unit2} + self.model_name = "testmodel" + self.Model_mock.info.name = self.model_name def test_run_in_model(self): self.patch_object(model, 'Model') @@ -363,3 +369,8 @@ class TestModel(ut_utils.BaseTestCase): 'workload-status-message': 'Sure, I could do something'}}, timeout=1) self.assertTrue(self.system_ready) + + def test_get_current_model(self): + self.patch_object(model, 'Model') + self.Model.return_value = self.Model_mock + self.assertEqual(model.get_current_model(), self.model_name) diff --git a/zaza/charm_lifecycle/utils.py b/zaza/charm_lifecycle/utils.py index 3f5d1dc..571053f 100644 --- a/zaza/charm_lifecycle/utils.py +++ b/zaza/charm_lifecycle/utils.py @@ -2,6 +2,8 @@ import importlib import os import yaml +from zaza import model + BUNDLE_DIR = "./tests/bundles/" DEFAULT_TEST_CONFIG = "./tests/tests.yaml" @@ -47,9 +49,18 @@ def set_juju_model(model_name): def get_juju_model(): - """Retrieve current model from environment + """Retrieve current model + + First check the environment for JUJU_MODEL. If this is not set, get the + current active model. :returns: In focus model name :rtype: str """ - return os.environ["JUJU_MODEL"] + + try: + # Check the environment + return os.environ["JUJU_MODEL"] + except KeyError: + # If unset connect get the current active model + return model.get_current_model() diff --git a/zaza/configure/network.py b/zaza/configure/network.py index 5105938..06bcd19 100755 --- a/zaza/configure/network.py +++ b/zaza/configure/network.py @@ -199,7 +199,7 @@ def setup_gateway_ext_port(network_config, keystone_session=None): net_id=net_id) -def run_from_cli(): +def run_from_cli(**kwargs): """Run network configurations from CLI Use a YAML file of network configuration settings to configure the @@ -217,6 +217,7 @@ def run_from_cli(): start_floating_ip: 10.5.150.0 end_floating_ip: 10.5.200.254 + :param kwargs: Allow for override of argparse options :returns: None :rtype: None """ @@ -235,9 +236,12 @@ def run_from_cli(): default="network.yaml") # Handle CLI options options = parser.parse_args() - net_topology = _local_utils.parse_arg(options, "net_topology") - net_topology_file = _local_utils.parse_arg(options, "net_topology_file") - ignore_env_vars = _local_utils.parse_arg(options, "ignore_env_vars") + net_topology = (kwargs.get('net_toplogoy') or + _local_utils.parse_arg(options, "net_topology")) + net_topology_file = (kwargs.get('net_topology_file') or + _local_utils.parse_arg(options, "net_topology_file")) + ignore_env_vars = (kwargs.get('ignore_env_vars') or + _local_utils.parse_arg(options, "ignore_env_vars")) logging.info("Setting up %s network" % (net_topology)) network_config = _local_utils.get_network_config( diff --git a/zaza/model.py b/zaza/model.py index f3485fc..b0eceac 100644 --- a/zaza/model.py +++ b/zaza/model.py @@ -562,6 +562,25 @@ def get_actions(model_name, application_name): return yaml.load(subprocess.check_output(cmd)) +async def async_get_current_model(): + """Return the current active model name + + Connect to the current active model and return its name. + + :returns: String curenet model name + :rtype: str + """ + + model = Model() + await model.connect() + model_name = model.info.name + await model.disconnect() + return model_name + + +get_current_model = sync_wrapper(async_get_current_model) + + def main(): # Run the deploy coroutine in an asyncio event loop, using a helper # that abstracts loop creation and teardown.