diff --git a/releasenotes/notes/fail-on-wrong-env-dir-b1d0530052002e57.yaml b/releasenotes/notes/fail-on-wrong-env-dir-b1d0530052002e57.yaml new file mode 100644 index 000000000..f5b38f48e --- /dev/null +++ b/releasenotes/notes/fail-on-wrong-env-dir-b1d0530052002e57.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + ``overcloud deploy`` now fails early if a path specified for + ``--environment-directory`` does not exist. See `bug 1697031 + `__. diff --git a/tripleoclient/constants.py b/tripleoclient/constants.py index fc0ff5ede..338ce6770 100644 --- a/tripleoclient/constants.py +++ b/tripleoclient/constants.py @@ -39,3 +39,6 @@ RHEL_REGISTRATION_EXTRACONFIG_NAME = ( # The name of the file which holds the plan environment contents PLAN_ENVIRONMENT = 'plan-environment.yaml' + +# This directory may contain additional environments to use during deploy +DEFAULT_ENV_DIRECTORY = "~/.tripleo/environments" diff --git a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py index 7df3cdcf5..7a2874453 100644 --- a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py +++ b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py @@ -786,6 +786,47 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): parsed_args) self.assertIn('tmp/doesnexit.yaml', str(error)) + @mock.patch('tripleoclient.workflows.plan_management.tarball', + autospec=True) + @mock.patch('tripleoclient.utils.create_tempest_deployer_input', + autospec=True) + @mock.patch('tripleoclient.utils.write_overcloudrc', autospec=True) + @mock.patch('tripleoclient.utils.get_overcloud_endpoint', autospec=True) + @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' + '_deploy_postconfig', autospec=True) + @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' + '_update_parameters', autospec=True) + @mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.' + '_heat_deploy', autospec=True) + @mock.patch('shutil.copytree', autospec=True) + def test_environment_dirs_env_dir_not_found(self, mock_copy, + mock_deploy_heat, + mock_update_parameters, + mock_post_config, + mock_utils_endpoint, + mock_utils_createrc, + mock_utils_tempest, + mock_tarball): + + clients = self.app.client_manager + workflow_client = clients.workflow_engine + workflow_client.action_executions.create.return_value = mock.MagicMock( + output='{"result":[]}') + + mock_update_parameters.return_value = {} + mock_utils_endpoint.return_value = 'foo.bar' + os.mkdir(self.tmp_dir.join('env')) + os.mkdir(self.tmp_dir.join('common')) + + arglist = ['--templates', '--environment-directory', '/tmp/notthere'] + verifylist = [ + ('templates', '/usr/share/openstack-tripleo-heat-templates/'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + error = self.assertRaises(oscexc.CommandError, self.cmd.take_action, + parsed_args) + self.assertIn('/tmp/notthere', str(error)) + @mock.patch('tripleoclient.utils.create_tempest_deployer_input', autospec=True) @mock.patch('tripleoclient.utils.write_overcloudrc', autospec=True) @@ -1483,3 +1524,40 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.cmd.take_action, parsed_args) self.assertFalse(mock_deploy_tmpdir.called) + + +class TestArgumentValidation(fakes.TestDeployOvercloud): + + def setUp(self): + super(TestArgumentValidation, self).setUp() + + def is_dir(arg): + if arg == '/tmp/real_dir': + return True + else: + return False + + patcher = mock.patch('os.path.isdir') + mock_isdir = patcher.start() + mock_isdir.side_effect = is_dir + self.addCleanup(patcher.stop) + + app_args = mock.Mock() + app_args.verbose_level = 1 + self.validate = overcloud_deploy.DeployOvercloud( + self.app, app_args)._validate_args_environment_directory + + def test_validate_env_dir(self): + self.assertIsNone(self.validate(['/tmp/real_dir'])) + + def test_validate_env_dir_empty(self): + self.assertIsNone(self.validate([])) + + def test_validate_env_dir_not_a_real_directory(self): + self.assertRaises(oscexc.CommandError, + self.validate, + ['/tmp/not_a_real_dir']) + + def test_validate_env_dir_ignore_default_not_existing(self): + full_path = os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY) + self.assertIsNone(self.validate([full_path])) diff --git a/tripleoclient/v1/overcloud_deploy.py b/tripleoclient/v1/overcloud_deploy.py index 851f8fa5b..34486c1aa 100644 --- a/tripleoclient/v1/overcloud_deploy.py +++ b/tripleoclient/v1/overcloud_deploy.py @@ -593,6 +593,23 @@ class DeployOvercloud(command.Command): if parsed_args.validation_warnings_fatal: raise exceptions.InvalidConfiguration() + if parsed_args.environment_directories: + self._validate_args_environment_directory( + parsed_args.environment_directories) + + def _validate_args_environment_directory(self, directories): + default = os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY) + nonexisting_dirs = [] + + for d in directories: + if not os.path.isdir(d) and d != default: + nonexisting_dirs.append(d) + + if nonexisting_dirs: + raise oscexc.CommandError( + "Error: The following environment directories were not found" + ": {0}".format(", ".join(nonexisting_dirs))) + def _get_default_role_counts(self, parsed_args): if parsed_args.roles_file: @@ -686,8 +703,7 @@ class DeployOvercloud(command.Command): parser.add_argument( '--environment-directory', metavar='', action='append', dest='environment_directories', - default=[os.path.join(os.environ.get('HOME', ''), '.tripleo', - 'environments')], + default=[os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY)], help=_('Environment file directories that are automatically ' ' added to the heat stack-create or heat stack-update' ' commands. Can be specified more than once. Files in'