Update --template-object to support nested stacks

This patch updates heatclient so that it supports creating
stacks from an object (Swift container) which contain nested
stack relative links to nested stack URLs.

The motivation here:

We would like to be able to use heatclient to create stacks directly
from Swift containers in TripleO. The --template-object support already
exists and is great... it just needs to support loading the associated
nested stacks as well.

Change-Id: I53ac83e9f9985224d19993935467c03611aaef6a
Closes-bug: #1532326
This commit is contained in:
Dan Prince
2016-01-08 15:52:36 -05:00
parent 1eacabe686
commit 3b242e9575
2 changed files with 49 additions and 8 deletions

View File

@@ -30,6 +30,7 @@ def get_template_contents(template_file=None, template_url=None,
template_object=None, object_request=None,
files=None, existing=False):
is_object = False
# Transform a bare file path to a file:// URL.
if template_file:
template_url = utils.normalise_file_path_to_url(template_file)
@@ -38,6 +39,7 @@ def get_template_contents(template_file=None, template_url=None,
tpl = request.urlopen(template_url).read()
elif template_object:
is_object = True
template_url = template_object
tpl = object_request and object_request('GET',
template_object)
@@ -66,11 +68,13 @@ def get_template_contents(template_file=None, template_url=None,
tmpl_base_url = utils.base_url_for_url(template_url)
if files is None:
files = {}
resolve_template_get_files(template, files, tmpl_base_url)
resolve_template_get_files(template, files, tmpl_base_url, is_object,
object_request)
return files, template
def resolve_template_get_files(template, files, template_base_url):
def resolve_template_get_files(template, files, template_base_url,
is_object=False, object_request=None):
def ignore_if(key, value):
if key != 'get_file' and key != 'type':
@@ -86,7 +90,7 @@ def resolve_template_get_files(template, files, template_base_url):
return isinstance(value, (dict, list))
get_file_contents(template, files, template_base_url,
ignore_if, recurse_if)
ignore_if, recurse_if, is_object, object_request)
def is_template(file_content):
@@ -100,7 +104,8 @@ def is_template(file_content):
def get_file_contents(from_data, files, base_url=None,
ignore_if=None, recurse_if=None):
ignore_if=None, recurse_if=None,
is_object=False, object_request=None):
if recurse_if and recurse_if(from_data):
if isinstance(from_data, dict):
@@ -108,7 +113,8 @@ def get_file_contents(from_data, files, base_url=None,
else:
recurse_data = from_data
for value in recurse_data:
get_file_contents(value, files, base_url, ignore_if, recurse_if)
get_file_contents(value, files, base_url, ignore_if, recurse_if,
is_object, object_request)
if isinstance(from_data, dict):
for key, value in six.iteritems(from_data):
@@ -120,10 +126,18 @@ def get_file_contents(from_data, files, base_url=None,
str_url = parse.urljoin(base_url, value)
if str_url not in files:
file_content = utils.read_url_content(str_url)
if is_object and object_request:
file_content = object_request('GET', str_url)
else:
file_content = utils.read_url_content(str_url)
if is_template(file_content):
template = get_template_contents(
template_url=str_url, files=files)[1]
if is_object:
template = get_template_contents(
template_object=str_url, files=files,
object_request=object_request)[1]
else:
template = get_template_contents(
template_url=str_url, files=files)[1]
file_content = jsonutils.dumps(template)
files[str_url] = file_content
# replace the data value with the normalised absolute URL

View File

@@ -493,6 +493,33 @@ class TestGetTemplateContents(testtools.TestCase):
self.assertEqual({}, files)
self.assertTrue(self.object_requested)
def test_get_nested_stack_template_contents_object(self):
tmpl = ('{"heat_template_version": "2016-04-08",'
'"resources": {'
'"FooBar": {'
'"type": "foo/bar.yaml"}}}')
url = 'http://no.where/path/to/a.yaml'
self.m.ReplayAll()
self.object_requested = False
def object_request(method, object_url):
self.object_requested = True
self.assertEqual('GET', method)
self.assertTrue(object_url.startswith("http://no.where/path/to/"))
if object_url == url:
return tmpl
else:
return '{"heat_template_version": "2016-04-08"}'
files, tmpl_parsed = template_utils.get_template_contents(
template_object=url,
object_request=object_request)
self.assertEqual(files['http://no.where/path/to/foo/bar.yaml'],
'{"heat_template_version": "2016-04-08"}')
self.assertTrue(self.object_requested)
def check_non_utf8_content(self, filename, content):
base_url = 'file:///tmp'
url = '%s/%s' % (base_url, filename)