nixos/influxdb2: add initial setup automation and nixos tests

This commit is contained in:
oddlama 2023-08-15 00:26:41 +02:00
parent fd91dcf310
commit b4d718f14a
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
4 changed files with 157 additions and 7 deletions

View file

@ -1,8 +1,17 @@
{ config, lib, pkgs, ... }:
with lib;
let
inherit
(lib)
escapeShellArg
hasAttr
literalExpression
mkEnableOption
mkIf
mkOption
types
;
format = pkgs.formats.json { };
cfg = config.services.influxdb2;
configFile = format.generate "config.json" cfg.settings;
@ -24,14 +33,60 @@ in
description = lib.mdDoc ''configuration options for influxdb2, see <https://docs.influxdata.com/influxdb/v2.0/reference/config-options> for details.'';
type = format.type;
};
provision = {
enable = mkEnableOption "initial database setup and provisioning";
initialSetup = {
organization = mkOption {
type = types.str;
example = "main";
description = "Primary organization name";
};
bucket = mkOption {
type = types.str;
example = "example";
description = "Primary bucket name";
};
username = mkOption {
type = types.str;
default = "admin";
description = "Primary username";
};
retention = mkOption {
type = types.str;
default = "0";
description = ''
The duration for which the bucket will retain data (0 is infinite).
Accepted units are `ns` (nanoseconds), `us` or `µs` (microseconds), `ms` (milliseconds),
`s` (seconds), `m` (minutes), `h` (hours), `d` (days) and `w` (weeks).
'';
};
passwordFile = mkOption {
type = types.path;
description = "Password for primary user. Don't use a file from the nix store!";
};
tokenFile = mkOption {
type = types.path;
description = "API Token to set for the admin user. Don't use a file from the nix store!";
};
};
};
};
};
config = mkIf cfg.enable {
assertions = [{
assertion = !(builtins.hasAttr "bolt-path" cfg.settings) && !(builtins.hasAttr "engine-path" cfg.settings);
message = "services.influxdb2.config: bolt-path and engine-path should not be set as they are managed by systemd";
}];
assertions = [
{
assertion = !(hasAttr "bolt-path" cfg.settings) && !(hasAttr "engine-path" cfg.settings);
message = "services.influxdb2.config: bolt-path and engine-path should not be set as they are managed by systemd";
}
];
systemd.services.influxdb2 = {
description = "InfluxDB is an open-source, distributed, time series database";
@ -52,7 +107,62 @@ in
LimitNOFILE = 65536;
KillMode = "control-group";
Restart = "on-failure";
LoadCredential = [
"admin-password:${cfg.provision.initialSetup.passwordFile}"
"admin-token:${cfg.provision.initialSetup.tokenFile}"
];
};
path = [pkgs.influxdb2-cli];
# Mark if this is the first startup so postStart can do the initial setup
preStart = mkIf cfg.provision.enable ''
if ! test -e "$STATE_DIRECTORY/influxd.bolt"; then
touch "$STATE_DIRECTORY/.first_startup"
fi
'';
postStart = let
initCfg = cfg.provision.initialSetup;
in mkIf cfg.provision.enable (
''
set -euo pipefail
export INFLUX_HOST="http://"${escapeShellArg (cfg.settings.http-bind-address or "localhost:8086")}
# Wait for the influxdb server to come online
count=0
while ! influx ping &>/dev/null; do
if [ "$count" -eq 300 ]; then
echo "Tried for 30 seconds, giving up..."
exit 1
fi
if ! kill -0 "$MAINPID"; then
echo "Main server died, giving up..."
exit 1
fi
sleep 0.1
count=$((count++))
done
# Do the initial database setup. Pass /dev/null as configs-path to
# avoid saving the token as the active config.
if test -e "$STATE_DIRECTORY/.first_startup"; then
influx setup \
--configs-path /dev/null \
--org ${escapeShellArg initCfg.organization} \
--bucket ${escapeShellArg initCfg.bucket} \
--username ${escapeShellArg initCfg.username} \
--password "$(< "$CREDENTIALS_DIRECTORY/admin-password")" \
--token "$(< "$CREDENTIALS_DIRECTORY/admin-token")" \
--retention ${escapeShellArg initCfg.retention} \
--force >/dev/null
rm -f "$STATE_DIRECTORY/.first_startup"
fi
''
);
};
users.extraUsers.influxdb2 = {
@ -63,5 +173,5 @@ in
users.extraGroups.influxdb2 = {};
};
meta.maintainers = with lib.maintainers; [ nickcao ];
meta.maintainers = with lib.maintainers; [ nickcao oddlama ];
}

View file

@ -367,6 +367,7 @@ in {
iftop = handleTest ./iftop.nix {};
incron = handleTest ./incron.nix {};
influxdb = handleTest ./influxdb.nix {};
influxdb2 = handleTest ./influxdb2.nix {};
initrd-network-openvpn = handleTest ./initrd-network-openvpn {};
initrd-network-ssh = handleTest ./initrd-network-ssh {};
initrd-luks-empty-passphrase = handleTest ./initrd-luks-empty-passphrase.nix {};

36
nixos/tests/influxdb2.nix Normal file
View file

@ -0,0 +1,36 @@
import ./make-test-python.nix ({ pkgs, ...} : {
name = "influxdb2";
meta = with pkgs.lib.maintainers; {
maintainers = [ offline ];
};
nodes.machine = { lib, ... }: {
environment.systemPackages = [ pkgs.influxdb2-cli ];
services.influxdb2.enable = true;
services.influxdb2.provision = {
enable = true;
initialSetup = {
organization = "default";
bucket = "default";
passwordFile = pkgs.writeText "admin-pw" "ExAmPl3PA55W0rD";
tokenFile = pkgs.writeText "admin-token" "verysecureadmintoken";
};
};
};
testScript = { nodes, ... }:
let
tokenArg = "--token verysecureadmintoken";
in ''
machine.wait_for_unit("influxdb2.service")
machine.fail("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:wrongpassword")
machine.succeed("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:ExAmPl3PA55W0rD")
out = machine.succeed("influx org list ${tokenArg}")
assert "default" in out
out = machine.succeed("influx bucket list ${tokenArg} --org default")
assert "default" in out
'';
})

View file

@ -8,6 +8,7 @@
, rustPlatform
, stdenv
, libiconv
, nixosTests
}:
let
@ -107,6 +108,8 @@ in buildGoModule {
ldflags = [ "-X main.commit=v${version}" "-X main.version=${version}" ];
passthru.tests = { inherit (nixosTests) influxdb2; };
meta = with lib; {
description = "An open-source distributed time series database";
license = licenses.mit;