Add tests for resource-data delete bug.

Fixes bug 1201974

Change-Id: Id5fdfcde8541e83f68406c67250b815b35fbbf54
This commit is contained in:
Randall Burt 2013-07-16 19:31:25 -05:00
parent 319d3e158f
commit 5b9d98fb6f
3 changed files with 75 additions and 39 deletions

View File

@ -66,6 +66,18 @@ def raw_template_create(context, values):
return IMPL.raw_template_create(context, values)
def resource_data_get(resource, key):
return IMPL.resource_data_get(resource, key)
def resource_data_set(resource, key, value, redact=False):
return IMPL.resource_data_set(resource, key, value, redact=redact)
def resource_data_get_by_key(context, resource_id, key):
return IMPL.resource_data_get_by_key(context, resource_id, key)
def resource_get(context, resource_id):
return IMPL.resource_get(context, resource_id)

View File

@ -99,50 +99,36 @@ def resource_get_all(context):
def resource_data_get(resource, key):
"""Lookup value of resource's data by key."""
data_lst = filter(lambda x: x.key == key, resource.data)
if not data_lst:
return None
assert len(data_lst) == 1
data = data_lst[0]
result = resource_data_get_by_key(resource.context, resource.id, key)
return result.value
if data.redact:
return crypt.decrypt(data.value)
else:
return data.value
def resource_data_get_by_key(context, resource_id, key):
result = (model_query(context, models.ResourceData)
.filter_by(resource_id=resource_id)
.filter_by(key=key)
.first())
if not result:
raise exception.NotFound('No resource data found')
if result.redact and result.value:
result.value = crypt.decrypt(result.value)
return result
def resource_data_set(resource, key, value, redact=False):
"""Save resource's key/value pair to database."""
if redact:
value = crypt.encrypt(value)
data_lst = filter(lambda x: x.key == key, resource.data)
if data_lst: # Key exists in db, so check value & replace if necessary
assert len(data_lst) == 1
resource_data = data_lst[0]
# If the new value is the same, do nothing
if value == resource_data.value:
return None
# Otherwise, delete the old value
for i, d in enumerate(resource.data):
if d.key == key:
index = i
del(resource.data[index])
else: # Build a new key/value
resource_data = models.ResourceData()
resource_data.key = key
resource_data.resource_id = resource.id
resource_data.redact = True
resource_data.value = value
resource.data.append(resource_data)
# Save to new key/value pair to database
rs = model_query(resource.context, models.Resource).get(resource.id)
rs.update_and_save({'data': resource.data})
try:
current = resource_data_get_by_key(resource.context, resource.id, key)
except exception.NotFound:
current = models.ResourceData()
current.key = key
current.resource_id = resource.id
current.redact = redact
current.value = value
current.save()
return current
def resource_create(context, values):

View File

@ -16,12 +16,14 @@
from heat.common import context
from heat.common import exception
from heat.common import template_format
from heat.common import urlfetch
from heat.db import api as db_api
from heat.engine import parser
from heat.engine import resource
from heat.engine import scheduler
from heat.common import urlfetch
from heat.tests.common import HeatTestCase
from heat.tests import generic_resource as generic_rsrc
from heat.tests import utils
from heat.tests.common import HeatTestCase
from heat.tests.utils import setup_dummy_db
@ -113,3 +115,39 @@ Outputs:
rsrc.delete()
self.m.VerifyAll()
class ResDataResource(generic_rsrc.GenericResource):
def handle_create(self):
db_api.resource_data_set(self, "test", 'A secret value', True)
class ResDataNestedStackTest(NestedStackTest):
nested_template = '''
HeatTemplateFormatVersion: "2012-12-12"
Parameters:
KeyName:
Type: String
Resources:
nested_res:
Type: "res.data.resource"
Outputs:
Foo:
Value: bar
'''
def setUp(self):
resource._register_class("res.data.resource", ResDataResource)
super(ResDataNestedStackTest, self).setUp()
def test_res_data_delete(self):
urlfetch.get('https://localhost/the.template').AndReturn(
self.nested_template)
self.m.ReplayAll()
stack = self.create_stack(self.test_template)
res = stack['the_nested'].nested()['nested_res']
stack.delete()
self.assertEqual(stack.state, (stack.DELETE, stack.COMPLETE))
self.assertRaises(exception.NotFound, db_api.resource_data_get, res,
'test')