Improve error reporting for missing nested template
When the template for a TemplateResource was missing from the files dict and not otherwise available, we provided misleading feedback when validating the parent template. First, we log that we are fetching the template from a URL, even though we would not actually attempt to do so if it is a file:/// URL. Move the log to after the allowed scheme check, and log debug to indicate when we cannot find a template file. While an exception would be generated in TemplateResource._generate_schema() at resource initialisation time, it is suppressed and saved for later. An empty template is used to generate the properties schema. The exception is re-raised when validate() is called, but during a template validation we only call validate_template(), not validate(), so the first error we run into will be a mismatch of property names. (If no property values were passed in the parent template, we may not even get an error even though we won't be able to create a stack from the given data.) Also re-raise the stored exception at the beginning of validate_template() so that users will see the true source of the error. Change-Id: I1bc100684e1b84fc9ac54ef523d798b317e4dc51 Story: #1739447 Task: 22219
This commit is contained in:
parent
a53219b522
commit
3a96fd7e25
@ -39,13 +39,13 @@ def get(url, allowed_schemes=('http', 'https')):
|
|||||||
the allowed_schemes argument.
|
the allowed_schemes argument.
|
||||||
Raise an IOError if getting the data fails.
|
Raise an IOError if getting the data fails.
|
||||||
"""
|
"""
|
||||||
LOG.info('Fetching data from %s', url)
|
|
||||||
|
|
||||||
components = urllib.parse.urlparse(url)
|
components = urllib.parse.urlparse(url)
|
||||||
|
|
||||||
if components.scheme not in allowed_schemes:
|
if components.scheme not in allowed_schemes:
|
||||||
raise URLFetchError(_('Invalid URL scheme %s') % components.scheme)
|
raise URLFetchError(_('Invalid URL scheme %s') % components.scheme)
|
||||||
|
|
||||||
|
LOG.info('Fetching data from %s', url)
|
||||||
|
|
||||||
if components.scheme == 'file':
|
if components.scheme == 'file':
|
||||||
try:
|
try:
|
||||||
return urllib.request.urlopen(url).read()
|
return urllib.request.urlopen(url).read()
|
||||||
|
@ -195,6 +195,10 @@ class TemplateResource(stack_resource.StackResource):
|
|||||||
reported_excp = None
|
reported_excp = None
|
||||||
t_data = self.stack.t.files.get(self.template_url)
|
t_data = self.stack.t.files.get(self.template_url)
|
||||||
stored_t_data = t_data
|
stored_t_data = t_data
|
||||||
|
|
||||||
|
if t_data is None:
|
||||||
|
LOG.debug('TemplateResource data file "%s" not found in files.',
|
||||||
|
self.template_url)
|
||||||
if not t_data and self.template_url.endswith((".yaml", ".template")):
|
if not t_data and self.template_url.endswith((".yaml", ".template")):
|
||||||
try:
|
try:
|
||||||
t_data = self.get_template_file(self.template_url,
|
t_data = self.get_template_file(self.template_url,
|
||||||
@ -257,9 +261,8 @@ class TemplateResource(stack_resource.StackResource):
|
|||||||
raise exception.StackValidationFailed(message=msg)
|
raise exception.StackValidationFailed(message=msg)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.validation_exception is not None:
|
# Calls validate_template()
|
||||||
msg = six.text_type(self.validation_exception)
|
result = super(TemplateResource, self).validate()
|
||||||
raise exception.StackValidationFailed(message=msg)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.template_data()
|
self.template_data()
|
||||||
@ -280,7 +283,14 @@ class TemplateResource(stack_resource.StackResource):
|
|||||||
facade_cls = fri.get_class(files=self.stack.t.files)
|
facade_cls = fri.get_class(files=self.stack.t.files)
|
||||||
self._validate_against_facade(facade_cls)
|
self._validate_against_facade(facade_cls)
|
||||||
|
|
||||||
return super(TemplateResource, self).validate()
|
return result
|
||||||
|
|
||||||
|
def validate_template(self):
|
||||||
|
if self.validation_exception is not None:
|
||||||
|
msg = six.text_type(self.validation_exception)
|
||||||
|
raise exception.StackValidationFailed(message=msg)
|
||||||
|
|
||||||
|
return super(TemplateResource, self).validate_template()
|
||||||
|
|
||||||
def handle_adopt(self, resource_data=None):
|
def handle_adopt(self, resource_data=None):
|
||||||
return self.create_with_template(self.child_template(),
|
return self.create_with_template(self.child_template(),
|
||||||
|
@ -792,9 +792,11 @@ outputs:
|
|||||||
value:
|
value:
|
||||||
not-important
|
not-important
|
||||||
'''
|
'''
|
||||||
|
template = yaml.safe_load(self.template)
|
||||||
|
del template['resources']['thisone']['properties']['two']
|
||||||
try:
|
try:
|
||||||
self.stack_create(
|
self.stack_create(
|
||||||
template=self.template,
|
template=yaml.safe_dump(template),
|
||||||
environment=self.env,
|
environment=self.env,
|
||||||
files={'facade.yaml': self.templ_facade,
|
files={'facade.yaml': self.templ_facade,
|
||||||
'concrete.yaml': templ_missing_parameter},
|
'concrete.yaml': templ_missing_parameter},
|
||||||
|
Loading…
Reference in New Issue
Block a user