From 3397a00d4292af2e693ed5ed5b61f2468527156d Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Mon, 16 Mar 2026 22:40:29 -0400 Subject: [PATCH] =?UTF-8?q?d=C3=A9mockage=20pour=20type=20quantit=C3=A9=20?= =?UTF-8?q?restante?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- checks/check_life_noc_probe.py | 27 +++ domains.yaml | 234 +++++++++++++++++++++++++ icinga/services/actifs-chezlepro.conf | 16 +- icinga/services/animaux.conf | 32 +++- icinga/services/jardin.conf | 32 +++- icinga/services/resilience.conf | 32 +++- icinga/services/stock-alimentaire.conf | 96 +++++++--- lib/life_noc_inputs.py | 18 ++ scripts/generate_services.py | 11 +- scripts/life_noc_input_api.py | 18 ++ 10 files changed, 462 insertions(+), 54 deletions(-) diff --git a/checks/check_life_noc_probe.py b/checks/check_life_noc_probe.py index d4eccf3..a7bc0c7 100755 --- a/checks/check_life_noc_probe.py +++ b/checks/check_life_noc_probe.py @@ -108,6 +108,33 @@ def main() -> int: 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") + else: exit_with(2, f"CRITICAL - probe_type non supporté: {args.probe_type}") diff --git a/domains.yaml b/domains.yaml index d822f92..cb23c21 100644 --- a/domains.yaml +++ b/domains.yaml @@ -1200,6 +1200,24 @@ domains: - name: verification-carburant-generatrice date: 2026-04-01 notes: Vérification de l'approvisionnement propane lié à la génératrice + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/resilience.yaml + item_key: verification-carburant-generatrice + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: verification-procedure-bascule date: 2026-04-15 notes: Réviser la procédure de bascule en mode secours @@ -1225,6 +1243,24 @@ domains: - name: verification-stock-lampes-piles date: 2026-05-01 notes: Vérification des lampes, piles et éclairage d'urgence + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/resilience.yaml + item_key: verification-stock-lampes-piles + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: verification-trousses-urgence date: 2026-05-15 notes: Vérification des trousses d'urgence @@ -1301,21 +1337,129 @@ domains: - name: verification-reserve-eau date: 2026-04-15 notes: Vérification de la réserve d'eau potable + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: verification-reserve-eau + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: verification-mylar-absorbeurs date: 2026-05-01 notes: Vérifier l'intégrité des emballages Mylar et absorbeurs + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: verification-mylar-absorbeurs + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revue-inventaire-conserves date: 2026-04-15 notes: Revue des conserves et dates de rotation + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: revue-inventaire-conserves + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revue-inventaire-farine-riz-pates date: 2026-04-01 notes: Vérification des gros stocks alimentaires de base + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: revue-inventaire-farine-riz-pates + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: verification-bacs-legumes-racines date: 2026-10-01 notes: Vérification des bacs de stockage de légumes racines + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: verification-bacs-legumes-racines + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revue-supplements-vitamines date: 2026-05-01 notes: Vérification du stock de suppléments et dates utiles + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/stock-alimentaire.yaml + item_key: revue-supplements-vitamines + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true sante: - name: verification-trousse-premiers-soins date: 2026-04-01 @@ -1766,9 +1910,45 @@ domains: - name: revision-pharmacopée-jardin date: 2026-05-01 notes: Vérification du stock de soins pour végétaux + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/jardin.yaml + item_key: revision-pharmacopée-jardin + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revision-armoire-produits-jardin date: 2026-05-01 notes: Vérification et ordre de l'armoire des produits pour végétaux + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/jardin.yaml + item_key: revision-armoire-produits-jardin + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true outils-et-equipements: - name: entretien-outils-jardin date: 2026-04-15 @@ -2924,6 +3104,24 @@ domains: - name: verification-reserve-pieces date: 2026-06-01 notes: Vérifier les pièces de rechange critiques + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/actifs-chezlepro.yaml + item_key: verification-reserve-pieces + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revision-actifs-transferts date: 2026-06-15 notes: Réviser les actifs transférés ou à transférer à l'entreprise @@ -3283,9 +3481,45 @@ domains: - name: verification-stock-nourriture-chats date: 2026-04-15 notes: Vérification du stock de nourriture pour chats + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/animaux.yaml + item_key: verification-stock-nourriture-chats + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: verification-friandises-et-litiere date: 2026-04-15 notes: Vérification des stocks de friandises et de litière + probe: + type: remaining_quantity + source: + type: manual_value + inputs_file: /opt/life-noc/data/inputs/animaux.yaml + item_key: verification-friandises-et-litiere + metric: + unit: "%" + thresholds: + ok_gte: 50 + warning_lt: 50 + critical_lt: 25 + policy: + on_error: critical + ui: + form_mode: remaining_quantity + allow_complete: false + allow_manual_edit: true - name: revision-routine-soins-animaux date: 2026-05-01 notes: Revue de la routine de soins et des besoins matériels des chats diff --git a/icinga/services/actifs-chezlepro.conf b/icinga/services/actifs-chezlepro.conf index 43a0f93..70ff99b 100644 --- a/icinga/services/actifs-chezlepro.conf +++ b/icinga/services/actifs-chezlepro.conf @@ -56,11 +56,19 @@ apply Service "actifs-chezlepro-verification-serveurs-et-composants" { } apply Service "actifs-chezlepro-verification-reserve-pieces" { - import "service_echeance" - vars.date_echeance = "2026-06-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/actifs-chezlepro.yaml" + vars.life_noc_item_key = "verification-reserve-pieces" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-reserve-pieces" groups = [ "ACTIFS-CHEZLEPRO" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérifier les pièces de rechange critiques" vars.instructions_url = "/life-noc/item/actifs-chezlepro/verification-reserve-pieces" assign where host.name == "life-noc" diff --git a/icinga/services/animaux.conf b/icinga/services/animaux.conf index 365d8f4..727f5e3 100644 --- a/icinga/services/animaux.conf +++ b/icinga/services/animaux.conf @@ -5,22 +5,38 @@ */ apply Service "animaux-verification-stock-nourriture-chats" { - import "service_echeance" - vars.date_echeance = "2026-04-15" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/animaux.yaml" + vars.life_noc_item_key = "verification-stock-nourriture-chats" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-stock-nourriture-chats" groups = [ "ANIMAUX" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification du stock de nourriture pour chats" vars.instructions_url = "/life-noc/item/animaux/verification-stock-nourriture-chats" assign where host.name == "life-noc" } apply Service "animaux-verification-friandises-et-litiere" { - import "service_echeance" - vars.date_echeance = "2026-04-15" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/animaux.yaml" + vars.life_noc_item_key = "verification-friandises-et-litiere" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-friandises-et-litiere" groups = [ "ANIMAUX" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification des stocks de friandises et de litière" vars.instructions_url = "/life-noc/item/animaux/verification-friandises-et-litiere" assign where host.name == "life-noc" diff --git a/icinga/services/jardin.conf b/icinga/services/jardin.conf index 921ffcf..22b14bb 100644 --- a/icinga/services/jardin.conf +++ b/icinga/services/jardin.conf @@ -165,22 +165,38 @@ apply Service "jardin-entretien-houblon" { } apply Service "jardin-revision-pharmacopée-jardin" { - import "service_echeance" - vars.date_echeance = "2026-05-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/jardin.yaml" + vars.life_noc_item_key = "revision-pharmacopée-jardin" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "revision-pharmacopée-jardin" groups = [ "JARDIN" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification du stock de soins pour végétaux" vars.instructions_url = "/life-noc/item/jardin/revision-pharmacopée-jardin" assign where host.name == "life-noc" } apply Service "jardin-revision-armoire-produits-jardin" { - import "service_echeance" - vars.date_echeance = "2026-05-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/jardin.yaml" + vars.life_noc_item_key = "revision-armoire-produits-jardin" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "revision-armoire-produits-jardin" groups = [ "JARDIN" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification et ordre de l'armoire des produits pour végétaux" vars.instructions_url = "/life-noc/item/jardin/revision-armoire-produits-jardin" assign where host.name == "life-noc" diff --git a/icinga/services/resilience.conf b/icinga/services/resilience.conf index d1f7726..09540d7 100644 --- a/icinga/services/resilience.conf +++ b/icinga/services/resilience.conf @@ -25,11 +25,19 @@ apply Service "resilience-test-generatrice-propane" { } apply Service "resilience-verification-carburant-generatrice" { - import "service_echeance" - vars.date_echeance = "2026-04-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/resilience.yaml" + vars.life_noc_item_key = "verification-carburant-generatrice" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-carburant-generatrice" groups = [ "RESILIENCE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification de l'approvisionnement propane lié à la génératrice" vars.instructions_url = "/life-noc/item/resilience/verification-carburant-generatrice" assign where host.name == "life-noc" @@ -56,11 +64,19 @@ apply Service "resilience-verification-procedure-bascule" { } apply Service "resilience-verification-stock-lampes-piles" { - import "service_echeance" - vars.date_echeance = "2026-05-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/resilience.yaml" + vars.life_noc_item_key = "verification-stock-lampes-piles" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-stock-lampes-piles" groups = [ "RESILIENCE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification des lampes, piles et éclairage d'urgence" vars.instructions_url = "/life-noc/item/resilience/verification-stock-lampes-piles" assign where host.name == "life-noc" diff --git a/icinga/services/stock-alimentaire.conf b/icinga/services/stock-alimentaire.conf index 4c6c937..66fb497 100644 --- a/icinga/services/stock-alimentaire.conf +++ b/icinga/services/stock-alimentaire.conf @@ -25,66 +25,114 @@ apply Service "stock-alimentaire-rotation-nourriture-seche" { } apply Service "stock-alimentaire-verification-reserve-eau" { - import "service_echeance" - vars.date_echeance = "2026-04-15" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "verification-reserve-eau" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-reserve-eau" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification de la réserve d'eau potable" vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-reserve-eau" assign where host.name == "life-noc" } apply Service "stock-alimentaire-verification-mylar-absorbeurs" { - import "service_echeance" - vars.date_echeance = "2026-05-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "verification-mylar-absorbeurs" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-mylar-absorbeurs" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérifier l'intégrité des emballages Mylar et absorbeurs" vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-mylar-absorbeurs" assign where host.name == "life-noc" } apply Service "stock-alimentaire-revue-inventaire-conserves" { - import "service_echeance" - vars.date_echeance = "2026-04-15" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "revue-inventaire-conserves" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "revue-inventaire-conserves" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Revue des conserves et dates de rotation" vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-inventaire-conserves" assign where host.name == "life-noc" } apply Service "stock-alimentaire-revue-inventaire-farine-riz-pates" { - import "service_echeance" - vars.date_echeance = "2026-04-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "revue-inventaire-farine-riz-pates" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "revue-inventaire-farine-riz-pates" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification des gros stocks alimentaires de base" vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-inventaire-farine-riz-pates" assign where host.name == "life-noc" } apply Service "stock-alimentaire-verification-bacs-legumes-racines" { - import "service_echeance" - vars.date_echeance = "2026-10-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "verification-bacs-legumes-racines" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "verification-bacs-legumes-racines" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification des bacs de stockage de légumes racines" vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-bacs-legumes-racines" assign where host.name == "life-noc" } apply Service "stock-alimentaire-revue-supplements-vitamines" { - import "service_echeance" - vars.date_echeance = "2026-05-01" - vars.mock_state = "OK" - vars.mock_message = "Sous contrôle" + import "service_life_noc_probe" + vars.life_noc_probe_type = "remaining_quantity" + vars.life_noc_source_type = "manual_value" + vars.life_noc_source_value = "" + vars.life_noc_inputs_file = "/opt/life-noc/data/inputs/stock-alimentaire.yaml" + vars.life_noc_item_key = "revue-supplements-vitamines" + vars.life_noc_metric_unit = "%" + vars.life_noc_label = "revue-supplements-vitamines" groups = [ "STOCK-ALIMENTAIRE" ] + vars.life_noc_threshold_ok_gte = "50" + vars.life_noc_threshold_warning_lt = "50" + vars.life_noc_threshold_critical_lt = "25" + vars.life_noc_on_error = "critical" notes = "Vérification du stock de suppléments et dates utiles" vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-supplements-vitamines" assign where host.name == "life-noc" diff --git a/lib/life_noc_inputs.py b/lib/life_noc_inputs.py index 10f0e1d..4b5e96e 100644 --- a/lib/life_noc_inputs.py +++ b/lib/life_noc_inputs.py @@ -176,4 +176,22 @@ def compute_state_for_item(domain: str, item_key: str) -> str: return "OK" return "CRITICAL" + if probe_type == "remaining_quantity": + if source_type != "manual_value": + return "CRITICAL" + if metric_unit not in {"%", "units", "litres"}: + return "CRITICAL" + + value = float(str(item.get("value", "")).strip()) + + if "critical_lt" in thresholds and value < float(thresholds["critical_lt"]): + return "CRITICAL" + if "warning_lt" in thresholds and value < float(thresholds["warning_lt"]): + return "WARNING" + if "ok_gte" in thresholds and value >= float(thresholds["ok_gte"]): + return "OK" + if "unknown_gte" in thresholds and value >= float(thresholds["unknown_gte"]): + return "UNKNOWN" + return "CRITICAL" + return "CRITICAL" diff --git a/scripts/generate_services.py b/scripts/generate_services.py index 48de0ec..f59b27a 100644 --- a/scripts/generate_services.py +++ b/scripts/generate_services.py @@ -202,8 +202,8 @@ def validate_probe(item: dict) -> None: raise ValueError("probe doit être un objet") probe_type = str(probe.get("type", "")).strip() - if probe_type not in {"elapsed_time", "days_until_due", "elapsed_distance"}: - raise ValueError("seuls probe.type=elapsed_time, days_until_due et elapsed_distance sont supportés") + if probe_type not in {"elapsed_time", "days_until_due", "elapsed_distance", "remaining_quantity"}: + raise ValueError("seuls probe.type=elapsed_time, days_until_due, elapsed_distance et remaining_quantity sont supportés") source = probe.get("source") if not isinstance(source, dict): @@ -223,6 +223,11 @@ def validate_probe(item: dict) -> None: raise ValueError("seul probe.source.type=manual_counter est supporté pour elapsed_distance") if not has_store_ref: raise ValueError("probe.source.inputs_file + item_key requis pour elapsed_distance") + elif probe_type == "remaining_quantity": + if source_type != "manual_value": + raise ValueError("seul probe.source.type=manual_value est supporté pour remaining_quantity") + if not has_store_ref: + raise ValueError("probe.source.inputs_file + item_key requis pour remaining_quantity") metric = probe.get("metric") if not isinstance(metric, dict): @@ -232,6 +237,8 @@ def validate_probe(item: dict) -> None: raise ValueError("seul probe.metric.unit=days est supporté pour les sondes de date") if probe_type == "elapsed_distance" and metric_unit != "km": raise ValueError("seul probe.metric.unit=km est supporté pour elapsed_distance") + if probe_type == "remaining_quantity" and metric_unit not in {"%", "units", "litres"}: + raise ValueError("probe.metric.unit doit être %, units ou litres pour remaining_quantity") thresholds = probe.get("thresholds") if not isinstance(thresholds, dict): diff --git a/scripts/life_noc_input_api.py b/scripts/life_noc_input_api.py index 76cdfe5..ae8bda8 100644 --- a/scripts/life_noc_input_api.py +++ b/scripts/life_noc_input_api.py @@ -645,6 +645,24 @@ def page_item(domain: str, item_key: str) -> HTMLResponse: """ + elif allow_manual_edit and form_mode == "remaining_quantity": + unit = str(service.get("probe", {}).get("metric", {}).get("unit", "")).strip() + unit_hint = f" ({html_escape(unit)})" if unit else "" + manual_form_html = f""" +
+

Mettre à jour la quantité restante

+

Saisir la quantité actuellement disponible{unit_hint}.

+
+ + +
+ +
+
+
+ """ complete_form_html = "" if allow_complete: