Remove broken heat.resource_type custom constraint
This reverts the commits f5c32ad8fd
and
14fdf72b000c82a80abb2587189dd7c6c7dfa0a0e.
The constraint never worked and the stuff to pass the template to
constraints (which was broken because we actually passed a
ResourceDefinition instead) is a pain. Just get rid of it rather than
fix it.
Change-Id: I4e1e787ad94ac1951f472ea066a9b1c9d3e03611
Closes-Bug: #1661403
This commit is contained in:
parent
8c7b66a8a3
commit
c26f367b03
@ -1,45 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
|
||||
import six
|
||||
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import constraints
|
||||
|
||||
|
||||
class ResourceTypeConstraint(constraints.BaseCustomConstraint):
|
||||
|
||||
def validate(self, value, context, template=None):
|
||||
|
||||
if not isinstance(value, collections.Sequence):
|
||||
return False
|
||||
|
||||
if isinstance(value, six.string_types):
|
||||
value = [value]
|
||||
|
||||
invalid_types = []
|
||||
for t in value:
|
||||
try:
|
||||
template.env.get_class(t)
|
||||
except Exception:
|
||||
invalid_types.append(t)
|
||||
|
||||
if invalid_types:
|
||||
msg = _('The following resource types could not be found: %s')
|
||||
types = ','.join(invalid_types)
|
||||
self._error_message = msg % types
|
||||
return False
|
||||
|
||||
return True
|
@ -204,15 +204,14 @@ class Schema(collections.Mapping):
|
||||
|
||||
return value
|
||||
|
||||
def validate_constraints(self, value, context=None, skipped=None,
|
||||
template=None):
|
||||
def validate_constraints(self, value, context=None, skipped=None):
|
||||
if not skipped:
|
||||
skipped = []
|
||||
|
||||
try:
|
||||
for constraint in self.constraints:
|
||||
if type(constraint) not in skipped:
|
||||
constraint.validate(value, self, context, template)
|
||||
constraint.validate(value, self, context)
|
||||
except ValueError as ex:
|
||||
raise exception.StackValidationFailed(message=six.text_type(ex))
|
||||
|
||||
@ -296,8 +295,8 @@ class Constraint(collections.Mapping):
|
||||
|
||||
return '\n'.join(desc())
|
||||
|
||||
def validate(self, value, schema=None, context=None, template=None):
|
||||
if not self._is_valid(value, schema, context, template):
|
||||
def validate(self, value, schema=None, context=None):
|
||||
if not self._is_valid(value, schema, context):
|
||||
if self.description:
|
||||
err_msg = self.description
|
||||
else:
|
||||
@ -374,7 +373,7 @@ class Range(Constraint):
|
||||
self.min,
|
||||
self.max)
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
def _is_valid(self, value, schema, context):
|
||||
value = Schema.str_to_num(value)
|
||||
|
||||
if self.min is not None:
|
||||
@ -437,9 +436,8 @@ class Length(Range):
|
||||
self.min,
|
||||
self.max)
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
return super(Length, self)._is_valid(len(value), schema, context,
|
||||
template)
|
||||
def _is_valid(self, value, schema, context):
|
||||
return super(Length, self)._is_valid(len(value), schema, context)
|
||||
|
||||
|
||||
class Modulo(Constraint):
|
||||
@ -503,7 +501,7 @@ class Modulo(Constraint):
|
||||
return '%s is not a multiple of %s with an offset of %s)' % (
|
||||
value, self.step, self.offset)
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
def _is_valid(self, value, schema, context):
|
||||
value = Schema.str_to_num(value)
|
||||
|
||||
if value % self.step != self.offset:
|
||||
@ -551,7 +549,7 @@ class AllowedValues(Constraint):
|
||||
allowed = '[%s]' % ', '.join(str(a) for a in self.allowed)
|
||||
return '"%s" is not an allowed value %s' % (value, allowed)
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
def _is_valid(self, value, schema, context):
|
||||
# For list values, check if all elements of the list are contained
|
||||
# in allowed list.
|
||||
if isinstance(value, list):
|
||||
@ -594,7 +592,7 @@ class AllowedPattern(Constraint):
|
||||
def _err_msg(self, value):
|
||||
return '"%s" does not match pattern "%s"' % (value, self.pattern)
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
def _is_valid(self, value, schema, context):
|
||||
match = self.match(value)
|
||||
return match is not None and match.end() == len(value)
|
||||
|
||||
@ -645,19 +643,11 @@ class CustomConstraint(Constraint):
|
||||
return _('"%(value)s" does not validate %(name)s') % {
|
||||
"value": value, "name": self.name}
|
||||
|
||||
def _is_valid(self, value, schema, context, template):
|
||||
def _is_valid(self, value, schema, context):
|
||||
constraint = self.custom_constraint
|
||||
if not constraint:
|
||||
return False
|
||||
|
||||
try:
|
||||
result = constraint.validate(value, context,
|
||||
template=template)
|
||||
except TypeError:
|
||||
# for backwards compatibility with older service constraints
|
||||
result = constraint.validate(value, context)
|
||||
|
||||
return result
|
||||
return constraint.validate(value, context)
|
||||
|
||||
|
||||
class BaseCustomConstraint(object):
|
||||
@ -679,7 +669,7 @@ class BaseCustomConstraint(object):
|
||||
return _("Error validating value '%(value)s': %(message)s") % {
|
||||
"value": value, "message": self._error_message}
|
||||
|
||||
def validate(self, value, context, template=None):
|
||||
def validate(self, value, context):
|
||||
|
||||
@MEMOIZE
|
||||
def check_cache_or_validate_value(cache_value_prefix,
|
||||
|
@ -165,9 +165,8 @@ class Schema(constr.Schema):
|
||||
'false')).lower() == 'true',
|
||||
label=schema_dict.get(LABEL))
|
||||
|
||||
def validate_value(self, value, context=None, template=None):
|
||||
super(Schema, self).validate_constraints(value, context=context,
|
||||
template=template)
|
||||
def validate_value(self, value, context=None):
|
||||
super(Schema, self).validate_constraints(value, context)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key == self.TYPE:
|
||||
@ -219,7 +218,7 @@ class Parameter(object):
|
||||
self.user_value = value
|
||||
self.user_default = None
|
||||
|
||||
def validate(self, validate_value=True, context=None, template=None):
|
||||
def validate(self, validate_value=True, context=None):
|
||||
"""Validates the parameter.
|
||||
|
||||
This method validates if the parameter's schema is valid,
|
||||
@ -235,9 +234,9 @@ class Parameter(object):
|
||||
return
|
||||
|
||||
if self.user_value is not None:
|
||||
self._validate(self.user_value, context, template)
|
||||
self._validate(self.user_value, context)
|
||||
elif self.has_default():
|
||||
self._validate(self.default(), context, template)
|
||||
self._validate(self.default(), context)
|
||||
else:
|
||||
raise exception.UserParameterMissing(key=self.name)
|
||||
except exception.StackValidationFailed as ex:
|
||||
@ -316,12 +315,12 @@ class NumberParam(Parameter):
|
||||
"""Return a float representation of the parameter."""
|
||||
return float(super(NumberParam, self).value())
|
||||
|
||||
def _validate(self, val, context, template=None):
|
||||
def _validate(self, val, context):
|
||||
try:
|
||||
Schema.str_to_num(val)
|
||||
except (ValueError, TypeError) as ex:
|
||||
raise exception.StackValidationFailed(message=six.text_type(ex))
|
||||
self.schema.validate_value(val, context=context, template=template)
|
||||
self.schema.validate_value(val, context)
|
||||
|
||||
def value(self):
|
||||
return Schema.str_to_num(super(NumberParam, self).value())
|
||||
@ -332,12 +331,12 @@ class BooleanParam(Parameter):
|
||||
|
||||
__slots__ = tuple()
|
||||
|
||||
def _validate(self, val, context, template=None):
|
||||
def _validate(self, val, context):
|
||||
try:
|
||||
strutils.bool_from_string(val, strict=True)
|
||||
except ValueError as ex:
|
||||
raise exception.StackValidationFailed(message=six.text_type(ex))
|
||||
self.schema.validate_value(val, context=context, template=template)
|
||||
self.schema.validate_value(val, context)
|
||||
|
||||
def value(self):
|
||||
if self.user_value is not None:
|
||||
@ -352,8 +351,8 @@ class StringParam(Parameter):
|
||||
|
||||
__slots__ = tuple()
|
||||
|
||||
def _validate(self, val, context, template=None):
|
||||
self.schema.validate_value(val, context=context, template=template)
|
||||
def _validate(self, val, context):
|
||||
self.schema.validate_value(val, context=context)
|
||||
|
||||
def value(self):
|
||||
return self.schema.to_schema_type(super(StringParam, self).value())
|
||||
@ -418,12 +417,12 @@ class CommaDelimitedListParam(ParsedParameter, collections.Sequence):
|
||||
def _value_as_text(cls, value):
|
||||
return ",".join(value)
|
||||
|
||||
def _validate(self, val, context, template=None):
|
||||
def _validate(self, val, context):
|
||||
try:
|
||||
parsed = self.parse(val)
|
||||
except ValueError as ex:
|
||||
raise exception.StackValidationFailed(message=six.text_type(ex))
|
||||
self.schema.validate_value(parsed, context=context, template=template)
|
||||
self.schema.validate_value(parsed, context)
|
||||
|
||||
|
||||
class JsonParam(ParsedParameter):
|
||||
@ -467,12 +466,12 @@ class JsonParam(ParsedParameter):
|
||||
def _value_as_text(cls, value):
|
||||
return encodeutils.safe_decode(jsonutils.dumps(value))
|
||||
|
||||
def _validate(self, val, context, template=None):
|
||||
def _validate(self, val, context):
|
||||
try:
|
||||
parsed = self.parse(val)
|
||||
except ValueError as ex:
|
||||
raise exception.StackValidationFailed(message=six.text_type(ex))
|
||||
self.schema.validate_value(parsed, context=context, template=template)
|
||||
self.schema.validate_value(parsed, context)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
@ -525,7 +524,7 @@ class Parameters(collections.Mapping):
|
||||
self._validate_user_parameters()
|
||||
|
||||
for param in six.itervalues(self.params):
|
||||
param.validate(validate_value, context, self.tmpl)
|
||||
param.validate(validate_value, context)
|
||||
|
||||
def __contains__(self, key):
|
||||
"""Return whether the specified parameter exists."""
|
||||
|
@ -349,8 +349,7 @@ class Property(object):
|
||||
|
||||
raise TypeError(_('"%s" is not a valid boolean') % value)
|
||||
|
||||
def get_value(self, value, validate=False, template=None,
|
||||
translation=None):
|
||||
def get_value(self, value, validate=False, translation=None):
|
||||
"""Get value from raw value and sanitize according to data type."""
|
||||
|
||||
t = self.type()
|
||||
@ -370,8 +369,7 @@ class Property(object):
|
||||
_value = value
|
||||
|
||||
if validate:
|
||||
self.schema.validate_constraints(_value, self.context,
|
||||
template=template)
|
||||
self.schema.validate_constraints(_value, self.context)
|
||||
|
||||
return _value
|
||||
|
||||
@ -405,7 +403,7 @@ class Properties(collections.Mapping):
|
||||
in params_snippet.items())
|
||||
return {}
|
||||
|
||||
def validate(self, with_value=True, template=None):
|
||||
def validate(self, with_value=True):
|
||||
try:
|
||||
for key in self.data:
|
||||
if key not in self.props:
|
||||
@ -418,9 +416,7 @@ class Properties(collections.Mapping):
|
||||
continue
|
||||
if with_value:
|
||||
try:
|
||||
self._get_property_value(key,
|
||||
validate=True,
|
||||
template=template)
|
||||
self._get_property_value(key, validate=True)
|
||||
except exception.StackValidationFailed as ex:
|
||||
path = [key]
|
||||
path.extend(ex.path)
|
||||
@ -455,7 +451,7 @@ class Properties(collections.Mapping):
|
||||
if any(res.action == res.INIT for res in deps):
|
||||
return True
|
||||
|
||||
def get_user_value(self, key, validate=False, template=None):
|
||||
def get_user_value(self, key, validate=False):
|
||||
if key not in self:
|
||||
raise KeyError(_('Invalid Property %s') % key)
|
||||
|
||||
@ -477,7 +473,7 @@ class Properties(collections.Mapping):
|
||||
value,
|
||||
self.data)
|
||||
|
||||
return prop.get_value(value, validate, template=template,
|
||||
return prop.get_value(value, validate,
|
||||
translation=self.translation)
|
||||
# Children can raise StackValidationFailed with unique path which
|
||||
# is necessary for further use in StackValidationFailed exception.
|
||||
@ -490,23 +486,22 @@ class Properties(collections.Mapping):
|
||||
except Exception as e:
|
||||
raise ValueError(six.text_type(e))
|
||||
|
||||
def _get_property_value(self, key, validate=False, template=None):
|
||||
def _get_property_value(self, key, validate=False):
|
||||
if key not in self:
|
||||
raise KeyError(_('Invalid Property %s') % key)
|
||||
|
||||
prop = self.props[key]
|
||||
if not self.translation.is_deleted(prop.path) and key in self.data:
|
||||
return self.get_user_value(key, validate, template=template)
|
||||
return self.get_user_value(key, validate)
|
||||
elif self.translation.has_translation(prop.path):
|
||||
value = self.translation.translate(prop.path, prop_data=self.data,
|
||||
validate=validate,
|
||||
template=template)
|
||||
validate=validate)
|
||||
if value is not None or prop.has_default():
|
||||
return prop.get_value(value)
|
||||
elif prop.required():
|
||||
raise ValueError(_('Property %s not assigned') % key)
|
||||
elif prop.has_default():
|
||||
return prop.get_value(None, validate, template=template,
|
||||
return prop.get_value(None, validate,
|
||||
translation=self.translation)
|
||||
elif prop.required():
|
||||
raise ValueError(_('Property %s not assigned') % key)
|
||||
|
@ -1755,8 +1755,7 @@ class Resource(status.ResourceStatus):
|
||||
self.context).validate()
|
||||
try:
|
||||
validate = self.properties.validate(
|
||||
with_value=self.stack.strict_validate,
|
||||
template=self.t)
|
||||
with_value=self.stack.strict_validate)
|
||||
except exception.StackValidationFailed as ex:
|
||||
path = [self.stack.t.RESOURCES, self.t.name,
|
||||
self.stack.t.get_section_name(ex.path[0])]
|
||||
|
@ -197,8 +197,7 @@ class Translation(object):
|
||||
return (self.is_active and
|
||||
(key in self._rules or key in self.resolved_translations))
|
||||
|
||||
def translate(self, key, prop_value=None, prop_data=None, validate=False,
|
||||
template=None):
|
||||
def translate(self, key, prop_value=None, prop_data=None, validate=False):
|
||||
if key in self.resolved_translations:
|
||||
return self.resolved_translations[key]
|
||||
|
||||
@ -212,12 +211,10 @@ class Translation(object):
|
||||
result = None
|
||||
|
||||
if rule.rule == TranslationRule.REPLACE:
|
||||
result = self.replace(key, rule, result, prop_data, validate,
|
||||
template)
|
||||
result = self.replace(key, rule, result, prop_data, validate)
|
||||
|
||||
if rule.rule == TranslationRule.ADD:
|
||||
result = self.add(key, rule, result, prop_data, validate,
|
||||
template)
|
||||
result = self.add(key, rule, result, prop_data, validate)
|
||||
|
||||
if rule.rule == TranslationRule.RESOLVE:
|
||||
resolved_value = resolve_and_find(result,
|
||||
@ -231,7 +228,7 @@ class Translation(object):
|
||||
return result
|
||||
|
||||
def add(self, key, add_rule, prop_value=None, prop_data=None,
|
||||
validate=False, template=None):
|
||||
validate=False):
|
||||
value_path = add_rule.get_value_absolute_path()
|
||||
if prop_value is None:
|
||||
prop_value = []
|
||||
@ -252,8 +249,7 @@ class Translation(object):
|
||||
value = get_value(value_path,
|
||||
prop_data if add_rule.value_name else
|
||||
self.properties,
|
||||
validate,
|
||||
template)
|
||||
validate)
|
||||
self.is_active = True
|
||||
if value is not None:
|
||||
translation_value.extend(value if isinstance(value, list)
|
||||
@ -264,7 +260,7 @@ class Translation(object):
|
||||
return translation_value
|
||||
|
||||
def replace(self, key, replace_rule, prop_value=None, prop_data=None,
|
||||
validate=False, template=None):
|
||||
validate=False):
|
||||
value = None
|
||||
value_path = replace_rule.get_value_absolute_path(full_value_name=True)
|
||||
short_path = replace_rule.get_value_absolute_path()
|
||||
@ -280,7 +276,7 @@ class Translation(object):
|
||||
subpath = value_path
|
||||
props = prop_data if replace_rule.value_name else self.properties
|
||||
self.is_active = False
|
||||
value = get_value(subpath, props, validate, template)
|
||||
value = get_value(subpath, props, validate)
|
||||
self.is_active = True
|
||||
|
||||
if self.has_translation(prop_path):
|
||||
@ -304,7 +300,7 @@ class Translation(object):
|
||||
return result
|
||||
|
||||
|
||||
def get_value(path, props, validate=False, template=None):
|
||||
def get_value(path, props, validate=False):
|
||||
if not props:
|
||||
return None
|
||||
|
||||
@ -312,7 +308,7 @@ def get_value(path, props, validate=False, template=None):
|
||||
if isinstance(props, dict):
|
||||
prop = props.get(key)
|
||||
else:
|
||||
prop = props._get_property_value(key, validate, template)
|
||||
prop = props._get_property_value(key, validate)
|
||||
if len(path[1:]) == 0:
|
||||
return prop
|
||||
elif prop is None:
|
||||
|
@ -1,82 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from heat.engine.constraint import heat_constraints as hc
|
||||
from heat.tests import common
|
||||
|
||||
|
||||
class ResourceTypeConstraintTest(common.HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ResourceTypeConstraintTest, self).setUp()
|
||||
self.constraint = hc.ResourceTypeConstraint()
|
||||
|
||||
self.mock_template = mock.MagicMock()
|
||||
self.mock_env = mock.MagicMock()
|
||||
self.mock_template.env = self.mock_env
|
||||
|
||||
def test_validate(self):
|
||||
# Setup
|
||||
value = ['OS::Heat::None']
|
||||
|
||||
# Test
|
||||
result = self.constraint.validate(value, None, self.mock_template)
|
||||
|
||||
# Verify
|
||||
self.assertTrue(result)
|
||||
self.mock_env.get_class.assert_called_once_with(value[0])
|
||||
|
||||
def test_validate_failure(self):
|
||||
# Setup
|
||||
value = ['OS::Heat::None']
|
||||
self.mock_env.get_class.side_effect = Exception()
|
||||
|
||||
# Test
|
||||
result = self.constraint.validate(value, None, self.mock_template)
|
||||
|
||||
# Verify
|
||||
self.assertFalse(result)
|
||||
self.assertIn('OS::Heat::None', self.constraint._error_message)
|
||||
self.mock_env.get_class.assert_called_once_with(value[0])
|
||||
|
||||
def test_validate_multiple_failures(self):
|
||||
# Setup
|
||||
value = ['OS::Heat::None', 'OS::Heat::RandomString']
|
||||
self.mock_env.get_class.side_effect = [Exception(), Exception()]
|
||||
|
||||
# Test
|
||||
result = self.constraint.validate(value, None, self.mock_template)
|
||||
|
||||
# Verify
|
||||
self.assertFalse(result)
|
||||
self.assertIn('OS::Heat::None,OS::Heat::RandomString',
|
||||
self.constraint._error_message)
|
||||
self.mock_env.get_class.assert_has_calls([mock.call(value[0]),
|
||||
mock.call(value[1])])
|
||||
|
||||
def test_validate_single_item(self):
|
||||
# Setup
|
||||
value = 'OS::Heat::None'
|
||||
|
||||
# Test
|
||||
result = self.constraint.validate(value, None, self.mock_template)
|
||||
|
||||
# Verify
|
||||
self.assertTrue(result)
|
||||
self.mock_env.get_class.assert_called_once_with(value)
|
||||
|
||||
def test_validate_non_string(self):
|
||||
result = self.constraint.validate(dict(), None, self.mock_template)
|
||||
self.assertFalse(result)
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
deprecations:
|
||||
- The heat.resource_type custom constraint has been removed. This constraint
|
||||
never actually worked.
|
@ -104,7 +104,6 @@ heat.constraints =
|
||||
designate.domain = heat.engine.clients.os.designate:DesignateDomainConstraint
|
||||
designate.zone = heat.engine.clients.os.designate:DesignateZoneConstraint
|
||||
glance.image = heat.engine.clients.os.glance:ImageConstraint
|
||||
heat.resource_type = heat.engine.constraint.heat_constraints:ResourceTypeConstraint
|
||||
keystone.domain = heat.engine.clients.os.keystone.keystone_constraints:KeystoneDomainConstraint
|
||||
keystone.group = heat.engine.clients.os.keystone.keystone_constraints:KeystoneGroupConstraint
|
||||
keystone.project = heat.engine.clients.os.keystone.keystone_constraints:KeystoneProjectConstraint
|
||||
|
Loading…
Reference in New Issue
Block a user