Merge "Improve StackValidationFailed response in properties"
This commit is contained in:
commit
bc60a1543b
|
@ -83,6 +83,9 @@ class CfnTemplate(template.Template):
|
||||||
return dict((name, parameters.Schema.from_dict(name, schema))
|
return dict((name, parameters.Schema.from_dict(name, schema))
|
||||||
for name, schema in six.iteritems(params))
|
for name, schema in six.iteritems(params))
|
||||||
|
|
||||||
|
def get_section_name(self, section):
|
||||||
|
return section
|
||||||
|
|
||||||
def parameters(self, stack_identifier, user_params, param_defaults=None):
|
def parameters(self, stack_identifier, user_params, param_defaults=None):
|
||||||
return parameters.Parameters(stack_identifier, self,
|
return parameters.Parameters(stack_identifier, self,
|
||||||
user_params=user_params,
|
user_params=user_params,
|
||||||
|
|
|
@ -56,6 +56,12 @@ class HOTemplate20130523(template.Template):
|
||||||
cfn_template.CfnTemplate.RESOURCES: RESOURCES,
|
cfn_template.CfnTemplate.RESOURCES: RESOURCES,
|
||||||
cfn_template.CfnTemplate.OUTPUTS: OUTPUTS}
|
cfn_template.CfnTemplate.OUTPUTS: OUTPUTS}
|
||||||
|
|
||||||
|
_RESOURCE_HOT_TO_CFN_ATTRS = {'type': 'Type',
|
||||||
|
'properties': 'Properties',
|
||||||
|
'metadata': 'Metadata',
|
||||||
|
'depends_on': 'DependsOn',
|
||||||
|
'deletion_policy': 'DeletionPolicy',
|
||||||
|
'update_policy': 'UpdatePolicy'}
|
||||||
functions = {
|
functions = {
|
||||||
'Fn::GetAZs': cfn_funcs.GetAZs,
|
'Fn::GetAZs': cfn_funcs.GetAZs,
|
||||||
'get_param': hot_funcs.GetParam,
|
'get_param': hot_funcs.GetParam,
|
||||||
|
@ -157,15 +163,14 @@ class HOTemplate20130523(template.Template):
|
||||||
|
|
||||||
def _translate_resources(self, resources):
|
def _translate_resources(self, resources):
|
||||||
"""Get the resources of the template translated into CFN format."""
|
"""Get the resources of the template translated into CFN format."""
|
||||||
HOT_TO_CFN_ATTRS = {'type': 'Type',
|
|
||||||
'properties': 'Properties',
|
|
||||||
'metadata': 'Metadata',
|
|
||||||
'depends_on': 'DependsOn',
|
|
||||||
'deletion_policy': 'DeletionPolicy',
|
|
||||||
'update_policy': 'UpdatePolicy'}
|
|
||||||
|
|
||||||
return self._translate_section('resources', 'type', resources,
|
return self._translate_section('resources', 'type', resources,
|
||||||
HOT_TO_CFN_ATTRS)
|
self._RESOURCE_HOT_TO_CFN_ATTRS)
|
||||||
|
|
||||||
|
def get_section_name(self, section):
|
||||||
|
cfn_to_hot_attrs = dict(zip(self._RESOURCE_HOT_TO_CFN_ATTRS.values(),
|
||||||
|
self._RESOURCE_HOT_TO_CFN_ATTRS.keys()))
|
||||||
|
return cfn_to_hot_attrs.get(section, section)
|
||||||
|
|
||||||
def _translate_outputs(self, outputs):
|
def _translate_outputs(self, outputs):
|
||||||
"""Get the outputs of the template translated into CFN format."""
|
"""Get the outputs of the template translated into CFN format."""
|
||||||
|
|
|
@ -267,7 +267,6 @@ class Property(object):
|
||||||
keys = list(self.schema.schema)
|
keys = list(self.schema.schema)
|
||||||
schemata = dict((k, self.schema.schema[k]) for k in keys)
|
schemata = dict((k, self.schema.schema[k]) for k in keys)
|
||||||
properties = Properties(schemata, dict(child_values),
|
properties = Properties(schemata, dict(child_values),
|
||||||
parent_name=self.name,
|
|
||||||
context=self.context)
|
context=self.context)
|
||||||
if validate:
|
if validate:
|
||||||
properties.validate()
|
properties.validate()
|
||||||
|
@ -343,15 +342,16 @@ class Property(object):
|
||||||
class Properties(collections.Mapping):
|
class Properties(collections.Mapping):
|
||||||
|
|
||||||
def __init__(self, schema, data, resolver=lambda d: d, parent_name=None,
|
def __init__(self, schema, data, resolver=lambda d: d, parent_name=None,
|
||||||
context=None):
|
context=None, section=None):
|
||||||
self.props = dict((k, Property(s, k, context))
|
self.props = dict((k, Property(s, k, context))
|
||||||
for k, s in schema.items())
|
for k, s in schema.items())
|
||||||
self.resolve = resolver
|
self.resolve = resolver
|
||||||
self.data = data
|
self.data = data
|
||||||
if parent_name is None:
|
self.error_prefix = []
|
||||||
self.error_prefix = ''
|
if parent_name is not None:
|
||||||
else:
|
self.error_prefix.append(parent_name)
|
||||||
self.error_prefix = '%s: ' % parent_name
|
if section is not None:
|
||||||
|
self.error_prefix.append(section)
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -369,6 +369,12 @@ class Properties(collections.Mapping):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def validate(self, with_value=True):
|
def validate(self, with_value=True):
|
||||||
|
try:
|
||||||
|
for key in self.data:
|
||||||
|
if key not in self.props:
|
||||||
|
msg = _("Unknown Property %s") % key
|
||||||
|
raise exception.StackValidationFailed(message=msg)
|
||||||
|
|
||||||
for (key, prop) in self.props.items():
|
for (key, prop) in self.props.items():
|
||||||
# check that update_allowed and immutable
|
# check that update_allowed and immutable
|
||||||
# do not contradict each other
|
# do not contradict each other
|
||||||
|
@ -383,24 +389,38 @@ class Properties(collections.Mapping):
|
||||||
if with_value:
|
if with_value:
|
||||||
try:
|
try:
|
||||||
self._get_property_value(key, validate=True)
|
self._get_property_value(key, validate=True)
|
||||||
|
except exception.StackValidationFailed as ex:
|
||||||
|
path = [key]
|
||||||
|
path.extend(ex.path)
|
||||||
|
raise exception.StackValidationFailed(
|
||||||
|
path=path, message=ex.error_message)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
msg = _("Property error : %s") % e
|
if prop.required() and key not in self.data:
|
||||||
raise exception.StackValidationFailed(message=msg)
|
path = []
|
||||||
|
else:
|
||||||
|
path = [key]
|
||||||
|
raise exception.StackValidationFailed(
|
||||||
|
path=path, message=six.text_type(e))
|
||||||
|
|
||||||
# are there unimplemented Properties
|
# are there unimplemented Properties
|
||||||
if not prop.implemented() and key in self.data:
|
if not prop.implemented() and key in self.data:
|
||||||
msg = _("Property %s not implemented yet") % key
|
msg = _("Property %s not implemented yet") % key
|
||||||
raise exception.StackValidationFailed(message=msg)
|
raise exception.StackValidationFailed(message=msg)
|
||||||
|
except exception.StackValidationFailed as ex:
|
||||||
for key in self.data:
|
# NOTE(prazumovsky): should reraise exception for adding specific
|
||||||
if key not in self.props:
|
# error name and error_prefix to path for correct error message
|
||||||
msg = _("Unknown Property %s") % key
|
# building.
|
||||||
raise exception.StackValidationFailed(message=msg)
|
path = self.error_prefix
|
||||||
|
path.extend(ex.path)
|
||||||
|
raise exception.StackValidationFailed(
|
||||||
|
error=ex.error or 'Property error',
|
||||||
|
path=path,
|
||||||
|
message=ex.error_message
|
||||||
|
)
|
||||||
|
|
||||||
def _get_property_value(self, key, validate=False):
|
def _get_property_value(self, key, validate=False):
|
||||||
if key not in self:
|
if key not in self:
|
||||||
raise KeyError(_('%(prefix)sInvalid Property %(key)s') %
|
raise KeyError(_('Invalid Property %s') % key)
|
||||||
{'prefix': self.error_prefix, 'key': key})
|
|
||||||
|
|
||||||
prop = self.props[key]
|
prop = self.props[key]
|
||||||
|
|
||||||
|
@ -414,16 +434,20 @@ class Properties(collections.Mapping):
|
||||||
|
|
||||||
value = self.resolve(unresolved_value)
|
value = self.resolve(unresolved_value)
|
||||||
return prop.get_value(value, validate)
|
return prop.get_value(value, validate)
|
||||||
|
# Children can raise StackValidationFailed with unique path which
|
||||||
|
# is necessary for further use in StackValidationFailed exception.
|
||||||
|
# So we need to handle this exception in this method.
|
||||||
|
except exception.StackValidationFailed as e:
|
||||||
|
raise exception.StackValidationFailed(path=e.path,
|
||||||
|
message=e.error_message)
|
||||||
# the resolver function could raise any number of exceptions,
|
# the resolver function could raise any number of exceptions,
|
||||||
# so handle this generically
|
# so handle this generically
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError('%s%s %s' % (self.error_prefix, key,
|
raise ValueError(six.text_type(e))
|
||||||
six.text_type(e)))
|
|
||||||
elif prop.has_default():
|
elif prop.has_default():
|
||||||
return prop.get_value(None, validate)
|
return prop.get_value(None, validate)
|
||||||
elif prop.required():
|
elif prop.required():
|
||||||
raise ValueError(_('%(prefix)sProperty %(key)s not assigned') %
|
raise ValueError(_('Property %s not assigned') % key)
|
||||||
{'prefix': self.error_prefix, 'key': key})
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self._get_property_value(key)
|
return self._get_property_value(key)
|
||||||
|
|
|
@ -874,7 +874,18 @@ class Resource(object):
|
||||||
|
|
||||||
function.validate(self.t)
|
function.validate(self.t)
|
||||||
self.validate_deletion_policy(self.t.deletion_policy())
|
self.validate_deletion_policy(self.t.deletion_policy())
|
||||||
return self.properties.validate(with_value=self.stack.strict_validate)
|
try:
|
||||||
|
validate = self.properties.validate(
|
||||||
|
with_value=self.stack.strict_validate)
|
||||||
|
except exception.StackValidationFailed as ex:
|
||||||
|
path = [self.stack.t.RESOURCES, ex.path[0],
|
||||||
|
self.stack.t.get_section_name(ex.path[1])]
|
||||||
|
path.extend(ex.path[2:])
|
||||||
|
raise exception.StackValidationFailed(
|
||||||
|
error=ex.error,
|
||||||
|
path=path,
|
||||||
|
message=ex.error_message)
|
||||||
|
return validate
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_deletion_policy(cls, policy):
|
def validate_deletion_policy(cls, policy):
|
||||||
|
|
|
@ -183,7 +183,8 @@ class ResourceDefinitionCore(object):
|
||||||
require a context to validate constraints.
|
require a context to validate constraints.
|
||||||
"""
|
"""
|
||||||
return properties.Properties(schema, self._properties or {},
|
return properties.Properties(schema, self._properties or {},
|
||||||
function.resolve, self.name, context)
|
function.resolve, self.name, context,
|
||||||
|
section=PROPERTIES)
|
||||||
|
|
||||||
def deletion_policy(self):
|
def deletion_policy(self):
|
||||||
"""
|
"""
|
||||||
|
@ -201,7 +202,8 @@ class ResourceDefinitionCore(object):
|
||||||
require a context to validate constraints.
|
require a context to validate constraints.
|
||||||
"""
|
"""
|
||||||
return properties.Properties(schema, self._update_policy or {},
|
return properties.Properties(schema, self._update_policy or {},
|
||||||
function.resolve, self.name, context)
|
function.resolve, self.name, context,
|
||||||
|
section=UPDATE_POLICY)
|
||||||
|
|
||||||
def metadata(self):
|
def metadata(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -816,7 +816,7 @@ class EngineService(service.Service):
|
||||||
|
|
||||||
env = environment.Environment(params)
|
env = environment.Environment(params)
|
||||||
|
|
||||||
for res in tmpl_resources.values():
|
for name, res in six.iteritems(tmpl_resources):
|
||||||
ResourceClass = env.get_class(res['Type'])
|
ResourceClass = env.get_class(res['Type'])
|
||||||
if ResourceClass == resources.template_resource.TemplateResource:
|
if ResourceClass == resources.template_resource.TemplateResource:
|
||||||
# we can't validate a TemplateResource unless we instantiate
|
# we can't validate a TemplateResource unless we instantiate
|
||||||
|
@ -824,9 +824,12 @@ class EngineService(service.Service):
|
||||||
# parameters into properties_schema.
|
# parameters into properties_schema.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
props = properties.Properties(ResourceClass.properties_schema,
|
props = properties.Properties(
|
||||||
|
ResourceClass.properties_schema,
|
||||||
res.get('Properties', {}),
|
res.get('Properties', {}),
|
||||||
context=cnxt)
|
parent_name=six.text_type(name),
|
||||||
|
context=cnxt,
|
||||||
|
section='Properties')
|
||||||
deletion_policy = res.get('DeletionPolicy', 'Delete')
|
deletion_policy = res.get('DeletionPolicy', 'Delete')
|
||||||
try:
|
try:
|
||||||
ResourceClass.validate_deletion_policy(deletion_policy)
|
ResourceClass.validate_deletion_policy(deletion_policy)
|
||||||
|
|
|
@ -158,6 +158,11 @@ class Template(collections.Mapping):
|
||||||
'''Return a dict of parameters.Schema objects for the parameters.'''
|
'''Return a dict of parameters.Schema objects for the parameters.'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_section_name(self, section):
|
||||||
|
"""Return a correct section name."""
|
||||||
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def parameters(self, stack_identifier, user_params, param_defaults=None):
|
def parameters(self, stack_identifier, user_params, param_defaults=None):
|
||||||
'''Return a parameters.Parameters object for the stack.'''
|
'''Return a parameters.Parameters object for the stack.'''
|
||||||
|
|
|
@ -133,8 +133,10 @@ class LaunchConfigurationTest(common.HeatTestCase):
|
||||||
|
|
||||||
self.patchobject(nova.NovaClientPlugin, 'get_server',
|
self.patchobject(nova.NovaClientPlugin, 'get_server',
|
||||||
side_effect=exception.ServerNotFound(server='5678'))
|
side_effect=exception.ServerNotFound(server='5678'))
|
||||||
msg = ("Property error : LaunchConfig: InstanceId Error validating "
|
msg = ("Property error : "
|
||||||
"value '5678': The server (5678) could not be found.")
|
"Resources.LaunchConfig.Properties.InstanceId: "
|
||||||
|
"Error validating value '5678': The server (5678) "
|
||||||
|
"could not be found.")
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertIn(msg, six.text_type(exc))
|
self.assertIn(msg, six.text_type(exc))
|
||||||
|
@ -193,9 +195,10 @@ class LaunchConfigurationTest(common.HeatTestCase):
|
||||||
self.validate_launch_config, t,
|
self.validate_launch_config, t,
|
||||||
stack, 'LaunchConfig')
|
stack, 'LaunchConfig')
|
||||||
|
|
||||||
excepted_error = ('Property error : LaunchConfig: BlockDeviceMappings '
|
excepted_error = (
|
||||||
'Property error : BlockDeviceMappings: 0 Property '
|
'Property error : '
|
||||||
'error : 0: Property DeviceName not assigned')
|
'Resources.LaunchConfig.Properties.BlockDeviceMappings[0]: '
|
||||||
|
'Property DeviceName not assigned')
|
||||||
self.assertIn(excepted_error, six.text_type(e))
|
self.assertIn(excepted_error, six.text_type(e))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
|
@ -220,8 +220,10 @@ class TestAutoScalingGroupValidation(common.HeatTestCase):
|
||||||
rsrc = stack['WebServerGroup']
|
rsrc = stack['WebServerGroup']
|
||||||
self._stub_nova_server_get(not_found=True)
|
self._stub_nova_server_get(not_found=True)
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
msg = ("Property error : WebServerGroup: InstanceId Error validating "
|
msg = ("Property error : "
|
||||||
"value '5678': The server (5678) could not be found")
|
"Resources.WebServerGroup.Properties.InstanceId: "
|
||||||
|
"Error validating value '5678': The server (5678) could "
|
||||||
|
"not be found.")
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertIn(msg, six.text_type(exc))
|
self.assertIn(msg, six.text_type(exc))
|
||||||
|
|
|
@ -203,7 +203,9 @@ class VolumeTest(vt_base.BaseVolumeTest):
|
||||||
|
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
self.create_volume, self.t, stack, 'DataVolume')
|
self.create_volume, self.t, stack, 'DataVolume')
|
||||||
self.assertIn('Tags Property error', six.text_type(ex))
|
self.assertEqual("Property error : "
|
||||||
|
"Resources.DataVolume.Properties.Tags[0]: "
|
||||||
|
"Unknown Property Foo", six.text_type(ex))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
@ -664,8 +666,8 @@ class VolumeTest(vt_base.BaseVolumeTest):
|
||||||
self.create_volume,
|
self.create_volume,
|
||||||
self.t, stack, 'DataVolume')
|
self.t, stack, 'DataVolume')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : DataVolume: Size 0 is out of "
|
"Property error : Resources.DataVolume.Properties.Size: "
|
||||||
"range (min: 1, max: None)", six.text_type(error))
|
"0 is out of range (min: 1, max: None)", six.text_type(error))
|
||||||
|
|
||||||
def test_volume_attachment_updates_not_supported(self):
|
def test_volume_attachment_updates_not_supported(self):
|
||||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_server')
|
self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_server')
|
||||||
|
|
|
@ -103,8 +103,8 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
|
||||||
self.create_volume,
|
self.create_volume,
|
||||||
self.t, stack, 'volume')
|
self.t, stack, 'volume')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : volume: size 0 is out of "
|
"Property error : resources.volume.properties.size: "
|
||||||
"range (min: 1, max: None)", six.text_type(error))
|
"0 is out of range (min: 1, max: None)", six.text_type(error))
|
||||||
|
|
||||||
def test_cinder_create(self):
|
def test_cinder_create(self):
|
||||||
fv = vt_base.FakeVolume('creating')
|
fv = vt_base.FakeVolume('creating')
|
||||||
|
|
|
@ -377,8 +377,8 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
error = self.assertRaises(exception.StackValidationFailed,
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : MEMAlarmHigh: %s Value '60a' is not an "
|
"Property error : Resources.MEMAlarmHigh.Properties.%s: "
|
||||||
"integer" % p, six.text_type(error))
|
"Value '60a' is not an integer" % p, six.text_type(error))
|
||||||
|
|
||||||
def test_mem_alarm_high_not_integer_parameters(self):
|
def test_mem_alarm_high_not_integer_parameters(self):
|
||||||
snippet = template_format.parse(not_string_alarm_template)
|
snippet = template_format.parse(not_string_alarm_template)
|
||||||
|
@ -392,8 +392,9 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
error = self.assertRaises(exception.StackValidationFailed,
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : MEMAlarmHigh: %s int() argument must be "
|
"Property error : Resources.MEMAlarmHigh.Properties.%s: "
|
||||||
"a string or a number, not 'list'" % p, six.text_type(error))
|
"int() argument must be a string or a number, not "
|
||||||
|
"'list'" % p, six.text_type(error))
|
||||||
|
|
||||||
def test_mem_alarm_high_check_not_required_parameters(self):
|
def test_mem_alarm_high_check_not_required_parameters(self):
|
||||||
snippet = template_format.parse(not_string_alarm_template)
|
snippet = template_format.parse(not_string_alarm_template)
|
||||||
|
@ -406,7 +407,8 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
error = self.assertRaises(exception.StackValidationFailed,
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : MEMAlarmHigh: Property meter_name not assigned",
|
"Property error : Resources.MEMAlarmHigh.Properties: "
|
||||||
|
"Property meter_name not assigned",
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
for p in ('period', 'evaluation_periods', 'statistic',
|
for p in ('period', 'evaluation_periods', 'statistic',
|
||||||
|
@ -521,8 +523,9 @@ class CombinationAlarmTest(common.HeatTestCase):
|
||||||
error = self.assertRaises(exception.StackValidationFailed,
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
rsrc.validate)
|
rsrc.validate)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : CombinAlarm: alarm_ids length (0) is out of "
|
"Property error : Resources.CombinAlarm.Properties.alarm_ids: "
|
||||||
"range (min: 1, max: None)", six.text_type(error))
|
"length (0) is out of range (min: 1, max: None)",
|
||||||
|
six.text_type(error))
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
rsrc = self.create_alarm()
|
rsrc = self.create_alarm()
|
||||||
|
|
|
@ -99,7 +99,8 @@ class GlanceImageTest(common.HeatTestCase):
|
||||||
)
|
)
|
||||||
image = stack['image']
|
image = stack['image']
|
||||||
image.t['Properties']['min_disk'] = -1
|
image.t['Properties']['min_disk'] = -1
|
||||||
error_msg = 'min_disk -1 is out of range (min: 0, max: None)'
|
error_msg = ('Property error : resources.image.properties.min_disk: '
|
||||||
|
'-1 is out of range (min: 0, max: None)')
|
||||||
self._test_validate(image, error_msg)
|
self._test_validate(image, error_msg)
|
||||||
|
|
||||||
def test_invalid_min_ram(self):
|
def test_invalid_min_ram(self):
|
||||||
|
@ -111,7 +112,8 @@ class GlanceImageTest(common.HeatTestCase):
|
||||||
)
|
)
|
||||||
image = stack['image']
|
image = stack['image']
|
||||||
image.t['Properties']['min_ram'] = -1
|
image.t['Properties']['min_ram'] = -1
|
||||||
error_msg = 'min_ram -1 is out of range (min: 0, max: None)'
|
error_msg = ('Property error : resources.image.properties.min_ram: '
|
||||||
|
'-1 is out of range (min: 0, max: None)')
|
||||||
self._test_validate(image, error_msg)
|
self._test_validate(image, error_msg)
|
||||||
|
|
||||||
def test_miss_disk_format(self):
|
def test_miss_disk_format(self):
|
||||||
|
@ -135,7 +137,9 @@ class GlanceImageTest(common.HeatTestCase):
|
||||||
)
|
)
|
||||||
image = stack['image']
|
image = stack['image']
|
||||||
image.t['Properties']['disk_format'] = 'incorrect_format'
|
image.t['Properties']['disk_format'] = 'incorrect_format'
|
||||||
error_msg = ('disk_format "incorrect_format" is not an allowed value '
|
error_msg = ('Property error : '
|
||||||
|
'resources.image.properties.disk_format: '
|
||||||
|
'"incorrect_format" is not an allowed value '
|
||||||
'[ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, iso]')
|
'[ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, iso]')
|
||||||
self._test_validate(image, error_msg)
|
self._test_validate(image, error_msg)
|
||||||
|
|
||||||
|
@ -160,8 +164,10 @@ class GlanceImageTest(common.HeatTestCase):
|
||||||
)
|
)
|
||||||
image = stack['image']
|
image = stack['image']
|
||||||
image.t['Properties']['container_format'] = 'incorrect_format'
|
image.t['Properties']['container_format'] = 'incorrect_format'
|
||||||
error_msg = ('container_format "incorrect_format" is not an '
|
error_msg = ('Property error : '
|
||||||
'allowed value [ami, ari, aki, bare, ova, ovf]')
|
'resources.image.properties.container_format: '
|
||||||
|
'"incorrect_format" is not an allowed value '
|
||||||
|
'[ami, ari, aki, bare, ova, ovf]')
|
||||||
self._test_validate(image, error_msg)
|
self._test_validate(image, error_msg)
|
||||||
|
|
||||||
def test_miss_location(self):
|
def test_miss_location(self):
|
||||||
|
|
|
@ -227,8 +227,9 @@ class InstancesTest(common.HeatTestCase):
|
||||||
|
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
instance.validate)
|
instance.validate)
|
||||||
self.assertIn("VolumeId Error validating value '1234': "
|
self.assertIn("WebServer.Properties.Volumes[0].VolumeId: "
|
||||||
"The Volume (1234) could not be found.",
|
"Error validating value '1234': The Volume "
|
||||||
|
"(1234) could not be found.",
|
||||||
six.text_type(exc))
|
six.text_type(exc))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -322,9 +323,10 @@ class InstancesTest(common.HeatTestCase):
|
||||||
|
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
instance.validate)
|
instance.validate)
|
||||||
excepted_error = ('Property error : WebServer: BlockDeviceMappings '
|
excepted_error = (
|
||||||
'Property error : BlockDeviceMappings: 0 Property '
|
'Property error : '
|
||||||
'error : 0: Property DeviceName not assigned')
|
'Resources.WebServer.Properties.BlockDeviceMappings[0]: '
|
||||||
|
'Property DeviceName not assigned')
|
||||||
self.assertIn(excepted_error, six.text_type(exc))
|
self.assertIn(excepted_error, six.text_type(exc))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -382,9 +384,9 @@ class InstancesTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(instance.create)
|
create = scheduler.TaskRunner(instance.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"StackValidationFailed: Property error : WebServer: "
|
"StackValidationFailed: Property error : "
|
||||||
"ImageId Error validating value 'Slackware': "
|
"WebServer.Properties.ImageId: Error validating value "
|
||||||
"The Image (Slackware) could not be found.",
|
"'Slackware': The Image (Slackware) could not be found.",
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -409,9 +411,9 @@ class InstancesTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(instance.create)
|
create = scheduler.TaskRunner(instance.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'StackValidationFailed: Property error : WebServer: '
|
'StackValidationFailed: Property error : '
|
||||||
'ImageId Multiple physical resources were '
|
'WebServer.Properties.ImageId: Multiple physical '
|
||||||
'found with name (CentOS 5.2).',
|
'resources were found with name (CentOS 5.2).',
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -433,8 +435,8 @@ class InstancesTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(instance.create)
|
create = scheduler.TaskRunner(instance.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'StackValidationFailed: Property error : WebServer: '
|
'StackValidationFailed: Property error : '
|
||||||
'ImageId 404 (HTTP 404)',
|
'WebServer.Properties.ImageId: 404 (HTTP 404)',
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
|
@ -103,11 +103,11 @@ class NovaKeyPairTest(common.HeatTestCase):
|
||||||
definition = stack.t.resource_definitions(stack)['kp']
|
definition = stack.t.resource_definitions(stack)['kp']
|
||||||
kp_res = nova_keypair.KeyPair('kp', definition, stack)
|
kp_res = nova_keypair.KeyPair('kp', definition, stack)
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
create = scheduler.TaskRunner(kp_res.create)
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
kp_res.validate)
|
||||||
self.assertIn("Property error", six.text_type(error))
|
self.assertIn("Property error", six.text_type(error))
|
||||||
self.assertIn("name length (0) is out of range (min: 1, max: 255)",
|
self.assertIn("kp.properties.name: length (0) is out of "
|
||||||
six.text_type(error))
|
"range (min: 1, max: 255)", six.text_type(error))
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_create_key_excess_name_length(self):
|
def test_create_key_excess_name_length(self):
|
||||||
|
@ -119,11 +119,11 @@ class NovaKeyPairTest(common.HeatTestCase):
|
||||||
definition = stack.t.resource_definitions(stack)['kp']
|
definition = stack.t.resource_definitions(stack)['kp']
|
||||||
kp_res = nova_keypair.KeyPair('kp', definition, stack)
|
kp_res = nova_keypair.KeyPair('kp', definition, stack)
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
create = scheduler.TaskRunner(kp_res.create)
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
kp_res.validate)
|
||||||
self.assertIn("Property error", six.text_type(error))
|
self.assertIn("Property error", six.text_type(error))
|
||||||
self.assertIn("name length (256) is out of range (min: 1, max: 255)",
|
self.assertIn("kp.properties.name: length (256) is out of "
|
||||||
six.text_type(error))
|
"range (min: 1, max: 255)", six.text_type(error))
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_delete_key(self):
|
def test_delete_key(self):
|
||||||
|
|
|
@ -882,8 +882,8 @@ class PropertyTest(common.HeatTestCase):
|
||||||
p = properties.Property({'Type': 'Map', 'Schema': map_schema})
|
p = properties.Property({'Type': 'Map', 'Schema': map_schema})
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
p.get_value, {'valid': 'fish'}, True)
|
p.get_value, {'valid': 'fish'}, True)
|
||||||
self.assertEqual('Property error : valid "fish" is not '
|
self.assertEqual('Property error : valid: "fish" is not a '
|
||||||
'a valid boolean', six.text_type(ex))
|
'valid boolean', six.text_type(ex))
|
||||||
|
|
||||||
def test_map_schema_missing_data(self):
|
def test_map_schema_missing_data(self):
|
||||||
map_schema = {'valid': {'Type': 'Boolean'}}
|
map_schema = {'valid': {'Type': 'Boolean'}}
|
||||||
|
@ -914,8 +914,8 @@ class PropertyTest(common.HeatTestCase):
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
p.get_value,
|
p.get_value,
|
||||||
[{'valid': 'True'}, {'valid': 'fish'}], True)
|
[{'valid': 'True'}, {'valid': 'fish'}], True)
|
||||||
self.assertEqual('Property error : 1 Property error : 1: valid '
|
self.assertEqual('Property error : [1].valid: "fish" is not '
|
||||||
'"fish" is not a valid boolean', six.text_type(ex))
|
'a valid boolean', six.text_type(ex))
|
||||||
|
|
||||||
def test_list_schema_int_good(self):
|
def test_list_schema_int_good(self):
|
||||||
list_schema = {'Type': 'Integer'}
|
list_schema = {'Type': 'Integer'}
|
||||||
|
@ -927,7 +927,7 @@ class PropertyTest(common.HeatTestCase):
|
||||||
p = properties.Property({'Type': 'List', 'Schema': list_schema})
|
p = properties.Property({'Type': 'List', 'Schema': list_schema})
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
p.get_value, [42, 'fish'], True)
|
p.get_value, [42, 'fish'], True)
|
||||||
self.assertEqual("Property error : 1 Value 'fish' is not "
|
self.assertEqual("Property error : [1]: Value 'fish' is not "
|
||||||
"an integer", six.text_type(ex))
|
"an integer", six.text_type(ex))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1056,16 +1056,6 @@ class PropertiesTest(common.HeatTestCase):
|
||||||
props = properties.Properties(schema, {'foo': None})
|
props = properties.Properties(schema, {'foo': None})
|
||||||
self.assertEqual(['one', 'two'], props['foo'])
|
self.assertEqual(['one', 'two'], props['foo'])
|
||||||
|
|
||||||
def test_bad_resolver(self):
|
|
||||||
schema = {'foo': {'Type': 'String', 'Default': 'bar'}}
|
|
||||||
|
|
||||||
def bad_resolver(prop):
|
|
||||||
raise Exception('resolution failed!')
|
|
||||||
|
|
||||||
props = properties.Properties(schema, {'foo': 'baz'}, bad_resolver)
|
|
||||||
err = self.assertRaises(ValueError, props.get, 'foo')
|
|
||||||
self.assertEqual('foo resolution failed!', six.text_type(err))
|
|
||||||
|
|
||||||
def test_resolve_returns_none(self):
|
def test_resolve_returns_none(self):
|
||||||
schema = {'foo': {'Type': 'String', "MinLength": "5"}}
|
schema = {'foo': {'Type': 'String', "MinLength": "5"}}
|
||||||
|
|
||||||
|
@ -1543,14 +1533,14 @@ class PropertiesValidationTest(common.HeatTestCase):
|
||||||
schema = {'foo': {'Type': 'String'}}
|
schema = {'foo': {'Type': 'String'}}
|
||||||
props = properties.Properties(schema, {'foo': ['foo', 'bar']})
|
props = properties.Properties(schema, {'foo': ['foo', 'bar']})
|
||||||
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
||||||
self.assertEqual('Property error : foo Value must be a string',
|
self.assertEqual('Property error : foo: Value must be a string',
|
||||||
six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_dict_instead_string(self):
|
def test_dict_instead_string(self):
|
||||||
schema = {'foo': {'Type': 'String'}}
|
schema = {'foo': {'Type': 'String'}}
|
||||||
props = properties.Properties(schema, {'foo': {'foo': 'bar'}})
|
props = properties.Properties(schema, {'foo': {'foo': 'bar'}})
|
||||||
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
|
||||||
self.assertEqual('Property error : foo Value must be a string',
|
self.assertEqual('Property error : foo: Value must be a string',
|
||||||
six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_none_string(self):
|
def test_none_string(self):
|
||||||
|
@ -1717,8 +1707,8 @@ class PropertiesValidationTest(common.HeatTestCase):
|
||||||
props = properties.Properties(schema, invalid_data)
|
props = properties.Properties(schema, invalid_data)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
props.validate)
|
props.validate)
|
||||||
self.assertEqual('Property error : foo Property error : foo: 0 '
|
self.assertEqual('Property error : foo[0]: Unknown Property bar',
|
||||||
'Unknown Property bar', six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_nested_properties_schema_invalid_property_in_map(self):
|
def test_nested_properties_schema_invalid_property_in_map(self):
|
||||||
child_schema = {'Key': {'Type': 'String',
|
child_schema = {'Key': {'Type': 'String',
|
||||||
|
@ -1736,8 +1726,8 @@ class PropertiesValidationTest(common.HeatTestCase):
|
||||||
props = properties.Properties(schema, invalid_data)
|
props = properties.Properties(schema, invalid_data)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
props.validate)
|
props.validate)
|
||||||
self.assertEqual('Property error : foo Property error : foo: boo '
|
self.assertEqual('Property error : foo.boo: Unknown Property bar',
|
||||||
'Unknown Property bar', six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_more_nested_properties_schema_invalid_property_in_list(self):
|
def test_more_nested_properties_schema_invalid_property_in_list(self):
|
||||||
nested_child_schema = {'Key': {'Type': 'String',
|
nested_child_schema = {'Key': {'Type': 'String',
|
||||||
|
@ -1754,8 +1744,7 @@ class PropertiesValidationTest(common.HeatTestCase):
|
||||||
props = properties.Properties(schema, invalid_data)
|
props = properties.Properties(schema, invalid_data)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
props.validate)
|
props.validate)
|
||||||
self.assertEqual('Property error : foo Property error : foo: 0 '
|
self.assertEqual('Property error : foo[0].doo: Unknown Property bar',
|
||||||
'Property error : 0: doo Unknown Property bar',
|
|
||||||
six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_more_nested_properties_schema_invalid_property_in_map(self):
|
def test_more_nested_properties_schema_invalid_property_in_map(self):
|
||||||
|
@ -1773,8 +1762,7 @@ class PropertiesValidationTest(common.HeatTestCase):
|
||||||
props = properties.Properties(schema, invalid_data)
|
props = properties.Properties(schema, invalid_data)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
props.validate)
|
props.validate)
|
||||||
self.assertEqual('Property error : foo Property error : foo: boo '
|
self.assertEqual('Property error : foo.boo.doo: Unknown Property bar',
|
||||||
'Property error : boo: doo Unknown Property bar',
|
|
||||||
six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
def test_schema_to_template_empty_schema(self):
|
def test_schema_to_template_empty_schema(self):
|
||||||
|
|
|
@ -223,7 +223,7 @@ Resources:
|
||||||
'''
|
'''
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
self.create_stack, template_random_string)
|
self.create_stack, template_random_string)
|
||||||
self.assertIn('length 513 is out of range (min: 1, max: 512)',
|
self.assertIn('513 is out of range (min: 1, max: 512)',
|
||||||
six.text_type(exc))
|
six.text_type(exc))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -547,7 +547,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
tmpl = rsrc_defn.ResourceDefinition(rname, 'Foo', {})
|
tmpl = rsrc_defn.ResourceDefinition(rname, 'Foo', {})
|
||||||
res = generic_rsrc.ResourceWithRequiredProps(rname, tmpl, self.stack)
|
res = generic_rsrc.ResourceWithRequiredProps(rname, tmpl, self.stack)
|
||||||
|
|
||||||
estr = 'Property error : test_resource: Property Foo not assigned'
|
estr = ('Property error : test_resource.Properties: '
|
||||||
|
'Property Foo not assigned')
|
||||||
create = scheduler.TaskRunner(res.create)
|
create = scheduler.TaskRunner(res.create)
|
||||||
err = self.assertRaises(exception.ResourceFailure, create)
|
err = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertIn(estr, six.text_type(err))
|
self.assertIn(estr, six.text_type(err))
|
||||||
|
@ -559,7 +560,8 @@ class ResourceTest(common.HeatTestCase):
|
||||||
{'Food': 'abc'})
|
{'Food': 'abc'})
|
||||||
res = generic_rsrc.ResourceWithProps(rname, tmpl, self.stack)
|
res = generic_rsrc.ResourceWithProps(rname, tmpl, self.stack)
|
||||||
|
|
||||||
estr = 'StackValidationFailed: Unknown Property Food'
|
estr = ('StackValidationFailed: Property error : '
|
||||||
|
'test_resource.Properties: Unknown Property Food')
|
||||||
create = scheduler.TaskRunner(res.create)
|
create = scheduler.TaskRunner(res.create)
|
||||||
err = self.assertRaises(exception.ResourceFailure, create)
|
err = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertIn(estr, six.text_type(err))
|
self.assertIn(estr, six.text_type(err))
|
||||||
|
@ -1506,8 +1508,9 @@ class ResourceDependenciesTest(common.HeatTestCase):
|
||||||
stack = parser.Stack(utils.dummy_context(), 'test', tmpl)
|
stack = parser.Stack(utils.dummy_context(), 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed,
|
ex = self.assertRaises(exception.StackValidationFailed,
|
||||||
stack.validate)
|
stack.validate)
|
||||||
expected = "FooInt Value 'notanint' is not an integer"
|
self.assertIn("Property error : resources.bar.properties.FooInt: "
|
||||||
self.assertIn(expected, six.text_type(ex))
|
"Value 'notanint' is not an integer",
|
||||||
|
six.text_type(ex))
|
||||||
|
|
||||||
# You can turn off value validation via strict_validate
|
# You can turn off value validation via strict_validate
|
||||||
stack_novalidate = parser.Stack(utils.dummy_context(), 'test', tmpl,
|
stack_novalidate = parser.Stack(utils.dummy_context(), 'test', tmpl,
|
||||||
|
|
|
@ -328,7 +328,7 @@ class ResourceGroupTest(common.HeatTestCase):
|
||||||
resg = resource_group.ResourceGroup('test', snip, stack)
|
resg = resource_group.ResourceGroup('test', snip, stack)
|
||||||
exc = self.assertRaises(exception.StackValidationFailed,
|
exc = self.assertRaises(exception.StackValidationFailed,
|
||||||
resg.validate)
|
resg.validate)
|
||||||
errstr = "removal_policies \"'notallowed'\" is not a list"
|
errstr = "removal_policies: \"'notallowed'\" is not a list"
|
||||||
self.assertIn(errstr, six.text_type(exc))
|
self.assertIn(errstr, six.text_type(exc))
|
||||||
|
|
||||||
def test_invalid_removal_policies_nomap(self):
|
def test_invalid_removal_policies_nomap(self):
|
||||||
|
|
|
@ -188,8 +188,10 @@ class SaharaNodeGroupTemplateTest(common.HeatTestCase):
|
||||||
self.patchobject(ngt, 'is_using_neutron').return_value = False
|
self.patchobject(ngt, 'is_using_neutron').return_value = False
|
||||||
|
|
||||||
ex = self.assertRaises(exception.StackValidationFailed, ngt.validate)
|
ex = self.assertRaises(exception.StackValidationFailed, ngt.validate)
|
||||||
self.assertEqual(u"Property error : node-group: flavor Error "
|
self.assertEqual(u"Property error : "
|
||||||
u"validating value u'm1.large'", six.text_type(ex))
|
u"resources.node-group.properties.flavor: "
|
||||||
|
u"Error validating value u'm1.large'",
|
||||||
|
six.text_type(ex))
|
||||||
|
|
||||||
|
|
||||||
class SaharaClusterTemplateTest(common.HeatTestCase):
|
class SaharaClusterTemplateTest(common.HeatTestCase):
|
||||||
|
|
|
@ -425,8 +425,8 @@ class ServersTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(server.create)
|
create = scheduler.TaskRunner(server.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"StackValidationFailed: Property error : WebServer: "
|
"StackValidationFailed: Property error : "
|
||||||
"image Error validating value 'Slackware': "
|
"WebServer.Properties.image: Error validating value 'Slackware': "
|
||||||
"The Image (Slackware) could not be found.",
|
"The Image (Slackware) could not be found.",
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
|
@ -450,9 +450,9 @@ class ServersTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(server.create)
|
create = scheduler.TaskRunner(server.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'StackValidationFailed: Property error : WebServer: '
|
'StackValidationFailed: Property error : '
|
||||||
'image Multiple physical resources were '
|
'WebServer.Properties.image: Multiple physical '
|
||||||
'found with name (CentOS 5.2).',
|
'resources were found with name (CentOS 5.2).',
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
@ -474,8 +474,8 @@ class ServersTest(common.HeatTestCase):
|
||||||
create = scheduler.TaskRunner(server.create)
|
create = scheduler.TaskRunner(server.create)
|
||||||
error = self.assertRaises(exception.ResourceFailure, create)
|
error = self.assertRaises(exception.ResourceFailure, create)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"StackValidationFailed: Property error : WebServer: "
|
"StackValidationFailed: Property error : "
|
||||||
"image Error validating value '1': "
|
"WebServer.Properties.image: Error validating value '1': "
|
||||||
"The Image (1) could not be found.",
|
"The Image (1) could not be found.",
|
||||||
six.text_type(error))
|
six.text_type(error))
|
||||||
|
|
||||||
|
@ -1049,9 +1049,9 @@ class ServersTest(common.HeatTestCase):
|
||||||
error = self.assertRaises(exception.StackValidationFailed,
|
error = self.assertRaises(exception.StackValidationFailed,
|
||||||
server.validate)
|
server.validate)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Property error : WebServer: key_name Error validating "
|
"Property error : Resources.WebServer.Properties.key_name: "
|
||||||
"value 'test2': The Key (test2) could not be found.",
|
"Error validating value 'test2': The Key (test2) could not "
|
||||||
six.text_type(error))
|
"be found.", six.text_type(error))
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_server_validate_with_networks(self):
|
def test_server_validate_with_networks(self):
|
||||||
|
@ -3020,8 +3020,9 @@ class ServersTest(common.HeatTestCase):
|
||||||
# update
|
# update
|
||||||
updater = scheduler.TaskRunner(server.update, update_template)
|
updater = scheduler.TaskRunner(server.update, update_template)
|
||||||
err = self.assertRaises(exception.ResourceFailure, updater)
|
err = self.assertRaises(exception.ResourceFailure, updater)
|
||||||
self.assertEqual('StackValidationFailed: Property error : WebServer: '
|
self.assertEqual('StackValidationFailed: Property error : '
|
||||||
'image The Image (Update Image) could not be found.',
|
'WebServer.Properties.image: The Image '
|
||||||
|
'(Update Image) could not be found.',
|
||||||
six.text_type(err))
|
six.text_type(err))
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,8 @@ class SoftwareComponentValidationTest(common.HeatTestCase):
|
||||||
tool: script
|
tool: script
|
||||||
''',
|
''',
|
||||||
err=exc.StackValidationFailed,
|
err=exc.StackValidationFailed,
|
||||||
err_msg='actions length (0) is out of range '
|
err_msg='component.properties.configs[0].actions: '
|
||||||
'(min: 1, max: None)')
|
'length (0) is out of range (min: 1, max: None)')
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'multiple_configs_per_action_single',
|
'multiple_configs_per_action_single',
|
||||||
|
|
|
@ -124,6 +124,9 @@ class TestTemplatePluginManager(common.HeatTestCase):
|
||||||
def param_schemata(self):
|
def param_schemata(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_section_name(self, section):
|
||||||
|
pass
|
||||||
|
|
||||||
def parameters(self, stack_identifier, user_params):
|
def parameters(self, stack_identifier, user_params):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -160,8 +160,8 @@ class TroveClusterTest(common.HeatTestCase):
|
||||||
self.rsrc_defn['Properties']['instances'][0]['flavor'] = 'm1.small'
|
self.rsrc_defn['Properties']['instances'][0]['flavor'] = 'm1.small'
|
||||||
tc = trove_cluster.TroveCluster('cluster', self.rsrc_defn, self.stack)
|
tc = trove_cluster.TroveCluster('cluster', self.rsrc_defn, self.stack)
|
||||||
ex = self.assertRaises(exception.StackValidationFailed, tc.validate)
|
ex = self.assertRaises(exception.StackValidationFailed, tc.validate)
|
||||||
error_msg = ("Property error : cluster: instances Property error : "
|
error_msg = ("Property error : "
|
||||||
"instances: 0 Property error : 0: flavor "
|
"resources.cluster.properties.instances[0].flavor: "
|
||||||
"Error validating value 'm1.small': "
|
"Error validating value 'm1.small': "
|
||||||
"The Flavor ID (m1.small) could not be found.")
|
"The Flavor ID (m1.small) could not be found.")
|
||||||
self.assertEqual(error_msg, six.text_type(ex))
|
self.assertEqual(error_msg, six.text_type(ex))
|
||||||
|
|
|
@ -1035,7 +1035,8 @@ class validateTest(common.HeatTestCase):
|
||||||
t = template_format.parse(test_template_invalid_property)
|
t = template_format.parse(test_template_invalid_property)
|
||||||
engine = service.EngineService('a', 't')
|
engine = service.EngineService('a', 't')
|
||||||
res = dict(engine.validate_template(None, t, {}))
|
res = dict(engine.validate_template(None, t, {}))
|
||||||
self.assertEqual({'Error': 'Unknown Property UnknownProperty'}, res)
|
self.assertEqual({'Error': 'Property error : WikiDatabase.Properties: '
|
||||||
|
'Unknown Property UnknownProperty'}, res)
|
||||||
|
|
||||||
def test_invalid_resources(self):
|
def test_invalid_resources(self):
|
||||||
t = template_format.parse(test_template_invalid_resources)
|
t = template_format.parse(test_template_invalid_resources)
|
||||||
|
@ -1084,7 +1085,8 @@ class validateTest(common.HeatTestCase):
|
||||||
engine = service.EngineService('a', 't')
|
engine = service.EngineService('a', 't')
|
||||||
res = dict(engine.validate_template(None, t, {}))
|
res = dict(engine.validate_template(None, t, {}))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{'Error': 'Property SourceDestCheck not implemented yet'},
|
{'Error': 'Property error : WikiDatabase.Properties: '
|
||||||
|
'Property SourceDestCheck not implemented yet'},
|
||||||
res)
|
res)
|
||||||
|
|
||||||
def test_invalid_deletion_policy(self):
|
def test_invalid_deletion_policy(self):
|
||||||
|
|
|
@ -98,7 +98,7 @@ resources:
|
||||||
|
|
||||||
# Prove validation works for non-zero create/update
|
# Prove validation works for non-zero create/update
|
||||||
template_two_nested = self.template.replace("count: 0", "count: 2")
|
template_two_nested = self.template.replace("count: 0", "count: 2")
|
||||||
expected_err = "length Value 'BAD' is not an integer"
|
expected_err = "Value 'BAD' is not an integer"
|
||||||
ex = self.assertRaises(exc.HTTPBadRequest, self.update_stack,
|
ex = self.assertRaises(exc.HTTPBadRequest, self.update_stack,
|
||||||
stack_identifier, template_two_nested,
|
stack_identifier, template_two_nested,
|
||||||
environment=env, files=files)
|
environment=env, files=files)
|
||||||
|
|
Loading…
Reference in New Issue