Merge "Add support of extra variables."
This commit is contained in:
@@ -1440,3 +1440,73 @@ class TestAnsibleSymlink(TestCase):
|
||||
def test_ansible_symlink_not_needed(self, mock_path, mock_cmd):
|
||||
utils.ansible_symlink()
|
||||
mock_cmd.assert_not_called()
|
||||
|
||||
|
||||
class TestParseExtraVars(TestCase):
|
||||
def test_simple_case_text_format(self):
|
||||
input_parameter = ['key1=val1', 'key2=val2 key3=val3']
|
||||
expected = {
|
||||
'key1': 'val1',
|
||||
'key2': 'val2',
|
||||
'key3': 'val3'
|
||||
}
|
||||
result = utils.parse_extra_vars(input_parameter)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_simple_case_json_format(self):
|
||||
input_parameter = ['{"key1": "val1", "key2": "val2"}']
|
||||
expected = {
|
||||
'key1': 'val1',
|
||||
'key2': 'val2'
|
||||
}
|
||||
result = utils.parse_extra_vars(input_parameter)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_multiple_format(self):
|
||||
input_parameter = [
|
||||
'key1=val1', 'key2=val2 key3=val3',
|
||||
'{"key4": "val4", "key5": "val5"}']
|
||||
expected = {
|
||||
'key1': 'val1',
|
||||
'key2': 'val2',
|
||||
'key3': 'val3',
|
||||
'key4': 'val4',
|
||||
'key5': 'val5'
|
||||
}
|
||||
result = utils.parse_extra_vars(input_parameter)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_same_key(self):
|
||||
input_parameter = [
|
||||
'key1=val1', 'key2=val2 key3=val3',
|
||||
'{"key1": "other_value", "key5": "val5"}']
|
||||
expected = {
|
||||
'key1': 'other_value',
|
||||
'key2': 'val2',
|
||||
'key3': 'val3',
|
||||
'key5': 'val5'
|
||||
}
|
||||
result = utils.parse_extra_vars(input_parameter)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_with_multiple_space(self):
|
||||
input_parameter = ['key1=val1', ' key2=val2 key3=val3 ']
|
||||
expected = {
|
||||
'key1': 'val1',
|
||||
'key2': 'val2',
|
||||
'key3': 'val3'
|
||||
}
|
||||
result = utils.parse_extra_vars(input_parameter)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_invalid_string(self):
|
||||
input_parameter = [
|
||||
'key1=val1', 'key2=val2 key3=val3',
|
||||
'{"key1": "other_value", "key5": "val5']
|
||||
self.assertRaises(
|
||||
ValueError, utils.parse_extra_vars, input_parameter)
|
||||
|
||||
def test_invalid_format(self):
|
||||
input_parameter = ['key1 val1']
|
||||
self.assertRaises(
|
||||
ValueError, utils.parse_extra_vars, input_parameter)
|
||||
|
||||
@@ -61,5 +61,38 @@ class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='ceph',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
autospec=True)
|
||||
@mock.patch('os.path.expanduser')
|
||||
@mock.patch('oslo_concurrency.processutils.execute')
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
def test_update_with_user_and_extra_vars(self, mock_open, mock_execute,
|
||||
mock_expanduser, update_ansible):
|
||||
mock_expanduser.return_value = '/home/fake/'
|
||||
argslist = ['--ssh-user', 'tripleo-admin',
|
||||
'--extra-vars', 'key1=val1',
|
||||
'--extra-vars', 'key2=val2']
|
||||
verifylist = [
|
||||
('ssh_user', 'tripleo-admin'),
|
||||
('extra_vars', ['key1=val1', 'key2=val2'])
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
||||
with mock.patch('os.path.exists') as mock_exists:
|
||||
mock_exists.return_value = True
|
||||
self.cmd.take_action(parsed_args)
|
||||
update_ansible.assert_called_once_with(
|
||||
self.app.client_manager,
|
||||
nodes='all',
|
||||
inventory_file=mock_open().read(),
|
||||
playbook='external_update_steps_playbook.yaml',
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1,
|
||||
extra_vars={'key1': 'val1', 'key2': 'val2'}
|
||||
)
|
||||
|
||||
@@ -61,5 +61,38 @@ class TestOvercloudExternalUpgradeRun(fakes.TestOvercloudExternalUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='ceph',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars={}
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
autospec=True)
|
||||
@mock.patch('os.path.expanduser')
|
||||
@mock.patch('oslo_concurrency.processutils.execute')
|
||||
@mock.patch('six.moves.builtins.open')
|
||||
def test_upgrade_with_user_and_extra_vars(self, mock_open, mock_execute,
|
||||
mock_expanduser, update_ansible):
|
||||
mock_expanduser.return_value = '/home/fake/'
|
||||
argslist = ['--ssh-user', 'tripleo-admin',
|
||||
'--extra-vars', 'key1=val1',
|
||||
'--extra-vars', 'key2=val2']
|
||||
verifylist = [
|
||||
('ssh_user', 'tripleo-admin'),
|
||||
('extra_vars', ['key1=val1', 'key2=val2'])
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
||||
with mock.patch('os.path.exists') as mock_exists:
|
||||
mock_exists.return_value = True
|
||||
self.cmd.take_action(parsed_args)
|
||||
update_ansible.assert_called_once_with(
|
||||
self.app.client_manager,
|
||||
nodes='all',
|
||||
inventory_file=mock_open().read(),
|
||||
playbook='external_upgrade_steps_playbook.yaml',
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1,
|
||||
extra_vars={'key1': 'val1', 'key2': 'val2'}
|
||||
)
|
||||
|
||||
@@ -169,7 +169,8 @@ class TestFFWDUpgradeRun(fakes.TestFFWDUpgradeRun):
|
||||
node_user='heat-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -195,7 +196,8 @@ class TestFFWDUpgradeRun(fakes.TestFFWDUpgradeRun):
|
||||
node_user='my-user',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
|
||||
@@ -151,7 +151,8 @@ class TestOvercloudUpdateRun(fakes.TestOvercloudUpdateRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -182,7 +183,8 @@ class TestOvercloudUpdateRun(fakes.TestOvercloudUpdateRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -212,7 +214,8 @@ class TestOvercloudUpdateRun(fakes.TestOvercloudUpdateRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
|
||||
@@ -171,7 +171,8 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -204,7 +205,8 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='validation',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -238,6 +240,7 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
tags='validation',
|
||||
skip_tags='',
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -268,7 +271,8 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -299,7 +303,8 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
@@ -332,7 +337,8 @@ class TestOvercloudUpgradeRun(fakes.TestOvercloudUpgradeRun):
|
||||
node_user='tripleo-admin',
|
||||
tags='',
|
||||
skip_tags='pre-upgrade,validation',
|
||||
verbosity=1
|
||||
verbosity=1,
|
||||
extra_vars=None
|
||||
)
|
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible',
|
||||
|
||||
@@ -1042,7 +1042,7 @@ def process_multiple_environments(created_env_files, tht_root,
|
||||
|
||||
def run_update_ansible_action(log, clients, nodes, inventory, playbook,
|
||||
all_playbooks, action, ssh_user, tags='',
|
||||
skip_tags='', verbosity='1'):
|
||||
skip_tags='', verbosity='1', extra_vars=None):
|
||||
playbooks = [playbook]
|
||||
if playbook == "all":
|
||||
playbooks = all_playbooks
|
||||
@@ -1050,7 +1050,51 @@ def run_update_ansible_action(log, clients, nodes, inventory, playbook,
|
||||
log.debug("Running ansible playbook %s " % book)
|
||||
action.update_ansible(clients, nodes=nodes, inventory_file=inventory,
|
||||
playbook=book, node_user=ssh_user, tags=tags,
|
||||
skip_tags=skip_tags, verbosity=verbosity)
|
||||
skip_tags=skip_tags, verbosity=verbosity,
|
||||
extra_vars=extra_vars)
|
||||
|
||||
|
||||
def parse_extra_vars(extra_var_strings):
|
||||
"""Parses extra variables like Ansible would.
|
||||
|
||||
Each element in extra_var_strings is like the raw value of -e
|
||||
parameter of ansible-playbook command. It can either be very
|
||||
simple 'key=val key2=val2' format or it can be '{ ... }'
|
||||
representing a YAML/JSON object.
|
||||
|
||||
The 'key=val key2=val2' format gets processed as if it was
|
||||
'{"key": "val", "key2": "val2"}' object, and all YAML/JSON objects
|
||||
get shallow-merged together in the order as they appear in
|
||||
extra_var_strings, latter objects taking precedence over earlier
|
||||
ones.
|
||||
|
||||
:param extra_var_strings: unparsed value(s) of -e parameter(s)
|
||||
:type extra_var_strings: list of strings
|
||||
|
||||
:returns dict representing a merged object of all extra vars
|
||||
"""
|
||||
result = {}
|
||||
|
||||
for extra_var_string in extra_var_strings:
|
||||
invalid_yaml = False
|
||||
|
||||
try:
|
||||
parse_vars = yaml.safe_load(extra_var_string)
|
||||
except yaml.YAMLError:
|
||||
invalid_yaml = True
|
||||
|
||||
if invalid_yaml or not isinstance(parse_vars, dict):
|
||||
try:
|
||||
parse_vars = dict(
|
||||
item.split('=') for item in extra_var_string.split())
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
'Invalid format for {extra_var_string}'.format(
|
||||
extra_var_string=extra_var_string))
|
||||
|
||||
result.update(parse_vars)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def prepend_environment(environment_files, templates_dir, environment):
|
||||
|
||||
@@ -79,6 +79,10 @@ class ExternalUpdateRun(command.Command):
|
||||
'(default=Env: OVERCLOUD_STACK_NAME)'),
|
||||
default=utils.env('OVERCLOUD_STACK_NAME',
|
||||
default='overcloud'))
|
||||
parser.add_argument(
|
||||
'-e', '--extra-vars', dest='extra_vars', action='append',
|
||||
help='Set additional variables as key=value or yaml/json',
|
||||
default=[])
|
||||
|
||||
return parser
|
||||
|
||||
@@ -93,11 +97,13 @@ class ExternalUpdateRun(command.Command):
|
||||
parsed_args.static_inventory, parsed_args.ssh_user, stack)
|
||||
limit_hosts = 'all'
|
||||
playbook = 'all'
|
||||
extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars)
|
||||
|
||||
oooutils.run_update_ansible_action(
|
||||
self.log, clients, limit_hosts, inventory, playbook,
|
||||
constants.EXTERNAL_UPDATE_PLAYBOOKS,
|
||||
package_update, parsed_args.ssh_user,
|
||||
tags=parsed_args.tags, skip_tags=parsed_args.skip_tags,
|
||||
verbosity=verbosity)
|
||||
verbosity=verbosity, extra_vars=extra_vars)
|
||||
|
||||
self.log.info("Completed Overcloud External Update Run.")
|
||||
|
||||
@@ -79,6 +79,10 @@ class ExternalUpgradeRun(command.Command):
|
||||
'(default=Env: OVERCLOUD_STACK_NAME)'),
|
||||
default=utils.env('OVERCLOUD_STACK_NAME',
|
||||
default='overcloud'))
|
||||
parser.add_argument(
|
||||
'-e', '--extra-vars', dest='extra_vars', action='append',
|
||||
help='Set additional variables as key=value or yaml/json',
|
||||
default=[])
|
||||
|
||||
return parser
|
||||
|
||||
@@ -93,11 +97,13 @@ class ExternalUpgradeRun(command.Command):
|
||||
parsed_args.static_inventory, parsed_args.ssh_user, stack)
|
||||
limit_hosts = 'all'
|
||||
playbook = 'all'
|
||||
extra_vars = oooutils.parse_extra_vars(parsed_args.extra_vars)
|
||||
|
||||
oooutils.run_update_ansible_action(
|
||||
self.log, clients, limit_hosts, inventory, playbook,
|
||||
constants.EXTERNAL_UPGRADE_PLAYBOOKS,
|
||||
package_update, parsed_args.ssh_user,
|
||||
tags=parsed_args.tags, skip_tags=parsed_args.skip_tags,
|
||||
verbosity=verbosity)
|
||||
verbosity=verbosity, extra_vars=extra_vars)
|
||||
|
||||
self.log.info("Completed Overcloud External Upgrade Run.")
|
||||
|
||||
Reference in New Issue
Block a user