Make Event object independent of resource object
The event table is pretty much self contained. So we actually don't need to referece the corresponding resources to retrieve information. Fixes bug #1204506 Change-Id: If0b88e0f9e243cf3cc6d747ffa04b9a429ea83a2
This commit is contained in:
parent
d3bc51ffaf
commit
d233cf6703
|
@ -127,12 +127,12 @@ def format_event(event):
|
|||
api.EVENT_STACK_ID: dict(stack_identifier),
|
||||
api.EVENT_STACK_NAME: stack_identifier.stack_name,
|
||||
api.EVENT_TIMESTAMP: timeutils.isotime(event.timestamp),
|
||||
api.EVENT_RES_NAME: event.resource.name,
|
||||
api.EVENT_RES_NAME: event.logical_resource_id,
|
||||
api.EVENT_RES_PHYSICAL_ID: event.physical_resource_id,
|
||||
api.EVENT_RES_ACTION: event.action,
|
||||
api.EVENT_RES_STATUS: event.status,
|
||||
api.EVENT_RES_STATUS_DATA: event.reason,
|
||||
api.EVENT_RES_TYPE: event.resource.type(),
|
||||
api.EVENT_RES_TYPE: event.resource_type,
|
||||
api.EVENT_RES_PROPERTIES: event.resource_properties,
|
||||
}
|
||||
|
||||
|
|
|
@ -24,22 +24,22 @@ logger = logging.getLogger(__name__)
|
|||
class Event(object):
|
||||
'''Class representing a Resource state change.'''
|
||||
|
||||
def __init__(self, context, stack, resource,
|
||||
action, status, reason,
|
||||
physical_resource_id, resource_properties,
|
||||
timestamp=None, id=None):
|
||||
def __init__(self, context, stack, action, status, reason,
|
||||
physical_resource_id, resource_properties, resource_name,
|
||||
resource_type, timestamp=None, id=None):
|
||||
'''
|
||||
Initialise from a context, stack, resource, event information and
|
||||
current resource data. The timestamp and database ID may also be
|
||||
initialised if the event is already in the database.
|
||||
Initialise from a context, stack, and event information. The timestamp
|
||||
and database ID may also be initialised if the event is already in the
|
||||
database.
|
||||
'''
|
||||
self.context = context
|
||||
self.resource = resource
|
||||
self.stack = stack
|
||||
self.action = action
|
||||
self.status = status
|
||||
self.reason = reason
|
||||
self.physical_resource_id = physical_resource_id
|
||||
self.logical_resource_id = resource_name
|
||||
self.resource_type = resource_type
|
||||
try:
|
||||
self.resource_properties = dict(resource_properties)
|
||||
except ValueError as ex:
|
||||
|
@ -60,24 +60,22 @@ class Event(object):
|
|||
|
||||
st = stack if stack is not None else\
|
||||
parser.Stack.load(context, ev.stack_id)
|
||||
resource = st[ev.logical_resource_id]
|
||||
|
||||
return cls(context, st, resource,
|
||||
ev.resource_action, ev.resource_status,
|
||||
ev.resource_status_reason,
|
||||
ev.physical_resource_id, ev.resource_properties,
|
||||
ev.created_at, ev.id)
|
||||
return cls(context, st, ev.resource_action, ev.resource_status,
|
||||
ev.resource_status_reason, ev.physical_resource_id,
|
||||
ev.resource_properties, ev.logical_resource_id,
|
||||
ev.resource_type, ev.created_at, ev.id)
|
||||
|
||||
def store(self):
|
||||
'''Store the Event in the database.'''
|
||||
ev = {
|
||||
'logical_resource_id': self.resource.name,
|
||||
'logical_resource_id': self.logical_resource_id,
|
||||
'physical_resource_id': self.physical_resource_id,
|
||||
'stack_id': self.stack.id,
|
||||
'resource_action': self.action,
|
||||
'resource_status': self.status,
|
||||
'resource_status_reason': self.reason,
|
||||
'resource_type': self.resource.type(),
|
||||
'resource_type': self.resource_type,
|
||||
'resource_properties': self.resource_properties,
|
||||
}
|
||||
|
||||
|
@ -96,5 +94,7 @@ class Event(object):
|
|||
if self.id is None:
|
||||
return None
|
||||
|
||||
return identifier.EventIdentifier(event_id=str(self.id),
|
||||
**self.resource.identifier())
|
||||
res_id = identifier.ResourceIdentifier(
|
||||
resource_name=self.logical_resource_id, **self.stack.identifier())
|
||||
|
||||
return identifier.EventIdentifier(event_id=str(self.id), **res_id)
|
||||
|
|
|
@ -595,9 +595,9 @@ class Resource(object):
|
|||
|
||||
def _add_event(self, action, status, reason):
|
||||
'''Add a state change event to the database.'''
|
||||
ev = event.Event(self.context, self.stack, self,
|
||||
action, status, reason,
|
||||
self.resource_id, self.properties)
|
||||
ev = event.Event(self.context, self.stack, action, status, reason,
|
||||
self.resource_id, self.properties,
|
||||
self.name, self.type())
|
||||
|
||||
try:
|
||||
ev.store()
|
||||
|
|
|
@ -744,6 +744,64 @@ class StackServiceTest(HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
@stack_context('service_event_list_deleted_resource_test_stack')
|
||||
def test_stack_event_list_deleted_resource(self):
|
||||
rsrs._register_class('GenericResourceType',
|
||||
generic_rsrc.GenericResource)
|
||||
|
||||
def run(stack_id, func, *args):
|
||||
func(*args)
|
||||
self.eng._start_in_thread = run
|
||||
|
||||
new_tmpl = {'Resources': {'AResource': {'Type':
|
||||
'GenericResourceType'}}}
|
||||
|
||||
self.m.StubOutWithMock(instances.Instance, 'handle_delete')
|
||||
instances.Instance.handle_delete()
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
||||
result = self.eng.update_stack(self.ctx, self.stack.identifier(),
|
||||
new_tmpl, None, None, {})
|
||||
|
||||
# The self.stack reference needs to be updated. Since the underlying
|
||||
# stack is updated in update_stack, the original reference is now
|
||||
# pointing to an orphaned stack object.
|
||||
self.stack = parser.Stack.load(self.ctx, stack_id=result['stack_id'])
|
||||
|
||||
self.assertEqual(self.stack.identifier(), result)
|
||||
self.assertTrue(isinstance(result, dict))
|
||||
self.assertTrue(result['stack_id'])
|
||||
events = self.eng.list_events(self.ctx, self.stack.identifier())
|
||||
|
||||
self.assertEqual(6, len(events))
|
||||
|
||||
for ev in events:
|
||||
self.assertIn('event_identity', ev)
|
||||
self.assertEqual(dict, type(ev['event_identity']))
|
||||
self.assertTrue(ev['event_identity']['path'].rsplit('/', 1)[1])
|
||||
|
||||
self.assertIn('logical_resource_id', ev)
|
||||
self.assertIn('physical_resource_id', ev)
|
||||
self.assertIn('resource_properties', ev)
|
||||
self.assertIn('resource_status_reason', ev)
|
||||
|
||||
self.assertIn(ev['resource_action'], ('CREATE', 'DELETE'))
|
||||
self.assertIn(ev['resource_status'], ('IN_PROGRESS', 'COMPLETE'))
|
||||
|
||||
self.assertIn('resource_type', ev)
|
||||
self.assertIn(ev['resource_type'], ('AWS::EC2::Instance',
|
||||
'GenericResourceType'))
|
||||
|
||||
self.assertIn('stack_identity', ev)
|
||||
|
||||
self.assertIn('stack_name', ev)
|
||||
self.assertEqual(self.stack.name, ev['stack_name'])
|
||||
|
||||
self.assertIn('event_time', ev)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
@stack_context('service_event_list_test_stack')
|
||||
def test_stack_event_list_by_tenant(self):
|
||||
events = self.eng.list_events(self.ctx, None)
|
||||
|
|
|
@ -59,9 +59,9 @@ class EventTest(HeatTestCase):
|
|||
def test_load(self):
|
||||
self.resource.resource_id_set('resource_physical_id')
|
||||
|
||||
e = event.Event(self.ctx, self.stack, self.resource,
|
||||
'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties)
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type())
|
||||
|
||||
e.store()
|
||||
self.assertNotEqual(e.id, None)
|
||||
|
@ -69,8 +69,7 @@ class EventTest(HeatTestCase):
|
|||
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(self.resource.id, loaded_e.resource.id)
|
||||
self.assertEqual(self.resource.name, loaded_e.logical_resource_id)
|
||||
self.assertEqual('wibble', loaded_e.physical_resource_id)
|
||||
self.assertEqual('TEST', loaded_e.action)
|
||||
self.assertEqual('IN_PROGRESS', loaded_e.status)
|
||||
|
@ -81,9 +80,9 @@ class EventTest(HeatTestCase):
|
|||
def test_load_given_stack_event(self):
|
||||
self.resource.resource_id_set('resource_physical_id')
|
||||
|
||||
e = event.Event(self.ctx, self.stack, self.resource,
|
||||
'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties)
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type())
|
||||
|
||||
e.store()
|
||||
self.assertNotEqual(e.id, None)
|
||||
|
@ -93,8 +92,7 @@ class EventTest(HeatTestCase):
|
|||
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(self.resource.id, loaded_e.resource.id)
|
||||
self.assertEqual(self.resource.name, loaded_e.logical_resource_id)
|
||||
self.assertEqual('wibble', loaded_e.physical_resource_id)
|
||||
self.assertEqual('TEST', loaded_e.action)
|
||||
self.assertEqual('IN_PROGRESS', loaded_e.status)
|
||||
|
@ -103,9 +101,9 @@ class EventTest(HeatTestCase):
|
|||
self.assertEqual({'Foo': 'goo'}, loaded_e.resource_properties)
|
||||
|
||||
def test_identifier(self):
|
||||
e = event.Event(self.ctx, self.stack, self.resource,
|
||||
'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties)
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', self.resource.properties,
|
||||
self.resource.name, self.resource.type())
|
||||
|
||||
eid = e.store()
|
||||
expected_identifier = {
|
||||
|
@ -121,7 +119,6 @@ class EventTest(HeatTestCase):
|
|||
'Properties': {'Foo': False}}
|
||||
rname = 'bad_resource'
|
||||
res = generic_rsrc.ResourceWithRequiredProps(rname, tmpl, self.stack)
|
||||
e = event.Event(self.ctx, self.stack, res,
|
||||
'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', res.properties)
|
||||
e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing',
|
||||
'wibble', res.properties, res.name, res.type())
|
||||
self.assertTrue('Error' in e.resource_properties)
|
||||
|
|
Loading…
Reference in New Issue