211 lines
9.5 KiB
Python
Executable file
211 lines
9.5 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
import yaml
|
|
|
|
|
|
def exit_with(code: int, text: str) -> None:
|
|
print(text)
|
|
raise SystemExit(code)
|
|
|
|
|
|
def parse_date(value: str) -> datetime:
|
|
return datetime.strptime(value, "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
|
|
|
|
|
def load_input_item(inputs_file: str, item_key: str) -> dict:
|
|
path = Path(inputs_file)
|
|
if not path.exists():
|
|
raise ValueError(f"inputs file introuvable: {inputs_file}")
|
|
|
|
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
|
if not isinstance(data, dict):
|
|
raise ValueError(f"inputs file invalide: {inputs_file}")
|
|
|
|
if item_key not in data:
|
|
raise ValueError(f"item_key introuvable dans le store: {item_key}")
|
|
|
|
item = data[item_key]
|
|
if not isinstance(item, dict):
|
|
raise ValueError(f"entrée invalide pour item_key: {item_key}")
|
|
return item
|
|
|
|
|
|
def load_input_value(inputs_file: str, item_key: str) -> str:
|
|
item = load_input_item(inputs_file, item_key)
|
|
if "value" not in item:
|
|
raise ValueError(f"champ 'value' absent pour item_key: {item_key}")
|
|
return str(item["value"]).strip()
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--probe-type", required=True)
|
|
ap.add_argument("--source-type", required=True)
|
|
ap.add_argument("--source-value")
|
|
ap.add_argument("--inputs-file")
|
|
ap.add_argument("--item-key")
|
|
ap.add_argument("--unit", required=True)
|
|
|
|
ap.add_argument("--unknown-lt", type=float)
|
|
ap.add_argument("--unknown-gte", type=float)
|
|
|
|
ap.add_argument("--ok-gte", type=float)
|
|
ap.add_argument("--ok-lt", type=float)
|
|
|
|
ap.add_argument("--warning-gte", type=float)
|
|
ap.add_argument("--warning-lt", type=float)
|
|
|
|
ap.add_argument("--critical-gte", type=float)
|
|
ap.add_argument("--critical-lt", type=float)
|
|
|
|
ap.add_argument("--on-error", default="critical")
|
|
ap.add_argument("--label", default="life-noc")
|
|
args = ap.parse_args()
|
|
|
|
try:
|
|
if args.probe_type in {"elapsed_time", "days_until_due"}:
|
|
if args.source_type != "manual_date":
|
|
exit_with(2, f"CRITICAL - source_type non supporté: {args.source_type}")
|
|
if args.unit != "days":
|
|
exit_with(2, f"CRITICAL - unité non supportée: {args.unit}")
|
|
|
|
if args.inputs_file and args.item_key:
|
|
source_value = load_input_value(args.inputs_file, args.item_key)
|
|
elif args.source_value:
|
|
source_value = args.source_value
|
|
else:
|
|
raise ValueError("aucune source fournie: inputs-file/item-key ou source-value requis")
|
|
|
|
dt = parse_date(source_value)
|
|
now = datetime.now(timezone.utc)
|
|
|
|
elif args.probe_type == "elapsed_distance":
|
|
if args.source_type != "manual_counter":
|
|
exit_with(2, f"CRITICAL - source_type non supporté: {args.source_type}")
|
|
if args.unit != "km":
|
|
exit_with(2, f"CRITICAL - unité non supportée: {args.unit}")
|
|
|
|
if args.inputs_file and args.item_key:
|
|
item = load_input_item(args.inputs_file, args.item_key)
|
|
current_value = float(str(item.get("value", "")).strip())
|
|
reference_value = float(str(item.get("reference_value", "")).strip())
|
|
else:
|
|
raise ValueError("manual_counter exige inputs-file et item-key")
|
|
|
|
metric = current_value - reference_value
|
|
|
|
if args.unknown_lt is not None and metric < args.unknown_lt:
|
|
exit_with(3, f"UNKNOWN - {args.label}: écart compteur invalide ({metric:.0f} km)")
|
|
if args.critical_gte is not None and metric >= args.critical_gte:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.0f} km")
|
|
if args.warning_gte is not None and metric >= args.warning_gte:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.0f} km")
|
|
if args.ok_gte is not None and metric >= args.ok_gte:
|
|
exit_with(0, f"OK - {args.label}: {metric:.0f} km")
|
|
|
|
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
|
|
|
|
elif args.probe_type == "remaining_quantity":
|
|
if args.source_type != "manual_value":
|
|
exit_with(2, f"CRITICAL - source_type non supporté: {args.source_type}")
|
|
if args.unit not in {"%", "units", "litres"}:
|
|
exit_with(2, f"CRITICAL - unité non supportée: {args.unit}")
|
|
|
|
if args.inputs_file and args.item_key:
|
|
item = load_input_item(args.inputs_file, args.item_key)
|
|
metric = float(str(item.get("value", "")).strip())
|
|
elif args.source_value:
|
|
metric = float(str(args.source_value).strip())
|
|
else:
|
|
raise ValueError("manual_value exige inputs-file/item-key ou source-value")
|
|
|
|
unit_suffix = args.unit
|
|
|
|
if args.critical_lt is not None and metric < args.critical_lt:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} {unit_suffix} restants")
|
|
if args.warning_lt is not None and metric < args.warning_lt:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.1f} {unit_suffix} restants")
|
|
if args.ok_gte is not None and metric >= args.ok_gte:
|
|
exit_with(0, f"OK - {args.label}: {metric:.1f} {unit_suffix} restants")
|
|
if args.unknown_gte is not None and metric >= args.unknown_gte:
|
|
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} {unit_suffix} restants")
|
|
|
|
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
|
|
|
|
elif args.probe_type == "current_value":
|
|
if args.source_type != "manual_value":
|
|
exit_with(2, f"CRITICAL - source_type non supporté: {args.source_type}")
|
|
if args.unit not in {"%", "units", "litres", "volts", "watts"}:
|
|
exit_with(2, f"CRITICAL - unité non supportée: {args.unit}")
|
|
|
|
if args.inputs_file and args.item_key:
|
|
item = load_input_item(args.inputs_file, args.item_key)
|
|
metric = float(str(item.get("value", "")).strip())
|
|
elif args.source_value:
|
|
metric = float(str(args.source_value).strip())
|
|
else:
|
|
raise ValueError("manual_value exige inputs-file/item-key ou source-value")
|
|
|
|
unit_suffix = args.unit
|
|
|
|
if args.critical_lt is not None and metric < args.critical_lt:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.critical_gte is not None and metric >= args.critical_gte:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.warning_lt is not None and metric < args.warning_lt:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.warning_gte is not None and metric >= args.warning_gte:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.ok_gte is not None and metric >= args.ok_gte:
|
|
exit_with(0, f"OK - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.ok_lt is not None and metric < args.ok_lt:
|
|
exit_with(0, f"OK - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.unknown_gte is not None and metric >= args.unknown_gte:
|
|
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} {unit_suffix}")
|
|
if args.unknown_lt is not None and metric < args.unknown_lt:
|
|
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} {unit_suffix}")
|
|
|
|
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
|
|
|
|
else:
|
|
exit_with(2, f"CRITICAL - probe_type non supporté: {args.probe_type}")
|
|
|
|
if args.probe_type == "elapsed_time":
|
|
metric = (now - dt).total_seconds() / 86400.0
|
|
|
|
if args.critical_gte is not None and metric >= args.critical_gte:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} jours")
|
|
if args.warning_gte is not None and metric >= args.warning_gte:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.1f} jours")
|
|
if args.ok_gte is not None and metric >= args.ok_gte:
|
|
exit_with(0, f"OK - {args.label}: {metric:.1f} jours")
|
|
if args.unknown_lt is not None and metric < args.unknown_lt:
|
|
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} jours")
|
|
|
|
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
|
|
|
|
elif args.probe_type == "days_until_due":
|
|
metric = (dt - now).total_seconds() / 86400.0
|
|
|
|
if args.critical_lt is not None and metric < args.critical_lt:
|
|
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} jours restants")
|
|
if args.warning_lt is not None and metric < args.warning_lt:
|
|
exit_with(1, f"WARNING - {args.label}: {metric:.1f} jours restants")
|
|
if args.ok_lt is not None and metric < args.ok_lt:
|
|
exit_with(0, f"OK - {args.label}: {metric:.1f} jours restants")
|
|
if args.unknown_gte is not None and metric >= args.unknown_gte:
|
|
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} jours restants")
|
|
|
|
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
|
|
|
|
except Exception as exc:
|
|
if args.on_error == "critical":
|
|
exit_with(2, f"CRITICAL - erreur sonde: {exc}")
|
|
exit_with(3, f"UNKNOWN - erreur sonde: {exc}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|