Merge "Lazily load resources when loading a Stack"
This commit is contained in:
commit
3baf358e7c
|
@ -88,6 +88,8 @@ class Stack(object):
|
||||||
self.timeout_mins = timeout_mins
|
self.timeout_mins = timeout_mins
|
||||||
self.disable_rollback = disable_rollback
|
self.disable_rollback = disable_rollback
|
||||||
self.parent_resource = parent_resource
|
self.parent_resource = parent_resource
|
||||||
|
self._resources = None
|
||||||
|
self._dependencies = None
|
||||||
|
|
||||||
resources.initialise()
|
resources.initialise()
|
||||||
|
|
||||||
|
@ -102,12 +104,24 @@ class Stack(object):
|
||||||
else:
|
else:
|
||||||
self.outputs = {}
|
self.outputs = {}
|
||||||
|
|
||||||
template_resources = self.t[template.RESOURCES]
|
@property
|
||||||
self.resources = dict((name,
|
def resources(self):
|
||||||
resource.Resource(name, data, self))
|
if self._resources is None:
|
||||||
for (name, data) in template_resources.items())
|
template_resources = self.t[template.RESOURCES]
|
||||||
|
self._resources = dict((name, resource.Resource(name, data, self))
|
||||||
|
for (name, data) in
|
||||||
|
template_resources.items())
|
||||||
|
return self._resources
|
||||||
|
|
||||||
self.dependencies = self._get_dependencies(self.resources.itervalues())
|
@property
|
||||||
|
def dependencies(self):
|
||||||
|
if self._dependencies is None:
|
||||||
|
self._dependencies = self._get_dependencies(
|
||||||
|
self.resources.itervalues())
|
||||||
|
return self._dependencies
|
||||||
|
|
||||||
|
def reset_dependencies(self):
|
||||||
|
self._dependencies = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_stack(self):
|
def root_stack(self):
|
||||||
|
@ -460,8 +474,7 @@ class Stack(object):
|
||||||
while not updater.step():
|
while not updater.step():
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
cur_deps = self._get_dependencies(self.resources.itervalues())
|
self.reset_dependencies()
|
||||||
self.dependencies = cur_deps
|
|
||||||
|
|
||||||
if action == self.UPDATE:
|
if action == self.UPDATE:
|
||||||
reason = 'Stack successfully updated'
|
reason = 'Stack successfully updated'
|
||||||
|
|
|
@ -65,9 +65,7 @@ class StackUpdate(object):
|
||||||
try:
|
try:
|
||||||
yield update()
|
yield update()
|
||||||
finally:
|
finally:
|
||||||
prev_deps = self.previous_stack._get_dependencies(
|
self.previous_stack.reset_dependencies()
|
||||||
self.previous_stack.resources.itervalues())
|
|
||||||
self.previous_stack.dependencies = prev_deps
|
|
||||||
|
|
||||||
def _resource_update(self, res):
|
def _resource_update(self, res):
|
||||||
if res.name in self.new_stack and self.new_stack[res.name] is res:
|
if res.name in self.new_stack and self.new_stack[res.name] is res:
|
||||||
|
|
|
@ -30,6 +30,7 @@ import heat.rpc.api as engine_api
|
||||||
import heat.db.api as db_api
|
import heat.db.api as db_api
|
||||||
from heat.common import identifier
|
from heat.common import identifier
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
|
from heat.engine import dependencies
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.engine.resource import _register_class
|
from heat.engine.resource import _register_class
|
||||||
from heat.engine import service
|
from heat.engine import service
|
||||||
|
@ -44,7 +45,6 @@ from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import generic_resource as generic_rsrc
|
from heat.tests import generic_resource as generic_rsrc
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
|
|
||||||
|
|
||||||
wp_template = '''
|
wp_template = '''
|
||||||
{
|
{
|
||||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||||
|
@ -1773,3 +1773,38 @@ class StackServiceTest(HeatTestCase):
|
||||||
sl = self.eng.show_stack(self.ctx, None)
|
sl = self.eng.show_stack(self.ctx, None)
|
||||||
|
|
||||||
self.assertEqual(0, len(sl))
|
self.assertEqual(0, len(sl))
|
||||||
|
|
||||||
|
def test_lazy_load_resources(self):
|
||||||
|
stack_name = 'lazy_load_test'
|
||||||
|
res._register_class('GenericResourceType',
|
||||||
|
generic_rsrc.GenericResource)
|
||||||
|
|
||||||
|
lazy_load_template = {
|
||||||
|
'Resources': {
|
||||||
|
'foo': {'Type': 'GenericResourceType'},
|
||||||
|
'bar': {
|
||||||
|
'Type': 'ResourceWithPropsType',
|
||||||
|
'Properties': {
|
||||||
|
'Foo': {'Ref': 'foo'},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templ = parser.Template(lazy_load_template)
|
||||||
|
stack = parser.Stack(self.ctx, stack_name, templ,
|
||||||
|
environment.Environment({}))
|
||||||
|
|
||||||
|
self.assertEqual(stack._resources, None)
|
||||||
|
self.assertEqual(stack._dependencies, None)
|
||||||
|
|
||||||
|
resources = stack.resources
|
||||||
|
self.assertEqual(type(resources), dict)
|
||||||
|
self.assertEqual(len(resources), 2)
|
||||||
|
self.assertEqual(type(resources.get('foo')),
|
||||||
|
generic_rsrc.GenericResource)
|
||||||
|
self.assertEqual(type(resources.get('bar')),
|
||||||
|
generic_rsrc.ResourceWithProps)
|
||||||
|
|
||||||
|
stack_dependencies = stack.dependencies
|
||||||
|
self.assertEqual(type(stack_dependencies), dependencies.Dependencies)
|
||||||
|
self.assertEqual(len(stack_dependencies.graph()), 2)
|
||||||
|
|
|
@ -739,9 +739,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
||||||
|
|
||||||
def test_hot_ref_fail(self):
|
def test_hot_ref_fail(self):
|
||||||
|
@ -757,9 +757,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
||||||
|
|
||||||
def test_getatt(self):
|
def test_getatt(self):
|
||||||
|
@ -909,9 +909,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
||||||
|
|
||||||
def test_hot_getatt_fail(self):
|
def test_hot_getatt_fail(self):
|
||||||
|
@ -927,9 +927,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
|
||||||
|
|
||||||
def test_getatt_fail_nested_deep(self):
|
def test_getatt_fail_nested_deep(self):
|
||||||
|
@ -949,9 +949,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo.Fn::Join[1][3])', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo.Fn::Join[1][3])', str(ex))
|
||||||
|
|
||||||
def test_hot_getatt_fail_nested_deep(self):
|
def test_hot_getatt_fail_nested_deep(self):
|
||||||
|
@ -972,9 +972,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"baz" (in bar.Properties.Foo.Fn::Join[1][3])', str(ex))
|
self.assertIn('"baz" (in bar.Properties.Foo.Fn::Join[1][3])', str(ex))
|
||||||
|
|
||||||
def test_dependson(self):
|
def test_dependson(self):
|
||||||
|
@ -1005,9 +1005,9 @@ class ResourceDependenciesTest(HeatTestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
stack = parser.Stack(None, 'test', tmpl)
|
||||||
ex = self.assertRaises(exception.InvalidTemplateReference,
|
ex = self.assertRaises(exception.InvalidTemplateReference,
|
||||||
parser.Stack,
|
getattr, stack, 'dependencies')
|
||||||
None, 'test', tmpl)
|
|
||||||
self.assertIn('"wibble" (in foo)', str(ex))
|
self.assertIn('"wibble" (in foo)', str(ex))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
from testtools import skipIf
|
from testtools import skipIf
|
||||||
|
|
||||||
from heat.engine import clients
|
from heat.engine import clients
|
||||||
|
@ -23,7 +24,6 @@ from heat.engine import resources
|
||||||
from heat.engine.resources import instance as instances
|
from heat.engine.resources import instance as instances
|
||||||
from heat.engine import service
|
from heat.engine import service
|
||||||
from heat.openstack.common.importutils import try_import
|
from heat.openstack.common.importutils import try_import
|
||||||
import heat.db.api as db_api
|
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
|
@ -551,11 +551,6 @@ class validateTest(HeatTestCase):
|
||||||
t = template_format.parse(test_template_volumeattach % 'vdq')
|
t = template_format.parse(test_template_volumeattach % 'vdq')
|
||||||
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
||||||
|
|
||||||
self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
|
|
||||||
db_api.resource_get_by_name_and_stack(None, 'test_resource_name',
|
|
||||||
stack).AndReturn(None)
|
|
||||||
|
|
||||||
self.m.ReplayAll()
|
|
||||||
volumeattach = stack.resources['MountPoint']
|
volumeattach = stack.resources['MountPoint']
|
||||||
self.assertTrue(volumeattach.validate() is None)
|
self.assertTrue(volumeattach.validate() is None)
|
||||||
|
|
||||||
|
@ -563,11 +558,6 @@ class validateTest(HeatTestCase):
|
||||||
t = template_format.parse(test_template_volumeattach % 'sda')
|
t = template_format.parse(test_template_volumeattach % 'sda')
|
||||||
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(t))
|
||||||
|
|
||||||
self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
|
|
||||||
db_api.resource_get_by_name_and_stack(None, 'test_resource_name',
|
|
||||||
stack).AndReturn(None)
|
|
||||||
|
|
||||||
self.m.ReplayAll()
|
|
||||||
volumeattach = stack.resources['MountPoint']
|
volumeattach = stack.resources['MountPoint']
|
||||||
self.assertRaises(exception.StackValidationFailed,
|
self.assertRaises(exception.StackValidationFailed,
|
||||||
volumeattach.validate)
|
volumeattach.validate)
|
||||||
|
|
Loading…
Reference in New Issue