Merge "Return error with path in function validate"
This commit is contained in:
commit
bc6fa5dedf
|
@ -18,6 +18,7 @@ import weakref
|
|||
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
|
||||
|
||||
|
@ -198,16 +199,29 @@ def resolve(snippet):
|
|||
return snippet
|
||||
|
||||
|
||||
def validate(snippet):
|
||||
def validate(snippet, path=''):
|
||||
if isinstance(snippet, Function):
|
||||
snippet.validate()
|
||||
try:
|
||||
snippet.validate()
|
||||
except AssertionError:
|
||||
raise
|
||||
except Exception as e:
|
||||
path = '.'.join([path, snippet.fn_name])
|
||||
raise exception.StackValidationFailed(
|
||||
path=path, message=six.text_type(e))
|
||||
elif isinstance(snippet, collections.Mapping):
|
||||
for v in six.itervalues(snippet):
|
||||
validate(v)
|
||||
def mkpath(key):
|
||||
return '.'.join([path, key])
|
||||
|
||||
for k, v in six.iteritems(snippet):
|
||||
validate(v, mkpath(k))
|
||||
elif (not isinstance(snippet, six.string_types) and
|
||||
isinstance(snippet, collections.Iterable)):
|
||||
for v in snippet:
|
||||
validate(v)
|
||||
def mkpath(indx):
|
||||
return '.'.join([path, '[%d]' % indx])
|
||||
|
||||
for i, v in enumerate(snippet):
|
||||
validate(v, mkpath(i))
|
||||
|
||||
|
||||
def dependencies(snippet, path=''):
|
||||
|
|
|
@ -25,9 +25,9 @@ class OutputDefinition(object):
|
|||
self._resolved_value = None
|
||||
self._description = description
|
||||
|
||||
def validate(self):
|
||||
def validate(self, path=''):
|
||||
"""Validate the output value without resolving it."""
|
||||
function.validate(self._value)
|
||||
function.validate(self._value, path)
|
||||
|
||||
def dep_attrs(self, resource_name):
|
||||
"""Iterate over attributes of a given resource that this references.
|
||||
|
|
|
@ -1501,8 +1501,8 @@ class Resource(object):
|
|||
self.stack.context,
|
||||
self.t.resource_type
|
||||
)
|
||||
|
||||
function.validate(self.t)
|
||||
path = '.'.join([self.stack.t.RESOURCES, self.name])
|
||||
function.validate(self.t, path)
|
||||
self.validate_deletion_policy(self.t.deletion_policy())
|
||||
self.t.update_policy(self.update_policy_schema,
|
||||
self.context).validate()
|
||||
|
|
|
@ -838,15 +838,13 @@ class Stack(collections.Mapping):
|
|||
|
||||
for op_name, output in six.iteritems(self.outputs):
|
||||
try:
|
||||
output.validate()
|
||||
except exception.StackValidationFailed as ex:
|
||||
path = '.'.join([self.t.OUTPUTS, op_name,
|
||||
self.t.OUTPUT_VALUE])
|
||||
output.validate(path)
|
||||
except exception.StackValidationFailed:
|
||||
raise
|
||||
except AssertionError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
raise exception.StackValidationFailed(
|
||||
error='Validation error in output "%s"' % op_name,
|
||||
message=six.text_type(ex))
|
||||
|
||||
def requires_deferred_auth(self):
|
||||
"""Determine whether to perform API requests with deferred auth.
|
||||
|
|
|
@ -178,8 +178,9 @@ class ValidateTest(common.HeatTestCase):
|
|||
def test_validate_func(self):
|
||||
self.assertIsNone(function.validate(self.func))
|
||||
self.func = TestFunction(None, 'foo', ['bar'])
|
||||
ex = self.assertRaises(TypeError, function.validate, self.func)
|
||||
self.assertEqual('Need more arguments', six.text_type(ex))
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
'.foo: Need more arguments',
|
||||
function.validate, self.func)
|
||||
|
||||
def test_validate_dict(self):
|
||||
snippet = {'foo': 'bar', 'blarg': self.func}
|
||||
|
@ -187,8 +188,9 @@ class ValidateTest(common.HeatTestCase):
|
|||
|
||||
self.func = TestFunction(None, 'foo', ['bar'])
|
||||
snippet = {'foo': 'bar', 'blarg': self.func}
|
||||
ex = self.assertRaises(TypeError, function.validate, snippet)
|
||||
self.assertEqual('Need more arguments', six.text_type(ex))
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
'.blarg.foo: Need more arguments',
|
||||
function.validate, snippet)
|
||||
|
||||
def test_validate_list(self):
|
||||
snippet = ['foo', 'bar', 'baz', 'blarg', self.func]
|
||||
|
@ -196,8 +198,9 @@ class ValidateTest(common.HeatTestCase):
|
|||
|
||||
self.func = TestFunction(None, 'foo', ['bar'])
|
||||
snippet = {'foo': 'bar', 'blarg': self.func}
|
||||
ex = self.assertRaises(TypeError, function.validate, snippet)
|
||||
self.assertEqual('Need more arguments', six.text_type(ex))
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
'.blarg.foo: Need more arguments',
|
||||
function.validate, snippet)
|
||||
|
||||
def test_validate_all(self):
|
||||
snippet = ['foo', {'bar': ['baz', {'blarg': self.func}]}]
|
||||
|
@ -205,8 +208,9 @@ class ValidateTest(common.HeatTestCase):
|
|||
|
||||
self.func = TestFunction(None, 'foo', ['bar'])
|
||||
snippet = {'foo': 'bar', 'blarg': self.func}
|
||||
ex = self.assertRaises(TypeError, function.validate, snippet)
|
||||
self.assertEqual('Need more arguments', six.text_type(ex))
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
'.blarg.foo: Need more arguments',
|
||||
function.validate, snippet)
|
||||
|
||||
|
||||
class DependenciesTest(common.HeatTestCase):
|
||||
|
|
|
@ -1120,7 +1120,10 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
'data': {'var1': [1, 2, 3, 4]}}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
yaql = tmpl.parse(None, snippet)
|
||||
self.assertRaises(ValueError, function.validate, yaql)
|
||||
regxp = ('.yaql: Bad expression Parse error: unexpected end '
|
||||
'of statement.')
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed, regxp,
|
||||
function.validate, yaql)
|
||||
|
||||
def test_yaql_data_as_function(self):
|
||||
snippet = {'yaql': {'expression': '$.data.var1.len()',
|
||||
|
@ -1383,7 +1386,10 @@ conditions:
|
|||
snippet = {'repeat': {'template': 'this is %var%',
|
||||
'for_each': '%var%'}}
|
||||
repeat = tmpl.parse(None, snippet)
|
||||
self.assertRaises(TypeError, function.validate, repeat)
|
||||
regxp = ('.repeat: The "for_each" argument to "repeat" '
|
||||
'must contain a map')
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed, regxp,
|
||||
function.validate, repeat)
|
||||
|
||||
def test_digest(self):
|
||||
snippet = {'digest': ['md5', 'foobar']}
|
||||
|
@ -1626,10 +1632,11 @@ conditions:
|
|||
snippet = {'Fn::GetAZs': ''}
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
template.Template(hot_juno_tpl_empty))
|
||||
error = self.assertRaises(exception.InvalidTemplateVersion,
|
||||
function.validate,
|
||||
stack.t.parse(stack, snippet))
|
||||
self.assertIn(next(iter(snippet)), six.text_type(error))
|
||||
regxp = '.Fn::GetAZs: The template version is invalid'
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
regxp,
|
||||
function.validate,
|
||||
stack.t.parse(stack, snippet))
|
||||
|
||||
def test_add_resource(self):
|
||||
hot_tpl = template_format.parse('''
|
||||
|
|
|
@ -1846,13 +1846,11 @@ class StackTest(common.HeatTestCase):
|
|||
self.stack = stack.Stack(self.ctx, 'stack_with_correct_outputs',
|
||||
template.Template(tmpl))
|
||||
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
self.stack.validate)
|
||||
|
||||
self.assertEqual('Validation error in output "Resource_attr": '
|
||||
'The Referenced Attribute '
|
||||
'(AResource Bar) is incorrect.',
|
||||
six.text_type(ex))
|
||||
self.assertRaisesRegexp(
|
||||
exception.StackValidationFailed,
|
||||
('Outputs.Resource_attr.Value.Fn::GetAtt: The Referenced '
|
||||
'Attribute \(AResource Bar\) is incorrect.'),
|
||||
self.stack.validate)
|
||||
|
||||
def test_incorrect_outputs_cfn_incorrect_reference(self):
|
||||
tmpl = template_format.parse("""
|
||||
|
@ -2212,13 +2210,11 @@ class StackTest(common.HeatTestCase):
|
|||
self.stack = stack.Stack(self.ctx, 'stack_with_correct_outputs',
|
||||
template.Template(tmpl))
|
||||
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
self.stack.validate)
|
||||
|
||||
self.assertEqual('Validation error in output "resource_attr": '
|
||||
'The Referenced Attribute '
|
||||
'(AResource Bar) is incorrect.',
|
||||
six.text_type(ex))
|
||||
self.assertRaisesRegexp(
|
||||
exception.StackValidationFailed,
|
||||
('outputs.resource_attr.value.get_attr: The Referenced Attribute '
|
||||
'\(AResource Bar\) is incorrect.'),
|
||||
self.stack.validate)
|
||||
|
||||
def test_snapshot_save_called_first(self):
|
||||
def snapshotting_called_first(stack, action, status, reason):
|
||||
|
|
Loading…
Reference in New Issue