Add audit.strategy events
In this changeset, I implemented the following notifications: - audit.strategy.start - audit.strategy.end - audit.strategy.error Partially Implements: blueprint audit-versioned-notifications-api Change-Id: I6ae8468caf8d215bc8bc694813beb4dc94f53fdb
This commit is contained in:
parent
6f9f67cacc
commit
19fe0a0c56
70
doc/notification_samples/audit-strategy-end.json
Normal file
70
doc/notification_samples/audit-strategy-end.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"parameters": {
|
||||||
|
"para2": "hello",
|
||||||
|
"para1": 3.2
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"fault": 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": "AuditActionPayload",
|
||||||
|
"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.strategy.end",
|
||||||
|
"message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
|
||||||
|
}
|
80
doc/notification_samples/audit-strategy-error.json
Normal file
80
doc/notification_samples/audit-strategy-error.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"priority": "ERROR",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"parameters": {
|
||||||
|
"para2": "hello",
|
||||||
|
"para1": 3.2
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"fault": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"exception": "WatcherException",
|
||||||
|
"exception_message": "TEST",
|
||||||
|
"function_name": "test_send_audit_action_with_error",
|
||||||
|
"module_name": "watcher.tests.notifications.test_audit_notification"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ExceptionPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"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": "AuditActionPayload",
|
||||||
|
"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.strategy.error",
|
||||||
|
"message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
|
||||||
|
}
|
70
doc/notification_samples/audit-strategy-start.json
Normal file
70
doc/notification_samples/audit-strategy-start.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"priority": "INFO",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"parameters": {
|
||||||
|
"para2": "hello",
|
||||||
|
"para1": 3.2
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"fault": 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": "AuditActionPayload",
|
||||||
|
"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.strategy.start",
|
||||||
|
"message_id": "cbcf9f2c-7c53-4b4d-91ec-db49cca024b6"
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
# Copyright (c) 2015 b<>com
|
# Copyright (c) 2015 b<>com
|
||||||
#
|
#
|
||||||
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
|
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.com>
|
||||||
|
# Vincent FRANCOISE <vincent.francoise@b-com.com>
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -15,18 +16,50 @@
|
|||||||
# implied.
|
# implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
import abc
|
import abc
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from watcher import notifications
|
||||||
|
from watcher.objects import fields
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class BaseStrategyContext(object):
|
class StrategyContext(object):
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def execute_strategy(self, audit, request_context):
|
def execute_strategy(self, audit, request_context):
|
||||||
"""Execute the strategy for the given an audit
|
"""Execute the strategy for the given an audit
|
||||||
|
|
||||||
|
:param audit: Audit object
|
||||||
|
:type audit: :py:class:`~.objects.audit.Audit` instance
|
||||||
|
:param request_context: Current request context
|
||||||
|
:type request_context: :py:class:`~.RequestContext` instance
|
||||||
|
:returns: The computed solution
|
||||||
|
:rtype: :py:class:`~.BaseSolution` instance
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
notifications.audit.send_action_notification(
|
||||||
|
request_context, audit,
|
||||||
|
action=fields.NotificationAction.STRATEGY,
|
||||||
|
phase=fields.NotificationPhase.START)
|
||||||
|
solution = self.do_execute_strategy(audit, request_context)
|
||||||
|
notifications.audit.send_action_notification(
|
||||||
|
request_context, audit,
|
||||||
|
action=fields.NotificationAction.STRATEGY,
|
||||||
|
phase=fields.NotificationPhase.END)
|
||||||
|
return solution
|
||||||
|
except Exception:
|
||||||
|
notifications.audit.send_action_notification(
|
||||||
|
request_context, audit,
|
||||||
|
action=fields.NotificationAction.STRATEGY,
|
||||||
|
priority=fields.NotificationPriority.ERROR,
|
||||||
|
phase=fields.NotificationPhase.ERROR)
|
||||||
|
raise
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def do_execute_strategy(self, audit, request_context):
|
||||||
|
"""Execute the strategy for the given an audit
|
||||||
|
|
||||||
:param audit: Audit object
|
:param audit: Audit object
|
||||||
:type audit: :py:class:`~.objects.audit.Audit` instance
|
:type audit: :py:class:`~.objects.audit.Audit` instance
|
||||||
:param request_context: Current request context
|
:param request_context: Current request context
|
||||||
|
@ -25,12 +25,12 @@ from watcher import objects
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DefaultStrategyContext(base.BaseStrategyContext):
|
class DefaultStrategyContext(base.StrategyContext):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(DefaultStrategyContext, self).__init__()
|
super(DefaultStrategyContext, self).__init__()
|
||||||
LOG.debug("Initializing Strategy Context")
|
LOG.debug("Initializing Strategy Context")
|
||||||
|
|
||||||
def execute_strategy(self, audit, request_context):
|
def do_execute_strategy(self, audit, request_context):
|
||||||
osc = clients.OpenStackClients()
|
osc = clients.OpenStackClients()
|
||||||
# todo(jed) retrieve in audit parameters (threshold,...)
|
# todo(jed) retrieve in audit parameters (threshold,...)
|
||||||
# todo(jed) create ActionPlan
|
# todo(jed) create ActionPlan
|
||||||
@ -42,8 +42,8 @@ class DefaultStrategyContext(base.BaseStrategyContext):
|
|||||||
# it could specify the Strategy uuid in the Audit.
|
# it could specify the Strategy uuid in the Audit.
|
||||||
strategy_name = None
|
strategy_name = None
|
||||||
if audit.strategy_id:
|
if audit.strategy_id:
|
||||||
strategy = objects.Strategy.get_by_id(request_context,
|
strategy = objects.Strategy.get_by_id(
|
||||||
audit.strategy_id)
|
request_context, audit.strategy_id)
|
||||||
strategy_name = strategy.name
|
strategy_name = strategy.name
|
||||||
|
|
||||||
strategy_selector = default.DefaultStrategySelector(
|
strategy_selector = default.DefaultStrategySelector(
|
||||||
|
@ -20,6 +20,7 @@ from oslo_config import cfg
|
|||||||
|
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.notifications import base as notificationbase
|
from watcher.notifications import base as notificationbase
|
||||||
|
from watcher.notifications import exception as exception_notifications
|
||||||
from watcher.notifications import goal as goal_notifications
|
from watcher.notifications import goal as goal_notifications
|
||||||
from watcher.notifications import strategy as strategy_notifications
|
from watcher.notifications import strategy as strategy_notifications
|
||||||
from watcher.objects import base
|
from watcher.objects import base
|
||||||
@ -38,8 +39,6 @@ class AuditPayload(notificationbase.NotificationPayloadBase):
|
|||||||
'parameters': ('audit', 'parameters'),
|
'parameters': ('audit', 'parameters'),
|
||||||
'interval': ('audit', 'interval'),
|
'interval': ('audit', 'interval'),
|
||||||
'scope': ('audit', 'scope'),
|
'scope': ('audit', 'scope'),
|
||||||
# 'goal_uuid': ('audit', 'goal_uuid'),
|
|
||||||
# 'strategy_uuid': ('audit', 'strategy_uuid'),
|
|
||||||
|
|
||||||
'created_at': ('audit', 'created_at'),
|
'created_at': ('audit', 'created_at'),
|
||||||
'updated_at': ('audit', 'updated_at'),
|
'updated_at': ('audit', 'updated_at'),
|
||||||
@ -111,6 +110,22 @@ class AuditUpdatePayload(AuditPayload):
|
|||||||
strategy=strategy)
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class AuditActionPayload(AuditPayload):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
fields = {
|
||||||
|
'fault': wfields.ObjectField('ExceptionPayload', nullable=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, audit, goal, strategy, **kwargs):
|
||||||
|
super(AuditActionPayload, self).__init__(
|
||||||
|
audit=audit,
|
||||||
|
goal=goal,
|
||||||
|
strategy=strategy,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
@base.WatcherObjectRegistry.register_notification
|
@base.WatcherObjectRegistry.register_notification
|
||||||
class AuditDeletePayload(AuditPayload):
|
class AuditDeletePayload(AuditPayload):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
@ -124,16 +139,17 @@ class AuditDeletePayload(AuditPayload):
|
|||||||
strategy=strategy)
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
# @notificationbase.notification_sample('audit-create.json')
|
@notificationbase.notification_sample('audit-strategy-error.json')
|
||||||
# @notificationbase.notification_sample('audit-delete.json')
|
@notificationbase.notification_sample('audit-strategy-end.json')
|
||||||
# @base.WatcherObjectRegistry.register_notification
|
@notificationbase.notification_sample('audit-strategy-start.json')
|
||||||
# class AuditActionNotification(notificationbase.NotificationBase):
|
@base.WatcherObjectRegistry.register_notification
|
||||||
# # Version 1.0: Initial version
|
class AuditActionNotification(notificationbase.NotificationBase):
|
||||||
# VERSION = '1.0'
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
# fields = {
|
fields = {
|
||||||
# 'payload': wfields.ObjectField('AuditActionPayload')
|
'payload': wfields.ObjectField('AuditActionPayload')
|
||||||
# }
|
}
|
||||||
|
|
||||||
|
|
||||||
@notificationbase.notification_sample('audit-create.json')
|
@notificationbase.notification_sample('audit-create.json')
|
||||||
@ -261,3 +277,34 @@ def send_delete(context, audit, service='infra-optim', host=None):
|
|||||||
payload=versioned_payload)
|
payload=versioned_payload)
|
||||||
|
|
||||||
notification.emit(context)
|
notification.emit(context)
|
||||||
|
|
||||||
|
|
||||||
|
def send_action_notification(context, audit, action, phase=None,
|
||||||
|
priority=wfields.NotificationPriority.INFO,
|
||||||
|
service='infra-optim', host=None):
|
||||||
|
"""Emit an audit action notification."""
|
||||||
|
goal_payload, strategy_payload = _get_common_payload(audit)
|
||||||
|
|
||||||
|
fault = None
|
||||||
|
if phase == wfields.NotificationPhase.ERROR:
|
||||||
|
fault = exception_notifications.ExceptionPayload.from_exception()
|
||||||
|
|
||||||
|
versioned_payload = AuditActionPayload(
|
||||||
|
audit=audit,
|
||||||
|
goal=goal_payload,
|
||||||
|
strategy=strategy_payload,
|
||||||
|
fault=fault,
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = AuditActionNotification(
|
||||||
|
priority=priority,
|
||||||
|
event_type=notificationbase.EventType(
|
||||||
|
object='audit',
|
||||||
|
action=action,
|
||||||
|
phase=phase),
|
||||||
|
publisher=notificationbase.NotificationPublisher(
|
||||||
|
host=host or CONF.host,
|
||||||
|
binary=service),
|
||||||
|
payload=versioned_payload)
|
||||||
|
|
||||||
|
notification.emit(context)
|
||||||
|
@ -55,8 +55,10 @@ class NotificationObject(base.WatcherObject):
|
|||||||
|
|
||||||
@base.WatcherObjectRegistry.register_notification
|
@base.WatcherObjectRegistry.register_notification
|
||||||
class EventType(NotificationObject):
|
class EventType(NotificationObject):
|
||||||
|
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
VERSION = '1.0'
|
# Version 1.1: Added STRATEGY action in NotificationAction enum
|
||||||
|
VERSION = '1.1'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'object': wfields.StringField(),
|
'object': wfields.StringField(),
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
import sys
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ class ExceptionPayload(notificationbase.NotificationPayloadBase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_exception(cls, fault):
|
def from_exception(cls, fault=None):
|
||||||
|
fault = fault or sys.exc_info()[1]
|
||||||
trace = inspect.trace()[-1]
|
trace = inspect.trace()[-1]
|
||||||
# TODO(gibi): apply strutils.mask_password on exception_message and
|
# TODO(gibi): apply strutils.mask_password on exception_message and
|
||||||
# consider emitting the exception_message only if the safe flag is
|
# consider emitting the exception_message only if the safe flag is
|
||||||
|
@ -126,7 +126,9 @@ class NotificationAction(BaseWatcherEnum):
|
|||||||
EXCEPTION = 'exception'
|
EXCEPTION = 'exception'
|
||||||
DELETE = 'delete'
|
DELETE = 'delete'
|
||||||
|
|
||||||
ALL = (CREATE, UPDATE, EXCEPTION, DELETE)
|
STRATEGY = 'strategy'
|
||||||
|
|
||||||
|
ALL = (CREATE, UPDATE, EXCEPTION, DELETE, STRATEGY)
|
||||||
|
|
||||||
|
|
||||||
class NotificationPriorityField(BaseEnumField):
|
class NotificationPriorityField(BaseEnumField):
|
||||||
|
@ -21,7 +21,9 @@ from oslo_utils import uuidutils
|
|||||||
from watcher.decision_engine.audit import continuous
|
from watcher.decision_engine.audit import continuous
|
||||||
from watcher.decision_engine.audit import oneshot
|
from watcher.decision_engine.audit import oneshot
|
||||||
from watcher.decision_engine.model.collector import manager
|
from watcher.decision_engine.model.collector import manager
|
||||||
from watcher.objects import audit as audit_objects
|
from watcher.decision_engine.strategy.strategies import dummy_strategy
|
||||||
|
from watcher import notifications
|
||||||
|
from watcher import objects
|
||||||
from watcher.tests.db import base
|
from watcher.tests.db import base
|
||||||
from watcher.tests.decision_engine.model import faker_cluster_state as faker
|
from watcher.tests.decision_engine.model import faker_cluster_state as faker
|
||||||
from watcher.tests.objects import utils as obj_utils
|
from watcher.tests.objects import utils as obj_utils
|
||||||
@ -31,10 +33,16 @@ class TestOneShotAuditHandler(base.DbTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestOneShotAuditHandler, self).setUp()
|
super(TestOneShotAuditHandler, self).setUp()
|
||||||
|
p_audit_notifications = mock.patch.object(
|
||||||
|
notifications, 'audit', autospec=True)
|
||||||
|
self.m_audit_notifications = p_audit_notifications.start()
|
||||||
|
self.addCleanup(p_audit_notifications.stop)
|
||||||
|
|
||||||
self.goal = obj_utils.create_test_goal(
|
self.goal = obj_utils.create_test_goal(
|
||||||
self.context, id=1, name="dummy")
|
self.context, id=1, name=dummy_strategy.DummyStrategy.get_name())
|
||||||
self.strategy = obj_utils.create_test_strategy(
|
self.strategy = obj_utils.create_test_strategy(
|
||||||
self.context, name='dummy', goal_id=self.goal.id)
|
self.context, name=dummy_strategy.DummyStrategy.get_name(),
|
||||||
|
goal_id=self.goal.id)
|
||||||
audit_template = obj_utils.create_test_audit_template(
|
audit_template = obj_utils.create_test_audit_template(
|
||||||
self.context, strategy_id=self.strategy.id)
|
self.context, strategy_id=self.strategy.id)
|
||||||
self.audit = obj_utils.create_test_audit(
|
self.audit = obj_utils.create_test_audit(
|
||||||
@ -46,18 +54,82 @@ class TestOneShotAuditHandler(base.DbTestCase):
|
|||||||
goal=self.goal)
|
goal=self.goal)
|
||||||
|
|
||||||
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
||||||
def test_trigger_audit_without_errors(self, mock_collector):
|
def test_trigger_audit_without_errors(self, m_collector):
|
||||||
mock_collector.return_value = faker.FakerModelCollector()
|
m_collector.return_value = faker.FakerModelCollector()
|
||||||
audit_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
audit_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
||||||
audit_handler.execute(self.audit, self.context)
|
audit_handler.execute(self.audit, self.context)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.START),
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.END)]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
expected_calls,
|
||||||
|
self.m_audit_notifications.send_action_notification.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(dummy_strategy.DummyStrategy, "do_execute")
|
||||||
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
||||||
def test_trigger_audit_state_succeeded(self, mock_collector):
|
def test_trigger_audit_with_error(self, m_collector, m_do_execute):
|
||||||
mock_collector.return_value = faker.FakerModelCollector()
|
m_collector.return_value = faker.FakerModelCollector()
|
||||||
|
m_do_execute.side_effect = Exception
|
||||||
audit_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
audit_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
||||||
audit_handler.execute(self.audit, self.context)
|
audit_handler.execute(self.audit, self.context)
|
||||||
audit = audit_objects.Audit.get_by_uuid(self.context, self.audit.uuid)
|
|
||||||
self.assertEqual(audit_objects.State.SUCCEEDED, audit.state)
|
expected_calls = [
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.START),
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
priority=objects.fields.NotificationPriority.ERROR,
|
||||||
|
phase=objects.fields.NotificationPhase.ERROR)]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
expected_calls,
|
||||||
|
self.m_audit_notifications.send_action_notification.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
||||||
|
def test_trigger_audit_state_succeeded(self, m_collector):
|
||||||
|
m_collector.return_value = faker.FakerModelCollector()
|
||||||
|
audit_handler = oneshot.OneShotAuditHandler(mock.MagicMock())
|
||||||
|
audit_handler.execute(self.audit, self.context)
|
||||||
|
audit = objects.audit.Audit.get_by_uuid(self.context, self.audit.uuid)
|
||||||
|
self.assertEqual(objects.audit.State.SUCCEEDED, audit.state)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.START),
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.END)]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
expected_calls,
|
||||||
|
self.m_audit_notifications.send_action_notification.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
||||||
|
def test_trigger_audit_send_notification(self, m_collector):
|
||||||
|
messaging = mock.MagicMock()
|
||||||
|
m_collector.return_value = faker.FakerModelCollector()
|
||||||
|
audit_handler = oneshot.OneShotAuditHandler(messaging)
|
||||||
|
audit_handler.execute(self.audit, self.context)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.START),
|
||||||
|
mock.call(self.context, self.audit,
|
||||||
|
action=objects.fields.NotificationAction.STRATEGY,
|
||||||
|
phase=objects.fields.NotificationPhase.END)]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
expected_calls,
|
||||||
|
self.m_audit_notifications.send_action_notification.call_args_list)
|
||||||
|
|
||||||
|
|
||||||
class TestContinuousAuditHandler(base.DbTestCase):
|
class TestContinuousAuditHandler(base.DbTestCase):
|
||||||
@ -65,7 +137,7 @@ class TestContinuousAuditHandler(base.DbTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestContinuousAuditHandler, self).setUp()
|
super(TestContinuousAuditHandler, self).setUp()
|
||||||
self.goal = obj_utils.create_test_goal(
|
self.goal = obj_utils.create_test_goal(
|
||||||
self.context, id=1, name="dummy")
|
self.context, id=1, name=dummy_strategy.DummyStrategy.get_name())
|
||||||
audit_template = obj_utils.create_test_audit_template(
|
audit_template = obj_utils.create_test_audit_template(
|
||||||
self.context)
|
self.context)
|
||||||
self.audits = [
|
self.audits = [
|
||||||
@ -75,31 +147,31 @@ class TestContinuousAuditHandler(base.DbTestCase):
|
|||||||
uuid=uuidutils.generate_uuid(),
|
uuid=uuidutils.generate_uuid(),
|
||||||
audit_template_id=audit_template.id,
|
audit_template_id=audit_template.id,
|
||||||
goal_id=self.goal.id,
|
goal_id=self.goal.id,
|
||||||
audit_type=audit_objects.AuditType.CONTINUOUS.value,
|
audit_type=objects.audit.AuditType.CONTINUOUS.value,
|
||||||
goal=self.goal)
|
goal=self.goal)
|
||||||
for id_ in range(2, 4)]
|
for id_ in range(2, 4)]
|
||||||
|
|
||||||
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
@mock.patch.object(manager.CollectorManager, "get_cluster_model_collector")
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
||||||
@mock.patch.object(audit_objects.Audit, 'list')
|
@mock.patch.object(objects.audit.Audit, 'list')
|
||||||
def test_launch_audits_periodically(self, mock_list, mock_jobs,
|
def test_launch_audits_periodically(self, mock_list, mock_jobs,
|
||||||
mock_add_job, mock_collector):
|
m_add_job, m_collector):
|
||||||
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
||||||
mock_list.return_value = self.audits
|
mock_list.return_value = self.audits
|
||||||
mock_jobs.return_value = mock.MagicMock()
|
mock_jobs.return_value = mock.MagicMock()
|
||||||
mock_add_job.return_value = audit_handler.execute_audit(
|
m_add_job.return_value = audit_handler.execute_audit(
|
||||||
self.audits[0], self.context)
|
self.audits[0], self.context)
|
||||||
mock_collector.return_value = faker.FakerModelCollector()
|
m_collector.return_value = faker.FakerModelCollector()
|
||||||
|
|
||||||
audit_handler.launch_audits_periodically()
|
audit_handler.launch_audits_periodically()
|
||||||
mock_add_job.assert_called()
|
m_add_job.assert_called()
|
||||||
|
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
||||||
@mock.patch.object(audit_objects.Audit, 'list')
|
@mock.patch.object(objects.audit.Audit, 'list')
|
||||||
def test_launch_multiply_audits_periodically(self, mock_list,
|
def test_launch_multiply_audits_periodically(self, mock_list,
|
||||||
mock_jobs, mock_add_job):
|
mock_jobs, m_add_job):
|
||||||
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
||||||
mock_list.return_value = self.audits
|
mock_list.return_value = self.audits
|
||||||
mock_jobs.return_value = mock.MagicMock()
|
mock_jobs.return_value = mock.MagicMock()
|
||||||
@ -109,26 +181,26 @@ class TestContinuousAuditHandler(base.DbTestCase):
|
|||||||
name='execute_audit',
|
name='execute_audit',
|
||||||
next_run_time=mock.ANY) for audit in self.audits]
|
next_run_time=mock.ANY) for audit in self.audits]
|
||||||
audit_handler.launch_audits_periodically()
|
audit_handler.launch_audits_periodically()
|
||||||
mock_add_job.assert_has_calls(calls)
|
m_add_job.assert_has_calls(calls)
|
||||||
|
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
@mock.patch.object(background.BackgroundScheduler, 'add_job')
|
||||||
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
@mock.patch.object(background.BackgroundScheduler, 'get_jobs')
|
||||||
@mock.patch.object(audit_objects.Audit, 'list')
|
@mock.patch.object(objects.audit.Audit, 'list')
|
||||||
def test_period_audit_not_called_when_deleted(self, mock_list,
|
def test_period_audit_not_called_when_deleted(self, mock_list,
|
||||||
mock_jobs, mock_add_job):
|
mock_jobs, m_add_job):
|
||||||
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
audit_handler = continuous.ContinuousAuditHandler(mock.MagicMock())
|
||||||
mock_list.return_value = self.audits
|
mock_list.return_value = self.audits
|
||||||
mock_jobs.return_value = mock.MagicMock()
|
mock_jobs.return_value = mock.MagicMock()
|
||||||
self.audits[1].state = audit_objects.State.CANCELLED
|
self.audits[1].state = objects.audit.State.CANCELLED
|
||||||
calls = [mock.call(audit_handler.execute_audit, 'interval',
|
calls = [mock.call(audit_handler.execute_audit, 'interval',
|
||||||
args=[mock.ANY, mock.ANY],
|
args=[mock.ANY, mock.ANY],
|
||||||
seconds=3600,
|
seconds=3600,
|
||||||
name='execute_audit',
|
name='execute_audit',
|
||||||
next_run_time=mock.ANY)]
|
next_run_time=mock.ANY)]
|
||||||
audit_handler.launch_audits_periodically()
|
audit_handler.launch_audits_periodically()
|
||||||
mock_add_job.assert_has_calls(calls)
|
m_add_job.assert_has_calls(calls)
|
||||||
|
|
||||||
audit_handler.update_audit_state(self.audits[1],
|
audit_handler.update_audit_state(self.audits[1],
|
||||||
audit_objects.State.CANCELLED)
|
objects.audit.State.CANCELLED)
|
||||||
is_inactive = audit_handler._is_audit_inactive(self.audits[1])
|
is_inactive = audit_handler._is_audit_inactive(self.audits[1])
|
||||||
self.assertTrue(is_inactive)
|
self.assertTrue(is_inactive)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# implied.
|
# implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from watcher.common import utils
|
from watcher.common import utils
|
||||||
@ -26,6 +27,7 @@ from watcher.tests.objects import utils as obj_utils
|
|||||||
|
|
||||||
|
|
||||||
class TestStrategyContext(base.DbTestCase):
|
class TestStrategyContext(base.DbTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestStrategyContext, self).setUp()
|
super(TestStrategyContext, self).setUp()
|
||||||
obj_utils.create_test_goal(self.context, id=1, name="DUMMY")
|
obj_utils.create_test_goal(self.context, id=1, name="DUMMY")
|
||||||
|
@ -293,3 +293,157 @@ class TestAuditNotification(base.DbTestCase):
|
|||||||
},
|
},
|
||||||
payload
|
payload
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
|
||||||
|
@mock.patch.object(notifications.audit.AuditActionNotification, '_emit')
|
||||||
|
def test_send_audit_action(self, mock_emit):
|
||||||
|
goal = utils.create_test_goal(mock.Mock())
|
||||||
|
strategy = utils.create_test_strategy(mock.Mock())
|
||||||
|
audit = utils.create_test_audit(
|
||||||
|
mock.Mock(), state=objects.audit.State.ONGOING,
|
||||||
|
goal_id=goal.id, strategy_id=strategy.id,
|
||||||
|
goal=goal, strategy=strategy)
|
||||||
|
notifications.audit.send_action_notification(
|
||||||
|
mock.MagicMock(), audit, host='node0',
|
||||||
|
action='strategy', phase='start')
|
||||||
|
|
||||||
|
self.assertEqual(1, mock_emit.call_count)
|
||||||
|
notification = mock_emit.call_args_list[0][1]
|
||||||
|
|
||||||
|
self.assertDictEqual(
|
||||||
|
{
|
||||||
|
"event_type": "audit.strategy.start",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"fault": None,
|
||||||
|
"goal": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"display_name": "test goal",
|
||||||
|
"efficacy_specification": [],
|
||||||
|
"name": "TEST",
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "GoalPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"interval": 3600,
|
||||||
|
"parameters": {},
|
||||||
|
"scope": [],
|
||||||
|
"state": "ONGOING",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"name": "TEST",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "AuditActionPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0"
|
||||||
|
},
|
||||||
|
notification
|
||||||
|
)
|
||||||
|
|
||||||
|
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
|
||||||
|
@mock.patch.object(notifications.audit.AuditActionNotification, '_emit')
|
||||||
|
def test_send_audit_action_with_error(self, mock_emit):
|
||||||
|
goal = utils.create_test_goal(mock.Mock())
|
||||||
|
strategy = utils.create_test_strategy(mock.Mock())
|
||||||
|
audit = utils.create_test_audit(
|
||||||
|
mock.Mock(), state=objects.audit.State.ONGOING,
|
||||||
|
goal_id=goal.id, strategy_id=strategy.id,
|
||||||
|
goal=goal, strategy=strategy)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# This is to load the exception in sys.exc_info()
|
||||||
|
raise exception.WatcherException("TEST")
|
||||||
|
except exception.WatcherException:
|
||||||
|
notifications.audit.send_action_notification(
|
||||||
|
mock.MagicMock(), audit, host='node0',
|
||||||
|
action='strategy', priority='error', phase='error')
|
||||||
|
|
||||||
|
self.assertEqual(1, mock_emit.call_count)
|
||||||
|
notification = mock_emit.call_args_list[0][1]
|
||||||
|
self.assertDictEqual(
|
||||||
|
{
|
||||||
|
"event_type": "audit.strategy.error",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"fault": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"exception": "WatcherException",
|
||||||
|
"exception_message": "TEST",
|
||||||
|
"function_name": (
|
||||||
|
"test_send_audit_action_with_error"),
|
||||||
|
"module_name": "watcher.tests.notifications."
|
||||||
|
"test_audit_notification"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ExceptionPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"goal": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"display_name": "test goal",
|
||||||
|
"efficacy_specification": [],
|
||||||
|
"name": "TEST",
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "GoalPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"interval": 3600,
|
||||||
|
"parameters": {},
|
||||||
|
"scope": [],
|
||||||
|
"state": "ONGOING",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": None,
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"name": "TEST",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "AuditActionPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0"
|
||||||
|
},
|
||||||
|
notification
|
||||||
|
)
|
||||||
|
@ -250,7 +250,7 @@ class TestNotificationBase(testbase.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
expected_notification_fingerprints = {
|
expected_notification_fingerprints = {
|
||||||
'EventType': '1.0-92100a9f0908da98dfcfff9c42e0018c',
|
'EventType': '1.1-652f407fcf72d2045d65974d23c78173',
|
||||||
'ExceptionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
'ExceptionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
||||||
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
||||||
@ -262,6 +262,8 @@ expected_notification_fingerprints = {
|
|||||||
'AuditCreatePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
'AuditCreatePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||||
'AuditDeleteNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
'AuditDeleteNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
'AuditDeletePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
'AuditDeletePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||||
|
'AuditActionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
|
'AuditActionPayload': '1.0-09f5d005f94ba9e5f6b9200170332c52',
|
||||||
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
|
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
|
||||||
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
|
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user