diff --git a/source/logic.old/channels/_interface.py b/source/logic.old/channels/_interface.py deleted file mode 100644 index 2856d78..0000000 --- a/source/logic.old/channels/_interface.py +++ /dev/null @@ -1,13 +0,0 @@ -class interface_notification_channel(object): - - def parameters_schema(self): - raise NotImplementedError - - - def normalize_order_node(self, node): - raise NotImplementedError - - - def notify(self, parameters, name, data, state, info): - raise NotImplementedError - diff --git a/source/logic.old/channels/console.py b/source/logic.old/channels/console.py deleted file mode 100644 index 44c8667..0000000 --- a/source/logic.old/channels/console.py +++ /dev/null @@ -1,41 +0,0 @@ -class implementation_notification_channel_console(interface_notification_channel): - - ''' - [implementation] - ''' - def parameters_schema(self): - return { - "type": "object", - "additionalProperties": False, - "properties": { - }, - "required": [ - ] - } - - - ''' - [implementation] - ''' - def normalize_order_node(self, node): - return dict_merge( - { - }, - node - ) - - - ''' - [implementation] - ''' - def notify(self, parameters, name, data, state, info): - _sys.stdout.write( - string_coin( - "[{{title}}] <{{condition}}> {{info}}\n", - { - "title": data["title"], - "condition": condition_show(state["condition"]), - "info": _json.dumps(info, indent = "\t", ensure_ascii = False), - } - ) - ) diff --git a/source/logic.old/check_kinds/_interface.py b/source/logic.old/check_kinds/_interface.py deleted file mode 100644 index 14ef36a..0000000 --- a/source/logic.old/check_kinds/_interface.py +++ /dev/null @@ -1,16 +0,0 @@ -class interface_check_kind(object): - - def parameters_schema(self): - raise NotImplementedError - - - def normalize_order_node(self, node): - raise NotImplementedError - - - ''' - return record - ''' - def run(self, parameters): - raise NotImplementedError - diff --git a/source/logic.old/check_kinds/http_request.py b/source/logic.old/check_kinds/http_request.py deleted file mode 100644 index 3ac306f..0000000 --- a/source/logic.old/check_kinds/http_request.py +++ /dev/null @@ -1,270 +0,0 @@ -class implementation_check_kind_http_request(interface_check_kind): - - ''' - [implementation] - ''' - def parameters_schema(self): - return { - "type": "object", - "additionalProperties": False, - "properties": { - "request": { - "type": "object", - "additionalProperties": False, - "properties": { - "target": { - "description": "URL", - "type": "string" - }, - "method": { - "type": "string", - "enum": [ - "GET", - "POST" - ], - "default": "GET" - } - }, - "required": [ - "target" - ] - }, - "timeout": { - "description": "maximum allowed execution time in seconds", - "type": "float", - "default": 5.0 - }, - "follow_redirects": { - "description": "whether redirect instructions in responses shall be followend instead of being exposed as result", - "type": "boolean", - "default": False - }, - "response": { - "type": "object", - "additionalProperties": False, - "properties": { - "status_code": { - "description": "checks whether the response status code is this", - "type": ["null", "integer"], - "default": 200 - }, - "headers": { - "description": "conjunctively checks header key-value pairs", - "type": "object", - "additionalProperties": { - "description": "header value", - "type": "string" - }, - "properties": { - }, - "required": [ - ], - "default": {} - }, - "body_part": { - "description": "checks whether the response body contains this string", - "type": "string" - } - }, - "required": [ - ] - }, - "critical": { - "description": "whether a violation of this check shall be leveled as critical instead of concerning", - "type": "boolean", - "default": True - }, - "strict": { - "deprecated": True, - "description": "alias for 'critical'", - "type": "boolean", - "default": True - }, - }, - "required": [ - "request", - ] - } - - - ''' - [implementation] - ''' - def normalize_order_node(self, node): - version = ( - "v1" - if (not ("critical" in node)) else - "v2" - ) - - if (version == "v1"): - node_ = dict_merge( - { - "request": { - "method": "GET" - }, - "timeout": 5.0, - "follow_redirects": False, - "response": { - "status_code": 200 - }, - "strict": True, - }, - node, - True - ) - allowed_methods = set(["GET", "POST"]) - if (node_["request"]["method"] not in allowed_methods): - raise ValueError("invalid HTTP request method: %s" % node_["request"]["method"]) - else: - return { - "request": node_["request"], - "timeout": node_["timeout"], - "follow_redirects": node_["follow_redirects"], - "response": node_["response"], - "critical": node_["strict"], - } - elif (version == "v2"): - node_ = dict_merge( - { - "request": { - "method": "GET" - }, - "timeout": 5.0, - "follow_redirects": False, - "response": { - "status_code": 200 - }, - "critical": True, - }, - node, - True - ) - allowed_methods = set(["GET", "POST"]) - if (node_["request"]["method"] not in allowed_methods): - raise ValueError("invalid HTTP request method: %s" % node_["request"]["method"]) - else: - return node_ - else: - raise ValueError("unhandled") - - - ''' - [implementation] - ''' - def run(self, parameters): - if (parameters["request"]["method"] == "GET"): - try: - response = _requests.get( - parameters["request"]["target"], - timeout = parameters["timeout"], - allow_redirects = parameters["follow_redirects"] - ) - error = None - except Exception as error_: - error = error_ - response = None - elif (parameters["request"]["method"] == "POST"): - try: - response = _requests.post( - parameters["request"]["target"], - timeout = parameters["timeout"], - allow_redirects = parameters["follow_redirects"] - ) - error = None - except Exception as error_: - error = error_ - response = None - else: - raise ValueError("impossible") - if (response is None): - return { - "condition": ( - enum_condition.critical - if parameters["strict"] else - enum_condition.concerning - ), - "info": { - "request": parameters["request"], - "faults": [ - translation_get("checks.http_request.request_failed"), - ], - } - } - else: - faults = [] - for (key, value, ) in parameters["response"].items(): - if (key == "status_code"): - if ((value is None) or (response.status_code == value)): - pass - else: - faults.append( - translation_get( - "checks.http_request.status_code_mismatch", - { - "status_code_actual": ("%u" % response.status_code), - "status_code_expected": ("%u" % value), - } - ) - ) - elif (key == "headers"): - for (header_key, header_value, ) in value.items(): - if (not (header_key in response.headers)): - faults.append( - translation_get( - "checks.http_request.header_missing", - { - "key": header_key, - "value_expected": header_value, - } - ) - ) - else: - if (not (response.headers[header_key] == header_value)): - faults.append( - translation_get( - "checks.http_request.header_value_mismatch", - { - "key": header_key, - "value_actual": response.headers[header_key], - "value_expected": header_value, - } - ) - ) - else: - pass - elif (key == "body_part"): - if (response.text.find(value) >= 0): - pass - else: - faults.append( - translation_get( - "checks.http_request.body_misses_part", - { - "part": value, - } - ) - ) - else: - raise ValueError("unhandled") - return { - "condition": ( - enum_condition.ok - if (len(faults) <= 0) else - ( - enum_condition.critical - if parameters["strict"] else - enum_condition.concerning - ) - ), - "info": { - "request": parameters["request"], - "response": { - "status_code": response.status_code, - "headers": dict(map(lambda pair: pair, response.headers.items())), - # "body": response.text, - }, - "faults": faults, - } - } - diff --git a/source/logic.old/condition.py b/source/logic.old/condition.py deleted file mode 100644 index 09e8075..0000000 --- a/source/logic.old/condition.py +++ /dev/null @@ -1,39 +0,0 @@ -class enum_condition(_enum.Enum): - unknown = 0 - ok = 1 - concerning = 2 - critical = 3 - - -''' -converts a condition to a human readable string -''' -def condition_show(condition): - return translation_get( - { - enum_condition.unknown: "conditions.unknown", - enum_condition.ok: "conditions.ok", - enum_condition.concerning: "conditions.concerning", - enum_condition.critical: "conditions.critical", - }[condition] - ) - - -def condition_encode(condition): - return { - enum_condition.unknown: "unknown", - enum_condition.ok: "ok", - enum_condition.concerning: "concerning", - enum_condition.critical: "critical", - }[condition] - - -def condition_decode(condition_encoded): - return { - "unknown": enum_condition.unknown, - "ok": enum_condition.ok, - "warning": enum_condition.concerning, # deprecated - "concerning": enum_condition.concerning, - "critical": enum_condition.critical, - }[condition_encoded] - diff --git a/source/logic.old/localization.py b/source/logic.old/localization.py deleted file mode 100644 index 231ae5a..0000000 --- a/source/logic.old/localization.py +++ /dev/null @@ -1,52 +0,0 @@ -translation_language_fallback = None - -translation_language_shall = None - -def translation_initialize(language_fallback, language_shall): - global translation_language_fallback - global translation_language_shall - translation_language_fallback = language_fallback - translation_language_shall = language_shall - - -def translation_get(key, arguments = None): - global translation_language_fallback - global translation_language_shall - global localization_data - if (arguments is None): - arguments = {} - languages = list( - filter( - lambda language: (language is not None), - [translation_language_shall, translation_language_fallback] - ) - ) - for language in languages: - if (language not in localization_data): - _sys.stderr.write( - string_coin( - "[notice] missing localization data for language '{{language}}'\n", - { - "language": language, - } - ) - ) - else: - if (key not in localization_data[language]): - _sys.stderr.write( - string_coin( - "[notice] missing translation in language '{{language}}' for key '{{key}}'\n", - { - "language": language, - "key": key, - } - ) - ) - else: - return string_coin( - localization_data[language][key], - arguments - ) - return ("{{%s}}" % key) - - diff --git a/source/logic.old/order.py b/source/logic.old/order.py deleted file mode 100644 index 2f6c1b9..0000000 --- a/source/logic.old/order.py +++ /dev/null @@ -1,476 +0,0 @@ -def order_schema_active( -): - return { - "description": "whether the check shall be executed", - "type": "boolean", - "default": True, - } - - -def order_schema_threshold( -): - return { - "description": "how often a condition has to occur in order to be reported", - "type": "integer", - "minimum": 1, - "default": 3, - } - - -def order_schema_annoy( -): - return { - "description": "whether notifications about non-ok states shall be kept sending after the threshold has been surpassed", - "type": "boolean", - "default": False, - } - - -def order_schema_interval( - allow_null, - default -): - return { - "anyOf": [ - { - "description": "in seconds", - "type": ("integer" if allow_null else ["null", "integer"]), - "exclusiveMinimum": 0, - }, - { - "description": "as text", - "type": "string", - "enum": [ - "minute", - "hour", - "day", - "week", - ] - }, - ], - "default": default, - } - - -def order_schema_schedule( -): - return { - "type": "object", - "additionalProperties": False, - "properties": { - "regular_interval": order_schema_interval(False, (60 * 60)), - "attentive_interval": order_schema_interval(False, (60 * 2)), - "reminding_interval": order_schema_interval(True, (60 * 60 * 24)), - }, - "required": [ - ], - } - - -def order_schema_notifications( - notification_channel_implementations -): - return { - "type": "array", - "items": { - "anyOf": list( - map( - lambda pair: { - "title": ("notification channel '%s'" % pair[0]), - "type": "object", - "unevaluatedProperties": False, - "properties": { - "kind": { - "type": "string", - "enum": [pair[0]] - }, - "parameters": pair[1].parameters_schema(), - }, - "required": [ - "kind", - "parameters" - ], - }, - notification_channel_implementations.items() - ) - ) - }, - "default": [ - { - "kind": "console", - "parameters": { - } - }, - ], - } - - -def order_schema_root( - check_kind_implementations, - notification_channel_implementations -): - return { - "type": "object", - "additionalProperties": False, - "properties": { - "defaults": { - "description": "default values for checks", - "type": "object", - "additionalProperties": False, - "properties": { - "active": order_schema_active(), - "threshold": order_schema_threshold(), - "annoy": order_schema_annoy(), - "schedule": order_schema_schedule(), - "notifications": order_schema_notifications(notification_channel_implementations), - }, - "required": [ - ], - }, - "includes": { - "type": "array", - "items": { - "type": "string" - }, - "default": [], - "description": "list of relative or absolute paths to other hmdl files on the local machine, which shall be subsumed in the overall monitoring task" - }, - "checks": { - "type": "array", - "items": { - "allOf": [ - { - "description": "should represent a specific check", - "type": "object", - "unevaluatedProperties": False, - "properties": { - "name": { - "type": "string" - }, - "title": { - "type": "string" - }, - "active": order_schema_active(), - "threshold": order_schema_threshold(), - "annoy": order_schema_annoy(), - "schedule": order_schema_schedule(), - "notifications": order_schema_notifications(notification_channel_implementations), - }, - "required": [ - "name", - ], - }, - { - "anyOf": list( - map( - lambda pair: { - "title": ("check '%s'" % pair[0]), - "type": "object", - "unevaluatedProperties": False, - "properties": { - "kind": { - "type": "string", - "enum": [pair[0]] - }, - "parameters": pair[1].parameters_schema(), - "custom": { - "description": "custom data, which shall be attached to notifications", - "default": None, - }, - }, - "required": [ - "kind", - "parameters", - ] - }, - check_kind_implementations.items() - ) - ), - }, - ] - } - } - }, - "required": [ - ] - } - - -def order_normalize_interval( - interval_raw -): - if (interval_raw is None): - return None - else: - if (type(interval_raw) == int): - return interval_raw - elif (type(interval_raw) == str): - map_ = { - "minute": (60), - "hour": (60 * 60), - "day": (60 * 60 * 24), - "week": (60 * 60 * 24 * 7), - } - if (interval_raw not in map_): - raise ValueError("invalid string interval value: %s" % interval_raw) - else: - return map_[interval_raw] - else: - raise ValueError("invalid type for interval value") - - -def order_normalize_schedule( - node -): - node_ = dict_merge( - { - "regular_interval": (60 * 60), - "attentive_interval": (60 * 2), - "reminding_interval": (60 * 60 * 24), - }, - node - ) - return { - "regular_interval": order_normalize_interval(node_["regular_interval"]), - "attentive_interval": order_normalize_interval(node_["attentive_interval"]), - "reminding_interval": order_normalize_interval(node_["reminding_interval"]), - } - - -def order_normalize_notification( - notification_channel_implementations, - node -): - if (node["kind"] not in notification_channel_implementations): - raise ValueError("invalid notification kind: %s" % notification["kind"]) - else: - return { - "kind": node["kind"], - "parameters": notification_channel_implementations[node["kind"]].normalize_order_node(node["parameters"]), - } - - -def order_normalize_defaults( - notification_channel_implementations, - node -): - node_ = dict_merge( - { - "active": True, - "threshold": 3, - "annoy": False, - "schedule": { - "regular_interval": (60 * 60), - "attentive_interval": (60 * 2), - "reminding_interval": (60 * 60 * 24), - }, - "notifications": [ - ], - }, - node - ) - return { - "active": node_["active"], - "threshold": node_["threshold"], - "annoy": node_["annoy"], - "schedule": node_["schedule"], - "notifications": list( - map( - lambda x: order_normalize_notification(notification_channel_implementations, x), - node_["notifications"] - ) - ), - } - - -def order_normalize_check( - check_kind_implementations, - notification_channel_implementations, - defaults, - node -): - if ("name" not in node): - raise ValueError("missing mandatory field in 'check' node: 'name'") - else: - if ("kind" not in node): - raise ValueError("missing mandatory field in 'check' node: 'kind'") - else: - if (node["kind"] not in check_kind_implementations): - raise ValueError("invalid check kind: '%s'" % node["kind"]) - else: - node_ = dict_merge( - dict_merge( - defaults, - { - "title": node["name"], - "parameters": {}, - "custom": None, - }, - ), - node - ) - node__ = {} - if True: - node__["name"] = node_["name"] - if True: - node__["title"] = node_["title"] - if ("active" in node_): - node__["active"] = node_["active"] - if ("threshold" in node_): - node__["threshold"] = node_["threshold"] - if ("annoy" in node_): - node__["annoy"] = node_["annoy"] - if ("schedule" in node_): - node__["schedule"] = order_normalize_schedule(node_["schedule"]) - if ("notifications" in node_): - node__["notifications"] = list( - map( - lambda x: order_normalize_notification(notification_channel_implementations, x), - node_["notifications"] - ) - ) - if ("kind" in node_): - node__["kind"] = node_["kind"] - if True: - node__["parameters"] = check_kind_implementations[node_["kind"]].normalize_order_node(node_["parameters"]) - if ("custom" in node_): - node__["custom"] = node_["custom"] - return node__ - - -def order_normalize_root( - check_kind_implementations, - notification_channel_implementations, - node, - options = None -): - options = dict_merge( - { - "use_implicit_default_values": True, - }, - ({} if (options is None) else options) - ) - counts = {} - checks_raw = ( - node["checks"] - if ("checks" in node) else - [] - ) - for node_ in checks_raw: - if (node_["name"] not in counts): - counts[node_["name"]] = 0 - counts[node_["name"]] += 1 - fails = list(filter(lambda pair: (pair[1] > 1), counts.items())) - if (len(fails) > 0): - raise ValueError( - string_coin( - "ambiguous check names: {{names}}", - { - "names": ",".join(map(lambda pair: pair[0], fails)), - } - ) - ) - else: - defaults_raw = ( - node["defaults"] - if ("defaults" in node) else - {} - ) - defaults = ( - order_normalize_defaults( - notification_channel_implementations, - defaults_raw - ) - if options["use_implicit_default_values"] else - defaults_raw - ) - includes = ( - node["includes"] - if ("includes" in node) else - [] - ) - return { - "defaults": defaults, - "includes": includes, - "checks": list( - map( - lambda node_: order_normalize_check( - check_kind_implementations, - notification_channel_implementations, - defaults, - node_ - ), - checks_raw - ) - ) - } - - -def order_load( - check_kind_implementations, - notification_channel_implementations, - path, - options = None -): - options = dict_merge( - { - "root": True, - "already_included": set([]), - }, - ({} if (options is None) else options) - ) - if (path in options["already_included"]): - raise ValueError("circular dependency detected") - else: - order_raw = _json.loads(file_read(path)) - includes = ( - order_raw["includes"] - if ("includes" in order_raw) else - [] - ) - for index in range(len(includes)): - path_ = includes[index] - sub_order = order_load( - check_kind_implementations, - notification_channel_implementations, - ( - path_ - if _os.path.isabs(path_) else - _os.path.join(_os.path.dirname(path), path_) - ), - { - "root": False, - "already_included": (options["already_included"] | {path}) - } - ) - if (not "checks" in order_raw): - order_raw["checks"] = [] - order_raw["checks"].extend( - list( - map( - lambda check: dict_merge( - check, - { - "name": string_coin( - "{{prefix}}.{{original_name}}", - { - "prefix": _os.path.basename(path_).split(".")[0], - "original_name": check["name"], - } - ), - } - ), - sub_order["checks"] - ) - ) - ) - order_raw["includes"] = [] - return order_normalize_root( - check_kind_implementations, - notification_channel_implementations, - order_raw, - { - "use_implicit_default_values": options["root"], - } - ) - diff --git a/source/logic.old/packages.py b/source/logic.old/packages.py deleted file mode 100644 index 9b4bddc..0000000 --- a/source/logic.old/packages.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys as _sys -import os as _os -import subprocess as _subprocess -import math as _math -import hashlib as _hashlib -import tempfile as _tempfile -import argparse as _argparse -import json as _json -import requests as _requests -import enum as _enum -import time as _time -import datetime as _datetime -import smtplib as _smtplib -from email.mime.text import MIMEText -import ssl as _ssl -import socket as _socket -import sqlite3 as _sqlite3 diff --git a/source/logic/main.ts b/source/logic/main.ts index ed8ca71..a4ddf89 100644 --- a/source/logic/main.ts +++ b/source/logic/main.ts @@ -4,7 +4,8 @@ async function main( // consts const version : string = "0.8"; - // init + // init translations + // TODO: use env language await lib_plankton.translate.initialize_promise( { "verbosity": 1,