[int]
This commit is contained in:
parent
d13b3776e2
commit
4dbb7474e7
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
.geany
|
||||
source/__pycache__/
|
||||
temp/
|
||||
build/
|
||||
|
||||
|
|
|
|||
1775
lib/plankton/plankton.d.ts
vendored
Normal file
1775
lib/plankton/plankton.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
5427
lib/plankton/plankton.js
Normal file
5427
lib/plankton/plankton.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -12,6 +12,7 @@
|
|||
"help.args.send_ok_notifications": "ob '{{condition_name}}'-Zustände gemeldet werden sollen",
|
||||
"help.args.language": "welche Sprache verwendet werden soll (statt der in den Umgebungs-Variablen gesetzten)",
|
||||
"help.args.erase_state": "ob der Zustand bei Start gelöscht werden soll; das hat zur Folge, dass alle Prüfungen unmittelbar durchgeführt werden",
|
||||
"help.args.show_help": "nur die Hilfe zur Standard-Ausgabe schreiben und beenden",
|
||||
"help.args.show_schema": "nur das hmdl-JSON-Schema zur Standard-Ausgabe schreiben und beenden",
|
||||
"help.args.expose_full_order": "nur den Pfad zur Datenbank-Datei zur Standard-Ausgabe schreiben und beenden (nützlich für Fehlersuche)",
|
||||
"help.args.show_version": "nur die Version zur Standard-Ausgabe schreiben und beenden",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"help.args.send_ok_notifications": "whether an '{{condition_name}}' condition shall be reported",
|
||||
"help.args.language": "language to use (instead of the language, set in the environment variables)",
|
||||
"help.args.erase_state": "whether the state shall be deleted on start; this will cause that all checks are executed immediatly",
|
||||
"help.args.show_schema": "print help to stdout and exit",
|
||||
"help.args.show_schema": "print the hmdl JSON schema to stdout and exit",
|
||||
"help.args.expose_full_order": "only print the extended order to stdout and exit (useful for debugging)",
|
||||
"help.args.show_version": "only print the version to stdout and exit",
|
||||
|
|
|
|||
12
source/logic/channels/_type.ts
Normal file
12
source/logic/channels/_type.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
namespace _heimdall.channels
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_channel = {
|
||||
parameters_schema : (() => _heimdall.helpers.json_schema.type_schema);
|
||||
normalize_order_node : ((node : any) => any);
|
||||
notify : (parameters, name, data, state, info) => Promise<void>;
|
||||
};
|
||||
|
||||
}
|
||||
12
source/logic/checks/_type.ts
Normal file
12
source/logic/checks/_type.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
namespace _heimdall.checks
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_check = {
|
||||
parameters_schema : (() => _heimdall.helpers.json_schema.type_schema);
|
||||
normalize_order_node : ((node : any) => any);
|
||||
run : (parameters) => Promise<{condition : _heimdall.enum_condition; info : any;}>;
|
||||
};
|
||||
|
||||
}
|
||||
13
source/logic/condition.ts
Normal file
13
source/logic/condition.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
namespace _heimdall
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
export enum enum_condition {
|
||||
unknown = 0,
|
||||
ok = 1,
|
||||
concerning = 2,
|
||||
critical = 3,
|
||||
};
|
||||
|
||||
}
|
||||
47
source/logic/helpers/json_schema.ts
Normal file
47
source/logic/helpers/json_schema.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
namespace _heimdall.helpers.json_schema
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
type type_type = (
|
||||
"null"
|
||||
|
|
||||
"boolean"
|
||||
|
|
||||
"integer"
|
||||
|
|
||||
"float"
|
||||
|
|
||||
"string"
|
||||
|
|
||||
"array"
|
||||
|
|
||||
"object"
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export type type_schema = {
|
||||
type ?: (
|
||||
type_type
|
||||
|
|
||||
Array<type_type>
|
||||
);
|
||||
additionalProperties ?: (
|
||||
false
|
||||
|
|
||||
type_schema
|
||||
);
|
||||
properties ?: Record<string, type_schema>;
|
||||
required ?: Array<string>;
|
||||
description ?: string;
|
||||
default ?: any;
|
||||
minimum ?: int;
|
||||
maximum ?: int;
|
||||
enum ?: Array<any>;
|
||||
items ?: type_schema;
|
||||
anyOf ?: Array<type_schema>;
|
||||
};
|
||||
|
||||
}
|
||||
237
source/logic/main.ts
Normal file
237
source/logic/main.ts
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
async function main(
|
||||
) : Promise<void>
|
||||
{
|
||||
// consts
|
||||
const version : string = "0.8";
|
||||
|
||||
// init
|
||||
await lib_plankton.translate.initialize_promise(
|
||||
{
|
||||
"verbosity": 1,
|
||||
"order": ["de", "en"],
|
||||
"packages": await Promise.all(
|
||||
[
|
||||
{"identifier": "de", "path": "localization/de.json"},
|
||||
{"identifier": "en", "path": "localization/en.json"},
|
||||
]
|
||||
.map(
|
||||
(entry) => (
|
||||
lib_plankton.file.read(entry.path)
|
||||
.then(content => Promise.resolve(JSON.parse(content)))
|
||||
.then(tree => Promise.resolve({"meta": {"identifier": entry.identifier}, "tree": tree}))
|
||||
)
|
||||
)
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
// args
|
||||
const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler(
|
||||
{
|
||||
"order_path": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "order_path",
|
||||
"type": lib_plankton.args.enum_type.string,
|
||||
"kind": lib_plankton.args.enum_kind.positional,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": "monitoring.hmdl.json",
|
||||
"parameters": {
|
||||
"index": 0,
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.order_path"),
|
||||
}
|
||||
),
|
||||
"show_help": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "help",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["help"],
|
||||
"indicators_short": ["h"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.show_help"),
|
||||
}
|
||||
),
|
||||
"show_version": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "version",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["version"],
|
||||
"indicators_short": ["v"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.show_version"),
|
||||
}
|
||||
),
|
||||
"show_schema": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "schema",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["schema"],
|
||||
"indicators_short": ["s"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.show_schema"),
|
||||
}
|
||||
),
|
||||
"expose_full_order": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "expose_full_order",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["expose-full-order"],
|
||||
"indicators_short": ["e"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.expose_full_order"),
|
||||
}
|
||||
),
|
||||
"erase_state": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "erase_state",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["erase-state"],
|
||||
"indicators_short": ["x"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.erase_state"),
|
||||
}
|
||||
),
|
||||
"database_path": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "database_path",
|
||||
"type": lib_plankton.args.enum_type.string,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["database-path"],
|
||||
"indicators_short": ["d"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.database_path"),
|
||||
}
|
||||
),
|
||||
"mutex_path": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "mutex_path",
|
||||
"type": lib_plankton.args.enum_type.string,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["mutex-path"],
|
||||
"indicators_short": ["m"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.mutex_path"),
|
||||
}
|
||||
),
|
||||
"send_ok_notifications": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "send_ok_notifications",
|
||||
"type": lib_plankton.args.enum_type.boolean,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["send-ok-notifications"],
|
||||
"indicators_short": ["y"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.send_ok_notifications"),
|
||||
}
|
||||
),
|
||||
"language": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "language",
|
||||
"type": lib_plankton.args.enum_type.string,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": false,
|
||||
"parameters": {
|
||||
"indicators_long": ["language"],
|
||||
"indicators_short": ["l"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.language"),
|
||||
}
|
||||
),
|
||||
"time_to_live": new lib_plankton.args.class_argument(
|
||||
{
|
||||
"name": "time_to_live",
|
||||
"type": lib_plankton.args.enum_type.float,
|
||||
"kind": lib_plankton.args.enum_kind.volatile,
|
||||
"mode": lib_plankton.args.enum_mode.replace,
|
||||
"default": (60 * 60 * 24 * 7),
|
||||
"parameters": {
|
||||
"indicators_long": ["time-to-live"],
|
||||
"indicators_short": ["t"],
|
||||
},
|
||||
"info": lib_plankton.translate.get("help.args.time_to_live"),
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
const args : Record<string, any> = arg_handler.read(
|
||||
lib_plankton.args.enum_environment.cli,
|
||||
process.argv.slice(2).join(" ")
|
||||
);
|
||||
|
||||
// exec
|
||||
if (args.show_help) {
|
||||
process.stdout.write(
|
||||
arg_handler.generate_help(
|
||||
{
|
||||
"programname": "heimdall",
|
||||
"description": lib_plankton.translate.get("help.title"),
|
||||
"executable": "heimdall",
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
if (args.show_version) {
|
||||
process.stdout.write(version + "\n");
|
||||
}
|
||||
else {
|
||||
if (args.show_version) {
|
||||
process.stdout.write(version + "\n");
|
||||
}
|
||||
else {
|
||||
const check_kind_implementations : Record<string, _heimdall.checks.type_check> = {
|
||||
};
|
||||
const channel_kind_implementations : Record<string, _heimdall.channels.type_channel> = {
|
||||
};
|
||||
if (args.show_schema) {
|
||||
process.stdout.write(
|
||||
lib_plankton.json.encode(
|
||||
_heimdall.order.schema_root(
|
||||
check_kind_implementations,
|
||||
channel_kind_implementations
|
||||
),
|
||||
true
|
||||
)
|
||||
+
|
||||
"\n"
|
||||
)
|
||||
}
|
||||
else {
|
||||
process.stdout.write(JSON.stringify(args, undefined, "\t") + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
546
source/logic/order.ts
Normal file
546
source/logic/order.ts
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
namespace _heimdall.order
|
||||
{
|
||||
|
||||
function schema_active(
|
||||
) : _heimdall.helpers.json_schema.type_schema
|
||||
{
|
||||
return {
|
||||
"description": "whether the check shall be executed",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function schema_threshold(
|
||||
) : _heimdall.helpers.json_schema.type_schema
|
||||
{
|
||||
return {
|
||||
"description": "how often a condition has to occur in order to be reported",
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"default": 3,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function schema_annoy(
|
||||
) : _heimdall.helpers.json_schema.type_schema
|
||||
{
|
||||
return {
|
||||
"description": "whether notifications about non-ok states shall be kept sending after the threshold has been surpassed",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function schema_interval(
|
||||
allow_null,
|
||||
default_
|
||||
) : _heimdall.helpers.json_schema.type_schema
|
||||
{
|
||||
return {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "in seconds",
|
||||
"type": (allow_null ? "integer" : ["null", "integer"]),
|
||||
"exclusiveMinimum": 0,
|
||||
},
|
||||
{
|
||||
"description": "as text",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"minute",
|
||||
"hour",
|
||||
"day",
|
||||
"week",
|
||||
]
|
||||
},
|
||||
],
|
||||
"default": default_,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function schema_schedule(
|
||||
)
|
||||
{
|
||||
return {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"regular_interval": schema_interval(false, (60 * 60)),
|
||||
"attentive_interval": schema_interval(false, (60 * 2)),
|
||||
"reminding_interval": schema_interval(true, (60 * 60 * 24)),
|
||||
},
|
||||
"required": [
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function schema_notifications(
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>
|
||||
)
|
||||
{
|
||||
return {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": (
|
||||
Object.entries(channel_implementations)
|
||||
.map(
|
||||
([key, value]) => ({
|
||||
"title": ("notification channel '" + key + "'"),
|
||||
"type": "object",
|
||||
"unevaluatedProperties": false,
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [key]
|
||||
},
|
||||
"parameters": value.parameters_schema(),
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"parameters"
|
||||
],
|
||||
})
|
||||
)
|
||||
)
|
||||
},
|
||||
"default": [
|
||||
{
|
||||
"kind": "console",
|
||||
"parameters": {
|
||||
}
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function schema_root(
|
||||
check_kind_implementations : Record<string, _heimdall.checks.type_check>,
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
)
|
||||
{
|
||||
return {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"defaults": {
|
||||
"description": "default values for checks",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"active": schema_active(),
|
||||
"threshold": schema_threshold(),
|
||||
"annoy": schema_annoy(),
|
||||
"schedule": schema_schedule(),
|
||||
"notifications": schema_notifications(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": schema_active(),
|
||||
"threshold": schema_threshold(),
|
||||
"annoy": schema_annoy(),
|
||||
"schedule": schema_schedule(),
|
||||
"notifications": schema_notifications(channel_implementations),
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
],
|
||||
},
|
||||
{
|
||||
"anyOf": (
|
||||
Object.entries(check_kind_implementations)
|
||||
.map(
|
||||
([key, value]) => ({
|
||||
"title": ("check '" + key + "'"),
|
||||
"type": "object",
|
||||
"unevaluatedProperties": false,
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [key]
|
||||
},
|
||||
"parameters": value.parameters_schema(),
|
||||
"custom": {
|
||||
"description": "custom data, which shall be attached to notifications",
|
||||
"default": null,
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"parameters",
|
||||
]
|
||||
})
|
||||
)
|
||||
),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function normalize_interval(
|
||||
interval_raw
|
||||
)
|
||||
{
|
||||
if (interval_raw === null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if (typeof(interval_raw) === "number") {
|
||||
return interval_raw;
|
||||
}
|
||||
else if (typeof(interval_raw) === "string") {
|
||||
const map_ = {
|
||||
"minute": (60),
|
||||
"hour": (60 * 60),
|
||||
"day": (60 * 60 * 24),
|
||||
"week": (60 * 60 * 24 * 7),
|
||||
};
|
||||
if (! (interval_raw in map_)) {
|
||||
throw new Error("invalid string interval value: " + interval_raw);
|
||||
}
|
||||
else {
|
||||
return map_[interval_raw];
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("invalid type for interval value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function normalize_schedule(
|
||||
node
|
||||
)
|
||||
{
|
||||
const node_ = Object.assign(
|
||||
{
|
||||
"regular_interval": (60 * 60),
|
||||
"attentive_interval": (60 * 2),
|
||||
"reminding_interval": (60 * 60 * 24),
|
||||
},
|
||||
node
|
||||
);
|
||||
return {
|
||||
"regular_interval": normalize_interval(node_["regular_interval"]),
|
||||
"attentive_interval": normalize_interval(node_["attentive_interval"]),
|
||||
"reminding_interval": normalize_interval(node_["reminding_interval"]),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function normalize_notification(
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
node
|
||||
)
|
||||
{
|
||||
if (! (node["kind"] in channel_implementations)) {
|
||||
throw new Error("invalid notification kind: " + node["kind"]);
|
||||
}
|
||||
else {
|
||||
return {
|
||||
"kind": node["kind"],
|
||||
"parameters": channel_implementations[node["kind"]].normalize_order_node(node["parameters"]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function normalize_defaults(
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
node
|
||||
)
|
||||
{
|
||||
const node_ = Object.assign(
|
||||
{
|
||||
"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": (
|
||||
node_["notifications"]
|
||||
.map(x => normalize_notification(channel_implementations, x))
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function normalize_check(
|
||||
check_kind_implementations : Record<string, _heimdall.checks.type_check>,
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
defaults,
|
||||
node
|
||||
)
|
||||
{
|
||||
if (! ("name" in node)) {
|
||||
throw new Error("missing mandatory field in 'check' node: 'name'");
|
||||
}
|
||||
else {
|
||||
if (! ("kind" in node)) {
|
||||
throw new Error("missing mandatory field in 'check' node: 'kind'");
|
||||
}
|
||||
else {
|
||||
if (! (node["kind"] in check_kind_implementations)) {
|
||||
throw new Error("invalid check kind: " + node["kind"]);
|
||||
}
|
||||
else {
|
||||
const node_ = Object.assign(
|
||||
Object.assign(
|
||||
defaults,
|
||||
{
|
||||
"title": node["name"],
|
||||
"parameters": {},
|
||||
"custom": null,
|
||||
},
|
||||
),
|
||||
node
|
||||
);
|
||||
let 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"] = normalize_schedule(node_["schedule"]);
|
||||
}
|
||||
if ("notifications" in node_) {
|
||||
node__["notifications"] = (
|
||||
node_["notifications"]
|
||||
.map(
|
||||
x => normalize_notification(channel_implementations, x),
|
||||
)
|
||||
);
|
||||
}
|
||||
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__;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function normalize_root(
|
||||
check_kind_implementations : Record<string, _heimdall.checks.type_check>,
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
node,
|
||||
options = {}
|
||||
)
|
||||
{
|
||||
options = Object.assign(
|
||||
{
|
||||
"use_implicit_default_values": true,
|
||||
},
|
||||
options
|
||||
)
|
||||
let counts = {};
|
||||
let checks_raw = (
|
||||
("checks" in node)
|
||||
? node["checks"]
|
||||
: []
|
||||
);
|
||||
checks_raw.forEach(
|
||||
node_ => {
|
||||
if (! (node_["name"] in counts)) {
|
||||
counts[node_["name"]] = 0;
|
||||
}
|
||||
counts[node_["name"]] += 1;
|
||||
}
|
||||
);
|
||||
let fails : Array<[string, int]> = (
|
||||
Object.entries(counts)
|
||||
.filter(
|
||||
([key, value]) => (value > 1)
|
||||
)
|
||||
);
|
||||
if (fails.length > 0) {
|
||||
throw new Error(
|
||||
lib_plankton.string.coin(
|
||||
"ambiguous check names: {{names}}",
|
||||
{
|
||||
"names": fails.map(([key, value]) => key).join(","),
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
let defaults_raw = (
|
||||
("defaults" in node)
|
||||
? node["defaults"]
|
||||
: {}
|
||||
)
|
||||
let defaults = (
|
||||
options["use_implicit_default_values"]
|
||||
? normalize_defaults(
|
||||
channel_implementations,
|
||||
defaults_raw
|
||||
)
|
||||
: defaults_raw
|
||||
)
|
||||
let includes = (
|
||||
("includes" in node)
|
||||
? node["includes"]
|
||||
: []
|
||||
)
|
||||
return {
|
||||
"defaults": defaults,
|
||||
"includes": includes,
|
||||
"checks": (
|
||||
checks_raw
|
||||
.map(
|
||||
node_ => normalize_check(
|
||||
check_kind_implementations,
|
||||
channel_implementations,
|
||||
defaults,
|
||||
node_
|
||||
)
|
||||
)
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function load(
|
||||
check_kind_implementations : Record<string, _heimdall.checks.type_check>,
|
||||
channel_implementations : Record<string, _heimdall.channels.type_channel>,
|
||||
path : string,
|
||||
options = {}
|
||||
)
|
||||
{
|
||||
options = Object.assign(
|
||||
{
|
||||
"root": true,
|
||||
"already_included": new Set([]),
|
||||
},
|
||||
options
|
||||
)
|
||||
if (path in options["already_included"]) {
|
||||
throw new Error("circular dependency detected")
|
||||
}
|
||||
else {
|
||||
const order_raw = lib_plankton.json.decode(await lib_plankton.file.read(path));
|
||||
let includes : Array<string> = (
|
||||
("includes" in order_raw)
|
||||
? order_raw["includes"]
|
||||
: []
|
||||
);
|
||||
for (let index = 0; index < includes.length; index += 1) {
|
||||
let path_ = includes[index];
|
||||
let sub_order = load(
|
||||
check_kind_implementations,
|
||||
channel_implementations,
|
||||
(
|
||||
_os.path.isabs(path_)
|
||||
? path_
|
||||
: _os.path.join(_os.path.dirname(path), path_)
|
||||
),
|
||||
{
|
||||
"root": false,
|
||||
// TODO set union
|
||||
"already_included": (options["already_included"] | {path})
|
||||
}
|
||||
)
|
||||
if (! ("checks" in order_raw)) {
|
||||
order_raw["checks"] = [];
|
||||
}
|
||||
order_raw["checks"].extend(
|
||||
sub_order["checks"]
|
||||
.map(
|
||||
check => Object.assign(
|
||||
check,
|
||||
{
|
||||
"name": lib_plankton.string.coin(
|
||||
"{{prefix}}.{{original_name}}",
|
||||
{
|
||||
"prefix": _os.path.basename(path_).split(".")[0],
|
||||
"original_name": check["name"],
|
||||
}
|
||||
),
|
||||
}
|
||||
),
|
||||
sub_order["checks"]
|
||||
)
|
||||
);
|
||||
order_raw["includes"] = [];
|
||||
}
|
||||
return normalize_root(
|
||||
check_kind_implementations,
|
||||
channel_implementations,
|
||||
order_raw,
|
||||
{
|
||||
"use_implicit_default_values": options["root"],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1
source/misc/head.js
Normal file
1
source/misc/head.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
#!/usr/bin/env node
|
||||
137
tools/build
137
tools/build
|
|
@ -1,136 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env sh
|
||||
|
||||
import sys as _sys
|
||||
import os as _os
|
||||
import json as _json
|
||||
import stat as _stat
|
||||
import argparse as _argparse
|
||||
## vars
|
||||
|
||||
path_prj_from=tools/heimdall.prj.json
|
||||
path_prj_to=heimdall.prj.json
|
||||
|
||||
def file_read(path):
|
||||
handle = open(path, "r")
|
||||
content = handle.read()
|
||||
handle.close()
|
||||
return content
|
||||
|
||||
|
||||
def file_write(path, content):
|
||||
handle = open(path, "w")
|
||||
handle.write(content)
|
||||
handle.close()
|
||||
|
||||
|
||||
def string_coin(template, arguments):
|
||||
result = template
|
||||
for (key, value, ) in arguments.items():
|
||||
result = result.replace("{{%s}}" % key, value)
|
||||
return result
|
||||
|
||||
|
||||
def python_data_encode(data):
|
||||
return _json.dumps(data, indent = "\t")
|
||||
|
||||
|
||||
def main():
|
||||
## consts
|
||||
dir_source = "source"
|
||||
dir_build = "build"
|
||||
sources_common = [
|
||||
_os.path.join(dir_source, "logic", "packages.py"),
|
||||
_os.path.join(dir_source, "logic", "lib.py"),
|
||||
_os.path.join(dir_source, "logic", "localization.py"),
|
||||
_os.path.join(dir_source, "logic", "condition.py"),
|
||||
_os.path.join(dir_source, "logic", "order.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "_interface.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "script.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "file_state.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "tls_certificate.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "http_request.py"),
|
||||
_os.path.join(dir_source, "logic", "checks", "generic_remote.py"),
|
||||
_os.path.join(dir_source, "logic", "channels", "_interface.py"),
|
||||
_os.path.join(dir_source, "logic", "channels", "console.py"),
|
||||
_os.path.join(dir_source, "logic", "channels", "email.py"),
|
||||
_os.path.join(dir_source, "logic", "channels", "libnotify.py"),
|
||||
]
|
||||
targets = {
|
||||
"app": {
|
||||
"sources": (
|
||||
sources_common
|
||||
+
|
||||
[
|
||||
_os.path.join(dir_source, "logic", "main.py"),
|
||||
]
|
||||
),
|
||||
"build": _os.path.join(dir_build, "heimdall"),
|
||||
},
|
||||
"test": {
|
||||
"sources": (
|
||||
sources_common
|
||||
+
|
||||
[
|
||||
_os.path.join(dir_source, "test", "test.py"),
|
||||
]
|
||||
),
|
||||
"build": _os.path.join(dir_build, "heimdall-test"),
|
||||
},
|
||||
}
|
||||
|
||||
## args
|
||||
argument_parser = _argparse.ArgumentParser(
|
||||
)
|
||||
argument_parser.add_argument(
|
||||
"-t",
|
||||
"--target",
|
||||
type = str,
|
||||
choices = ["app", "test"],
|
||||
default = "app",
|
||||
dest = "target_name",
|
||||
help = "which target to build",
|
||||
)
|
||||
args = argument_parser.parse_args()
|
||||
|
||||
## exec
|
||||
if (not _os.path.exists(dir_build)):
|
||||
_os.mkdir(dir_build)
|
||||
|
||||
compilation = ""
|
||||
compilation += "#!/usr/bin/env python3\n\n"
|
||||
|
||||
### localization
|
||||
if True:
|
||||
localization_data = dict(
|
||||
map(
|
||||
lambda entry: (
|
||||
entry.name.split(".")[0],
|
||||
_json.loads(file_read(entry.path)),
|
||||
),
|
||||
filter(
|
||||
lambda entry: (entry.is_file() and entry.name.endswith(".json")),
|
||||
_os.scandir(_os.path.join(dir_source, "localization"))
|
||||
)
|
||||
)
|
||||
)
|
||||
compilation += string_coin(
|
||||
"localization_data = {{data}}\n\n",
|
||||
{
|
||||
"data": python_data_encode(localization_data),
|
||||
}
|
||||
)
|
||||
|
||||
### logic
|
||||
for path in targets[args.target_name]["sources"]:
|
||||
compilation += (file_read(path) + "\n")
|
||||
|
||||
### write to file
|
||||
if _os.path.exists(targets[args.target_name]["build"]):
|
||||
_os.remove(targets[args.target_name]["build"])
|
||||
file_write(targets[args.target_name]["build"], compilation)
|
||||
|
||||
### postproess
|
||||
_os.chmod(
|
||||
targets[args.target_name]["build"],
|
||||
(_stat.S_IRWXU | _stat.S_IXGRP | _stat.S_IXOTH)
|
||||
)
|
||||
|
||||
|
||||
main()
|
||||
cp ${path_prj_from} ${path_prj_to}
|
||||
koralle --execute ${path_prj_to}
|
||||
rm ${path_prj_to}
|
||||
|
|
|
|||
68
tools/heimdall.prj.json
Normal file
68
tools/heimdall.prj.json
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"name": "heimdall",
|
||||
"version": "0.8",
|
||||
"dependencies": [
|
||||
],
|
||||
"roottask": {
|
||||
"name": "logic",
|
||||
"type": "group",
|
||||
"sub": [
|
||||
{
|
||||
"name": "postprocess",
|
||||
"sub": [
|
||||
{
|
||||
"name": "link",
|
||||
"sub": [
|
||||
{
|
||||
"name": "compile",
|
||||
"type": "typescript",
|
||||
"parameters": {
|
||||
"inputs": [
|
||||
"lib/plankton/plankton.d.ts",
|
||||
"source/logic/condition.ts",
|
||||
"source/logic/helpers/json_schema.ts",
|
||||
"source/logic/checks/_type.ts",
|
||||
"source/logic/channels/_type.ts",
|
||||
"source/logic/order.ts",
|
||||
"source/logic/main.ts"
|
||||
],
|
||||
"target": "es2020",
|
||||
"output": "temp/heimdall-unlinked"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "concat",
|
||||
"parameters": {
|
||||
"inputs": [
|
||||
"source/misc/head.js",
|
||||
"lib/plankton/plankton.js",
|
||||
"temp/heimdall-unlinked"
|
||||
],
|
||||
"output": "temp/heimdall-raw"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "script",
|
||||
"parameters": {
|
||||
"path": "tools/postprocess",
|
||||
"interpreter": null,
|
||||
"inputs": [
|
||||
"temp/heimdall-raw"
|
||||
],
|
||||
"outputs": [
|
||||
"build/heimdall"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "localization",
|
||||
"type": "copy",
|
||||
"parameters": {
|
||||
"folder": true,
|
||||
"input": "source/localization/",
|
||||
"output": "build/localization/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
14
tools/makefile
Normal file
14
tools/makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
## consts
|
||||
|
||||
dir_lib := lib
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
|
||||
cmd_mkdir := mkdir -p
|
||||
cmd_tsc := tsc
|
||||
cmd_chmod := chmod
|
||||
|
||||
|
||||
## rules
|
||||
|
||||
${dir_build}
|
||||
7
tools/postprocess
Executable file
7
tools/postprocess
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
path_input=$1
|
||||
path_output=$2
|
||||
|
||||
cp ${path_input} ${path_output}
|
||||
chmod +x ${path_output}
|
||||
23
tools/update-plankton
Executable file
23
tools/update-plankton
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
## consts
|
||||
|
||||
dir_lib=lib
|
||||
dir_plankton=${dir_lib}/plankton
|
||||
|
||||
|
||||
## vars
|
||||
|
||||
modules=""
|
||||
modules="${modules} string"
|
||||
modules="${modules} json"
|
||||
modules="${modules} file"
|
||||
modules="${modules} translate"
|
||||
modules="${modules} args"
|
||||
|
||||
|
||||
## exec
|
||||
|
||||
mkdir -p ${dir_plankton}
|
||||
cd ${dir_plankton}
|
||||
ptk bundle node ${modules}
|
||||
Loading…
Reference in a new issue