Merge "Removes redundant validation of template (1)"
This commit is contained in:
commit
4f433fcbc9
@ -15,6 +15,7 @@ import abc
|
|||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import functools
|
import functools
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import six
|
import six
|
||||||
@ -115,8 +116,10 @@ class Template(collections.Mapping):
|
|||||||
self.files = files or {}
|
self.files = files or {}
|
||||||
self.maps = self[self.MAPPINGS]
|
self.maps = self[self.MAPPINGS]
|
||||||
self.env = env or environment.Environment({})
|
self.env = env or environment.Environment({})
|
||||||
|
|
||||||
self.version = get_version(self.t,
|
self.version = get_version(self.t,
|
||||||
list(six.iterkeys(_template_classes)))
|
list(six.iterkeys(_template_classes)))
|
||||||
|
self.t_digest = None
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
return Template(copy.deepcopy(self.t, memo), files=self.files,
|
return Template(copy.deepcopy(self.t, memo), files=self.files,
|
||||||
@ -226,6 +229,18 @@ class Template(collections.Mapping):
|
|||||||
sections (e.g. parameters are check by parameters schema class).
|
sections (e.g. parameters are check by parameters schema class).
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
t_digest = hashlib.sha256(six.text_type(self.t)).hexdigest()
|
||||||
|
|
||||||
|
# TODO(kanagaraj-manickam) currently t_digest is stored in self. which
|
||||||
|
# is used to check whether already template is validated or not.
|
||||||
|
# But it needs to be loaded from dogpile cache backend once its
|
||||||
|
# available in heat (http://specs.openstack.org/openstack/heat-specs/
|
||||||
|
# specs/liberty/constraint-validation-cache.html). This is required
|
||||||
|
# as multiple heat-engines may process the same template at least
|
||||||
|
# in case of instance_group. And it fixes partially bug 1444316
|
||||||
|
|
||||||
|
if t_digest == self.t_digest:
|
||||||
|
return
|
||||||
|
|
||||||
# check top-level sections
|
# check top-level sections
|
||||||
for k in six.iterkeys(self.t):
|
for k in six.iterkeys(self.t):
|
||||||
@ -243,6 +258,7 @@ class Template(collections.Mapping):
|
|||||||
message = _('Resources must contain Resource. '
|
message = _('Resources must contain Resource. '
|
||||||
'Found a [%s] instead') % type(res)
|
'Found a [%s] instead') % type(res)
|
||||||
raise exception.StackValidationFailed(message=message)
|
raise exception.StackValidationFailed(message=message)
|
||||||
|
self.t_digest = t_digest
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_empty_template(cls,
|
def create_empty_template(cls,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
@ -271,6 +272,27 @@ class ParserTest(common.HeatTestCase):
|
|||||||
|
|
||||||
class TestTemplateValidate(common.HeatTestCase):
|
class TestTemplateValidate(common.HeatTestCase):
|
||||||
|
|
||||||
|
def test_template_validate_cfn_check_t_digest(self):
|
||||||
|
t = {
|
||||||
|
'AWSTemplateFormatVersion': '2010-09-09',
|
||||||
|
'Description': 'foo',
|
||||||
|
'Parameters': {},
|
||||||
|
'Mappings': {},
|
||||||
|
'Resources': {
|
||||||
|
'server': {
|
||||||
|
'Type': 'OS::Nova::Server'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Outputs': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl = template.Template(t)
|
||||||
|
self.assertIsNone(tmpl.t_digest)
|
||||||
|
tmpl.validate()
|
||||||
|
self.assertEqual(hashlib.sha256(six.text_type(t)).hexdigest(),
|
||||||
|
tmpl.t_digest,
|
||||||
|
'invalid template digest')
|
||||||
|
|
||||||
def test_template_validate_cfn_good(self):
|
def test_template_validate_cfn_good(self):
|
||||||
t = {
|
t = {
|
||||||
'AWSTemplateFormatVersion': '2010-09-09',
|
'AWSTemplateFormatVersion': '2010-09-09',
|
||||||
@ -328,15 +350,35 @@ class TestTemplateValidate(common.HeatTestCase):
|
|||||||
|
|
||||||
def test_template_validate_cfn_empty(self):
|
def test_template_validate_cfn_empty(self):
|
||||||
t = template_format.parse('''
|
t = template_format.parse('''
|
||||||
AWSTemplateFormatVersion: 2010-09-09
|
AWSTemplateFormatVersion: 2010-09-09
|
||||||
Parameters:
|
Parameters:
|
||||||
Resources:
|
Resources:
|
||||||
Outputs:
|
Outputs:
|
||||||
''')
|
''')
|
||||||
tmpl = template.Template(t)
|
tmpl = template.Template(t)
|
||||||
err = tmpl.validate()
|
err = tmpl.validate()
|
||||||
self.assertIsNone(err)
|
self.assertIsNone(err)
|
||||||
|
|
||||||
|
def test_template_validate_hot_check_t_digest(self):
|
||||||
|
t = {
|
||||||
|
'heat_template_version': '2015-04-30',
|
||||||
|
'description': 'foo',
|
||||||
|
'parameters': {},
|
||||||
|
'resources': {
|
||||||
|
'server': {
|
||||||
|
'type': 'OS::Nova::Server'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'outputs': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl = template.Template(t)
|
||||||
|
self.assertIsNone(tmpl.t_digest)
|
||||||
|
tmpl.validate()
|
||||||
|
self.assertEqual(hashlib.sha256(six.text_type(t)).hexdigest(),
|
||||||
|
tmpl.t_digest,
|
||||||
|
'invalid template digest')
|
||||||
|
|
||||||
def test_template_validate_hot_good(self):
|
def test_template_validate_hot_good(self):
|
||||||
t = {
|
t = {
|
||||||
'heat_template_version': '2013-05-23',
|
'heat_template_version': '2013-05-23',
|
||||||
@ -508,16 +550,16 @@ class TemplateTest(common.HeatTestCase):
|
|||||||
|
|
||||||
def test_invalid_template(self):
|
def test_invalid_template(self):
|
||||||
scanner_error = '''
|
scanner_error = '''
|
||||||
1
|
1
|
||||||
Mappings:
|
Mappings:
|
||||||
ValidMapping:
|
ValidMapping:
|
||||||
TestKey: TestValue
|
TestKey: TestValue
|
||||||
'''
|
'''
|
||||||
parser_error = '''
|
parser_error = '''
|
||||||
Mappings:
|
Mappings:
|
||||||
ValidMapping:
|
ValidMapping:
|
||||||
TestKey: {TestKey1: "Value1" TestKey2: "Value2"}
|
TestKey: {TestKey1: "Value1" TestKey2: "Value2"}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
self.assertRaises(ValueError, template_format.parse, scanner_error)
|
self.assertRaises(ValueError, template_format.parse, scanner_error)
|
||||||
self.assertRaises(ValueError, template_format.parse, parser_error)
|
self.assertRaises(ValueError, template_format.parse, parser_error)
|
||||||
|
Loading…
Reference in New Issue
Block a user