tripleo deploy accept plan environment
This enables passing a different plan environment file, and also avoids hard-coded references to some of the environment files such as the overcloud-resource-registry-puppet.yaml which we may want to rename to enable plans per application e.g openstack, openshift, ceph standalone etc in future. This also aligns better with the overcloud deploy command. Change-Id: I61763f62c5d44f098ad60f9426871caef16cd6de
This commit is contained in:
parent
d3106dbd99
commit
bfaefda0f1
|
@ -13,6 +13,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import fixtures
|
||||||
import mock
|
import mock
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -362,9 +363,6 @@ class TestDeployUndercloud(TestPluginV1):
|
||||||
env_files)
|
env_files)
|
||||||
self.assertEqual(expected, results)
|
self.assertEqual(expected, results)
|
||||||
|
|
||||||
@mock.patch('os.path.exists', return_value=False)
|
|
||||||
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
|
||||||
'_create_working_dirs')
|
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_environment_and_files', return_value=({}, {}),
|
'process_environment_and_files', return_value=({}, {}),
|
||||||
autospec=True)
|
autospec=True)
|
||||||
|
@ -374,68 +372,80 @@ class TestDeployUndercloud(TestPluginV1):
|
||||||
@mock.patch('tripleoclient.utils.'
|
@mock.patch('tripleoclient.utils.'
|
||||||
'process_multiple_environments', autospec=True)
|
'process_multiple_environments', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
||||||
'_process_hieradata_overrides', return_value='foo.yaml',
|
'_process_hieradata_overrides', return_value='hiera_or.yaml',
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
||||||
'_update_passwords_env', autospec=True)
|
'_update_passwords_env', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.'
|
@mock.patch('tripleoclient.utils.'
|
||||||
'run_command_and_log', autospec=True)
|
'run_command_and_log', autospec=True)
|
||||||
@mock.patch('six.moves.builtins.open')
|
def test_setup_heat_environments(self,
|
||||||
@mock.patch('shutil.copy', autospec=True)
|
|
||||||
def test_setup_heat_environments(self, mock_cp, mock_open,
|
|
||||||
mock_run,
|
mock_run,
|
||||||
mock_update_pass_env,
|
mock_update_pass_env,
|
||||||
mock_process_hiera,
|
mock_process_hiera,
|
||||||
mock_process_multiple_environments,
|
mock_process_multiple_environments,
|
||||||
mock_hc_get_templ_cont,
|
mock_hc_get_templ_cont,
|
||||||
mock_hc_process,
|
mock_hc_process):
|
||||||
mock_createdirs,
|
|
||||||
mock_exists):
|
|
||||||
|
|
||||||
mock_update_pass_env.return_value = '/my/tripleo-heat-installer-' \
|
tmpdir = self.useFixture(fixtures.TempDir()).path
|
||||||
'templates/passwords.yaml'
|
tht_from = os.path.join(tmpdir, 'tht-from')
|
||||||
|
os.mkdir(tht_from)
|
||||||
|
tht_outside = os.path.join(tmpdir, 'tht-outside')
|
||||||
|
os.mkdir(tht_outside)
|
||||||
|
tht_to = os.path.join(tmpdir, 'tht-to')
|
||||||
|
os.mkdir(tht_to)
|
||||||
|
plan_env_path = os.path.join(tht_from, 'plan-environment.yaml')
|
||||||
|
with open(plan_env_path, mode='w') as plan_file:
|
||||||
|
yaml.dump({'environments': [{'path': 'env.yaml'}]}, plan_file)
|
||||||
|
self.assertTrue(os.path.exists(plan_env_path))
|
||||||
|
with open(os.path.join(tht_from, 'env.yaml'),
|
||||||
|
mode='w') as env_file:
|
||||||
|
yaml.dump({}, env_file)
|
||||||
|
with open(os.path.join(tht_from, 'foo.yaml'),
|
||||||
|
mode='w') as env_file:
|
||||||
|
yaml.dump({}, env_file)
|
||||||
|
with open(os.path.join(tht_outside, 'outside.yaml'),
|
||||||
|
mode='w') as env_file:
|
||||||
|
yaml.dump({}, env_file)
|
||||||
|
|
||||||
|
tht_render = os.path.join(tht_to, 'tripleo-heat-installer-templates')
|
||||||
|
mock_update_pass_env.return_value = os.path.join(
|
||||||
|
tht_render, 'passwords.yaml')
|
||||||
mock_run.return_value = 0
|
mock_run.return_value = 0
|
||||||
|
|
||||||
# logic handled in _standalone_deploy and _create_working_dirs
|
# logic handled in _standalone_deploy
|
||||||
self.cmd.output_dir = '/my'
|
self.cmd.output_dir = tht_to
|
||||||
self.cmd.tht_render = '/my/tripleo-heat-installer-templates'
|
# Note we don't create tht_render as _populate_templates_dir creates it
|
||||||
|
self.cmd.tht_render = tht_render
|
||||||
|
self.cmd._populate_templates_dir(tht_from)
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd,
|
parsed_args = self.check_parser(self.cmd,
|
||||||
['--local-ip', '127.0.0.1/8',
|
['--local-ip', '127.0.0.1/8',
|
||||||
'--templates', '/tmp/thtroot',
|
'--templates', tht_from,
|
||||||
'--output-dir', '/my',
|
'--output-dir', tht_to,
|
||||||
'--hieradata-override',
|
'--hieradata-override',
|
||||||
'legacy.yaml',
|
'legacy.yaml',
|
||||||
'-e',
|
'-e',
|
||||||
'/tmp/thtroot/puppet/foo.yaml',
|
os.path.join(tht_from, 'foo.yaml'),
|
||||||
'-e',
|
'-e',
|
||||||
'/tmp/thtroot//docker/bar.yaml',
|
os.path.join(tht_outside,
|
||||||
'-e',
|
'outside.yaml'),
|
||||||
'/tmp/thtroot42/notouch.yaml',
|
], [])
|
||||||
'-e', '~/custom.yaml',
|
|
||||||
'-e', 'something.yaml',
|
|
||||||
'-e', '../../../outside.yaml'], [])
|
|
||||||
expected_env = [
|
expected_env = [
|
||||||
'/my/tripleo-heat-installer-templates/'
|
os.path.join(tht_render, 'env.yaml'),
|
||||||
'overcloud-resource-registry-puppet.yaml',
|
os.path.join(tht_render, 'passwords.yaml'),
|
||||||
'/my/tripleo-heat-installer-templates/passwords.yaml',
|
os.path.join(tht_render,
|
||||||
'/my/tripleo-heat-installer-templates/'
|
'environments/config-download-environment.yaml'),
|
||||||
'environments/config-download-environment.yaml',
|
os.path.join(tht_render,
|
||||||
'/my/tripleo-heat-installer-templates/'
|
'environments/deployed-server-noop-ctlplane.yaml'),
|
||||||
'environments/deployed-server-noop-ctlplane.yaml',
|
os.path.join(tht_render,
|
||||||
'/my/tripleo-heat-installer-templates/'
|
'tripleoclient-hosts-portmaps.yaml'),
|
||||||
'tripleoclient-hosts-portmaps.yaml',
|
'hiera_or.yaml',
|
||||||
'/my/tripleo-heat-installer-templates/puppet/foo.yaml',
|
os.path.join(tht_render, 'foo.yaml'),
|
||||||
'/my/tripleo-heat-installer-templates//docker/bar.yaml',
|
os.path.join(tht_render, 'outside.yaml')]
|
||||||
'/my/tripleo-heat-installer-templates/notouch.yaml',
|
|
||||||
'/my/tripleo-heat-installer-templates/custom.yaml',
|
|
||||||
'/my/tripleo-heat-installer-templates/something.yaml',
|
|
||||||
'/my/tripleo-heat-installer-templates/outside.yaml',
|
|
||||||
'foo.yaml']
|
|
||||||
|
|
||||||
environment = self.cmd._setup_heat_environments(parsed_args)
|
environment = self.cmd._setup_heat_environments(parsed_args)
|
||||||
|
|
||||||
self.assertEqual(environment, expected_env)
|
self.assertEqual(expected_env, environment)
|
||||||
|
|
||||||
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
@mock.patch('tripleoclient.v1.tripleo_deploy.Deploy.'
|
||||||
'_create_working_dirs', autospec=True)
|
'_create_working_dirs', autospec=True)
|
||||||
|
|
|
@ -1139,3 +1139,14 @@ def build_prepare_env(environment_files, environment_directories):
|
||||||
object_request=get_env_file))
|
object_request=get_env_file))
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def rel_or_abs_path(tht_root, file_path):
|
||||||
|
'''Find a file, either absolute path or relative to the t-h-t dir'''
|
||||||
|
path = os.path.abspath(file_path)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
path = os.path.abspath(os.path.join(tht_root, file_path))
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise exceptions.DeploymentError(
|
||||||
|
"Can't find path %s %s" % (file_path, path))
|
||||||
|
return path
|
||||||
|
|
|
@ -464,13 +464,14 @@ class Deploy(command.Command):
|
||||||
|
|
||||||
# TODO(aschultz): in overcloud deploy we have a --environments-dir
|
# TODO(aschultz): in overcloud deploy we have a --environments-dir
|
||||||
# we might want to handle something similar for this
|
# we might want to handle something similar for this
|
||||||
|
# (shardy) alternatively perhaps we should rely on the plan-environment
|
||||||
|
# environments list instead?
|
||||||
if parsed_args.environment_files:
|
if parsed_args.environment_files:
|
||||||
env_files.extend(parsed_args.environment_files)
|
env_files.extend(parsed_args.environment_files)
|
||||||
|
|
||||||
# ensure any user provided templates get copied into tht_render
|
# ensure any user provided templates get copied into tht_render
|
||||||
environments = self._normalize_user_templates(parsed_args.templates,
|
user_environments = self._normalize_user_templates(
|
||||||
self.tht_render,
|
parsed_args.templates, self.tht_render, env_files)
|
||||||
env_files)
|
|
||||||
|
|
||||||
# generate jinja templates by its work dir location
|
# generate jinja templates by its work dir location
|
||||||
self.log.debug(_("Using roles file %s") % self.roles_file)
|
self.log.debug(_("Using roles file %s") % self.roles_file)
|
||||||
|
@ -487,25 +488,30 @@ class Deploy(command.Command):
|
||||||
# NOTE(aschultz): the next set of environment files are system included
|
# NOTE(aschultz): the next set of environment files are system included
|
||||||
# so we have to include them at the front of our environment list so a
|
# so we have to include them at the front of our environment list so a
|
||||||
# user can override anything in them.
|
# user can override anything in them.
|
||||||
resource_registry_path = os.path.join(
|
|
||||||
self.tht_render, 'overcloud-resource-registry-puppet.yaml')
|
# Include any environments from the plan-environment.yaml
|
||||||
environments.insert(0, resource_registry_path)
|
plan_env_path = utils.rel_or_abs_path(
|
||||||
|
self.tht_render, parsed_args.plan_environment_file)
|
||||||
|
with open(plan_env_path, 'r') as f:
|
||||||
|
plan_env_data = yaml.safe_load(f)
|
||||||
|
environments = [utils.rel_or_abs_path(self.tht_render, e.get('path'))
|
||||||
|
for e in plan_env_data.get('environments', {})]
|
||||||
|
|
||||||
# this will allow the user to overwrite passwords with custom envs
|
# this will allow the user to overwrite passwords with custom envs
|
||||||
pw_file = self._update_passwords_env(self.output_dir)
|
pw_file = self._update_passwords_env(self.output_dir)
|
||||||
environments.insert(1, pw_file)
|
environments.append(pw_file)
|
||||||
|
|
||||||
# use deployed-server because we run os-collect-config locally
|
# use deployed-server because we run os-collect-config locally
|
||||||
deployed_server_env = os.path.join(
|
deployed_server_env = os.path.join(
|
||||||
self.tht_render, 'environments',
|
self.tht_render, 'environments',
|
||||||
'config-download-environment.yaml')
|
'config-download-environment.yaml')
|
||||||
environments.insert(2, deployed_server_env)
|
environments.append(deployed_server_env)
|
||||||
|
|
||||||
# use deployed-server because we run os-collect-config locally
|
# use deployed-server because we run os-collect-config locally
|
||||||
deployed_server_env = os.path.join(
|
deployed_server_env = os.path.join(
|
||||||
self.tht_render, 'environments',
|
self.tht_render, 'environments',
|
||||||
'deployed-server-noop-ctlplane.yaml')
|
'deployed-server-noop-ctlplane.yaml')
|
||||||
environments.insert(3, deployed_server_env)
|
environments.append(deployed_server_env)
|
||||||
|
|
||||||
self.log.info(_("Deploying templates in the directory {0}").format(
|
self.log.info(_("Deploying templates in the directory {0}").format(
|
||||||
os.path.abspath(self.tht_render)))
|
os.path.abspath(self.tht_render)))
|
||||||
|
@ -534,7 +540,7 @@ class Deploy(command.Command):
|
||||||
with open(maps_file, 'w') as env_file:
|
with open(maps_file, 'w') as env_file:
|
||||||
yaml.safe_dump({'parameter_defaults': tmp_env}, env_file,
|
yaml.safe_dump({'parameter_defaults': tmp_env}, env_file,
|
||||||
default_flow_style=False)
|
default_flow_style=False)
|
||||||
environments.insert(4, maps_file)
|
environments.append(maps_file)
|
||||||
|
|
||||||
# NOTE(aschultz): this doesn't get copied into tht_root but
|
# NOTE(aschultz): this doesn't get copied into tht_root but
|
||||||
# we always include the hieradata override stuff last.
|
# we always include the hieradata override stuff last.
|
||||||
|
@ -543,7 +549,7 @@ class Deploy(command.Command):
|
||||||
parsed_args.hieradata_override,
|
parsed_args.hieradata_override,
|
||||||
parsed_args.standalone_role))
|
parsed_args.standalone_role))
|
||||||
|
|
||||||
return environments
|
return environments + user_environments
|
||||||
|
|
||||||
def _prepare_container_images(self, env):
|
def _prepare_container_images(self, env):
|
||||||
roles_data = self._get_roles_data()
|
roles_data = self._get_roles_data()
|
||||||
|
@ -700,6 +706,12 @@ class Deploy(command.Command):
|
||||||
'directory') % constants.UNDERCLOUD_ROLES_FILE,
|
'directory') % constants.UNDERCLOUD_ROLES_FILE,
|
||||||
default=constants.UNDERCLOUD_ROLES_FILE
|
default=constants.UNDERCLOUD_ROLES_FILE
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--plan-environment-file', '-p',
|
||||||
|
help=_('Plan Environment file, overrides the default %s in the '
|
||||||
|
'--templates directory') % constants.PLAN_ENVIRONMENT,
|
||||||
|
default=constants.PLAN_ENVIRONMENT
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--heat-api-port', metavar='<HEAT_API_PORT>',
|
'--heat-api-port', metavar='<HEAT_API_PORT>',
|
||||||
dest='heat_api_port',
|
dest='heat_api_port',
|
||||||
|
|
Loading…
Reference in New Issue