Allow model constraints to be passed via env vars
Allow model constraints to be applied to models that zaza creates.
This commit is contained in:
@@ -9,54 +9,54 @@ class TestCharmLifecyclePrepare(ut_utils.BaseTestCase):
|
||||
|
||||
MODEL_CONFIG_DEFAULTS = lc_prepare.MODEL_DEFAULTS
|
||||
|
||||
def base_get_model_settings(self, env, expect):
|
||||
def base_parse_option_list_string(self, env, expect):
|
||||
with mock.patch.dict(lc_prepare.os.environ, env):
|
||||
self.assertEqual(lc_prepare.get_model_settings(), expect)
|
||||
|
||||
def test_parse_option_list_string_empty_config(self):
|
||||
self.assertEqual(
|
||||
lc_prepare.parse_option_list_string(option_list=""),
|
||||
{})
|
||||
|
||||
def test_parse_option_list_string_single_value(self):
|
||||
self.assertEqual(
|
||||
lc_prepare.parse_option_list_string(
|
||||
option_list='image-stream=released'),
|
||||
{'image-stream': 'released'})
|
||||
|
||||
def test_parse_option_list_string_multiple_values(self):
|
||||
self.assertEqual(
|
||||
lc_prepare.parse_option_list_string(
|
||||
option_list='image-stream=released;no-proxy=jujucharms.com'),
|
||||
{
|
||||
'image-stream': 'released',
|
||||
'no-proxy': 'jujucharms.com'})
|
||||
|
||||
def test_parse_option_list_string_whitespace(self):
|
||||
self.assertEqual(
|
||||
lc_prepare.parse_option_list_string(
|
||||
option_list=' test-mode= false ; image-stream= released'),
|
||||
{
|
||||
'test-mode': 'false',
|
||||
'image-stream': 'released'})
|
||||
|
||||
def test_get_model_settings_no_config(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
self.base_get_model_settings({}, expect_config)
|
||||
|
||||
def test_get_model_settings_empty_config(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
self.base_get_model_settings({'MODEL_SETTINGS': ''}, expect_config)
|
||||
|
||||
def test_get_model_settings_single_value(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
expect_config.update({'virt-type': 'kvm'})
|
||||
self.base_get_model_settings(
|
||||
{'MODEL_SETTINGS': 'virt-type=kvm'},
|
||||
expect_config)
|
||||
|
||||
def test_get_model_settings_multiple_values(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
expect_config.update({
|
||||
'virt-type': 'kvm',
|
||||
'no-proxy': 'jujucharms.com'})
|
||||
self.base_get_model_settings(
|
||||
{'MODEL_SETTINGS': 'virt-type=kvm;no-proxy=jujucharms.com'},
|
||||
expect_config)
|
||||
self.base_parse_option_list_string({}, self.MODEL_CONFIG_DEFAULTS)
|
||||
|
||||
def test_get_model_settings_multiple_values_override(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
expect_config.update({'test-mode': 'false'})
|
||||
self.base_get_model_settings(
|
||||
self.base_parse_option_list_string(
|
||||
{'MODEL_SETTINGS': 'test-mode=false'},
|
||||
expect_config)
|
||||
|
||||
def test_get_model_settings_whitespace(self):
|
||||
expect_config = copy.deepcopy(self.MODEL_CONFIG_DEFAULTS)
|
||||
expect_config.update({
|
||||
'test-mode': 'false',
|
||||
'virt-type': 'kvm'})
|
||||
self.base_get_model_settings(
|
||||
{'MODEL_SETTINGS': ' test-mode= false ; virt-type= kvm'},
|
||||
expect_config)
|
||||
|
||||
def test_prepare(self):
|
||||
self.patch_object(lc_prepare.zaza.controller, 'add_model')
|
||||
self.patch_object(lc_prepare, 'get_model_settings')
|
||||
self.patch_object(lc_prepare, 'get_model_constraints')
|
||||
self.patch_object(lc_prepare.zaza.model, 'set_model_constraints')
|
||||
self.get_model_settings.return_value = lc_prepare.MODEL_DEFAULTS
|
||||
self.get_model_constraints.return_value = {'image-stream': 'released'}
|
||||
lc_prepare.prepare('newmodel')
|
||||
self.add_model.assert_called_once_with(
|
||||
'newmodel',
|
||||
@@ -69,6 +69,9 @@ class TestCharmLifecyclePrepare(ut_utils.BaseTestCase):
|
||||
'enable-os-upgrade': 'false',
|
||||
'automatically-retry-hooks': 'false',
|
||||
'use-default-secgroup': 'true'})
|
||||
self.set_model_constraints.assert_called_once_with(
|
||||
constraints={'image-stream': 'released'},
|
||||
model_name='newmodel')
|
||||
|
||||
def test_parser(self):
|
||||
args = lc_prepare.parse_args(['-m', 'newmodel'])
|
||||
|
||||
@@ -6,6 +6,7 @@ import os
|
||||
import sys
|
||||
|
||||
import zaza.controller
|
||||
import zaza.model
|
||||
|
||||
MODEL_DEFAULTS = {
|
||||
# Model defaults from charm-test-infra
|
||||
@@ -23,21 +24,51 @@ MODEL_DEFAULTS = {
|
||||
}
|
||||
|
||||
|
||||
def get_model_settings():
|
||||
"""Construct settings for model from defaults and env variables.
|
||||
def parse_option_list_string(option_list, delimiter=None):
|
||||
"""Convert the given string to a dictionary of options.
|
||||
|
||||
:returns: Settings to usee for model
|
||||
Each pair must be of the form 'k=v', the delimiter seperates the
|
||||
pairs from each other not the key from the value.
|
||||
|
||||
:param option_list: A string representation of key value pairs.
|
||||
:type option_list: str
|
||||
:param delimiter: Delimiter to use to seperate each pair.
|
||||
:type delimiter: str
|
||||
:returns: A dictionary of settings.
|
||||
:rtype: Dict
|
||||
"""
|
||||
model_settings = copy.deepcopy(MODEL_DEFAULTS)
|
||||
for setting in os.environ.get('MODEL_SETTINGS', '').split(';'):
|
||||
settings = {}
|
||||
if delimiter is None:
|
||||
delimiter = ';'
|
||||
for setting in option_list.split(delimiter):
|
||||
if not setting:
|
||||
continue
|
||||
key, value = setting.split('=')
|
||||
model_settings[key.strip()] = value.strip()
|
||||
settings[key.strip()] = value.strip()
|
||||
return settings
|
||||
|
||||
|
||||
def get_model_settings():
|
||||
"""Construct settings for model from defaults and env variables.
|
||||
|
||||
:returns: Settings to use for model
|
||||
:rtype: Dict
|
||||
"""
|
||||
model_settings = copy.deepcopy(MODEL_DEFAULTS)
|
||||
model_settings.update(
|
||||
parse_option_list_string(os.environ.get('MODEL_SETTINGS', '')))
|
||||
return model_settings
|
||||
|
||||
|
||||
def get_model_constraints():
|
||||
"""Construct constraints for model.
|
||||
|
||||
:returns: Constraints to apply to model
|
||||
:rtype: Dict
|
||||
"""
|
||||
return parse_option_list_string(os.environ.get('MODEL_CONSTRAINTS', ''))
|
||||
|
||||
|
||||
def prepare(model_name):
|
||||
"""Run all steps to prepare the environment before a functional test run.
|
||||
|
||||
@@ -45,6 +76,9 @@ def prepare(model_name):
|
||||
:type bundle: str
|
||||
"""
|
||||
zaza.controller.add_model(model_name, config=get_model_settings())
|
||||
zaza.model.set_model_constraints(
|
||||
model_name=model_name,
|
||||
constraints=get_model_constraints())
|
||||
|
||||
|
||||
def parse_args(args):
|
||||
|
||||
@@ -1008,3 +1008,25 @@ async def async_get_relation_id(application_name, remote_application_name,
|
||||
return(rel.id)
|
||||
|
||||
get_relation_id = sync_wrapper(async_get_relation_id)
|
||||
|
||||
|
||||
def set_model_constraints(constraints, model_name=None):
|
||||
"""
|
||||
Set constraints on a model.
|
||||
|
||||
Note: Subprocessing out to 'juju' is a temporary solution until
|
||||
https://bit.ly/2ujbVPA lands in libjuju.
|
||||
|
||||
:param model_name: Name of model to operate on
|
||||
:type model_name: str
|
||||
:param constraints: Constraints to be applied to model
|
||||
:type constraints: dict
|
||||
|
||||
"""
|
||||
if not constraints:
|
||||
return
|
||||
if not model_name:
|
||||
model_name = get_juju_model()
|
||||
cmd = ['juju', 'set-model-constraints', '-m', model_name]
|
||||
cmd.extend(['{}={}'.format(k, v) for k, v in constraints.items()])
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
Reference in New Issue
Block a user