Fix resource loading in resource filtering

We try to be careful when filtering resources from stack, to not load
all of them, but unfortunately it breaks as soon as you have
dependencies with resources that are not returned. To be on the safe
side we need to load them all and filter them afterwards.

Change-Id: I399545a6a4fd77d9707505ec9c4058d384877dec
Closes-Bug: #1585931
This commit is contained in:
Thomas Herve 2016-05-26 11:32:20 +02:00
parent b2e02dd923
commit de96d030ff
2 changed files with 58 additions and 21 deletions

View File

@ -286,38 +286,32 @@ class Stack(collections.Mapping):
def resources(self):
return self._find_resources()
def _find_resources(self, filters=None):
def _find_resources(self):
if self._resources is None:
res_defns = self.t.resource_definitions(self)
if not filters:
self._resources = dict((name,
resource.Resource(name, data, self))
for (name, data) in res_defns.items())
else:
self._resources = dict()
self._db_resources = dict()
for rsc in six.itervalues(
resource_objects.Resource.get_all_by_stack(
self.context, self.id, True, filters)):
self._db_resources[rsc.name] = rsc
res = resource.Resource(rsc.name,
res_defns[rsc.name],
self)
self._resources[rsc.name] = res
# There is no need to continue storing the db resources
# after resource creation
self._db_resources = None
self._resources = dict((name,
resource.Resource(name, data, self))
for (name, data) in res_defns.items())
return self._resources
def _find_filtered_resources(self, filters):
for rsc in six.itervalues(
resource_objects.Resource.get_all_by_stack(
self.context, self.id, True, filters)):
yield self.resources[rsc.name]
def iter_resources(self, nested_depth=0, filters=None):
"""Iterates over all the resources in a stack.
Iterating includes nested stacks up to `nested_depth` levels below.
"""
for res in six.itervalues(self._find_resources(filters)):
if not filters:
resources = six.itervalues(self.resources)
else:
resources = self._find_filtered_resources(filters)
for res in resources:
yield res
if not res.has_nested() or nested_depth == 0:

View File

@ -0,0 +1,43 @@
# 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.
from heat_integrationtests.functional import functional_base
test_template_depend = {
'heat_template_version': '2013-05-23',
'resources': {
'test1': {
'type': 'OS::Heat::TestResource',
'properties': {
'value': 'Test1',
}
},
'test2': {
'type': 'OS::Heat::TestResource',
'depends_on': ['test1'],
'properties': {
'value': 'Test2',
}
}
}
}
class ResourcesList(functional_base.FunctionalTestsBase):
def test_filtering_with_depend(self):
stack_identifier = self.stack_create(template=test_template_depend)
[test2] = self.client.resources.list(stack_identifier,
filters={'name': 'test2'})
self.assertEqual('CREATE_COMPLETE', test2.resource_status)