Use Event versioned object for event_list formatting
This change removes the event.Event.load method, and switches api.format_event to using the Event versioned object instead. Since the only purpose of loading the stack is to get its identifier, this is now also coming from a Stack versioned object. Related-Bug: #1588561 Change-Id: I7b1fc99894818b44cde08cf08b010b1d1fb94e9f
This commit is contained in:
parent
d9855dfe0b
commit
7bfbace79f
@ -379,20 +379,17 @@ def format_stack_preview(stack):
|
||||
return fmt_stack
|
||||
|
||||
|
||||
def format_event(event):
|
||||
stack_identifier = event.stack.identifier()
|
||||
event_timestamp = event.timestamp or timeutils.utcnow()
|
||||
|
||||
def format_event(event, stack_identifier):
|
||||
result = {
|
||||
rpc_api.EVENT_ID: dict(event.identifier()),
|
||||
rpc_api.EVENT_ID: dict(event.identifier(stack_identifier)),
|
||||
rpc_api.EVENT_STACK_ID: dict(stack_identifier),
|
||||
rpc_api.EVENT_STACK_NAME: stack_identifier.stack_name,
|
||||
rpc_api.EVENT_TIMESTAMP: event_timestamp.isoformat(),
|
||||
rpc_api.EVENT_TIMESTAMP: event.created_at.isoformat(),
|
||||
rpc_api.EVENT_RES_NAME: event.resource_name,
|
||||
rpc_api.EVENT_RES_PHYSICAL_ID: event.physical_resource_id,
|
||||
rpc_api.EVENT_RES_ACTION: event.action,
|
||||
rpc_api.EVENT_RES_STATUS: event.status,
|
||||
rpc_api.EVENT_RES_STATUS_DATA: event.reason,
|
||||
rpc_api.EVENT_RES_ACTION: event.resource_action,
|
||||
rpc_api.EVENT_RES_STATUS: event.resource_status,
|
||||
rpc_api.EVENT_RES_STATUS_DATA: event.resource_status_reason,
|
||||
rpc_api.EVENT_RES_TYPE: event.resource_type,
|
||||
rpc_api.EVENT_RES_PROPERTIES: event.resource_properties,
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ import six
|
||||
import oslo_db.exception
|
||||
from oslo_log import log as logging
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.common import identifier
|
||||
from heat.objects import event as event_object
|
||||
|
||||
@ -54,25 +52,6 @@ class Event(object):
|
||||
self.timestamp = timestamp
|
||||
self.id = id
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, event_id, event=None, stack=None):
|
||||
"""Retrieve an Event from the database."""
|
||||
from heat.engine import stack as parser
|
||||
|
||||
ev = (event if event is not None else
|
||||
event_object.Event.get_by_id(context, event_id))
|
||||
if ev is None:
|
||||
message = _('No event exists with id "%s"') % str(event_id)
|
||||
raise exception.NotFound(message)
|
||||
|
||||
st = (stack if stack is not None else
|
||||
parser.Stack.load(context, ev.stack_id))
|
||||
|
||||
return cls(context, st, ev.resource_action, ev.resource_status,
|
||||
ev.resource_status_reason, ev.physical_resource_id,
|
||||
ev.resource_properties, ev.resource_name,
|
||||
ev.resource_type, ev.uuid, ev.created_at, ev.id)
|
||||
|
||||
def store(self):
|
||||
"""Store the Event in the database."""
|
||||
ev = {
|
||||
|
@ -47,7 +47,6 @@ from heat.engine import attributes
|
||||
from heat.engine.cfn import template as cfntemplate
|
||||
from heat.engine import clients
|
||||
from heat.engine import environment
|
||||
from heat.engine import event as evt
|
||||
from heat.engine.hot import functions as hot_functions
|
||||
from heat.engine import parameter_groups
|
||||
from heat.engine import properties
|
||||
@ -1592,8 +1591,10 @@ class EngineService(service.Service):
|
||||
:param sort_dir: the direction of the sort ('asc' or 'desc').
|
||||
"""
|
||||
|
||||
stacks = {}
|
||||
if stack_identity is not None:
|
||||
st = self._get_stack(cnxt, stack_identity, show_deleted=True)
|
||||
stacks[st.id] = st
|
||||
|
||||
events = event_object.Event.get_all_by_stack(
|
||||
cnxt,
|
||||
@ -1611,16 +1612,18 @@ class EngineService(service.Service):
|
||||
sort_dir=sort_dir,
|
||||
filters=filters)
|
||||
|
||||
stacks = {}
|
||||
|
||||
def get_stack(stack_id):
|
||||
def get_stack_identifier(stack_id):
|
||||
if stack_id not in stacks:
|
||||
stacks[stack_id] = parser.Stack.load(cnxt, stack_id)
|
||||
return stacks[stack_id]
|
||||
s = stack_object.Stack.get_by_id(
|
||||
cnxt,
|
||||
stack_id,
|
||||
show_deleted=True)
|
||||
if not s:
|
||||
return
|
||||
stacks[stack_id] = s
|
||||
return stacks[stack_id].identifier()
|
||||
|
||||
return [api.format_event(evt.Event.load(cnxt,
|
||||
e.id, e,
|
||||
get_stack(e.stack_id)))
|
||||
return [api.format_event(e, get_stack_identifier(e.stack_id))
|
||||
for e in events]
|
||||
|
||||
def _authorize_stack_user(self, cnxt, stack, resource_name):
|
||||
|
@ -17,6 +17,7 @@
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from heat.common import identifier
|
||||
from heat.db import api as db_api
|
||||
from heat.objects import base as heat_base
|
||||
from heat.objects import fields as heat_fields
|
||||
@ -80,3 +81,11 @@ class Event(
|
||||
def create(cls, context, values):
|
||||
return cls._from_db_object(context, cls(),
|
||||
db_api.event_create(context, values))
|
||||
|
||||
def identifier(self, stack_identifier):
|
||||
"""Return a unique identifier for the event."""
|
||||
|
||||
res_id = identifier.ResourceIdentifier(
|
||||
resource_name=self.resource_name, **stack_identifier)
|
||||
|
||||
return identifier.EventIdentifier(event_id=str(self.uuid), **res_id)
|
||||
|
@ -20,13 +20,13 @@ from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import identifier
|
||||
from heat.common import template_format
|
||||
from heat.engine import api
|
||||
from heat.engine import event
|
||||
from heat.engine import parameters
|
||||
from heat.engine import stack as parser
|
||||
from heat.engine import template
|
||||
from heat.objects import event as event_object
|
||||
from heat.rpc import api as rpc_api
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
@ -49,17 +49,19 @@ class FormatTest(common.HeatTestCase):
|
||||
'generic4': {'Type': 'StackResourceType'}
|
||||
}
|
||||
})
|
||||
self.stack = parser.Stack(utils.dummy_context(), 'test_stack',
|
||||
self.context = utils.dummy_context()
|
||||
self.stack = parser.Stack(self.context, 'test_stack',
|
||||
tmpl, stack_id=str(uuid.uuid4()))
|
||||
|
||||
def _dummy_event(self, event_id):
|
||||
def _dummy_event(self):
|
||||
resource = self.stack['generic1']
|
||||
return event.Event(utils.dummy_context(), self.stack, 'CREATE',
|
||||
'COMPLETE', 'state changed',
|
||||
'z3455xyc-9f88-404d-a85b-5315293e67de',
|
||||
resource.properties, resource.name, resource.type(),
|
||||
uuid='abc123yc-9f88-404d-a85b-531529456xyz',
|
||||
id=event_id)
|
||||
ev = event.Event(self.context, self.stack, 'CREATE',
|
||||
'COMPLETE', 'state changed',
|
||||
'z3455xyc-9f88-404d-a85b-5315293e67de',
|
||||
resource.properties, resource.name, resource.type(),
|
||||
uuid='abc123yc-9f88-404d-a85b-531529456xyz')
|
||||
event_id = ev.store()
|
||||
return event_object.Event.get_by_id(self.context, event_id)
|
||||
|
||||
def test_format_stack_resource(self):
|
||||
self.stack.created_time = datetime(2015, 8, 3, 17, 5, 1)
|
||||
@ -281,10 +283,7 @@ class FormatTest(common.HeatTestCase):
|
||||
self.assertEqual('foobar', formatted[rpc_api.RES_PARENT_RESOURCE])
|
||||
|
||||
def test_format_event_identifier_uuid(self):
|
||||
self._test_format_event('abc123yc-9f88-404d-a85b-531529456xyz')
|
||||
|
||||
def _test_format_event(self, event_id):
|
||||
event = self._dummy_event(event_id)
|
||||
event = self._dummy_event()
|
||||
|
||||
event_keys = set((
|
||||
rpc_api.EVENT_ID,
|
||||
@ -299,16 +298,16 @@ class FormatTest(common.HeatTestCase):
|
||||
rpc_api.EVENT_RES_TYPE,
|
||||
rpc_api.EVENT_RES_PROPERTIES))
|
||||
|
||||
formatted = api.format_event(event)
|
||||
formatted = api.format_event(event, self.stack.identifier())
|
||||
self.assertEqual(event_keys, set(formatted.keys()))
|
||||
|
||||
event_id_formatted = formatted[rpc_api.EVENT_ID]
|
||||
event_identifier = identifier.EventIdentifier(
|
||||
event_id_formatted['tenant'],
|
||||
event_id_formatted['stack_name'],
|
||||
event_id_formatted['stack_id'],
|
||||
event_id_formatted['path'])
|
||||
self.assertEqual(event_id, event_identifier.event_id)
|
||||
self.assertEqual({
|
||||
'path': '/resources/generic1/events/%s' % event.uuid,
|
||||
'stack_id': self.stack.id,
|
||||
'stack_name': 'test_stack',
|
||||
'tenant': 'test_tenant_id'
|
||||
}, event_id_formatted)
|
||||
|
||||
@mock.patch.object(api, 'format_stack_resource')
|
||||
def test_format_stack_preview(self, mock_fmt_resource):
|
||||
|
@ -14,9 +14,7 @@
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
import oslo_db.exception
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine import event
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import stack
|
||||
@ -104,73 +102,6 @@ class EventTest(EventCommon):
|
||||
super(EventTest, self).setUp()
|
||||
self._setup_stack(tmpl)
|
||||
|
||||
def test_load(self):
|
||||
self.resource.resource_id_set('resource_physical_id')
|
||||
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type())
|
||||
|
||||
e.store()
|
||||
self.assertIsNotNone(e.id)
|
||||
|
||||
loaded_e = event.Event.load(self.ctx, e.id)
|
||||
|
||||
self.assertEqual(self.stack.id, loaded_e.stack.id)
|
||||
self.assertEqual(self.resource.name, loaded_e.resource_name)
|
||||
self.assertEqual('wibble', loaded_e.physical_resource_id)
|
||||
self.assertEqual('TEST', loaded_e.action)
|
||||
self.assertEqual('IN_PROGRESS', loaded_e.status)
|
||||
self.assertEqual('Testing', loaded_e.reason)
|
||||
self.assertIsNotNone(loaded_e.timestamp)
|
||||
self.assertEqual({'Foo': 'goo'}, loaded_e.resource_properties)
|
||||
|
||||
def test_load_with_timestamp(self):
|
||||
self.resource.resource_id_set('resource_physical_id')
|
||||
timestamp = timeutils.utcnow()
|
||||
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type(),
|
||||
timestamp=timestamp)
|
||||
|
||||
e.store()
|
||||
self.assertIsNotNone(e.id)
|
||||
|
||||
loaded_e = event.Event.load(self.ctx, e.id)
|
||||
|
||||
self.assertEqual(timestamp, loaded_e.timestamp)
|
||||
|
||||
def test_load_no_event(self):
|
||||
with mock.patch("heat.objects.event.Event") as event_mock:
|
||||
event_mock.get_by_id.return_value = None
|
||||
self.assertRaisesRegex(exception.NotFound,
|
||||
"^No event exists with id",
|
||||
event.Event.load, self.ctx, 1)
|
||||
|
||||
def test_load_given_stack_event(self):
|
||||
self.resource.resource_id_set('resource_physical_id')
|
||||
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type())
|
||||
|
||||
e.store()
|
||||
self.assertIsNotNone(e.id)
|
||||
|
||||
ev = event_object.Event.get_by_id(self.ctx, e.id)
|
||||
|
||||
loaded_e = event.Event.load(self.ctx, e.id, stack=self.stack, event=ev)
|
||||
|
||||
self.assertEqual(self.stack.id, loaded_e.stack.id)
|
||||
self.assertEqual(self.resource.name, loaded_e.resource_name)
|
||||
self.assertEqual('wibble', loaded_e.physical_resource_id)
|
||||
self.assertEqual('TEST', loaded_e.action)
|
||||
self.assertEqual('IN_PROGRESS', loaded_e.status)
|
||||
self.assertEqual('Testing', loaded_e.reason)
|
||||
self.assertIsNotNone(loaded_e.timestamp)
|
||||
self.assertEqual({'Foo': 'goo'}, loaded_e.resource_properties)
|
||||
|
||||
def test_store_caps_events(self):
|
||||
cfg.CONF.set_override('event_purge_batch_size', 1, enforce_type=True)
|
||||
cfg.CONF.set_override('max_events_per_stack', 1, enforce_type=True)
|
||||
|
Loading…
Reference in New Issue
Block a user