Implemented audit.create notification

In this changeset, I implemented the audit.create notification.

Change-Id: Ia092ca3a3dc951e3313a07f15a98aec5818e9ab0
Partially-Implements: blueprint audit-versioned-notifications-api
This commit is contained in:
Vincent Françoise 2016-10-20 09:37:49 +02:00
parent 9405eb0806
commit 0c0a9c84d6
16 changed files with 332 additions and 88 deletions

View File

@ -0,0 +1,69 @@
{
"priority": "INFO",
"payload": {
"watcher_object.data": {
"audit_type": "ONESHOT",
"parameters": {
"para2": "hello",
"para1": 3.2
},
"state": "PENDING",
"updated_at": null,
"deleted_at": null,
"goal": {
"watcher_object.data": {
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
"name": "dummy",
"updated_at": null,
"deleted_at": null,
"efficacy_specification": [],
"created_at": "2016-11-04T16:25:35Z",
"display_name": "Dummy goal"
},
"watcher_object.name": "GoalPayload",
"watcher_object.version": "1.0",
"watcher_object.namespace": "watcher"
},
"interval": null,
"scope": [],
"strategy": {
"watcher_object.data": {
"parameters_spec": {
"properties": {
"para2": {
"type": "string",
"default": "hello",
"description": "string parameter example"
},
"para1": {
"description": "number parameter example",
"maximum": 10.2,
"type": "number",
"default": 3.2,
"minimum": 1.0
}
}
},
"name": "dummy",
"uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
"updated_at": null,
"deleted_at": null,
"created_at": "2016-11-04T16:25:35Z",
"display_name": "Dummy strategy"
},
"watcher_object.name": "StrategyPayload",
"watcher_object.version": "1.0",
"watcher_object.namespace": "watcher"
},
"created_at": "2016-11-04T16:29:20Z",
"uuid": "4a97b9dd-2023-43dc-b713-815bdd94d4d6"
},
"watcher_object.name": "AuditCreatePayload",
"watcher_object.version": "1.0",
"watcher_object.namespace": "watcher"
},
"publisher_id": "infra-optim:localhost",
"timestamp": "2016-11-04 16:31:36.264673 ",
"event_type": "audit.create",
"message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
}

View File

@ -82,6 +82,19 @@ class AuditStateUpdatePayload(notificationbase.NotificationPayloadBase):
}
@base.WatcherObjectRegistry.register_notification
class AuditCreatePayload(AuditPayload):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {}
def __init__(self, audit, goal, strategy):
super(AuditCreatePayload, self).__init__(
audit=audit,
goal=goal,
strategy=strategy)
@base.WatcherObjectRegistry.register_notification
class AuditUpdatePayload(AuditPayload):
# Version 1.0: Initial version
@ -98,6 +111,29 @@ class AuditUpdatePayload(AuditPayload):
strategy=strategy)
# @notificationbase.notification_sample('audit-create.json')
# @notificationbase.notification_sample('audit-delete.json')
# @base.WatcherObjectRegistry.register_notification
# class AuditActionNotification(notificationbase.NotificationBase):
# # Version 1.0: Initial version
# VERSION = '1.0'
# fields = {
# 'payload': wfields.ObjectField('AuditActionPayload')
# }
@notificationbase.notification_sample('audit-create.json')
@base.WatcherObjectRegistry.register_notification
class AuditCreateNotification(notificationbase.NotificationBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'payload': wfields.ObjectField('AuditCreatePayload')
}
@notificationbase.notification_sample('audit-update.json')
@base.WatcherObjectRegistry.register_notification
class AuditUpdateNotification(notificationbase.NotificationBase):
@ -109,9 +145,7 @@ class AuditUpdateNotification(notificationbase.NotificationBase):
}
def send_update(context, audit, service='infra-optim',
host=None, old_state=None):
"""Emit an audit.update notification."""
def _get_common_payload(audit):
goal = None
strategy = None
try:
@ -128,6 +162,37 @@ def send_update(context, audit, service='infra-optim',
strategy_payload = strategy_notifications.StrategyPayload(
strategy=strategy)
return goal_payload, strategy_payload
def send_create(context, audit, service='infra-optim', host=None):
"""Emit an audit.create notification."""
goal_payload, strategy_payload = _get_common_payload(audit)
versioned_payload = AuditCreatePayload(
audit=audit,
goal=goal_payload,
strategy=strategy_payload,
)
notification = AuditCreateNotification(
priority=wfields.NotificationPriority.INFO,
event_type=notificationbase.EventType(
object='audit',
action=wfields.NotificationAction.CREATE),
publisher=notificationbase.NotificationPublisher(
host=host or CONF.host,
binary=service),
payload=versioned_payload)
notification.emit(context)
def send_update(context, audit, service='infra-optim',
host=None, old_state=None):
"""Emit an audit.update notification."""
goal_payload, strategy_payload = _get_common_payload(audit)
state_update = AuditStateUpdatePayload(
old_state=old_state,
state=audit.state if old_state else None)

View File

@ -145,6 +145,12 @@ class NotificationBase(NotificationObject):
'publisher': wfields.ObjectField('NotificationPublisher'),
}
def save(self, context):
raise exception.UnsupportedError()
def obj_load_attr(self, attrname):
raise exception.UnsupportedError()
def _should_notify(self):
"""Determine whether the notification should be sent.

View File

@ -236,6 +236,11 @@ class Audit(base.WatcherPersistentObject, base.WatcherObject,
# notifications containing information about the related relationships
self._from_db_object(self, db_audit, eager=True)
def _notify():
notifications.audit.send_create(self._context, self)
_notify()
@base.remotable
def destroy(self):
"""Delete the Audit from the DB."""

View File

@ -155,7 +155,7 @@ class WatcherPersistentObject(object):
if obj[rel_id]
)
for obj_field, related_obj_cls, rel_id in loadable_fields:
if db_object.get(obj_field) and obj[rel_id]:
if getattr(db_object, obj_field, None) and obj[rel_id]:
# The object field data was eagerly loaded alongside
# the main object data
obj[obj_field] = related_obj_cls._from_db_object(

View File

@ -88,9 +88,12 @@ def audit_post_data(**kw):
def audit_template_post_data(**kw):
audit_template = db_utils.get_test_audit_template(**kw)
internal = audit_template_ctrl.AuditTemplatePatchType.internal_attrs()
return remove_internal(audit_template, internal)
attrs = audit_template_ctrl.AuditTemplatePostType._wsme_attributes
audit_template = db_utils.get_test_audit_template()
fields = [field.key for field in attrs]
post_data = {k: v for k, v in audit_template.items() if k in fields}
post_data.update({k: v for k, v in kw.items() if k in fields})
return post_data
def action_post_data(**kw):

View File

@ -189,7 +189,8 @@ class TestListAction(api_base.FunctionalTest):
def test_filter_by_action_plan_uuid(self):
action_plan_1 = obj_utils.create_test_action_plan(
self.context,
uuid=utils.generate_uuid())
uuid=utils.generate_uuid(),
audit_id=self.audit.id)
action_list = []
for id_ in range(3):
@ -201,7 +202,8 @@ class TestListAction(api_base.FunctionalTest):
action_plan_2 = obj_utils.create_test_action_plan(
self.context,
uuid=utils.generate_uuid())
uuid=utils.generate_uuid(),
audit_id=self.audit.id)
for id_ in range(4, 5, 6):
obj_utils.create_test_action(
@ -221,14 +223,12 @@ class TestListAction(api_base.FunctionalTest):
self.assertEqual(action_plan_2.uuid, action['action_plan_uuid'])
def test_details_and_filter_by_action_plan_uuid(self):
audit = obj_utils.create_test_audit(self.context,
uuid=utils.generate_uuid())
action_plan = obj_utils.create_test_action_plan(
self.context,
uuid=utils.generate_uuid(),
audit_id=audit.id)
audit_id=self.audit.id)
for id_ in range(3):
for id_ in range(1, 3):
action = obj_utils.create_test_action(
self.context, id=id_,
action_plan_id=action_plan.id,
@ -240,33 +240,29 @@ class TestListAction(api_base.FunctionalTest):
self.assertEqual(action_plan.uuid, action['action_plan_uuid'])
def test_details_and_filter_by_audit_uuid(self):
audit = obj_utils.create_test_audit(self.context,
uuid=utils.generate_uuid())
action_plan = obj_utils.create_test_action_plan(
self.context,
uuid=utils.generate_uuid(),
audit_id=audit.id)
audit_id=self.audit.id)
for id_ in range(3):
for id_ in range(1, 3):
action = obj_utils.create_test_action(
self.context, id=id_,
action_plan_id=action_plan.id,
uuid=utils.generate_uuid())
response = self.get_json(
'/actions/detail?audit_uuid=%s' % audit.uuid)
'/actions/detail?audit_uuid=%s' % self.audit.uuid)
for action in response['actions']:
self.assertEqual(action_plan.uuid, action['action_plan_uuid'])
def test_filter_by_action_plan_and_audit_uuids(self):
audit = obj_utils.create_test_audit(
self.context, uuid=utils.generate_uuid())
action_plan = obj_utils.create_test_action_plan(
self.context,
uuid=utils.generate_uuid(),
audit_id=audit.id)
audit_id=self.audit.id)
url = '/actions?action_plan_uuid=%s&audit_uuid=%s' % (
action_plan.uuid, audit.uuid)
action_plan.uuid, self.audit.uuid)
response = self.get_json(url, expect_errors=True)
self.assertEqual(400, response.status_int)

View File

@ -172,8 +172,9 @@ class TestListActionPlan(api_base.FunctionalTest):
def test_many_with_audit_uuid(self):
action_plan_list = []
audit = obj_utils.create_test_audit(self.context,
id=2,
uuid=utils.generate_uuid())
for id_ in range(5):
for id_ in range(2, 5):
action_plan = obj_utils.create_test_action_plan(
self.context, id=id_, uuid=utils.generate_uuid(),
audit_id=audit.id)
@ -186,14 +187,16 @@ class TestListActionPlan(api_base.FunctionalTest):
def test_many_with_audit_uuid_filter(self):
action_plan_list1 = []
audit1 = obj_utils.create_test_audit(self.context,
id=2,
uuid=utils.generate_uuid())
for id_ in range(5):
for id_ in range(2, 5):
action_plan = obj_utils.create_test_action_plan(
self.context, id=id_, uuid=utils.generate_uuid(),
audit_id=audit1.id)
action_plan_list1.append(action_plan.uuid)
audit2 = obj_utils.create_test_audit(self.context,
id=3,
uuid=utils.generate_uuid())
action_plan_list2 = []
for id_ in [5, 6, 7]:
@ -241,8 +244,9 @@ class TestListActionPlan(api_base.FunctionalTest):
def test_many_with_sort_key_audit_uuid(self):
audit_list = []
for id_ in range(5):
for id_ in range(2, 5):
audit = obj_utils.create_test_audit(self.context,
id=id_,
uuid=utils.generate_uuid())
obj_utils.create_test_action_plan(
self.context, id=id_, uuid=utils.generate_uuid(),
@ -251,7 +255,7 @@ class TestListActionPlan(api_base.FunctionalTest):
response = self.get_json('/action_plans/?sort_key=audit_uuid')
self.assertEqual(5, len(response['action_plans']))
self.assertEqual(3, len(response['action_plans']))
uuids = [s['audit_uuid'] for s in response['action_plans']]
self.assertEqual(sorted(audit_list), uuids)

View File

@ -32,14 +32,11 @@ from watcher.tests.objects import utils as obj_utils
def post_get_test_audit_template(**kw):
audit_template = api_utils.audit_template_post_data(**kw)
goal = db_utils.get_test_goal()
strategy = db_utils.get_test_strategy(goal_id=goal['id'])
del audit_template['uuid']
del audit_template['goal_id']
del audit_template['strategy_id']
audit_template['goal'] = kw.get('goal', goal['uuid'])
audit_template['strategy'] = kw.get('strategy', strategy['uuid'])
kw['goal'] = kw.get('goal', goal['uuid'])
kw['strategy'] = kw.get('strategy', strategy['uuid'])
audit_template = api_utils.audit_template_post_data(**kw)
return audit_template
@ -57,20 +54,16 @@ class FunctionalTestWithSetup(api_base.FunctionalTest):
def setUp(self):
super(FunctionalTestWithSetup, self).setUp()
self.fake_goal1 = obj_utils.get_test_goal(
self.fake_goal1 = obj_utils.create_test_goal(
self.context, id=1, uuid=utils.generate_uuid(), name="dummy_1")
self.fake_goal2 = obj_utils.get_test_goal(
self.fake_goal2 = obj_utils.create_test_goal(
self.context, id=2, uuid=utils.generate_uuid(), name="dummy_2")
self.fake_goal1.create()
self.fake_goal2.create()
self.fake_strategy1 = obj_utils.get_test_strategy(
self.fake_strategy1 = obj_utils.create_test_strategy(
self.context, id=1, uuid=utils.generate_uuid(), name="strategy_1",
goal_id=self.fake_goal1.id)
self.fake_strategy2 = obj_utils.get_test_strategy(
self.fake_strategy2 = obj_utils.create_test_strategy(
self.context, id=2, uuid=utils.generate_uuid(), name="strategy_2",
goal_id=self.fake_goal2.id)
self.fake_strategy1.create()
self.fake_strategy2.create()
class TestListAuditTemplate(FunctionalTestWithSetup):

View File

@ -23,6 +23,7 @@ from watcher.db.sqlalchemy import api as sqla_api
from watcher.db.sqlalchemy import migration
from watcher.db.sqlalchemy import models
from watcher.tests import base
from watcher.tests.db import utils
CONF = cfg.CONF
@ -65,6 +66,9 @@ class Database(fixtures.Fixture):
class DbTestCase(base.TestCase):
def get_next_id(self):
return next(self._id_gen)
def setUp(self):
cfg.CONF.set_override("enable_authentication", False,
enforce_type=True)
@ -81,3 +85,4 @@ class DbTestCase(base.TestCase):
_DB_CACHE = Database(sqla_api, migration,
sql_connection=CONF.database.connection)
self.useFixture(_DB_CACHE)
self._id_gen = utils.id_generator()

View File

@ -17,9 +17,30 @@
from oslo_utils import timeutils
from watcher.db import api as db_api
from watcher.db.sqlalchemy import models
from watcher import objects
def id_generator():
id_ = 1
while True:
yield id_
id_ += 1
def _load_relationships(model, db_data):
rel_data = {}
relationships = db_api.get_instance()._get_relationships(model)
for name, relationship in relationships.items():
related_model = relationship.argument
if not db_data.get(name):
rel_data[name] = None
else:
rel_data[name] = related_model(**db_data.get(name))
return rel_data
def get_test_audit_template(**kwargs):
audit_template_data = {
'id': kwargs.get('id', 1),
@ -36,10 +57,8 @@ def get_test_audit_template(**kwargs):
# ObjectField doesn't allow None nor dict, so if we want to simulate a
# non-eager object loading, the field should not be referenced at all.
if kwargs.get('goal'):
audit_template_data['goal'] = kwargs.get('goal')
if kwargs.get('strategy'):
audit_template_data['strategy'] = kwargs.get('strategy')
audit_template_data.update(
_load_relationships(models.AuditTemplate, kwargs))
return audit_template_data
@ -77,10 +96,7 @@ def get_test_audit(**kwargs):
}
# ObjectField doesn't allow None nor dict, so if we want to simulate a
# non-eager object loading, the field should not be referenced at all.
if kwargs.get('goal'):
audit_data['goal'] = kwargs.get('goal')
if kwargs.get('strategy'):
audit_data['strategy'] = kwargs.get('strategy')
audit_data.update(_load_relationships(models.Audit, kwargs))
return audit_data
@ -121,8 +137,7 @@ def get_test_action(**kwargs):
# ObjectField doesn't allow None nor dict, so if we want to simulate a
# non-eager object loading, the field should not be referenced at all.
if kwargs.get('action_plan'):
action_data['action_plan'] = kwargs.get('action_plan')
action_data.update(_load_relationships(models.Action, kwargs))
return action_data
@ -158,10 +173,7 @@ def get_test_action_plan(**kwargs):
# ObjectField doesn't allow None nor dict, so if we want to simulate a
# non-eager object loading, the field should not be referenced at all.
if kwargs.get('audit'):
action_plan_data['audit'] = kwargs.get('audit')
if kwargs.get('strategy'):
action_plan_data['strategy'] = kwargs.get('strategy')
action_plan_data.update(_load_relationships(models.ActionPlan, kwargs))
return action_plan_data
@ -244,10 +256,9 @@ def get_test_strategy(**kwargs):
'parameters_spec': kwargs.get('parameters_spec', {}),
}
# goal ObjectField doesn't allow None nor dict, so if we want to simulate a
# ObjectField doesn't allow None nor dict, so if we want to simulate a
# non-eager object loading, the field should not be referenced at all.
if kwargs.get('goal'):
strategy_data['goal'] = kwargs.get('goal')
strategy_data.update(_load_relationships(models.Strategy, kwargs))
return strategy_data

View File

@ -50,17 +50,17 @@ class TestStrategyContext(base.DbTestCase):
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector",
mock.Mock())
def test_execute_force_dummy(self):
obj_utils.create_test_goal(self.context, id=50,
uuid=utils.generate_uuid(),
name="my_goal")
goal = obj_utils.create_test_goal(
self.context, id=50, uuid=utils.generate_uuid(), name="my_goal")
strategy = obj_utils.create_test_strategy(self.context,
id=42,
uuid=utils.generate_uuid(),
name="dummy")
strategy = obj_utils.create_test_strategy(
self.context, id=42, uuid=utils.generate_uuid(), name="dummy",
goal_id=goal.id)
audit = obj_utils.create_test_audit(
self.context,
id=2,
goal_id=goal.id,
strategy_id=strategy.id,
uuid=utils.generate_uuid(),
)
@ -87,6 +87,7 @@ class TestStrategyContext(base.DbTestCase):
audit = obj_utils.create_test_audit(
self.context,
id=2,
strategy_id=strategy.id,
uuid=utils.generate_uuid(),
)

View File

@ -16,32 +16,33 @@ import freezegun
import mock
from watcher.common import exception
from watcher.notifications import audit as auditnotifs
from watcher.tests import base as testbase
from watcher import notifications
from watcher.tests.db import base
from watcher.tests.objects import utils
class TestAuditNotification(testbase.TestCase):
class TestAuditNotification(base.DbTestCase):
@mock.patch.object(auditnotifs.AuditUpdateNotification, '_emit')
@mock.patch.object(notifications.audit.AuditUpdateNotification, '_emit')
def test_send_version_invalid_audit(self, mock_emit):
audit = utils.get_test_audit(mock.Mock(), state='DOESNOTMATTER',
goal_id=1)
self.assertRaises(
exception.InvalidAudit,
auditnotifs.send_update,
notifications.audit.send_update,
mock.MagicMock(), audit, 'host', 'node0')
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
@mock.patch.object(auditnotifs.AuditUpdateNotification, '_emit')
@mock.patch.object(notifications.audit.AuditUpdateNotification, '_emit')
def test_send_version_audit_update_with_strategy(self, mock_emit):
goal = utils.get_test_goal(mock.Mock(), id=1)
strategy = utils.get_test_strategy(mock.Mock(), id=1)
audit = utils.get_test_audit(mock.Mock(), state='ONGOING',
goal = utils.create_test_goal(mock.Mock())
strategy = utils.create_test_strategy(mock.Mock())
audit = utils.create_test_audit(
mock.Mock(), state='ONGOING',
goal_id=goal.id, strategy_id=strategy.id,
goal=goal, strategy=strategy)
auditnotifs.send_update(
notifications.audit.send_update(
mock.MagicMock(), audit, 'host', 'node0', old_state='PENDING')
self.assertEqual(1, mock_emit.call_count)
@ -62,7 +63,7 @@ class TestAuditNotification(testbase.TestCase):
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
"name": "TEST",
"parameters_spec": {},
"created_at": None,
"created_at": "2016-10-18T09:52:05Z",
"display_name": "test strategy",
"deleted_at": None
},
@ -78,7 +79,7 @@ class TestAuditNotification(testbase.TestCase):
"uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
"name": "TEST",
"efficacy_specification": [],
"created_at": None,
"created_at": "2016-10-18T09:52:05Z",
"display_name": "test goal",
"deleted_at": None
},
@ -88,7 +89,7 @@ class TestAuditNotification(testbase.TestCase):
"scope": [],
"state": "ONGOING",
"updated_at": None,
"created_at": None,
"created_at": "2016-10-18T09:52:05Z",
"state_update": {
"watcher_object.namespace": "watcher",
"watcher_object.version": "1.0",
@ -106,12 +107,12 @@ class TestAuditNotification(testbase.TestCase):
)
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
@mock.patch.object(auditnotifs.AuditUpdateNotification, '_emit')
@mock.patch.object(notifications.audit.AuditUpdateNotification, '_emit')
def test_send_version_audit_update_without_strategy(self, mock_emit):
goal = utils.get_test_goal(mock.Mock(), id=1)
goal = utils.create_test_goal(mock.Mock(), id=1)
audit = utils.get_test_audit(
mock.Mock(), state='ONGOING', goal_id=goal.id, goal=goal)
auditnotifs.send_update(
notifications.audit.send_update(
mock.MagicMock(), audit, 'host', 'node0', old_state='PENDING')
self.assertEqual(1, mock_emit.call_count)
@ -134,7 +135,7 @@ class TestAuditNotification(testbase.TestCase):
"uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
"name": "TEST",
"efficacy_specification": [],
"created_at": None,
"created_at": "2016-10-18T09:52:05Z",
"display_name": "test goal",
"deleted_at": None
},
@ -161,3 +162,67 @@ class TestAuditNotification(testbase.TestCase):
},
payload
)
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
@mock.patch.object(notifications.audit.AuditCreateNotification, '_emit')
def test_send_version_audit_create(self, mock_emit):
goal = utils.create_test_goal(mock.Mock())
strategy = utils.create_test_strategy(mock.Mock())
audit = utils.get_test_audit(
mock.Mock(), state='PENDING',
goal_id=goal.id, strategy_id=strategy.id,
goal=goal.as_dict(), strategy=strategy.as_dict())
notifications.audit.send_create(
mock.MagicMock(), audit, 'host', 'node0')
self.assertEqual(1, mock_emit.call_count)
notification = mock_emit.call_args_list[0][1]
payload = notification['payload']
self.assertDictEqual(
{
"watcher_object.namespace": "watcher",
"watcher_object.version": "1.0",
"watcher_object.data": {
"interval": 3600,
"strategy": {
"watcher_object.namespace": "watcher",
"watcher_object.version": "1.0",
"watcher_object.data": {
"updated_at": None,
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
"name": "TEST",
"parameters_spec": {},
"created_at": "2016-10-18T09:52:05Z",
"display_name": "test strategy",
"deleted_at": None
},
"watcher_object.name": "StrategyPayload"
},
"parameters": {},
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
"goal": {
"watcher_object.namespace": "watcher",
"watcher_object.version": "1.0",
"watcher_object.data": {
"updated_at": None,
"uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
"name": "TEST",
"efficacy_specification": [],
"created_at": "2016-10-18T09:52:05Z",
"display_name": "test goal",
"deleted_at": None
},
"watcher_object.name": "GoalPayload"
},
"deleted_at": None,
"scope": [],
"state": "PENDING",
"updated_at": None,
"created_at": None,
"audit_type": "ONESHOT"
},
"watcher_object.name": "AuditCreatePayload"
},
payload
)

View File

@ -258,6 +258,8 @@ expected_notification_fingerprints = {
'AuditStateUpdatePayload': '1.0-1a1b606bf14a2c468800c2b010801ce5',
'AuditUpdateNotification': '1.0-9b69de0724fda8310d05e18418178866',
'AuditUpdatePayload': '1.0-d3aace28d9eb978c1ecf833e108f61f7',
'AuditCreateNotification': '1.0-9b69de0724fda8310d05e18418178866',
'AuditCreatePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
}

View File

@ -217,9 +217,14 @@ class TestAuditObjectSendNotifications(base.DbTestCase):
@mock.patch.object(db_api.Connection, 'update_audit', mock.Mock())
@mock.patch.object(db_api.Connection, 'get_audit_by_uuid')
def test_send_update_notification(self, mock_get_audit):
mock_get_audit.return_value = self.fake_audit
uuid = self.fake_audit['uuid']
def test_send_update_notification(self, m_get_audit):
fake_audit = utils.get_test_audit(
goal=self.fake_goal.as_dict(),
strategy_id=self.fake_strategy.id,
strategy=self.fake_strategy.as_dict())
m_get_audit.return_value = fake_audit
uuid = fake_audit['uuid']
audit = objects.Audit.get_by_uuid(self.context, uuid, eager=True)
audit.state = objects.audit.State.ONGOING
audit.save()

View File

@ -18,6 +18,18 @@ from watcher import objects
from watcher.tests.db import utils as db_utils
def _load_related_objects(context, cls, db_data):
"""Replace the DB data with its object counterpart"""
obj_data = db_data.copy()
for name, (obj_cls, _) in cls.object_fields.items():
if obj_data.get(name):
obj_data[name] = obj_cls(context, **obj_data.get(name).as_dict())
else:
del obj_data[name]
return obj_data
def get_test_audit_template(context, **kw):
"""Return a AuditTemplate object with appropriate attributes.
@ -53,12 +65,14 @@ def get_test_audit(context, **kw):
that a create() could be used to commit it to the DB.
"""
db_audit = db_utils.get_test_audit(**kw)
obj_data = _load_related_objects(context, objects.Audit, db_audit)
# Let DB generate ID if it isn't specified explicitly
if 'id' not in kw:
del db_audit['id']
audit = objects.Audit(context)
for key in db_audit:
setattr(audit, key, db_audit[key])
for key in obj_data:
setattr(audit, key, obj_data[key])
return audit