Add validating of section 'conditions'

Validate section 'conditions' when stack validate.

Change-Id: I0cf1abcc4656c573afbbd41e02b573ada63c1ae6
Blueprint: support-conditions-function
This commit is contained in:
huangtianhua 2016-07-22 18:04:27 +08:00
parent 0803639788
commit d072f6e7f1
7 changed files with 117 additions and 0 deletions

View File

@ -133,6 +133,11 @@ class InvalidConditionFunction(HeatException):
msg_fmt = _("The function is not supported in condition: %(func)s")
class InvalidConditionDefinition(HeatException):
msg_fmt = _("The definition of condition (%(cd)s) is "
"invalid: %(definition)s")
class ImmutableParameterModified(HeatException):
msg_fmt = _("The following parameters are immutable and may not be "
"updated: %(keys)s")

View File

@ -176,6 +176,9 @@ class CfnTemplate(CfnTemplateBase):
(n, function.Invalid) for n in self.functions)
self._parser_condition_functions.update(self.condition_functions)
def get_condition_definitions(self):
return self[self.CONDITIONS]
class HeatTemplate(CfnTemplateBase):
functions = {

View File

@ -511,3 +511,6 @@ class HOTemplate20161014(HOTemplate20160408):
else:
self._parser_condition_functions[n] = f
self._parser_condition_functions.update(self.condition_functions)
def get_condition_definitions(self):
return self[self.CONDITIONS]

View File

@ -779,6 +779,9 @@ class Stack(collections.Mapping):
parameter_groups = param_groups.ParameterGroups(self.t)
parameter_groups.validate()
# Validate condition definition of conditions section
self.t.validate_condition_definitions(self)
# Validate types of sections in ResourceDefinitions
self.t.validate_resource_definitions(self)

View File

@ -211,6 +211,11 @@ class Template(collections.Mapping):
"""Check section's type of ResourceDefinitions."""
pass
@abc.abstractmethod
def validate_condition_definitions(self, stack):
"""Check conditions section."""
pass
@abc.abstractmethod
def resource_definitions(self, stack):
"""Return a dictionary of ResourceDefinition objects."""

View File

@ -74,3 +74,33 @@ class CommonTemplate(template.Template):
self.validate_resource_definition(name, data)
except (TypeError, ValueError, KeyError) as ex:
raise exception.StackValidationFailed(message=six.text_type(ex))
def validate_condition_definitions(self, stack):
"""Check conditions section."""
resolved_cds = self.resolve_conditions(stack)
if resolved_cds:
for cd_key, cd_value in six.iteritems(resolved_cds):
if not isinstance(cd_value, bool):
raise exception.InvalidConditionDefinition(
cd=cd_key,
definition=cd_value)
def resolve_conditions(self, stack):
cd_snippet = self.get_condition_definitions()
result = {}
if cd_snippet:
for cd_key, cd_value in six.iteritems(cd_snippet):
# hasn't been resolved yet
if not isinstance(cd_value, bool):
condition_func = self.parse_condition(
stack, cd_value)
resolved_cd_value = function.resolve(condition_func)
result[cd_key] = resolved_cd_value
else:
result[cd_key] = cd_value
return result
def get_condition_definitions(self):
return {}

View File

@ -138,6 +138,9 @@ class TestTemplatePluginManager(common.HeatTestCase):
def validate_resource_definitions(self, stack):
pass
def validate_condition_definitions(self, stack):
pass
def resource_definitions(self, stack):
pass
@ -274,6 +277,71 @@ class ParserTest(common.HeatTestCase):
self.assertIsNot(raw, parsed)
class TestTemplateConditionParser(common.HeatTestCase):
def setUp(self):
super(TestTemplateConditionParser, self).setUp()
self.ctx = utils.dummy_context()
def test_conditions_with_non_supported_functions(self):
t = {
'heat_template_version': '2016-10-14',
'parameters': {
'env_type': {
'type': 'string',
'default': 'test'
}
},
'conditions': {
'prod_env': {
'equals': [{'get_param': 'env_type'},
{'get_attr': [None, 'att']}]}}}
# test with get_attr in equals
tmpl = template.Template(t)
stk = stack.Stack(self.ctx, 'test_condition_with_get_attr_func', tmpl)
ex = self.assertRaises(exception.InvalidConditionFunction,
tmpl.resolve_conditions, stk)
self.assertIn('The function is not supported in condition: get_attr',
six.text_type(ex))
# test with get_resource in top level of a condition
tmpl.t['conditions']['prod_env'] = {'get_resource': 'R1'}
stk = stack.Stack(self.ctx, 'test_condition_with_get_attr_func', tmpl)
ex = self.assertRaises(exception.InvalidConditionFunction,
tmpl.resolve_conditions, stk)
self.assertIn('The function is not supported in condition: '
'get_resource', six.text_type(ex))
# test with get_attr in top level of a condition
tmpl.t['conditions']['prod_env'] = {'get_attr': [None, 'att']}
stk = stack.Stack(self.ctx, 'test_condition_with_get_attr_func', tmpl)
ex = self.assertRaises(exception.InvalidConditionFunction,
tmpl.resolve_conditions, stk)
self.assertIn('The function is not supported in condition: get_attr',
six.text_type(ex))
def test_condition_resolved_not_boolean(self):
t = {
'heat_template_version': '2016-10-14',
'parameters': {
'env_type': {
'type': 'string',
'default': 'test'
}
},
'conditions': {
'prod_env': {'get_param': 'env_type'}}}
# test with get_attr in equals
tmpl = template.Template(t)
stk = stack.Stack(self.ctx, 'test_condition_not_boolean', tmpl)
ex = self.assertRaises(exception.InvalidConditionDefinition,
tmpl.validate_condition_definitions, stk)
self.assertIn('The definition of condition (prod_env) is invalid',
six.text_type(ex))
class TestTemplateValidate(common.HeatTestCase):
def test_template_validate_cfn_check_t_digest(self):