nixos/tests/prometheus-exporters: migrate to nspawn (#531599)

This commit is contained in:
Martin Weinelt
2026-06-14 13:12:56 +00:00
committed by GitHub
8 changed files with 25 additions and 181 deletions
@@ -114,7 +114,6 @@ let
"restic"
"rtl_433"
"sabnzbd"
"scaphandre"
"script"
"shelly"
"smartctl"
@@ -521,26 +520,6 @@ in
'services.prometheus.exporters.sql.configFile'
'';
}
{
assertion = cfg.scaphandre.enable -> (pkgs.stdenv.targetPlatform.isx86_64 == true);
message = ''
Scaphandre only support x86_64 architectures.
'';
}
{
assertion =
cfg.scaphandre.enable
-> ((lib.kernel.whenHelpers pkgs.linux.version).whenOlder "5.11" true).condition == false;
message = ''
Scaphandre requires a kernel version newer than '5.11', '${pkgs.linux.version}' given.
'';
}
{
assertion = cfg.scaphandre.enable -> (builtins.elem "intel_rapl_common" config.boot.kernelModules);
message = ''
Scaphandre needs 'intel_rapl_common' kernel module to be enabled. Please add it in 'boot.kernelModules'.
'';
}
{
assertion =
cfg.idrac.enable -> ((cfg.idrac.configurationPath == null) != (cfg.idrac.configuration == null));
@@ -1,36 +0,0 @@
{
config,
lib,
pkgs,
options,
...
}:
let
logPrefix = "services.prometheus.exporter.scaphandre";
cfg = config.services.prometheus.exporters.scaphandre;
in
{
port = 8080;
extraOpts = {
telemetryPath = lib.mkOption {
type = lib.types.str;
default = "/metrics";
description = ''
Path under which to expose metrics.
'';
};
};
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.scaphandre}/bin/scaphandre prometheus \
--address ${cfg.listenAddress} \
--port ${toString cfg.port} \
--suffix ${cfg.telemetryPath} \
${lib.concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}
-1
View File
@@ -1491,7 +1491,6 @@ in
sanoid = runTest ./sanoid.nix;
saunafs = runTest ./saunafs.nix;
scanservjs = runTest ./scanservjs.nix;
scaphandre = runTest ./scaphandre.nix;
schleuder = runTest ./schleuder.nix;
scion-freestanding-deployment = runTest ./scion/freestanding-deployment;
scrutiny = runTest ./scrutiny.nix;
+22 -26
View File
@@ -21,6 +21,9 @@ let
* `nodeName` (optional)
* override an incompatible testnode name
*
* `testBackend` (optional)
* whether to run in `containers` (default) or `nodes` scope
*
* Example:
* exporterTests.<exporterName> = {
* exporterConfig = {
@@ -168,6 +171,7 @@ let
blackbox =
{ pkgs, ... }:
{
testBackend = "nodes";
exporterConfig = {
enable = true;
configFile = pkgs.writeText "config.yml" (
@@ -373,16 +377,23 @@ let
};
dovecot =
{ ... }:
{ pkgs, ... }:
{
testBackend = "nodes";
exporterConfig = {
enable = true;
scopes = [ "global" ];
socketPath = "/var/run/dovecot2/old-stats";
socketPath = "/var/run/dovecot2/stats-reader";
user = "root"; # <- don't use user root in production
};
metricProvider = {
services.dovecot2.enable = true;
services.dovecot2 = {
enable = true;
settings = {
dovecot_config_version = pkgs.dovecot.version;
dovecot_storage_version = pkgs.dovecot.version;
};
};
};
exporterTest = ''
wait_for_unit("prometheus-dovecot-exporter.service")
@@ -423,6 +434,7 @@ let
ebpf =
{ ... }:
{
testBackend = "nodes";
exporterConfig = {
enable = true;
names = [ "timers" ];
@@ -447,7 +459,6 @@ let
# `services.elasticsearch` is unmaintained; OpenSearch is the same
# engine class and is explicitly supported by the exporter.
services.opensearch.enable = true;
virtualisation.memorySize = 2048;
};
exporterTest = ''
wait_for_unit("opensearch.service")
@@ -463,6 +474,7 @@ let
fail2ban =
{ ... }:
{
testBackend = "nodes"; # setfacl
exporterConfig = {
enable = true;
exitOnError = true;
@@ -964,6 +976,7 @@ let
modemmanager =
{ ... }:
{
testBackend = "nodes";
exporterConfig = {
enable = true;
refreshRate = "10s";
@@ -1099,7 +1112,7 @@ let
wait_for_unit("nginx.service")
wait_for_unit("prometheus-nextcloud-exporter.service")
wait_for_open_port(9205)
succeed("curl -sSf http://localhost:9205/metrics | grep 'nextcloud_up 1'")
wait_until_succeeds("curl -sSf http://localhost:9205/metrics | grep 'nextcloud_up 1'")
'';
};
@@ -1658,24 +1671,6 @@ let
'';
};
scaphandre =
{ ... }:
{
exporterConfig = {
enable = true;
};
metricProvider = {
boot.kernelModules = [ "intel_rapl_common" ];
};
exporterTest = ''
wait_for_unit("prometheus-scaphandre-exporter.service")
wait_for_open_port(8080)
wait_until_succeeds(
"curl -sSf 'localhost:8080/metrics'"
)
'';
};
shelly =
{ pkgs, ... }:
{
@@ -2143,6 +2138,7 @@ let
zfs =
{ ... }:
{
testBackend = "nodes"; # zfs kmod
exporterConfig = {
enable = true;
};
@@ -2165,13 +2161,14 @@ lib.mapAttrs (
{ pkgs, lib, ... }:
let
testConfig = testConfigFun { inherit pkgs lib; };
nodeName = testConfig.nodeName or exporter;
testBackend = testConfig.testBackend or "containers";
nodeName = "machine";
in
{
name = "prometheus-${exporter}-exporter";
node.pkgsReadOnly = testConfig.pkgsReadOnly or true;
nodes.${nodeName} = lib.mkMerge [
${testBackend}.${nodeName} = lib.mkMerge [
{
services.prometheus.exporters.${exporter} = testConfig.exporterConfig;
}
@@ -2196,7 +2193,6 @@ lib.mapAttrs (
"${nodeName}.${line}"
) (lib.splitString "\n" (lib.removeSuffix "\n" testConfig.exporterTest))
)}
${nodeName}.shutdown()
'';
meta.maintainers = [ ];
-18
View File
@@ -1,18 +0,0 @@
{
name = "scaphandre";
nodes.scaphandre =
{ pkgs, ... }:
{
boot.kernelModules = [ "intel_rapl_common" ];
environment.systemPackages = [ pkgs.scaphandre ];
};
testScript = ''
scaphandre.start()
scaphandre.wait_until_succeeds(
"scaphandre stdout -t 4",
)
'';
}
@@ -23,6 +23,8 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
prometheus-client
];
pythonRelaxDeps = [ "prometheus-client" ];
nativeCheckInputs = with python3.pkgs; [
pytest-mock
pytestCheckHook
-79
View File
@@ -1,79 +0,0 @@
{
lib,
rustPlatform,
fetchFromGitHub,
pkg-config,
openssl,
nix-update-script,
runCommand,
dieHook,
nixosTests,
testers,
scaphandre,
}:
rustPlatform.buildRustPackage rec {
pname = "scaphandre";
version = "1.0.2";
src = fetchFromGitHub {
owner = "hubblo-org";
repo = "scaphandre";
rev = "v${version}";
hash = "sha256-I+cECdpLoIj4yuWXfirwHlcn0Hkm9NxPqo/EqFiBObw=";
};
cargoHash = "sha256-OIoQ2r/T0ZglF1pe25ND8xe/BEWgP9JbWytJp4k7yyg=";
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl ];
checkPhase = ''
runHook preCheck
# Work around to pass test due to non existing path
# https://github.com/hubblo-org/scaphandre/blob/v1.0.2/src/sensors/powercap_rapl.rs#L29
export SCAPHANDRE_POWERCAP_PATH="$(mktemp -d)/scaphandre"
mkdir -p "$SCAPHANDRE_POWERCAP_PATH"
runHook postCheck
'';
passthru = {
updateScript = nix-update-script { };
tests = {
stdout =
self:
runCommand "${pname}-test"
{
buildInputs = [
self
dieHook
];
}
''
${self}/bin/scaphandre stdout -t 4 > $out || die "Scaphandre failed to measure consumption"
[ -s $out ]
'';
vm = nixosTests.scaphandre;
version = testers.testVersion {
inherit version;
package = scaphandre;
command = "scaphandre --version";
};
};
};
meta = {
description = "Electrical power consumption metrology agent";
homepage = "https://github.com/hubblo-org/scaphandre";
license = lib.licenses.asl20;
platforms = [ "x86_64-linux" ];
maintainers = [ ];
mainProgram = "scaphandre";
# Upstream needs to decide what to do about a broken dependency
# https://github.com/hubblo-org/scaphandre/issues/403
broken = true;
};
}
+1
View File
@@ -1955,6 +1955,7 @@ mapAliases {
ryujinx = throw "'ryujinx' has been replaced by 'ryubing' as the new upstream"; # Added 2025-07-30
ryujinx-greemdev = throw "'ryujinx-greemdev' has been renamed to/replaced by 'ryubing'"; # Converted to throw 2025-10-27
scantailor = throw "'scantailor' has been renamed to/replaced by 'scantailor-advanced'"; # Converted to throw 2025-10-27
scaphandra = throw "'scaphandra' was broken with no upstream progress since February 2025"; # Added 2026-06-14
scitoken-cpp = throw "'scitoken-cpp' has been renamed to/replaced by 'scitokens-cpp'"; # Converted to throw 2025-10-27
scudcloud = throw "'scudcloud' has been removed as it was archived by upstream"; # Added 2025-07-24
SDL2_classic = throw "'SDL2_classic' has been removed. Consider upgrading to 'sdl2-compat', also available as 'SDL2'."; # Added 2025-05-20