summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix62
-rw-r--r--nixos/tests/prometheus-exporters.nix15
3 files changed, 78 insertions, 0 deletions
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index 995afca96ff..1f8c5aeded1 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -41,6 +41,7 @@ let
     "openvpn"
     "postfix"
     "postgres"
+    "py-air-control"
     "redis"
     "rspamd"
     "rtl_433"
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix
new file mode 100644
index 00000000000..d9a627ca2ea
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix
@@ -0,0 +1,62 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus.exporters.py-air-control;
+
+  py-air-control-exporter-env = pkgs.python3.withPackages (pyPkgs: [
+      pyPkgs.py-air-control-exporter
+  ]);
+
+  workingDir = "/var/lib/${cfg.stateDir}";
+
+in
+{
+  port = 9896;
+  extraOpts = {
+    deviceHostname = mkOption {
+      type = types.str;
+      example = "192.168.1.123";
+      description = ''
+        The hostname of the air purification device from which to scrape the metrics.
+      '';
+    };
+    protocol = mkOption {
+      type = types.str;
+      default = "http";
+      description = ''
+        The protocol to use when communicating with the air purification device.
+        Available: [http, coap, plain_coap]
+      '';
+    };
+    stateDir = mkOption {
+      type = types.str;
+      default = "prometheus-py-air-control-exporter";
+      description = ''
+        Directory below <literal>/var/lib</literal> to store runtime data.
+        This directory will be created automatically using systemd's StateDirectory mechanism.
+      '';
+    };
+  };
+  serviceOpts = {
+    serviceConfig = {
+      DynamicUser = false;
+      StateDirectory = cfg.stateDir;
+      WorkingDirectory = workingDir;
+      ExecStart = ''
+        ${py-air-control-exporter-env}/bin/python -c \
+          "from py_air_control_exporter import app; app.create_app().run( \
+              debug=False, \
+              port=${toString cfg.port}, \
+              host='${cfg.listenAddress}', \
+          )"
+      '';
+      Environment = [
+        "PY_AIR_CONTROL_HOST=${cfg.deviceHostname}"
+        "PY_AIR_CONTROL_PROTOCOL=${cfg.protocol}"
+        "HOME=${workingDir}"
+      ];
+    };
+  };
+}
diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix
index 0b9957404f3..3eb4341e39c 100644
--- a/nixos/tests/prometheus-exporters.nix
+++ b/nixos/tests/prometheus-exporters.nix
@@ -530,6 +530,21 @@ let
       '';
     };
 
+    py-air-control = {
+      nodeName = "py_air_control";
+      exporterConfig = {
+        enable = true;
+        deviceHostname = "127.0.0.1";
+      };
+      exporterTest = ''
+        wait_for_unit("prometheus-py-air-control-exporter.service")
+        wait_for_open_port(9896)
+        succeed(
+            "curl -sSf http://localhost:9896/metrics | grep -q 'py_air_control_sampling_error_total'"
+        )
+      '';
+    };
+
     redis = {
       exporterConfig = {
         enable = true;