Ensure cached conditions match stack

Ensure that the caching we do of conditions in TemplateCommon always
applies to the stack that has been passed in as an argument.

This was not the case previously, and in fact it was required not to be the
case because in the convergence path the new parameter values were not
copied into the stack at the start of an update. This patch rectifies that.

Change-Id: I942b53570222bf4e0d1bf78e584792d445c14090
This commit is contained in:
Zane Bitter 2016-09-09 15:23:10 -04:00
parent 7b129f666f
commit 0327c339f5
3 changed files with 28 additions and 15 deletions

View File

@ -1200,6 +1200,8 @@ class Stack(collections.Mapping):
if new_stack is not None:
self.disable_rollback = new_stack.disable_rollback
self.timeout_mins = new_stack.timeout_mins
self.parameters = new_stack.parameters
self._set_param_stackid()
self.tags = new_stack.tags
@ -1455,7 +1457,6 @@ class Stack(collections.Mapping):
updater = scheduler.TaskRunner(update_task)
self.parameters = newstack.parameters
self.t._conditions = newstack.t.conditions(newstack)
self.t.files = newstack.t.files
self.t.env = newstack.t.env
self.disable_rollback = newstack.disable_rollback

View File

@ -128,7 +128,6 @@ class Template(collections.Mapping):
self.files = files or {}
self.maps = self[self.MAPPINGS]
self.env = env or environment.Environment({})
self._conditions = None
self.merge_sections = [self.PARAMETERS]
self.version = get_version(self.t, _template_classes.keys())

View File

@ -12,6 +12,7 @@
# under the License.
import collections
import weakref
import six
@ -30,6 +31,11 @@ class CommonTemplate(template.Template):
classes from it do so at their own risk.
"""
def __init__(self, template, template_id=None, files=None, env=None):
super(CommonTemplate, self).__init__(template, template_id=template_id,
files=files, env=env)
self._conditions_cache = None, None
@classmethod
def validate_resource_key_type(cls, key, valid_types, typename,
rsrc_name, rsrc_data):
@ -91,21 +97,28 @@ class CommonTemplate(template.Template):
return {}
def conditions(self, stack):
if self._conditions is None:
raw_defs = self._get_condition_definitions()
if not isinstance(raw_defs, collections.Mapping):
message = _('Condition definitions must be a map. Found a '
'%s instead') % type(raw_defs).__name__
raise exception.StackValidationFailed(
error='Conditions validation error',
message=message)
get_cache_stack, cached_conds = self._conditions_cache
if (cached_conds is not None and
get_cache_stack is not None and
get_cache_stack() is stack):
return cached_conds
parsed = {n: self.parse_condition(stack, c,
'.'.join([self.CONDITIONS, n]))
for n, c in raw_defs.items()}
self._conditions = conditions.Conditions(parsed)
raw_defs = self._get_condition_definitions()
if not isinstance(raw_defs, collections.Mapping):
message = _('Condition definitions must be a map. Found a '
'%s instead') % type(raw_defs).__name__
raise exception.StackValidationFailed(
error='Conditions validation error',
message=message)
return self._conditions
parsed = {n: self.parse_condition(stack, c,
'.'.join([self.CONDITIONS, n]))
for n, c in raw_defs.items()}
conds = conditions.Conditions(parsed)
get_cache_stack = weakref.ref(stack) if stack is not None else None
self._conditions_cache = get_cache_stack, conds
return conds
def outputs(self, stack):
conds = self.conditions(stack)