diff --git a/brian_polling_manager/sensu.py b/brian_polling_manager/sensu.py
index b1d429568e6a218afdd698cb3f98f495ad7190e6..e31545ba678c64a4542fcdc6c5df5a556609c074 100644
--- a/brian_polling_manager/sensu.py
+++ b/brian_polling_manager/sensu.py
@@ -1,7 +1,7 @@
"""
Sensu api utilities
"""
-import functools
+import copy
import logging
import random
import requests
@@ -97,7 +97,7 @@ def checks_match(a, b) -> bool:
class AbstractCheck(object):
"""
- not explicitly using abc.ABC, to avoid stacks of decorators
+ not explicitly using abc.ABC ... more readable than stacks of decorators
"""
INTERVAL_S = 300
@@ -106,12 +106,54 @@ class AbstractCheck(object):
METRIC_HANDLERS = ['influx-db-handler']
NAMESPACE = 'default'
+ CHECK_DICT_SCHEMA = {
+ # for unit tests
+ '$schema': 'http://json-schema.org/draft-07/schema#',
+
+ 'definitions': {
+ 'metadata': {
+ 'type': 'object',
+ 'properties': {
+ 'name': {'type': 'string'},
+ 'namespace': {'type': 'string'}
+ },
+ 'required': ['name', 'namespace']
+ }
+ },
+
+ 'type': 'object',
+ 'properties': {
+ 'command': {'type': 'string'},
+ 'interval': {'type': 'integer'},
+ 'subscriptions': {
+ 'type': 'array',
+ 'items': {'type': 'string'},
+ 'minItems': 1
+ },
+ 'proxy_entity_name': {'type': 'string'},
+ 'round_robin': {'type': 'boolean'},
+ 'output_metric_format': {'type': 'string'},
+ 'output_metric_handlers': {
+ 'type': 'array',
+ 'items': {'type': 'string'},
+ 'minItems': 1
+ },
+ 'metadata': {'$ref': '#/definitions/metadata'},
+ 'publish': {'type': 'boolean'}
+ },
+ 'required': [
+ 'command', 'interval', 'subscriptions',
+ 'proxy_entity_name', 'round_robin',
+ 'output_metric_format', 'output_metric_handlers',
+ 'metadata', 'publish']
+ }
+
def __init__(self):
self.publish = True
self.round_robin = True
self.interval = AbstractCheck.INTERVAL_S
- self.subscriptions = AbstractCheck.SUBSCRIPTIONS
- self.output_metric_handlers = AbstractCheck.METRIC_HANDLERS
+ self.subscriptions = copy.copy(AbstractCheck.SUBSCRIPTIONS)
+ self.output_metric_handlers = copy.copy(AbstractCheck.METRIC_HANDLERS)
self.output_metric_format = AbstractCheck.METRIC_FORMAT
self.namespace = AbstractCheck.NAMESPACE
diff --git a/test/test_sensu_checks.py b/test/test_sensu_checks.py
index 7e48b600c8142a4a090ac017397cb1598bba4328..a57762165b8d46a7e2ba9dd26d591dd4aebdbf41 100644
--- a/test/test_sensu_checks.py
+++ b/test/test_sensu_checks.py
@@ -1,6 +1,7 @@
import copy
import random
+import jsonschema
import responses
from brian_polling_manager import sensu, inventory, interfaces
@@ -38,3 +39,85 @@ def test_check_lifecycle(config, mocked_sensu, mocked_inventory):
# delete the check and confirm the correct call was made
sensu.delete_check(config['sensu'], check_name)
assert check_name not in mocked_sensu
+
+
+class TestingCheck(sensu.AbstractCheck):
+
+ def __init__(self, name, command, proxy_entity_name):
+ super().__init__()
+ self._name = name
+ self._command = command
+ self._proxy_entity_name = proxy_entity_name
+
+ @sensu.AbstractCheck.name.getter
+ def name(self):
+ return self._name
+
+ @sensu.AbstractCheck.command.getter
+ def command(self):
+ return self._command
+
+ @sensu.AbstractCheck.proxy_entity_name.getter
+ def proxy_entity_name(self):
+ return self._proxy_entity_name
+
+
+def test_check_dict_schema():
+ c = TestingCheck(name='x', command='y', proxy_entity_name='z')
+ jsonschema.validate(c.to_dict(), sensu.AbstractCheck.CHECK_DICT_SCHEMA)
+
+
+def test_check_compare():
+ a = TestingCheck(name='x', command='y', proxy_entity_name='z')
+ b = TestingCheck(name='x', command='y', proxy_entity_name='z')
+ assert sensu.checks_match(a.to_dict(), b.to_dict())
+
+
+def test_checks_differ():
+ a = TestingCheck(name='x', command='x', proxy_entity_name='1')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='2')
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='1', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='2', proxy_entity_name='x')
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='1', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='2', command='x', proxy_entity_name='x')
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.publish = not a.publish
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.interval += 1
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.round_robin = not a.round_robin
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.output_metric_format = a.output_metric_format + 'x'
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.subscriptions.append('x')
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.output_metric_handlers.append('x')
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+
+ a = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ b = TestingCheck(name='x', command='x', proxy_entity_name='x')
+ a.namespace = a.namespace + 'x'
+ assert not sensu.checks_match(a.to_dict(), b.to_dict())
+