Merge "Add resource_properties_data assoc. to resource, event objs"
This commit is contained in:
commit
77b8073a01
@ -20,7 +20,7 @@ from oslo_versionedobjects import fields
|
||||
from heat.common import identifier
|
||||
from heat.db.sqlalchemy import api as db_api
|
||||
from heat.objects import base as heat_base
|
||||
from heat.objects import fields as heat_fields
|
||||
from heat.objects import resource_properties_data as rpd
|
||||
|
||||
|
||||
class Event(
|
||||
@ -37,7 +37,8 @@ class Event(
|
||||
'physical_resource_id': fields.StringField(nullable=True),
|
||||
'resource_status_reason': fields.StringField(nullable=True),
|
||||
'resource_type': fields.StringField(nullable=True),
|
||||
'resource_properties': heat_fields.JsonField(nullable=True),
|
||||
'rsrc_prop_data': fields.ObjectField(
|
||||
rpd.ResourcePropertiesData),
|
||||
'created_at': fields.DateTimeField(read_only=True),
|
||||
'updated_at': fields.DateTimeField(nullable=True),
|
||||
}
|
||||
@ -45,11 +46,23 @@ class Event(
|
||||
@staticmethod
|
||||
def _from_db_object(context, event, db_event):
|
||||
for field in event.fields:
|
||||
event[field] = db_event[field]
|
||||
event[field] = db_event[field]
|
||||
if db_event['rsrc_prop_data']:
|
||||
event['rsrc_prop_data'] = \
|
||||
rpd.ResourcePropertiesData._from_db_object(
|
||||
rpd.ResourcePropertiesData(context), context,
|
||||
db_event['rsrc_prop_data'])
|
||||
event._resource_properties = event['rsrc_prop_data'].data
|
||||
else:
|
||||
event._resource_properties = db_event['resource_properties'] or {}
|
||||
event._context = context
|
||||
event.obj_reset_changes()
|
||||
return event
|
||||
|
||||
@property
|
||||
def resource_properties(self):
|
||||
return self._resource_properties
|
||||
|
||||
@classmethod
|
||||
def get_by_id(cls, context, event_id):
|
||||
db_event = db_api.event_get(context, event_id)
|
||||
|
@ -18,6 +18,7 @@
|
||||
import collections
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
import six
|
||||
@ -26,13 +27,17 @@ import tenacity
|
||||
from heat.common import crypt
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.common.i18n import _LE
|
||||
from heat.db.sqlalchemy import api as db_api
|
||||
from heat.objects import base as heat_base
|
||||
from heat.objects import fields as heat_fields
|
||||
from heat.objects import resource_data
|
||||
from heat.objects import resource_properties_data as rpd
|
||||
|
||||
cfg.CONF.import_opt('encrypt_parameters_and_properties', 'heat.common.config')
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def retry_on_conflict(func):
|
||||
wrapper = tenacity.retry(
|
||||
@ -74,12 +79,14 @@ class Resource(
|
||||
'status_reason': fields.StringField(nullable=True),
|
||||
'action': fields.StringField(nullable=True),
|
||||
'rsrc_metadata': heat_fields.JsonField(nullable=True),
|
||||
'properties_data': heat_fields.JsonField(nullable=True),
|
||||
'properties_data_encrypted': fields.BooleanField(default=False),
|
||||
'data': fields.ListOfObjectsField(
|
||||
resource_data.ResourceData,
|
||||
nullable=True
|
||||
),
|
||||
'rsrc_prop_data': fields.ObjectField(
|
||||
rpd.ResourcePropertiesData, nullable=True),
|
||||
'rsrc_prop_data_id': fields.ObjectField(
|
||||
fields.IntegerField(nullable=True)),
|
||||
'engine_id': fields.StringField(nullable=True),
|
||||
'atomic_key': fields.IntegerField(nullable=True),
|
||||
'current_template_id': fields.IntegerField(),
|
||||
@ -102,14 +109,38 @@ class Resource(
|
||||
else:
|
||||
resource[field] = db_resource[field]
|
||||
|
||||
if resource.properties_data_encrypted and resource.properties_data:
|
||||
decrypted_data = crypt.decrypted_dict(resource.properties_data)
|
||||
resource.properties_data = decrypted_data
|
||||
if db_resource['rsrc_prop_data'] is not None:
|
||||
resource['rsrc_prop_data'] = \
|
||||
rpd.ResourcePropertiesData._from_db_object(
|
||||
rpd.ResourcePropertiesData(context), context,
|
||||
db_resource['rsrc_prop_data'])
|
||||
resource._properties_data = resource['rsrc_prop_data'].data
|
||||
if db_resource['properties_data']:
|
||||
LOG.error(
|
||||
_LE('Unexpected condition where resource.rsrc_prop_data '
|
||||
'and resource.properties_data are both not null. '
|
||||
'rsrc_prop_data.id: %(rsrc_prop_data_id)s ,'
|
||||
'resource id: %(res_id)s')
|
||||
% {'rsrc_prop_data_id': resource['rsrc_prop_data'].id,
|
||||
'res_id': resource['id']})
|
||||
elif db_resource['properties_data']: # legacy field
|
||||
if db_resource['properties_data_encrypted']:
|
||||
decrypted_data = crypt.decrypted_dict(
|
||||
db_resource['properties_data'])
|
||||
resource._properties_data = decrypted_data
|
||||
else:
|
||||
resource._properties_data = db_resource['properties_data']
|
||||
else:
|
||||
resource._properties_data = {}
|
||||
|
||||
resource._context = context
|
||||
resource.obj_reset_changes()
|
||||
return resource
|
||||
|
||||
@property
|
||||
def properties_data(self):
|
||||
return self._properties_data
|
||||
|
||||
@classmethod
|
||||
def get_obj(cls, context, resource_id, refresh=False):
|
||||
resource_db = db_api.resource_get(context, resource_id,
|
||||
|
@ -14,12 +14,15 @@
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
import oslo_db.exception
|
||||
import uuid
|
||||
|
||||
from heat.db.sqlalchemy import models
|
||||
from heat.engine import event
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import stack
|
||||
from heat.engine import template
|
||||
from heat.objects import event as event_object
|
||||
from heat.objects import resource_properties_data as rpd_object
|
||||
from heat.objects import stack as stack_object
|
||||
from heat.tests import common
|
||||
from heat.tests import generic_resource as generic_rsrc
|
||||
@ -210,6 +213,24 @@ class EventTest(EventCommon):
|
||||
'version': '0.1'}}
|
||||
self.assertEqual(expected, e.as_dict())
|
||||
|
||||
def test_event_object_resource_properties_data(self):
|
||||
cfg.CONF.set_override('encrypt_parameters_and_properties', True,
|
||||
enforce_type=True)
|
||||
data = {'p1': 'hello',
|
||||
'p2': 'too soon?'}
|
||||
rpd_obj = rpd_object.ResourcePropertiesData().create(self.ctx, data)
|
||||
rpd_db_obj = self.ctx.session.query(
|
||||
models.ResourcePropertiesData).get(rpd_obj.id)
|
||||
e_obj = event_object.Event().create(
|
||||
self.ctx,
|
||||
{'stack_id': self.stack.id,
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'rsrc_prop_data': rpd_db_obj})
|
||||
e_obj = event_object.Event().get_by_id(utils.dummy_context(),
|
||||
e_obj.id)
|
||||
# properties data appears unencrypted to event object
|
||||
self.assertEqual(data, e_obj.rsrc_prop_data.data)
|
||||
|
||||
|
||||
class EventTestSingleLargeProp(EventCommon):
|
||||
|
||||
|
@ -28,6 +28,7 @@ from heat.common.i18n import _
|
||||
from heat.common import short_id
|
||||
from heat.common import timeutils
|
||||
from heat.db.sqlalchemy import api as db_api
|
||||
from heat.db.sqlalchemy import models
|
||||
from heat.engine import attributes
|
||||
from heat.engine.cfn import functions as cfn_funcs
|
||||
from heat.engine import clients
|
||||
@ -48,6 +49,7 @@ from heat.engine import template
|
||||
from heat.engine import translation
|
||||
from heat.objects import resource as resource_objects
|
||||
from heat.objects import resource_data as resource_data_object
|
||||
from heat.objects import resource_properties_data as rpd_object
|
||||
from heat.tests import common
|
||||
from heat.tests import generic_resource as generic_rsrc
|
||||
from heat.tests import utils
|
||||
@ -563,6 +565,40 @@ class ResourceTest(common.HeatTestCase):
|
||||
res._store_or_update(res.UPDATE, res.COMPLETE, 'should not change')
|
||||
self.assertIsNone(res.updated_time)
|
||||
|
||||
def test_resource_object_resource_properties_data(self):
|
||||
cfg.CONF.set_override('encrypt_parameters_and_properties', True,
|
||||
enforce_type=True)
|
||||
data = {'p1': 'i see',
|
||||
'p2': 'good times, good times'}
|
||||
rpd_obj = rpd_object.ResourcePropertiesData().create(
|
||||
self.stack.context, data)
|
||||
rpd_db_obj = self.stack.context.session.query(
|
||||
models.ResourcePropertiesData).get(rpd_obj.id)
|
||||
res_obj1 = resource_objects.Resource().create(
|
||||
self.stack.context,
|
||||
{'stack_id': self.stack.id,
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'rsrc_prop_data': rpd_db_obj})
|
||||
res_obj2 = resource_objects.Resource().create(
|
||||
self.stack.context,
|
||||
{'stack_id': self.stack.id,
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'rsrc_prop_data_id': rpd_db_obj.id})
|
||||
ctx2 = utils.dummy_context()
|
||||
res_obj1 = resource_objects.Resource().get_obj(
|
||||
ctx2, res_obj1.id)
|
||||
res_obj2 = resource_objects.Resource().get_obj(
|
||||
ctx2, res_obj2.id)
|
||||
|
||||
# verify the resource_properties_data association
|
||||
# can be set by id or object
|
||||
self.assertEqual(rpd_db_obj.id, res_obj1.rsrc_prop_data.id)
|
||||
self.assertEqual(res_obj1.rsrc_prop_data.id,
|
||||
res_obj2.rsrc_prop_data.id)
|
||||
# properties data appears unencrypted to resource object
|
||||
self.assertEqual(data, res_obj1.rsrc_prop_data.data)
|
||||
self.assertEqual(data, res_obj2.rsrc_prop_data.data)
|
||||
|
||||
def test_store_or_update(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
|
||||
res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack)
|
||||
|
Loading…
Reference in New Issue
Block a user