diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 9518e571d65c..c893b7bc7e8f 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -752,6 +752,7 @@ in hitch = handleTest ./hitch { }; hledger-web = runTest ./hledger-web.nix; hockeypuck = runTest ./hockeypuck.nix; + holo-daemon-modular-service = runTest ./holo-daemon-modular.nix; home-assistant = runTest ./home-assistant.nix; homebox = runTest ./homebox.nix; homebridge = runTest ./homebridge.nix; diff --git a/nixos/tests/holo-daemon-modular.nix b/nixos/tests/holo-daemon-modular.nix new file mode 100644 index 000000000000..af32d7e5d472 --- /dev/null +++ b/nixos/tests/holo-daemon-modular.nix @@ -0,0 +1,66 @@ +{ ... }: +{ + _class = "nixosTest"; + name = "holo-daemon-modular-service-test"; + + nodes = { + machine = + { pkgs, ... }: + { + environment.systemPackages = [ + pkgs.holo-daemon + pkgs.holo-cli + ]; + system.services.holo-daemon = { + imports = [ pkgs.holo-daemon.services.default ]; + }; + users.users.holo = { + isSystemUser = true; + group = "holo"; + home = "/var/lib/holo"; + createHome = true; + }; + users.groups.holo = { }; + services.getty.autologinUser = "root"; + }; + }; + + testScript = + { nodes, ... }: + '' + import time + + start_all() + + # holo-cli connects to the daemon at startup + # features a bash-like editing functionality for interactive use + # uses -c option to execute arguments as commands + + machine.wait_for_unit("multi-user.target") + + machine.wait_for_unit("holo-daemon.service") + + machine.succeed("holo-cli -V") + + # wait for cli to connect to the daemon + machine.wait_for_open_port(50051) + + # Test the running configuration is empty + machine.succeed("holo-cli -c 'show running format json'") + + # Configure an OSPFv3 instance: + # as seen in https://asciinema.org/a/qYxmDu1QjGPBAt5gNyNKvXhHk + + machine.send_chars("holo-cli\n", 1) + time.sleep(5) + machine.send_chars("configure\n", 1) + machine.send_chars("routing control-plane-protocols control-plane-protocol ietf-ospf:ospfv3 main\n", 1) + machine.send_chars("ospf preference inter-area 50\n", 1) + machine.send_chars("show changes\n", 1) + machine.send_chars("commit\n", 1) + machine.send_chars("exit\n", 1) + + # Verify the configuration was applied (in interactive test) + machine.succeed("test \"$(holo-cli -c 'show running format json')\" != \"{}\""); + ''; +} diff --git a/pkgs/by-name/ho/holo-daemon/package.nix b/pkgs/by-name/ho/holo-daemon/package.nix index 5889281c5363..6f4338c29970 100644 --- a/pkgs/by-name/ho/holo-daemon/package.nix +++ b/pkgs/by-name/ho/holo-daemon/package.nix @@ -6,6 +6,7 @@ pkg-config, protobuf, pcre2, + pkgs, nix-update-script, }: @@ -20,8 +21,6 @@ rustPlatform.buildRustPackage (finalAttrs: { hash = "sha256-zZrse46NJb8gD4BtM20FfdtRdxVNLZ+/51dy2nuiOd8="; }; - passthru.updateScript = nix-update-script { }; - cargoHash = "sha256-cHJzwI7FDVA1iwqg+x9sMlao22SGQoOuq+MB0XtYsEc="; # Use rust nightly features @@ -36,6 +35,18 @@ rustPlatform.buildRustPackage (finalAttrs: { pcre2 ]; + passthru = { + updateScript = nix-update-script { }; + services.default = { + imports = [ + (lib.modules.importApply ./service.nix { + inherit pkgs; + }) + ]; + holo-daemon.package = lib.mkDefault finalAttrs.finalPackage; + }; + }; + meta = { description = "`holo` daemon that provides the routing protocols, tools and policies"; homepage = "https://github.com/holo-routing/holo"; diff --git a/pkgs/by-name/ho/holo-daemon/service.nix b/pkgs/by-name/ho/holo-daemon/service.nix new file mode 100644 index 000000000000..124a1fa30719 --- /dev/null +++ b/pkgs/by-name/ho/holo-daemon/service.nix @@ -0,0 +1,133 @@ +# Non-module dependencies (`importApply`) +{ pkgs }: + +# Service module +{ + config, + lib, + ... +}: +let + inherit (lib) + mkPackageOption + mkOption + types + ; + cfg = config.holo-daemon; + format = pkgs.formats.toml { }; + configFile = format.generate "holod.toml" cfg.settings; +in +{ + _class = "service"; + + options.holo-daemon = { + package = mkPackageOption pkgs "holo-daemon" { }; + settings = mkOption { + type = types.submodule { + freeformType = format.type; + options = { + user = mkOption { + type = types.str; + description = "User for the holo daemon"; + default = "holo"; + }; + group = mkOption { + type = types.str; + description = "Group for the holo daemon"; + default = "holo"; + }; + # Needs to be writable by @user or @group + database_path = mkOption { + type = types.str; + description = "Path to the holo database"; + default = "/var/run/holod/holod.db"; + }; + logging = mkOption { + type = types.submodule { + freeformType = format.type; + options = { + journald = mkOption { + type = types.submodule { + options = { + enabled = mkOption { + type = types.bool; + description = "Enable or disable journald logging"; + default = true; + }; + }; + }; + description = "Journald logging configuration"; + default = { }; + }; + file = mkOption { + type = types.submodule { + options = { + enabled = mkOption { + type = types.bool; + description = "Enable or disable file logging"; + default = true; + }; + dir = mkOption { + type = types.str; + description = "Directory for log files"; + default = "/var/log/"; + }; + name = mkOption { + type = types.str; + description = "Name of the log file"; + default = "holod.log"; + }; + }; + }; + description = "File logging configuration"; + default = { }; + }; + }; + }; + description = "Logging configuration for the holo daemon"; + default = { }; + }; + plugins = mkOption { + type = types.submodule { + freeformType = format.type; + options = { + grpc = mkOption { + type = types.submodule { + options = { + enabled = mkOption { + type = types.bool; + description = "Enable or disable gRPC plugin"; + default = true; + }; + address = mkOption { + type = types.str; + description = "gRPC server listening address"; + default = "[::]:50051"; + }; + }; + }; + description = "gRPC plugin configuration"; + default = { }; + }; + }; + }; + description = "Plugin configuration for the holo daemon"; + default = { }; + }; + }; + }; + description = "Configuration for the holo daemon"; + default = { }; + }; + }; + + config = { + process.argv = [ + "${cfg.package}/bin/holod" + "-c" + configFile + ]; + }; + + meta.maintainers = with lib.maintainers; [ themadbit ]; +}