Add support for an answers file
Adding an --answers-file parameter to overcloud deploy and overcloud update that takes a YAML file: templates: ~/templates environments: - ~/test-env1.yaml - ~/test-env2.yaml - ~/test-env3.yaml Change-Id: I623143924951d02fcc9179c1da7705b4b7b551b7
This commit is contained in:
parent
c838918d81
commit
0821856178
@ -43,6 +43,7 @@ Deploy an overcloud stack
|
||||
[--reg-org REG_ORG] [--reg-force]
|
||||
[--reg-sat-url REG_SAT_URL]
|
||||
[--reg-activation-key REG_ACTIVATION_KEY]
|
||||
[--answers-file <ANSWERS FILE>]
|
||||
|
||||
.. option:: --stack <stack_name>
|
||||
|
||||
@ -193,3 +194,14 @@ Deploy an overcloud stack
|
||||
.. option:: --reg-activation-key <key>
|
||||
|
||||
Activation key to use for registration.
|
||||
|
||||
.. option:: --answers-file <file>
|
||||
|
||||
Point to a file that specifies a templates directory and a list
|
||||
of environment files in YAML format::
|
||||
|
||||
templates: ~/templates
|
||||
environments:
|
||||
- ~/test-env1.yaml
|
||||
- ~/test-env2.yaml
|
||||
- ~/test-env3.yaml
|
||||
|
@ -18,6 +18,7 @@ import json
|
||||
import os
|
||||
import six
|
||||
import tempfile
|
||||
import yaml
|
||||
|
||||
import mock
|
||||
|
||||
@ -814,3 +815,67 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||
self.assertFalse(mock_oc_endpoint.called)
|
||||
self.assertFalse(mock_create_ocrc.called)
|
||||
self.assertFalse(mock_create_tempest_deployer_input.called)
|
||||
|
||||
@mock.patch('tripleoclient.utils.check_nodes_count',
|
||||
autospec=True)
|
||||
@mock.patch('tripleoclient.utils.create_tempest_deployer_input',
|
||||
autospec=True)
|
||||
@mock.patch('tripleoclient.utils.create_overcloudrc', autospec=True)
|
||||
@mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True)
|
||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||
'_heat_deploy', autospec=True)
|
||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||
'set_overcloud_passwords', autospec=True)
|
||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||
'_pre_heat_deploy', autospec=True)
|
||||
def test_answers_file(self,
|
||||
mock_pre_deploy,
|
||||
mock_set_overcloud_passwords,
|
||||
mock_heat_deploy,
|
||||
mock_oc_endpoint,
|
||||
mock_create_ocrc,
|
||||
mock_create_tempest_deployer_input,
|
||||
mock_check_nodes_count):
|
||||
clients = self.app.client_manager
|
||||
network_client = clients.network
|
||||
network_client.stacks.get.return_value = None
|
||||
net = network_client.api.find_attr('networks', 'ctlplane')
|
||||
net.configure_mock(__getitem__=lambda x, y: 'testnet')
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode="w+t") as answerfile:
|
||||
yaml.dump(
|
||||
{'templates': '/dev/null',
|
||||
'environments': ['/tmp/foo.yaml']
|
||||
},
|
||||
answerfile
|
||||
)
|
||||
answerfile.flush()
|
||||
|
||||
arglist = ['--answers-file', answerfile.name,
|
||||
'--environment-file', '/tmp/environment.yaml',
|
||||
'--block-storage-scale', '3']
|
||||
verifylist = [
|
||||
('answers_file', answerfile.name),
|
||||
('environment_files', ['/tmp/environment.yaml']),
|
||||
('block_storage_scale', 3)
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
self.assertTrue(result)
|
||||
self.assertTrue(mock_heat_deploy.called)
|
||||
self.assertTrue(mock_oc_endpoint.called)
|
||||
self.assertTrue(mock_create_ocrc.called)
|
||||
self.assertTrue(mock_create_tempest_deployer_input.called)
|
||||
|
||||
# Check that Heat was called with correct parameters:
|
||||
call_args = mock_heat_deploy.call_args[0]
|
||||
self.assertEqual(call_args[3],
|
||||
'/dev/null/overcloud-without-mergepy.yaml')
|
||||
self.assertIn('/tmp/foo.yaml', call_args[5])
|
||||
self.assertIn('/tmp/environment.yaml', call_args[5])
|
||||
foo_index = call_args[5].index('/tmp/foo.yaml')
|
||||
env_index = call_args[5].index('/tmp/environment.yaml')
|
||||
self.assertGreater(env_index, foo_index)
|
||||
|
||||
mock_create_tempest_deployer_input.assert_called_with()
|
||||
|
@ -14,6 +14,7 @@
|
||||
#
|
||||
|
||||
import mock
|
||||
import tempfile
|
||||
|
||||
from tripleoclient.tests.v1.overcloud_update import fakes
|
||||
from tripleoclient.v1 import overcloud_update
|
||||
@ -35,9 +36,41 @@ class TestOvercloudUpdate(fakes.TestOvercloudUpdate):
|
||||
verifylist = [
|
||||
('stack', 'overcloud'),
|
||||
('interactive', True),
|
||||
('templates', '/usr/share/openstack-tripleo-heat-templates/')
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
||||
self.cmd.take_action(parsed_args)
|
||||
update_manager.get_status.called_once()
|
||||
update_manager.update.called_once()
|
||||
update_manager.do_interactive_update.called_once()
|
||||
|
||||
@mock.patch('tripleo_common.update.PackageUpdateManager')
|
||||
def test_update_answerfile(self, update_manager):
|
||||
answers = ("templates: {templates}\n"
|
||||
"environments:\n"
|
||||
" - {environment}\n")
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode="w+t") as answerfile:
|
||||
answerfile.write(answers.format(
|
||||
templates='/dev/null',
|
||||
environment='/dev/null'))
|
||||
answerfile.flush()
|
||||
|
||||
update_manager.return_value.get_status.return_value = (
|
||||
'UPDATE_COMPLETE', {})
|
||||
argslist = ['overcloud', '-i', '--answers-file', answerfile.name]
|
||||
verifylist = [
|
||||
('stack', 'overcloud'),
|
||||
('interactive', True),
|
||||
('answers_file', answerfile.name)
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
update_manager.get_status.called_once()
|
||||
update_manager.update.called_once()
|
||||
update_manager.do_interactive_update.called_once()
|
||||
|
||||
called_args = update_manager.call_args[1]
|
||||
self.assertEqual(called_args['tht_dir'], '/dev/null')
|
||||
self.assertEqual(called_args['environment_files'], ['/dev/null'])
|
||||
|
@ -26,6 +26,7 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import uuid
|
||||
import yaml
|
||||
|
||||
from cliff import command
|
||||
from heatclient.common import event_utils
|
||||
@ -97,6 +98,18 @@ class DeployOvercloud(command.Command):
|
||||
timestamp = int(time.time())
|
||||
parameters['DeployIdentifier'] = timestamp
|
||||
|
||||
# Update parameters from answers file:
|
||||
if args.answers_file is not None:
|
||||
with open(args.answers_file, 'r') as answers_file:
|
||||
answers = yaml.load(answers_file)
|
||||
|
||||
if args.templates is None:
|
||||
args.templates = answers['templates']
|
||||
if 'environments' in answers:
|
||||
if args.environment_files is not None:
|
||||
answers['environments'].extend(args.environment_files)
|
||||
args.environment_files = answers['environments']
|
||||
|
||||
param_args = (
|
||||
('NeutronPublicInterface', 'neutron_public_interface'),
|
||||
('NeutronBridgeMappings', 'neutron_bridge_mappings'),
|
||||
@ -492,6 +505,10 @@ class DeployOvercloud(command.Command):
|
||||
compute_client.flavors.create('m1.demo', 512, 1, 10, 'auto')
|
||||
|
||||
def _validate_args(self, parsed_args):
|
||||
if parsed_args.templates is None and parsed_args.answers_file is None:
|
||||
raise oscexc.CommandError(
|
||||
"You must specify either --templates or --answers-file")
|
||||
|
||||
network_type = parsed_args.neutron_network_type
|
||||
tunnel_types = parsed_args.neutron_tunnel_types
|
||||
tunnel_disabled = parsed_args.neutron_disable_tunneling
|
||||
@ -770,7 +787,6 @@ class DeployOvercloud(command.Command):
|
||||
parser.add_argument(
|
||||
'--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES,
|
||||
help=_("The directory containing the Heat templates to deploy"),
|
||||
required=True
|
||||
)
|
||||
parser.add_argument('--stack',
|
||||
help=_("Stack name to create or update"),
|
||||
@ -938,6 +954,10 @@ class DeployOvercloud(command.Command):
|
||||
default='',
|
||||
help=_('Activation key to use for registration.')
|
||||
)
|
||||
parser.add_argument(
|
||||
'--answers-file',
|
||||
help=_('Path to a YAML file with arguments and parameters.')
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
@ -14,8 +14,10 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
import yaml
|
||||
|
||||
from cliff import command
|
||||
from openstackclient.common import exceptions as oscexc
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.i18n import _
|
||||
from tripleo_common import update
|
||||
@ -38,7 +40,6 @@ class UpdateOvercloud(command.Command):
|
||||
parser.add_argument(
|
||||
'--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES,
|
||||
help=_("The directory containing the Heat templates to deploy"),
|
||||
required=True
|
||||
)
|
||||
parser.add_argument('-i', '--interactive', dest='interactive',
|
||||
action='store_true')
|
||||
@ -51,9 +52,29 @@ class UpdateOvercloud(command.Command):
|
||||
'or heat stack-update command. (Can be specified more than '
|
||||
'once.)')
|
||||
)
|
||||
parser.add_argument(
|
||||
'--answers-file',
|
||||
help=_('Path to a YAML file with arguments and parameters.')
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
if parsed_args.templates is None and parsed_args.answers_file is None:
|
||||
raise oscexc.CommandError(
|
||||
"You must specify either --templates or --answers-file")
|
||||
|
||||
if parsed_args.answers_file is not None:
|
||||
with open(parsed_args.answers_file, 'r') as answers_file:
|
||||
answers = yaml.load(answers_file)
|
||||
|
||||
if parsed_args.templates is None:
|
||||
parsed_args.templates = answers['templates']
|
||||
if 'environments' in answers:
|
||||
if parsed_args.environment_files is not None:
|
||||
answers.environments.extend(
|
||||
parsed_args.environment_files)
|
||||
parsed_args.environment_files = answers['environments']
|
||||
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
osc_plugin = self.app.client_manager.tripleoclient
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user