diff --git a/packages/checks/ascensions.nix b/packages/checks/ascensions.nix new file mode 100644 index 0000000..6e04906 --- /dev/null +++ b/packages/checks/ascensions.nix @@ -0,0 +1,113 @@ +{ nixosTest, nixosModules }: + +let + dataDir = { + node1 = "/data/before"; + node2 = "/data/nested/after"; + }; + kvPath = { + node1 = "before"; + node2 = "after"; + }; + addr = { + consul = "10.0.0.10"; + node1 = "10.0.0.1"; + node2 = "10.0.0.2"; + }; +in + +nixosTest { + name = "ascensions"; + nodes = let + network = { config, lib, ... }: { + networking.interfaces.eth1.ipv4.addresses = lib.mkForce [ + { + address = addr.${config.networking.hostName}; + prefixLength = 24; + } + ]; + }; + common = { config, lib, ... }: let + inherit (config.networking) hostName; + in { + imports = [ + nixosModules.ascensions + nixosModules.systemd-extras + nixosModules.consul-distributed-services + ]; + systemd.services = { + create-file = { + serviceConfig.Type = "oneshot"; + script = '' + if ! test -e ${dataDir.${hostName}}/file.txt; then + mkdir -p ${dataDir.${hostName}} + echo "${hostName}" > ${dataDir.${hostName}}/file.txt + fi + ''; + }; + create-kv = { + serviceConfig.Type = "oneshot"; + path = [ config.services.consul.package ]; + script = '' + if ! consul kv get ${kvPath.${hostName}}; then + consul kv put ${kvPath.${hostName}} ${hostName} + fi + ''; + environment.CONSUL_HTTP_ADDR = "${addr.consul}:8500"; + }; + ascend-create-kv = { + environment.CONSUL_HTTP_ADDR = "${addr.consul}:8500"; + }; + }; + system.ascensions = { + create-file = { + before = [ "create-file.service" ]; + incantations = m: with m; lib.optionals (hostName == "node2") [ + (move dataDir.node1 dataDir.node2) + ]; + }; + create-kv = { + distributed = true; + before = [ "create-kv.service" ]; + incantations = m: with m; lib.optionals (hostName == "node2") [ + (execShellWith [ config.services.consul.package ] '' + consul kv put ${kvPath.node2} $(consul kv get ${kvPath.node1}) + consul kv delete ${kvPath.node1} + '') + ]; + }; + }; + }; + in { + consul = { + imports = [ network ]; + networking.firewall.allowedTCPPorts = [ 8500 ]; + services.consul = { + enable = true; + extraConfig = { + addresses.http = addr.consul; + bind_addr = addr.consul; + server = true; + bootstrap_expect = 1; + }; + }; + }; + node1.imports = [ network common ]; + node2.imports = [ network common ]; + }; + testScript = /*python*/ '' + start_all() + consul.wait_for_unit("consul.service") + consul.wait_until_succeeds("CONSUL_HTTP_ADDR=${addr.consul}:8500 consul members") + node1.wait_for_unit("multi-user.target") + node1.succeed("systemctl start create-file create-kv") + node1.succeed("tar cvf /tmp/shared/data.tar /data /var/lib/ascensions") + + node2.wait_for_unit("multi-user.target") + node2.succeed("tar xvf /tmp/shared/data.tar -C /") + node2.succeed("systemctl start create-file create-kv") + + assert "node1" in node2.succeed("cat ${dataDir.node2}/file.txt") + assert "node1" in consul.succeed("CONSUL_HTTP_ADDR=${addr.consul}:8500 consul kv get ${kvPath.node2}") + ''; +} diff --git a/packages/checks/default.nix b/packages/checks/default.nix index b51b4c7..ffb02d6 100644 --- a/packages/checks/default.nix +++ b/packages/checks/default.nix @@ -3,6 +3,10 @@ { perSystem = { filters, pkgs, self', ... }: { checks = filters.doFilter filters.checks { + ascensions = pkgs.callPackage ./ascensions.nix { + inherit (self) nixosModules; + }; + jellyfin-stateless = pkgs.callPackage ./jellyfin-stateless.nix { inherit (self'.packages) jellyfin; inherit (config) cluster; diff --git a/packages/system-filter.nix b/packages/system-filter.nix index f2f0f82..f66cffb 100644 --- a/packages/system-filter.nix +++ b/packages/system-filter.nix @@ -12,6 +12,7 @@ tempo = [ "x86_64-linux" ]; }; checks = { + ascensions = [ "x86_64-linux" ]; jellyfin-stateless = [ "x86_64-linux" ]; keycloak = [ "x86_64-linux" ]; patroni = [ "x86_64-linux" ];