Lazy-load stack tags

Tags for a stack need to be loaded in the following scenarios:
- To display during a stack show
- To store during a create or update

All other operations which require a loaded stack will likely not
reference the tags, so the extra SQL query which always loads them is
often not necessary.

This change removes the tags loading from stack_object.Stack and
stack.Stack.load and implements annotated properties functions for a
Stack.tags property so that they are loaded from the database on
command.

Change-Id: Iecbf4f101b7f264a42b57f720a8428b0aed706e2
Partial-Bug: #1578851
This commit is contained in:
Steve Baker 2016-05-18 11:36:38 +12:00
parent e416943538
commit 56b95a00d8
3 changed files with 36 additions and 9 deletions

View File

@ -172,6 +172,7 @@ class Stack(collections.Mapping):
self._dependencies = None
self._access_allowed_handlers = {}
self._db_resources = None
self._tags = tags
self.adopt_stack_data = adopt_stack_data
self.stack_user_project_id = stack_user_project_id
self.created_time = created_time
@ -230,6 +231,19 @@ class Stack(collections.Mapping):
else:
self.outputs = {}
@property
def tags(self):
if self._tags is None:
tags = stack_tag_object.StackTagList.get(
self.context, self.id)
if tags:
self._tags = [t.tag for t in tags]
return self._tags
@tags.setter
def tags(self, value):
self._tags = value
@property
def worker_client(self):
"""Return a client for making engine RPC calls."""
@ -494,9 +508,6 @@ class Stack(collections.Mapping):
use_stored_context=False, cache_data=None):
template = tmpl.Template.load(
context, stack.raw_template_id, stack.raw_template)
tags = None
if stack.tags:
tags = [t.tag for t in stack.tags]
return cls(context, stack.name, template,
stack_id=stack.id,
action=stack.action, status=stack.status,
@ -512,7 +523,7 @@ class Stack(collections.Mapping):
user_creds_id=stack.user_creds_id, tenant_id=stack.tenant,
use_stored_context=use_stored_context,
username=stack.username, convergence=stack.convergence,
current_traversal=stack.current_traversal, tags=tags,
current_traversal=stack.current_traversal,
prev_raw_template_id=stack.prev_raw_template_id,
current_deps=stack.current_deps, cache_data=cache_data)

View File

@ -60,7 +60,6 @@ class Stack(
'current_deps': heat_fields.JsonField(),
'prev_raw_template_id': fields.IntegerField(),
'prev_raw_template': fields.ObjectField('RawTemplate'),
'tags': fields.ObjectField('StackTagList'),
'parent_resource_name': fields.StringField(nullable=True),
}
@ -71,9 +70,6 @@ class Stack(
stack['raw_template'] = (
raw_template.RawTemplate.get_by_id(
context, db_stack['raw_template_id']))
elif field == 'tags':
stack['tags'] = stack_tag.StackTagList.from_db_object(
context, db_stack.get(field))
else:
stack[field] = db_stack.__dict__.get(field)
stack._context = context
@ -215,3 +211,7 @@ class Stack(
def identifier(self):
"""Return an identifier for this stack."""
return identifier.HeatIdentifier(self.tenant, self.name, self.id)
@property
def tags(self):
return stack_tag.StackTagList.get(self._context, self.id)

View File

@ -347,7 +347,6 @@ class StackTest(common.HeatTestCase):
username=mox.IgnoreArg(),
convergence=False,
current_traversal=self.stack.current_traversal,
tags=mox.IgnoreArg(),
prev_raw_template_id=None,
current_deps=None, cache_data=None)
@ -1276,6 +1275,23 @@ class StackTest(common.HeatTestCase):
ctx_expected['auth_token'] = None
self.assertEqual(ctx_expected, self.stack.stored_context().to_dict())
def test_tags_property_get_set(self):
self.stack = stack.Stack(self.ctx, 'stack_tags', self.tmpl)
self.stack.store()
stack_id = self.stack.id
test_stack = stack.Stack.load(self.ctx, stack_id=stack_id)
self.assertIsNone(test_stack.tags)
self.stack = stack.Stack(self.ctx, 'stack_name', self.tmpl)
self.stack.tags = ['tag1', 'tag2']
self.assertEqual(['tag1', 'tag2'], self.stack._tags)
self.stack.store()
stack_id = self.stack.id
test_stack = stack.Stack.load(self.ctx, stack_id=stack_id)
self.assertIsNone(test_stack._tags)
self.assertEqual(['tag1', 'tag2'], test_stack.tags)
self.assertEqual(['tag1', 'tag2'], test_stack._tags)
def test_load_reads_tags(self):
self.stack = stack.Stack(self.ctx, 'stack_tags', self.tmpl)
self.stack.store()