#!/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_value(inputs_file: str, item_key: str) -> str: 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}") 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.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) 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") else: exit_with(2, f"CRITICAL - probe_type non supporté: {args.probe_type}") 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())