Add resource_properties_data assoc. to resource, event objs
Add the resource_properties_data association to resource and event objects. The resource and event engine objects do not use yet it but will soon. Change-Id: Idecaafffbc5e9bfcd2355e2a165836a5ed89b16f
This commit is contained in:
parent
1ea6bb8bf6
commit
791c245c14
@ -20,7 +20,7 @@ from oslo_versionedobjects import fields
|
|||||||
from heat.common import identifier
|
from heat.common import identifier
|
||||||
from heat.db.sqlalchemy import api as db_api
|
from heat.db.sqlalchemy import api as db_api
|
||||||
from heat.objects import base as heat_base
|
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(
|
class Event(
|
||||||
@ -37,7 +37,8 @@ class Event(
|
|||||||
'physical_resource_id': fields.StringField(nullable=True),
|
'physical_resource_id': fields.StringField(nullable=True),
|
||||||
'resource_status_reason': fields.StringField(nullable=True),
|
'resource_status_reason': fields.StringField(nullable=True),
|
||||||
'resource_type': 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),
|
'created_at': fields.DateTimeField(read_only=True),
|
||||||
'updated_at': fields.DateTimeField(nullable=True),
|
'updated_at': fields.DateTimeField(nullable=True),
|
||||||
}
|
}
|
||||||
@ -46,10 +47,22 @@ class Event(
|
|||||||
def _from_db_object(context, event, db_event):
|
def _from_db_object(context, event, db_event):
|
||||||
for field in event.fields:
|
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._context = context
|
||||||
event.obj_reset_changes()
|
event.obj_reset_changes()
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
@property
|
||||||
|
def resource_properties(self):
|
||||||
|
return self._resource_properties
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_id(cls, context, event_id):
|
def get_by_id(cls, context, event_id):
|
||||||
db_event = db_api.event_get(context, event_id)
|
db_event = db_api.event_get(context, event_id)
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
import collections
|
import collections
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
from oslo_versionedobjects import base
|
from oslo_versionedobjects import base
|
||||||
from oslo_versionedobjects import fields
|
from oslo_versionedobjects import fields
|
||||||
import six
|
import six
|
||||||
@ -26,13 +27,17 @@ import tenacity
|
|||||||
from heat.common import crypt
|
from heat.common import crypt
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
|
from heat.common.i18n import _LE
|
||||||
from heat.db.sqlalchemy import api as db_api
|
from heat.db.sqlalchemy import api as db_api
|
||||||
from heat.objects import base as heat_base
|
from heat.objects import base as heat_base
|
||||||
from heat.objects import fields as heat_fields
|
from heat.objects import fields as heat_fields
|
||||||
from heat.objects import resource_data
|
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')
|
cfg.CONF.import_opt('encrypt_parameters_and_properties', 'heat.common.config')
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def retry_on_conflict(func):
|
def retry_on_conflict(func):
|
||||||
wrapper = tenacity.retry(
|
wrapper = tenacity.retry(
|
||||||
@ -74,12 +79,14 @@ class Resource(
|
|||||||
'status_reason': fields.StringField(nullable=True),
|
'status_reason': fields.StringField(nullable=True),
|
||||||
'action': fields.StringField(nullable=True),
|
'action': fields.StringField(nullable=True),
|
||||||
'rsrc_metadata': heat_fields.JsonField(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(
|
'data': fields.ListOfObjectsField(
|
||||||
resource_data.ResourceData,
|
resource_data.ResourceData,
|
||||||
nullable=True
|
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),
|
'engine_id': fields.StringField(nullable=True),
|
||||||
'atomic_key': fields.IntegerField(nullable=True),
|
'atomic_key': fields.IntegerField(nullable=True),
|
||||||
'current_template_id': fields.IntegerField(),
|
'current_template_id': fields.IntegerField(),
|
||||||
@ -102,14 +109,38 @@ class Resource(
|
|||||||
else:
|
else:
|
||||||
resource[field] = db_resource[field]
|
resource[field] = db_resource[field]
|
||||||
|
|
||||||
if resource.properties_data_encrypted and resource.properties_data:
|
if db_resource['rsrc_prop_data'] is not None:
|
||||||
decrypted_data = crypt.decrypted_dict(resource.properties_data)
|
resource['rsrc_prop_data'] = \
|
||||||
resource.properties_data = decrypted_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._context = context
|
||||||
resource.obj_reset_changes()
|
resource.obj_reset_changes()
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
|
@property
|
||||||
|
def properties_data(self):
|
||||||
|
return self._properties_data
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_obj(cls, context, resource_id, refresh=False):
|
def get_obj(cls, context, resource_id, refresh=False):
|
||||||
resource_db = db_api.resource_get(context, resource_id,
|
resource_db = db_api.resource_get(context, resource_id,
|
||||||
|
@ -14,12 +14,15 @@
|
|||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import oslo_db.exception
|
import oslo_db.exception
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from heat.db.sqlalchemy import models
|
||||||
from heat.engine import event
|
from heat.engine import event
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
from heat.engine import stack
|
from heat.engine import stack
|
||||||
from heat.engine import template
|
from heat.engine import template
|
||||||
from heat.objects import event as event_object
|
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.objects import stack as stack_object
|
||||||
from heat.tests import common
|
from heat.tests import common
|
||||||
from heat.tests import generic_resource as generic_rsrc
|
from heat.tests import generic_resource as generic_rsrc
|
||||||
@ -210,6 +213,24 @@ class EventTest(EventCommon):
|
|||||||
'version': '0.1'}}
|
'version': '0.1'}}
|
||||||
self.assertEqual(expected, e.as_dict())
|
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):
|
class EventTestSingleLargeProp(EventCommon):
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from heat.common.i18n import _
|
|||||||
from heat.common import short_id
|
from heat.common import short_id
|
||||||
from heat.common import timeutils
|
from heat.common import timeutils
|
||||||
from heat.db.sqlalchemy import api as db_api
|
from heat.db.sqlalchemy import api as db_api
|
||||||
|
from heat.db.sqlalchemy import models
|
||||||
from heat.engine import attributes
|
from heat.engine import attributes
|
||||||
from heat.engine.cfn import functions as cfn_funcs
|
from heat.engine.cfn import functions as cfn_funcs
|
||||||
from heat.engine import clients
|
from heat.engine import clients
|
||||||
@ -48,6 +49,7 @@ from heat.engine import template
|
|||||||
from heat.engine import translation
|
from heat.engine import translation
|
||||||
from heat.objects import resource as resource_objects
|
from heat.objects import resource as resource_objects
|
||||||
from heat.objects import resource_data as resource_data_object
|
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 common
|
||||||
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
|
||||||
@ -552,6 +554,40 @@ class ResourceTest(common.HeatTestCase):
|
|||||||
res._store_or_update(res.UPDATE, res.COMPLETE, 'should not change')
|
res._store_or_update(res.UPDATE, res.COMPLETE, 'should not change')
|
||||||
self.assertIsNone(res.updated_time)
|
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):
|
def test_store_or_update(self):
|
||||||
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
|
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
|
||||||
res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack)
|
res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack)
|
||||||
|
Loading…
Reference in New Issue
Block a user