diff options
author | Zuul <zuul@review.opendev.org> | 2020-02-21 07:54:54 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2020-02-21 07:54:54 +0000 |
commit | 6b071d397e9ba8ff81962f5709f3d14d6408dd2f (patch) | |
tree | eec9367fa3da8d0add066965c7150f0c662a3567 | |
parent | 866e90374ec08727161a5e00b409804a7c2e945f (diff) | |
parent | bd2bfaa514cfc6769b74bd0c213c58bcc1eef6ea (diff) | |
download | python-heatclient-6b071d397e9ba8ff81962f5709f3d14d6408dd2f.tar.gz |
Merge "Add files-container option for stack create and update"
-rw-r--r-- | heatclient/common/template_utils.py | 62 | ||||
-rw-r--r-- | heatclient/osc/v1/stack.py | 32 | ||||
-rw-r--r-- | heatclient/osc/v1/template.py | 16 | ||||
-rw-r--r-- | heatclient/tests/unit/test_template_utils.py | 12 | ||||
-rw-r--r-- | releasenotes/notes/add-files-container-stack-create-update-324b931f8f474b3d.yaml | 8 |
5 files changed, 99 insertions, 31 deletions
diff --git a/heatclient/common/template_utils.py b/heatclient/common/template_utils.py index cdb330a..2c66f2b 100644 --- a/heatclient/common/template_utils.py +++ b/heatclient/common/template_utils.py @@ -27,7 +27,8 @@ from heatclient.common import utils from heatclient import exc -def process_template_path(template_path, object_request=None, existing=False): +def process_template_path(template_path, object_request=None, + existing=False, fetch_child=True): """Read template from template path. Attempt to read template first as a file or url. If that is unsuccessful, @@ -37,17 +38,20 @@ def process_template_path(template_path, object_request=None, existing=False): :param object_request: custom object request function used to get template if local or uri path fails :param existing: if the current stack's template should be used + :param fetch_child: Whether to fetch the child templates :returns: get_file dict and template contents :raises: error.URLError """ try: return get_template_contents(template_file=template_path, - existing=existing) + existing=existing, + fetch_child=fetch_child) except error.URLError as template_file_exc: try: return get_template_contents(template_object=template_path, object_request=object_request, - existing=existing) + existing=existing, + fetch_child=fetch_child) except exc.HTTPNotFound: # The initial exception gives the user better failure context. raise template_file_exc @@ -55,7 +59,8 @@ def process_template_path(template_path, object_request=None, existing=False): def get_template_contents(template_file=None, template_url=None, template_object=None, object_request=None, - files=None, existing=False): + files=None, existing=False, + fetch_child=True): is_object = False # Transform a bare file path to a file:// URL. @@ -93,12 +98,13 @@ def get_template_contents(template_file=None, template_url=None, except ValueError as e: raise exc.CommandError(_('Error parsing template %(url)s %(error)s') % {'url': template_url, 'error': e}) - - tmpl_base_url = utils.base_url_for_url(template_url) if files is None: files = {} - resolve_template_get_files(template, files, tmpl_base_url, is_object, - object_request) + + if fetch_child: + tmpl_base_url = utils.base_url_for_url(template_url) + resolve_template_get_files(template, files, tmpl_base_url, is_object, + object_request) return files, template @@ -212,7 +218,8 @@ def process_multiple_environments_and_files(env_paths=None, template=None, template_url=None, env_path_is_object=None, object_request=None, - env_list_tracker=None): + env_list_tracker=None, + fetch_env_files=True): """Reads one or more environment files. Reads in each specified environment file and returns a dictionary @@ -239,6 +246,7 @@ def process_multiple_environments_and_files(env_paths=None, template=None, :type env_list_tracker: list or None :return: tuple of files dict and a dict of the consolidated environment :rtype: tuple + :param fetch_env_files: fetch env_files or leave it to server """ merged_files = {} merged_env = {} @@ -249,24 +257,28 @@ def process_multiple_environments_and_files(env_paths=None, template=None, if env_paths: for env_path in env_paths: - files, env = process_environment_and_files( - env_path=env_path, - template=template, - template_url=template_url, - env_path_is_object=env_path_is_object, - object_request=object_request, - include_env_in_files=include_env_in_files) - - # 'files' looks like {"filename1": contents, "filename2": contents} - # so a simple update is enough for merging - merged_files.update(files) - - # 'env' can be a deeply nested dictionary, so a simple update is - # not enough - merged_env = deep_update(merged_env, env) + if fetch_env_files: + files, env = process_environment_and_files( + env_path=env_path, + template=template, + template_url=template_url, + env_path_is_object=env_path_is_object, + object_request=object_request, + include_env_in_files=include_env_in_files) + + # 'files' looks like: + # {"filename1": contents, "filename2": contents} + # so a simple update is enough for merging + merged_files.update(files) + + # 'env' can be a deeply nested dictionary, so a simple + # update is not enough + merged_env = deep_update(merged_env, env) + env_url = utils.normalise_file_path_to_url(env_path) + else: + env_url = env_path if env_list_tracker is not None: - env_url = utils.normalise_file_path_to_url(env_path) env_list_tracker.append(env_url) return merged_files, merged_env diff --git a/heatclient/osc/v1/stack.py b/heatclient/osc/v1/stack.py index 761b323..a25844b 100644 --- a/heatclient/osc/v1/stack.py +++ b/heatclient/osc/v1/stack.py @@ -48,6 +48,13 @@ class CreateStack(command.ShowOne): help=_('Path to the environment. Can be specified multiple times') ) parser.add_argument( + '-s', '--files-container', + metavar='<files-container>', + help=_('Swift files container name. Local files other than ' + 'root template would be ignored. If other files are not ' + 'found in swift, heat engine would raise an error.') + ) + parser.add_argument( '--timeout', metavar='<timeout>', type=int, @@ -130,13 +137,15 @@ class CreateStack(command.ShowOne): tpl_files, template = template_utils.process_template_path( parsed_args.template, - object_request=http.authenticated_fetcher(client)) + object_request=http.authenticated_fetcher(client), + fetch_child=parsed_args.files_container is None) env_files_list = [] env_files, env = ( template_utils.process_multiple_environments_and_files( env_paths=parsed_args.environment, - env_list_tracker=env_files_list)) + env_list_tracker=env_files_list, + fetch_env_files=parsed_args.files_container is None)) parameters = heat_utils.format_all_parameters( parsed_args.parameter, @@ -160,6 +169,9 @@ class CreateStack(command.ShowOne): if env_files_list: fields['environment_files'] = env_files_list + if parsed_args.files_container: + fields['files_container'] = parsed_args.files_container + if parsed_args.tags: fields['tags'] = parsed_args.tags if parsed_args.timeout: @@ -212,6 +224,13 @@ class UpdateStack(command.ShowOne): help=_('Path to the template') ) parser.add_argument( + '-s', '--files-container', + metavar='<files-container>', + help=_('Swift files container name. Local files other than ' + 'root template would be ignored. If other files are not ' + 'found in swift, heat engine would raise an error.') + ) + parser.add_argument( '-e', '--environment', metavar='<environment>', action='append', help=_('Path to the environment. Can be specified multiple times') @@ -308,13 +327,15 @@ class UpdateStack(command.ShowOne): tpl_files, template = template_utils.process_template_path( parsed_args.template, object_request=http.authenticated_fetcher(client), - existing=parsed_args.existing) + existing=parsed_args.existing, + fetch_child=parsed_args.files_container is None) env_files_list = [] env_files, env = ( template_utils.process_multiple_environments_and_files( env_paths=parsed_args.environment, - env_list_tracker=env_files_list)) + env_list_tracker=env_files_list, + fetch_env_files=parsed_args.files_container is None)) parameters = heat_utils.format_all_parameters( parsed_args.parameter, @@ -338,6 +359,9 @@ class UpdateStack(command.ShowOne): if env_files_list: fields['environment_files'] = env_files_list + if parsed_args.files_container: + fields['files_container'] = parsed_args.files_container + if parsed_args.tags: fields['tags'] = parsed_args.tags if parsed_args.timeout: diff --git a/heatclient/osc/v1/template.py b/heatclient/osc/v1/template.py index c501812..f25263e 100644 --- a/heatclient/osc/v1/template.py +++ b/heatclient/osc/v1/template.py @@ -123,6 +123,13 @@ class Validate(format_utils.YamlFormat): 'specified multiple times') ) parser.add_argument( + '-s', '--files-container', + metavar='<files-container>', + help=_('Swift files container name. Local files other than ' + 'root template would be ignored. If other files are not ' + 'found in swift, heat engine would raise an error.') + ) + parser.add_argument( '--ignore-errors', metavar='<error1,error2,...>', help=_('List of heat errors to ignore') @@ -145,11 +152,13 @@ class Validate(format_utils.YamlFormat): def _validate(heat_client, args): tpl_files, template = template_utils.process_template_path( args.template, - object_request=http.authenticated_fetcher(heat_client)) + object_request=http.authenticated_fetcher(heat_client), + fetch_child=args.files_container is None) env_files_list = [] env_files, env = template_utils.process_multiple_environments_and_files( - env_paths=args.environment, env_list_tracker=env_files_list) + env_paths=args.environment, env_list_tracker=env_files_list, + fetch_env_files=args.files_container is None) fields = { 'template': template, @@ -168,6 +177,9 @@ def _validate(heat_client, args): if args.show_nested: fields['show_nested'] = args.show_nested + if args.files_container: + fields['files_container'] = args.files_container + validation = heat_client.stacks.validate(**fields) data = list(six.itervalues(validation)) columns = list(six.iterkeys(validation)) diff --git a/heatclient/tests/unit/test_template_utils.py b/heatclient/tests/unit/test_template_utils.py index 3d0d478..082283a 100644 --- a/heatclient/tests/unit/test_template_utils.py +++ b/heatclient/tests/unit/test_template_utils.py @@ -127,6 +127,18 @@ class ShellEnvironmentTest(testtools.TestCase): mock.call('file:///home/my/dir/a.yaml') ]) + def test_process_multiple_environment_files_container(self): + + env_list_tracker = [] + env_paths = ['/home/my/dir/env.yaml'] + files, env = template_utils.process_multiple_environments_and_files( + env_paths, env_list_tracker=env_list_tracker, + fetch_env_files=False) + + self.assertEqual(env_paths, env_list_tracker) + self.assertEqual({}, files) + self.assertEqual({}, env) + @mock.patch('six.moves.urllib.request.urlopen') def test_process_environment_relative_file_up(self, mock_url): diff --git a/releasenotes/notes/add-files-container-stack-create-update-324b931f8f474b3d.yaml b/releasenotes/notes/add-files-container-stack-create-update-324b931f8f474b3d.yaml new file mode 100644 index 0000000..6d19428 --- /dev/null +++ b/releasenotes/notes/add-files-container-stack-create-update-324b931f8f474b3d.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Adds ``files-container`` option for stack create, update and + template validate with openstackclient. If specified, no local + files other than root template would be sent to heat engine. + Heat engine would try and download the all other files relative + to the ``files-container``, else raise an error. |