diff --git a/brian_polling_manager/configuration.py b/brian_polling_manager/configuration.py index 699633a04bf94e468488f8eeaea150b47a8a44e6..6175539e868f7192cfeb27ec5fa02aae0abd6840 100644 --- a/brian_polling_manager/configuration.py +++ b/brian_polling_manager/configuration.py @@ -47,6 +47,10 @@ _DEFAULT_CONFIG = { 'measurement': 'multicast', 'command': '{script} --inventory http://localhost:18080' ' --measurement {measurement} --hostname {hostname}' + }, + 'interface-error-report': { + 'script': '/home/brian_checks/venv/report-interface-errors', + 'config': '/home/brian_checks/conf/report-interface-errors.config.json' } }, 'statedir': '/tmp/', @@ -81,6 +85,15 @@ CONFIG_SCHEMA = { 'required': ['script', 'config', 'command'], 'additionalProperties': False }, + 'interface-error-report': { + 'type': 'object', + 'properties': { + 'script': {'type': 'string'}, + 'config': {'type': 'string'}, + }, + 'required': ['script', 'config'], + 'additionalProperties': False + }, 'sensu': { 'type': 'object', 'properties': { @@ -98,6 +111,9 @@ CONFIG_SCHEMA = { {'$ref': '#/definitions/influx-check'}, 'eumetsat-multicast-check': {'$ref': '#/definitions/influx-check'}, + 'interface-error-report': { + '$ref': '#/definitions/interface-error-report' + } }, 'required': [ 'api-base', 'api-key', diff --git a/brian_polling_manager/error_report/check.py b/brian_polling_manager/error_report/check.py new file mode 100644 index 0000000000000000000000000000000000000000..726698106b19c4bebde109bc37508c2198ff45a0 --- /dev/null +++ b/brian_polling_manager/error_report/check.py @@ -0,0 +1,46 @@ +from brian_polling_manager import sensu + +ERROR_REPORT_CHECK_NAME = "interface-error-report" + + +def load_checks(sensu_params, filter_by): + checks = filter(filter_by, sensu.load_all_checks(sensu_params)) + return {c["metadata"]["name"]: c for c in checks} + + +def load_error_report_checks(sensu_params): + return load_checks( + sensu_params, lambda c: c["metadata"]["name"] == ERROR_REPORT_CHECK_NAME + ) + + +class ErrorReportCheck(sensu.AbstractCheck): + INTERVAL_S = 3600 * 24 # daily + METRIC_FORMAT = "" + METRIC_HANDLERS = None + + COMMAND = "{script} --config {config}" + + def __init__(self, ifc_check_params): + super().__init__() + self.ifc_check_params = ifc_check_params + + @sensu.AbstractCheck.name.getter + def name(self): + return ERROR_REPORT_CHECK_NAME + + @sensu.AbstractCheck.command.getter + def command(self): + return self.COMMAND.format(**self.ifc_check_params) + + @sensu.AbstractCheck.proxy_entity_name.getter + def proxy_entity_name(self): + return ERROR_REPORT_CHECK_NAME + + +def refresh(sensu_params): + return sensu.refresh( + sensu_params, + [ErrorReportCheck(sensu_params["interface-error-report"])], + load_error_report_checks(sensu_params), + ) diff --git a/brian_polling_manager/main.py b/brian_polling_manager/main.py index 1228b238a0b512b172b8cc631e8e646ca81e4797..2e4f657093f15c12ca4dca27a60a4e0292f88258 100644 --- a/brian_polling_manager/main.py +++ b/brian_polling_manager/main.py @@ -29,7 +29,7 @@ import click import jsonschema from statsd import StatsClient -from brian_polling_manager import inventory, configuration, \ +from brian_polling_manager import error_report, inventory, configuration, \ interfaces, gws_direct, gws_indirect, eumetsat_multicast, sensu logger = logging.getLogger(__name__) @@ -56,6 +56,7 @@ REFRESH_RESULT_SCHEMA = { 'gws_direct': {'$ref': '#/definitions/refresh-result'}, 'gws_indirect': {'$ref': '#/definitions/refresh-result'}, 'eumetsat_multicast': {'$ref': '#/definitions/refresh-result'}, + 'interface_error_report': {'$ref': '#/definitions/refresh-result'}, }, 'required': ['interfaces'], 'additionalProperties': False @@ -96,6 +97,7 @@ def refresh(config, force=False): config['sensu'], state.gws_indirect), 'eumetsat_multicast': eumetsat_multicast.refresh( config['sensu'], state.eumetsat_multicast), + 'interface_error_report': error_report.check.refresh(config['sensu']) } jsonschema.validate(result, REFRESH_RESULT_SCHEMA) # sanity diff --git a/brian_polling_manager/sensu.py b/brian_polling_manager/sensu.py index 87592d21f7ca815c75b5b5614780d95f741c4106..5e0d8e7f7343bb432ba36bad5556d27b892d30b6 100644 --- a/brian_polling_manager/sensu.py +++ b/brian_polling_manager/sensu.py @@ -212,29 +212,21 @@ class AbstractCheck(object): @staticmethod def match_check_dicts(a, b) -> bool: - if a["publish"] != b["publish"]: - return False - if a["command"] != b["command"]: - return False - if a["interval"] != b["interval"]: - return False - if a["proxy_entity_name"] != b["proxy_entity_name"]: - return False - if a["round_robin"] != b["round_robin"]: - return False - if a["output_metric_format"] != b["output_metric_format"]: - return False - if sorted(a["subscriptions"] or []) != sorted(b["subscriptions"] or []): - return False - if sorted(a["output_metric_handlers"] or []) != sorted( - b["output_metric_handlers"] or [] - ): - return False - if a["metadata"]["name"] != b["metadata"]["name"]: - return False - if a["metadata"]["namespace"] != b["metadata"]["namespace"]: - return False - return True + return ( + a["publish"] == b["publish"] + and a["command"] == b["command"] + and a["interval"] == b["interval"] + and a["proxy_entity_name"] == b["proxy_entity_name"] + and a["round_robin"] == b["round_robin"] + and a["output_metric_format"] == b["output_metric_format"] + and set(a["subscriptions"] or []) == set(b["subscriptions"] or []) + and set(a["output_metric_handlers"] or []) + == set(b["output_metric_handlers"] or []) + and a["metadata"]["name"] == b["metadata"]["name"] + and a["metadata"]["namespace"] == b["metadata"]["namespace"] + and a["interval"] == b["interval"] + and a["proxy_entity_name"] == b["proxy_entity_name"] + ) def refresh(sensu_params, required_checks, current_checks): diff --git a/test/conftest.py b/test/conftest.py index e2bd49b1f5ce643b6aefb26d57925b9947fb3360..310aa21336d695458bb66545fd258ed02c67790a 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -63,6 +63,10 @@ def config(): " --measurement {measurement}" " --hostname {hostname}", }, + "interface-error-report": { + "script": "/path/to/report-interface-errors", + "config": "/path/to/config", + }, }, "statedir": state_dir_name, "statsd": {"hostname": "localhost", "port": 11119, "prefix": "zzzzz"}, diff --git a/test/data/checks.json b/test/data/checks.json index 5e0232bb0c1d89a9c3a06518cd781c8069cb1f10..71d3a8a1f849732fe3f19333ee1b728e846be954 100644 --- a/test/data/checks.json +++ b/test/data/checks.json @@ -179,6 +179,32 @@ "created_by": "admin" }, "secrets": null + }, + { + "command": "/path/to/report-interface-errors --config /path/to/config", + "handlers": [], + "high_flap_threshold": 0, + "interval": 300, + "low_flap_threshold": 0, + "publish": false, + "runtime_assets": null, + "subscriptions": [], + "proxy_entity_name": "error-report", + "check_hooks": null, + "stdin": false, + "subdue": null, + "ttl": 0, + "timeout": 0, + "round_robin": true, + "output_metric_format": "", + "output_metric_handlers": [], + "env_vars": null, + "metadata": { + "name": "interface-error-report", + "namespace": "default", + "created_by": "admin" + }, + "secrets": null } ] diff --git a/test/error_report/test_check.py b/test/error_report/test_check.py new file mode 100644 index 0000000000000000000000000000000000000000..2e11f345262942e98a0661a6dcfd51ba3e7a339e --- /dev/null +++ b/test/error_report/test_check.py @@ -0,0 +1,40 @@ +from brian_polling_manager import sensu +from brian_polling_manager.error_report.check import ErrorReportCheck, refresh +import pytest +import responses + + +@pytest.fixture +def config(): + return { + "api-base": [ + "https://bogus-sensu01.xxx.yyy:12345", + "https://bogus-sensu02.xxx.yyy:12345", + "https://bogus-sensu03.xxx.yyy:12345", + ], + "api-key": "abc-sensu-key-blah-blah", + "interface-error-report": { + "script": "/path/to/report-interface-errors", + "config": "/path/to/config", + }, + } + + +def test_error_report_check(config): + check = ErrorReportCheck(config["interface-error-report"]).to_dict() + assert check["command"] == ( + "/path/to/report-interface-errors --config /path/to/config" + ) + assert check["proxy_entity_name"] == "interface-error-report" + assert check["metadata"]["name"] == "interface-error-report" + assert check["output_metric_format"] == "" + assert check["output_metric_handlers"] == [] + + +@responses.activate +def test_error_report_refresh(config, mocked_sensu, mocked_inventory): + result = refresh(config) + assert result == {"checks": 1, "input": 1, "created": 0, "updated": 1, "deleted": 0} + sensu.clear_cached_values() + result = refresh(config) + assert result == {"checks": 1, "input": 1, "created": 0, "updated": 0, "deleted": 0} diff --git a/test/test_api.py b/test/test_api.py index 0a647feed8c14f664ae78a5074f68bdd1835a8d1..2b753906c03b91e333a41de1e9fb009f8538e0d4 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -12,8 +12,10 @@ from brian_polling_manager.main import REFRESH_RESULT_SCHEMA @pytest.fixture def client(config_filename, mocked_sensu, mocked_inventory): - os.environ['CONFIG_FILENAME'] = config_filename - with brian_polling_manager.create_app().test_client() as c: + os.environ["CONFIG_FILENAME"] = config_filename + app = brian_polling_manager.create_app() + app.testing = True + with app.test_client() as c: yield c