Don't load new copies of current resources
The Stack._find_filtered_resources() method returns Resource objects for all resources associated with the Stack, regardless of whether they are current (present in the template; latest version in the case of convergence). To do this, it previously created a new Resource object for every resource found in the database. However, for those resources which *are* current this is unnecessary. We can access the Resource object simply through self.resources. It turns out this is necessary for obtaining the required_by list for legacy stacks, because only the Resources obtained from self.resources also appear in the Dependencies graph obtained from self.dependencies. The required_by list is read when listing or showing resources, which would either return an empty list or fail for legacy stacks. This patch also makes the Resource.required_by() method more robust in its error handling. Change-Id: Id438336e5c88dc7c2d168ba01ee703faa17e8b8e Closes-Bug: #1703703 Related-Bug: #1523748
This commit is contained in:
parent
8e4845c1ca
commit
5ce238fb17
@ -670,11 +670,18 @@ class Resource(status.ResourceStatus):
|
||||
directly.
|
||||
"""
|
||||
try:
|
||||
return [r.name for r in self.stack.dependencies.required_by(self)]
|
||||
reqd_by = self.stack.dependencies.required_by(self)
|
||||
except KeyError:
|
||||
# for convergence, fall back to building from needed_by
|
||||
return [r.name for r in self.stack.resources.values()
|
||||
if r.id in self.needed_by]
|
||||
if self.stack.convergence:
|
||||
# for convergence, fall back to building from needed_by
|
||||
needed_by_ids = self.needed_by or set()
|
||||
reqd_by = [r for r in self.stack.resources.values()
|
||||
if r.id in needed_by_ids]
|
||||
else:
|
||||
LOG.error('Getting required_by list for Resource not in '
|
||||
'dependency graph.')
|
||||
return []
|
||||
return [r.name for r in reqd_by]
|
||||
|
||||
def client(self, name=None, version=None):
|
||||
client_name = name or self.default_client_name
|
||||
|
@ -322,9 +322,9 @@ class Stack(collections.Mapping):
|
||||
else:
|
||||
resources = self._db_resources_get()
|
||||
for rsc in six.itervalues(resources):
|
||||
defn = self._rsrc_def_for_db_resource(rsc, rsrc_def_cache)
|
||||
if defn:
|
||||
yield resource.Resource(rsc.name, defn, self)
|
||||
loaded_res = self._resource_from_db_resource(rsc, rsrc_def_cache)
|
||||
if loaded_res is not None:
|
||||
yield loaded_res
|
||||
|
||||
def iter_resources(self, nested_depth=0, filters=None):
|
||||
"""Iterates over all the resources in a stack.
|
||||
@ -367,23 +367,32 @@ class Stack(collections.Mapping):
|
||||
self._db_resources = _db_resources
|
||||
return self._db_resources
|
||||
|
||||
def _rsrc_def_for_db_resource(self, db_res, rsrc_def_cache=None):
|
||||
def _resource_from_db_resource(self, db_res, rsrc_def_cache=None):
|
||||
tid = db_res.current_template_id
|
||||
if tid is None:
|
||||
tid = self.t.id
|
||||
|
||||
if tid == self.t.id:
|
||||
cur_res = self.resources[db_res.name]
|
||||
if cur_res.id == db_res.id:
|
||||
return cur_res
|
||||
|
||||
if rsrc_def_cache and tid in rsrc_def_cache:
|
||||
rsrc_def = rsrc_def_cache[tid]
|
||||
elif tid == self.t.id:
|
||||
rsrc_def = self.t.resource_definitions(self)
|
||||
if rsrc_def_cache:
|
||||
rsrc_def_cache[tid] = rsrc_def
|
||||
else:
|
||||
t = tmpl.Template.load(self.context, tid)
|
||||
rsrc_def = t.resource_definitions(self)
|
||||
if tid == self.t.id:
|
||||
rsrc_def = self.t.resource_definitions(self)
|
||||
else:
|
||||
t = tmpl.Template.load(self.context, tid)
|
||||
rsrc_def = t.resource_definitions(self)
|
||||
if rsrc_def_cache:
|
||||
rsrc_def_cache[tid] = rsrc_def
|
||||
return rsrc_def.get(db_res.name)
|
||||
defn = rsrc_def.get(db_res.name)
|
||||
|
||||
if defn is None:
|
||||
return None
|
||||
|
||||
return resource.Resource(db_res.name, defn, self)
|
||||
|
||||
def resource_get(self, name):
|
||||
"""Return a stack resource, even if not in the current template."""
|
||||
@ -394,9 +403,7 @@ class Stack(collections.Mapping):
|
||||
# fall back to getting the resource from the database
|
||||
db_res = self.db_resource_get(name)
|
||||
if db_res:
|
||||
defn = self._rsrc_def_for_db_resource(db_res)
|
||||
if defn:
|
||||
return resource.Resource(db_res.name, defn, self)
|
||||
return self._resource_from_db_resource(db_res)
|
||||
|
||||
return None
|
||||
|
||||
|
@ -41,3 +41,10 @@ class ResourcesList(functional_base.FunctionalTestsBase):
|
||||
filters={'name': 'test2'})
|
||||
|
||||
self.assertEqual('CREATE_COMPLETE', test2.resource_status)
|
||||
|
||||
def test_required_by(self):
|
||||
stack_identifier = self.stack_create(template=test_template_depend)
|
||||
[test1] = self.client.resources.list(stack_identifier,
|
||||
filters={'name': 'test1'})
|
||||
|
||||
self.assertEqual(['test2'], test1.required_by)
|
||||
|
Loading…
Reference in New Issue
Block a user