def test_store_caps_events_random_purge(self): cfg.CONF.set_override('event_purge_batch_size', 100, enforce_type=True) cfg.CONF.set_override('max_events_per_stack', 1, enforce_type=True) self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arkansas', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() # purge happens with mock.patch("random.uniform") as mock_random_uniform: mock_random_uniform.return_value = 2.0 / 100 - .0001 e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alaska', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() events = event_object.Event.get_all_by_stack(self.ctx, self.stack.id) self.assertEqual(1, len(events)) self.assertEqual('alaska', events[0].physical_resource_id) # no purge happens with mock.patch("random.uniform") as mock_random_uniform: mock_random_uniform.return_value = 2.0 / 100 + .0001 e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'aardvark', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() events = event_object.Event.get_all_by_stack(self.ctx, self.stack.id) self.assertEqual(2, len(events))
def test_store_caps_resource_props_data(self): cfg.CONF.set_override('event_purge_batch_size', 2) cfg.CONF.set_override('max_events_per_stack', 3) self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', self.resource._rsrc_prop_data_id, self.resource._stored_properties_data, self.resource.name, self.resource.type()) e.store() rpd1_id = self.resource._rsrc_prop_data_id rpd2 = rpd_object.ResourcePropertiesData.create( self.ctx, {'encrypted': False, 'data': {'foo': 'bar'}}) rpd2_id = rpd2.id e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arizona', rpd2_id, rpd2.data, self.resource.name, self.resource.type()) e.store() rpd3 = rpd_object.ResourcePropertiesData.create( self.ctx, {'encrypted': False, 'data': {'foo': 'bar'}}) rpd3_id = rpd3.id e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arkansas', rpd3_id, rpd3.data, self.resource.name, self.resource.type()) e.store() rpd4 = rpd_object.ResourcePropertiesData.create( self.ctx, {'encrypted': False, 'data': {'foo': 'bar'}}) rpd4_id = rpd4.id e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arkansas', rpd4_id, rpd4.data, self.resource.name, self.resource.type()) e.store() events = event_object.Event.get_all_by_stack(self.ctx, self.stack.id) self.assertEqual(2, len(events)) self.assertEqual('arkansas', events[0].physical_resource_id) # rpd1 should still exist since that is still referred to by # the resource. rpd2 shoud have been deleted along with the # 2nd event. self.assertIsNotNone(self.ctx.session.query( models.ResourcePropertiesData).get(rpd1_id)) self.assertIsNone(self.ctx.session.query( models.ResourcePropertiesData).get(rpd2_id)) # We didn't purge the last two events, so we ought to have # kept rsrc_prop_data for both. self.assertIsNotNone(self.ctx.session.query( models.ResourcePropertiesData).get(rpd3_id)) self.assertIsNotNone(self.ctx.session.query( models.ResourcePropertiesData).get(rpd4_id))
def test_as_dict(self): e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource.properties, self.resource.name, self.resource.type()) e.store() expected = { 'id': e.uuid, 'timestamp': e.timestamp.isoformat(), 'type': 'os.heat.event', 'version': '0.1', 'payload': { 'physical_resource_id': 'wibble', 'resource_action': 'TEST', 'resource_name': 'EventTestResource', 'resource_properties': { 'Foo': 'goo' }, 'resource_status': 'IN_PROGRESS', 'resource_status_reason': 'Testing', 'resource_type': 'ResourceWithRequiredProps', 'stack_id': self.stack.id, 'version': '0.1' } } self.assertEqual(expected, e.as_dict())
def test_props_encrypted(self): e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource._rsrc_prop_data_id, self.resource._stored_properties_data, self.resource.name, self.resource.type()) e.store() # verify the resource_properties_data db data is encrypted e_obj = event_object.Event.get_all_by_stack(self.resource.context, self.stack.id)[0] rpd_id = e_obj['rsrc_prop_data_id'] results = self.resource.context.session.query( models.ResourcePropertiesData).filter_by( id=rpd_id) self.assertNotEqual('goo', results[0]['data']['Foo']) self.assertTrue(results[0]['encrypted']) ev = event_object.Event.get_all_by_stack(self.ctx, self.stack.id)[0] # verify not eager loaded self.assertIsNone(ev._resource_properties) # verify encrypted data is decrypted when retrieved through # heat object layer (normally it would be eager loaded) self.assertEqual({'Foo': 'goo'}, ev.resource_properties) # verify eager load case (uuid is specified) filters = {'uuid': ev.uuid} ev = event_object.Event.get_all_by_stack(self.ctx, self.stack.id, filters=filters)[0] # verify eager loaded self.assertIsNotNone(ev._resource_properties) self.assertEqual({'Foo': 'goo'}, ev.resource_properties)
def test_identifier_is_none(self): e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource.properties, self.resource.name, self.resource.type()) e.store() self.assertIsNone(e.identifier())
def test_store_fail_one_prop(self): self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', 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) errors = [oslo_db.exception.DBError] def side_effect(*args): try: raise errors.pop() except IndexError: self.assertEqual( { 'Foo1': 'zoo', 'Foo2': '<Deleted, too large>', 'Foo3': '99999', 'Error': 'Resource properties are too large to store' }, args[1]['resource_properties']) return ev with mock.patch("heat.objects.event.Event") as mock_event: mock_event.create.side_effect = side_effect e.store()
def _add_event(self, action, status, reason): '''Add a state change event to the database.''' ev = event.Event(self.context, self.stack, action, status, reason, self.resource_id, self.properties, self.name, self.type()) ev.store()
def test_badprop(self): tmpl = {'Type': 'GenericResourceType', 'Properties': {'foo': 'abc'}} rname = 'bad_resource' res = generic_rsrc.GenericResource(rname, tmpl, self.stack) e = event.Event(self.ctx, self.stack, res, 'TEST_IN_PROGRESS', 'Testing', 'wibble', res.properties) self.assertTrue('Error' in e.resource_properties)
def _dummy_event(self, event_id): 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)
def test_badprop(self): rname = 'bad_resource' defn = rsrc_defn.ResourceDefinition(rname, 'ResourceWithRequiredProps', {'IntFoo': False}) res = generic_rsrc.ResourceWithRequiredProps(rname, defn, self.stack) e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', res.properties, res.name, res.type()) self.assertIn('Error', e.resource_properties)
def _dummy_event(self): resource = self.stack['generic1'] 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_store_caps_events(self): cfg.CONF.set_override('event_purge_batch_size', 1) cfg.CONF.set_override('max_events_per_stack', 1) self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', self.resource.properties, self.resource.name, self.resource.type()) e.store() self.assertEquals( 1, len(db_api.event_get_all_by_stack(self.ctx, self.stack.id))) e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arizona', self.resource.properties, self.resource.name, self.resource.type()) e.store() events = db_api.event_get_all_by_stack(self.ctx, self.stack.id) self.assertEquals(1, len(events)) self.assertEqual('arizona', events[0].physical_resource_id)
def _add_event(self, new_state, reason): '''Add a state change event to the database.''' ev = event.Event(self.context, self.stack, self, new_state, reason, self.resource_id, self.properties) try: ev.store() except Exception as ex: logger.error('DB error %s' % str(ex))
def _add_event(self, action, status, reason): '''Add a state change event to the database.''' ev = event.Event(self.context, self.stack, action, status, reason, self.resource_id, self.properties, self.name, self.type()) try: ev.store() except Exception as ex: logger.error(_('DB error %s') % str(ex))
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) self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() self.assertEqual(1, len(event_object.Event.get_all_by_stack( self.ctx, self.stack.id))) e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'arizona', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() events = event_object.Event.get_all_by_stack(self.ctx, self.stack.id) self.assertEqual(1, len(events)) self.assertEqual('arizona', events[0].physical_resource_id)
def test_badprop(self): tmpl = { 'Type': 'ResourceWithRequiredProps', 'Properties': { 'Foo': False } } rname = 'bad_resource' res = generic_rsrc.ResourceWithRequiredProps(rname, tmpl, self.stack) 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)
def test_identifier(self): 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 = { 'stack_name': self.stack.name, 'stack_id': self.stack.id, 'tenant': self.ctx.tenant_id, 'path': '/resources/EventTestResource/events/%s' % str(eid) } self.assertEqual(expected_identifier, e.identifier())
def test_too_large_multiple_prop(self): self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', 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) self.assertEqual( {'Error': 'Resource properties are too large to attempt to store'}, ev['resource_properties'])
def test_identifier(self): event_uuid = 'abc123yc-9f88-404d-a85b-531529456xyz' e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource.properties, self.resource.name, self.resource.type(), uuid=event_uuid) e.store() expected_identifier = { 'stack_name': self.stack.name, 'stack_id': self.stack.id, 'tenant': self.ctx.tenant_id, 'path': '/resources/EventTestResource/events/%s' % str(event_uuid) } self.assertEqual(expected_identifier, e.identifier())
def test_load_with_timestamp(self): self.resource.resource_id_set('resource_physical_id') timestamp = datetime.datetime.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_deprecated_prop_data(self): e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() # for test purposes, dress up the event to have the deprecated # properties_data field populated e_obj = self.ctx.session.query(models.Event).get(e.id) with self.ctx.session.begin(): e_obj['resource_properties'] = {'Time': 'not enough'} e_obj['rsrc_prop_data'] = None # verify the deprecated data gets loaded ev = event_object.Event.get_all_by_stack(self.ctx, self.stack.id)[0] self.assertEqual({'Time': 'not enough'}, ev.resource_properties)
def test_too_large_single_prop(self): self.resource.resource_id_set('resource_physical_id') e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'alabama', 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) self.assertEqual( {'Foo1': 'zoo', 'Foo2': '<Deleted, too large>', 'Foo3': '99999', 'Error': 'Resource properties are too large to store fully'}, ev['resource_properties'])
def test_props_encrypted(self): e = event.Event(self.ctx, self.stack, 'TEST', 'IN_PROGRESS', 'Testing', 'wibble', self.resource._rsrc_prop_data, self.resource.name, self.resource.type()) e.store() # verify the resource_properties_data db data is encrypted e_obj = event_object.Event.get_by_id(self.resource.context, e.id) rpd_id = e_obj['rsrc_prop_data'].id results = self.resource.context.session.query( models.ResourcePropertiesData).filter_by(id=rpd_id) self.assertNotEqual('goo', results[0]['data']['Foo']) self.assertTrue(results[0]['encrypted']) # verify encrypted data is decrypted when retrieved through # heat object layer ev = event_object.Event.get_by_id(self.ctx, e.id) self.assertEqual({'Foo': 'goo'}, ev.rsrc_prop_data.data)
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.store() self.assertNotEqual(e.id, None) loaded_e = event.Event.load(self.ctx, e.id) self.assertEqual(loaded_e.stack.id, self.stack.id) self.assertEqual(loaded_e.resource.name, self.resource.name) self.assertEqual(loaded_e.resource.id, self.resource.id) self.assertEqual(loaded_e.physical_resource_id, 'wibble') self.assertEqual(loaded_e.new_state, 'TEST_IN_PROGRESS') self.assertEqual(loaded_e.reason, 'Testing') self.assertNotEqual(loaded_e.timestamp, None) self.assertEqual(loaded_e.resource_properties, {'foo': True})
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.assertNotEqual(e.id, None) 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.assertNotEqual(None, loaded_e.timestamp) self.assertEqual({'Foo': 'goo'}, loaded_e.resource_properties)
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)