Add tests for resource-data delete bug.
Fixes bug 1201974 Change-Id: Id5fdfcde8541e83f68406c67250b815b35fbbf54
This commit is contained in:
parent
319d3e158f
commit
5b9d98fb6f
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user