From 4e42d4fb9e3f9de7a4fec9052725f8e2820f25d3 Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 30 Jul 2026 16:53:34 +0200 Subject: [PATCH 01/14] feat: adds local vm setup that can reach each other --- Makefile | 35 +++++++ flake.lock | 60 +++++++++++ flake.nix | 76 ++++++++++---- nix/hosts/client/configuration.nix | 162 +++++++++++++++++++++++++++++ nix/hosts/client/home.nix | 41 ++++++++ nix/hosts/server/configuration.nix | 116 +++++++++++++++++++++ 6 files changed, 470 insertions(+), 20 deletions(-) create mode 100644 nix/hosts/client/configuration.nix create mode 100644 nix/hosts/client/home.nix create mode 100644 nix/hosts/server/configuration.nix diff --git a/Makefile b/Makefile index b46181de..022918e4 100644 --- a/Makefile +++ b/Makefile @@ -84,3 +84,38 @@ build-mo: release: @goreleaser release --clean + +CLIENT_VM := abra-client +vm-client-status: + sudo systemctl status microvm@$(CLIENT_VM).service +vm-client-create: + sudo microvm -f git+file://$$(pwd) -c $(CLIENT_VM) +vm-client-start: + sudo systemctl start microvm@$(CLIENT_VM).service +vm-client-update: + sudo microvm -R -f git+file://$$(pwd) -u $(CLIENT_VM) +vm-client-run: + sudo microvm -f git+file://$$(pwd) -r $(CLIENT_VM) +vm-client-stop: + sudo systemctl stop microvm@$(CLIENT_VM) +vm-client-delete: vm-client-stop + sudo rm -rf /var/lib/microvms/$(CLIENT_VM) + +SERVER_VM := abra-server +vm-server-status: + sudo systemctl status microvm@$(SERVER_VM).service +vm-server-create: + sudo microvm -f git+file://$$(pwd) -c $(SERVER_VM) +vm-server-start: + sudo systemctl start microvm@$(SERVER_VM).service +vm-server-update: + sudo microvm -R -f git+file://$$(pwd) -u $(SERVER_VM) +vm-server-run: + sudo microvm -f git+file://$$(pwd) -r $(SERVER_VM) +vm-server-stop: + sudo systemctl stop microvm@$(SERVER_VM) +vm-server-delete: vm-stop + sudo rm -rf /var/lib/microvms/$(SERVER_VM) + +test-integration: + ssh-keygen -t ed25519 -f ./test-integration -q -N "" -C "abra integration test" diff --git a/flake.lock b/flake.lock index 9448fe0f..57e2bd06 100644 --- a/flake.lock +++ b/flake.lock @@ -18,6 +18,48 @@ "type": "github" } }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1785119570, + "narHash": "sha256-Rgs2xKnGLFWQscxUaXX07oyZeuMDOHEbqDOsgliLFGM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "d4fd24667c8cbef124bb70a20380cab75ec8474d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-26.05", + "repo": "home-manager", + "type": "github" + } + }, + "microvm": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, + "locked": { + "lastModified": 1784666190, + "narHash": "sha256-xgfS6slV7J3baMooNN1UuBi51RIgg9y0DbCxfSA0668=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "fa5340ac684cdce8a22b6d4a0bcebb0cc999275e", + "type": "github" + }, + "original": { + "owner": "astro", + "repo": "microvm.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1778443072, @@ -37,9 +79,27 @@ "root": { "inputs": { "flake-utils": "flake-utils", + "home-manager": "home-manager", + "microvm": "microvm", "nixpkgs": "nixpkgs" } }, + "spectrum": { + "flake": false, + "locked": { + "lastModified": 1783694892, + "narHash": "sha256-xO8f7Qng+18FK2UlB9vcrkxCaQMCt5WjCH24aW/11eg=", + "ref": "refs/heads/main", + "rev": "24c4346e30fdea8d8e80f34aec3554a15a667d24", + "revCount": 1410, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + }, + "original": { + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index fdc35b22..878081c8 100644 --- a/flake.nix +++ b/flake.nix @@ -3,35 +3,71 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager/release-26.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; flake-utils.url = "github:numtide/flake-utils"; + microvm = { + url = "github:astro/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { self, nixpkgs, + microvm, + home-manager, flake-utils, }: - flake-utils.lib.eachDefaultSystem ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in - { - packages = rec { - abra = pkgs.callPackage ./package.nix { }; - default = abra; - }; - apps = rec { - abra = flake-utils.lib.mkApp { drv = self.packages.${system}.abra; }; - default = abra; - }; - devShells.default = pkgs.mkShell { - packages = with pkgs; [ - go_1_26 - gnumake + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + publicKey = builtins.readFile ./test-integration.pub; + privateKey = builtins.readFile ./test-integration; + in + { + nixosConfigurations = { + abra-client = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + microvm.nixosModules.microvm + home-manager.nixosModules.home-manager + ./nix/hosts/client/configuration.nix ]; + specialArgs = { inherit publicKey privateKey; }; }; - } - ); + abra-server = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + microvm.nixosModules.microvm + ./nix/hosts/server/configuration.nix + ]; + specialArgs = { inherit publicKey privateKey; }; + }; + }; + packages = rec { + abra = pkgs.callPackage ./package.nix { }; + default = abra; + }; + apps = rec { + abra = flake-utils.lib.mkApp { drv = self.packages.${system}.abra; }; + default = abra; + }; + devShells.${system}.default = pkgs.mkShell { + # testing env variables + BATS_LIB_PATH = "~/.local/share/bats/"; + TEST_SERVER = "abra.local"; + ABRA_DIR = "$HOME/.abra_test"; + + packages = with pkgs; [ + go_1_26 + gnumake + gopls + ]; + }; + + }; } diff --git a/nix/hosts/client/configuration.nix b/nix/hosts/client/configuration.nix new file mode 100644 index 00000000..ccccd999 --- /dev/null +++ b/nix/hosts/client/configuration.nix @@ -0,0 +1,162 @@ +{ + lib, + pkgs, + publicKey, + privateKey, + ... +}: +let + index = 2; + mac = "00:00:00:00:00:01"; + serverIp = "10.0.0.3"; +in +{ + microvm = { + vcpu = 4; + mem = 2049; # see issue related in microvm repo with 2048, so add 1MB + interfaces = [ + { + id = "vm${toString index}"; + type = "tap"; + inherit mac; + } + ]; + shares = [ + { + proto = "virtiofs"; + tag = "repo"; + # Source path can be absolute or relative + # to /var/lib/microvms/$hostName + source = "/home/dev/Documents/abra"; + mountPoint = "/home/dev/abra"; + } + ]; + }; + + boot.tmp = { + useTmpfs = true; + tmpfsSize = "2G"; + }; + + networking = { + hostName = "abra-client"; + useNetworkd = true; + }; + systemd.network.networks."10-eth" = { + matchConfig.MACAddress = mac; + # Static IP configuration + address = [ + "10.0.0.${toString index}/32" + "fec0::${lib.toHexString index}/128" + ]; + routes = [ + { + # A route to the host + Destination = "10.0.0.0/32"; + GatewayOnLink = true; + } + { + # Route to server + Destination = "${serverIp}/32"; + Gateway = "10.0.0.0"; + GatewayOnLink = true; + } + { + # Default route + Destination = "0.0.0.0/0"; + Gateway = "10.0.0.0"; + GatewayOnLink = true; + } + { + # Default route + Destination = "::/0"; + Gateway = "fec0::"; + GatewayOnLink = true; + } + ]; + networkConfig = { + # DNS servers no longer come from DHCP nor Router + # Advertisements. Perhaps you want to change the defaults: + DNS = [ + # Quad9.net + "9.9.9.9" + "149.112.112.112" + "2620:fe::fe" + "2620:fe::9" + ]; + }; + }; + + # open the ports to allow ssh access from the host + networking.firewall.allowedTCPPorts = [ 22 ]; + networking.firewall.allowedUDPPorts = [ 22 ]; + + networking.extraHosts = '' + ${serverIp} abra.local + ${serverIp} app_check_bats.abra.local + ''; + + environment.variables = { + CGO_ENABLED = 0; + TEST_SERVER = "abra.local"; + ABRA_DIR = "$HOME/.abra_test"; + }; + + users.users.dev = { + isNormalUser = true; + password = "test"; + home = "/home/dev"; + description = "Alice Foobar"; + extraGroups = [ + "wheel" + "networkmanager" + ]; + openssh.authorizedKeys.keys = [ + publicKey + ]; + }; + # ssh agent with askpass + programs.ssh = { + startAgent = true; + }; + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; + AllowUsers = [ "dev" ]; + }; + }; + programs.git.enable = true; + + environment.systemPackages = with pkgs; [ + # build dependencies, copied from flake.nix + go_1_26 + gnumake + # testing dependencies + (bats.withLibraries (p: [ + p.bats-assert + p.bats-file + p.bats-support + ])) + jq + ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users.dev = + { ... }: + { + imports = [ + ./home.nix + ]; + }; + # pass args to home-manager + extraSpecialArgs = { + publicKey = publicKey; + privateKey = privateKey; + serverIp = serverIp; + }; + }; +} diff --git a/nix/hosts/client/home.nix b/nix/hosts/client/home.nix new file mode 100644 index 00000000..905a22f8 --- /dev/null +++ b/nix/hosts/client/home.nix @@ -0,0 +1,41 @@ +{ + serverIp, + ... +}: +{ + # Home Manager needs a bit of information about you and the + # paths it should manage. + home.username = "dev"; + home.homeDirectory = "/home/dev"; + + # This value determines the Home Manager release that your + # configuration is compatible with. This helps avoid breakage + # when a new Home Manager release introduces backwards + # incompatible changes. + # + # You can update Home Manager without changing this value. See + # the Home Manager release notes for a list of state version + # changes in each release. + home.stateVersion = "26.05"; + + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; + programs.ssh = { + enable = true; + enableDefaultConfig = false; + settings = { + "abra.local" = { + HostName = serverIp; + User = "dev"; + Port = 22; + IdentityFile = "/home/dev/abra/test-integration"; + }; + "*.abra.local" = { + HostName = serverIp; + User = "dev"; + Port = 22; + IdentityFile = "/home/dev/abra/test-integration"; + }; + }; + }; +} diff --git a/nix/hosts/server/configuration.nix b/nix/hosts/server/configuration.nix new file mode 100644 index 00000000..e4a739fb --- /dev/null +++ b/nix/hosts/server/configuration.nix @@ -0,0 +1,116 @@ +{ + lib, + publicKey, + ... +}: +let + index = 3; + mac = "00:00:00:00:00:02"; + clientIp = "10.0.0.2"; +in +{ + microvm = { + vcpu = 2; + mem = 2049; # see issue related in microvm repo with 2048, so add 1MB + interfaces = [ + { + id = "vm${toString index}"; + type = "tap"; + inherit mac; + } + ]; + }; + + boot.tmp = { + useTmpfs = true; + tmpfsSize = "2G"; + }; + + networking = { + hostName = "abra-server"; + useNetworkd = true; + }; + systemd.network.networks."11-eth" = { + matchConfig.MACAddress = mac; + # Static IP configuration + address = [ + "10.0.0.${toString index}/32" + "fec0::${lib.toHexString index}/128" + ]; + routes = [ + { + # A route to the host + Destination = "10.0.0.0/32"; + GatewayOnLink = true; + } + { + # Route to server + Destination = "${clientIp}/32"; + Gateway = "10.0.0.0"; + GatewayOnLink = true; + } + { + # Default route + Destination = "0.0.0.0/0"; + Gateway = "10.0.0.0"; + GatewayOnLink = true; + } + { + # Default route + Destination = "::/0"; + Gateway = "fec0::"; + GatewayOnLink = true; + } + ]; + networkConfig = { + # DNS servers no longer come from DHCP nor Router + # Advertisements. Perhaps you want to change the defaults: + DNS = [ + # Quad9.net + "9.9.9.9" + "149.112.112.112" + "2620:fe::fe" + "2620:fe::9" + ]; + }; + }; + + # open the ports to allow ssh access from the host + networking.firewall.allowedTCPPorts = [ + 22 + 80 + 443 + ]; + networking.firewall.allowedUDPPorts = [ + 22 + 80 + 443 + ]; + + users.users.dev = { + isNormalUser = true; + password = "test"; + home = "/home/dev"; + description = "Alice Foobar"; + extraGroups = [ + "wheel" + "networkmanager" + "docker" + ]; + openssh.authorizedKeys.keys = [ + publicKey + ]; + }; + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; + AllowUsers = [ "dev" ]; + }; + }; + virtualisation.docker = { + enable = true; + liveRestore = false; + }; +} -- 2.54.0 From 9bd8f4962a2e131c6555f7812e0bd7fef517c1aa Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 6 Aug 2026 22:00:29 +0200 Subject: [PATCH 02/14] feat: adds running integrations test suite --- Makefile | 12 +++- flake.nix | 38 +++++++++-- nix/hosts/client/configuration.nix | 66 +++++++++---------- nix/hosts/client/home.nix | 13 ++-- nix/hosts/server/configuration.nix | 51 ++++---------- nix/modules/docker.nix | 7 ++ nix/modules/ssh.nix | 33 ++++++++++ nix/modules/user.nix | 22 +++++++ package.nix => nix/package.nix | 0 tests/integration/app_deploy.bats | 19 ++++-- tests/integration/app_deploy_env_version.bats | 3 +- tests/integration/app_remove.bats | 15 +++-- .../integration/app_rollback_env_version.bats | 3 +- .../integration/app_upgrade_env_version.bats | 5 +- tests/integration/helpers/common.bash | 17 +++-- tests/integration/helpers/docker.bash | 36 ++++++++-- tests/integration/helpers/hosts.bash | 31 +++++++++ tests/integration/recipe_upgrade.bats | 2 - tests/integration/server_add.bats | 6 +- tests/resources/local_hosts | 58 ++++++++++++++++ tests/resources/local_integration_ssh | 7 ++ tests/resources/local_integration_ssh.pub | 1 + 22 files changed, 327 insertions(+), 118 deletions(-) create mode 100644 nix/modules/docker.nix create mode 100644 nix/modules/ssh.nix create mode 100644 nix/modules/user.nix rename package.nix => nix/package.nix (100%) create mode 100755 tests/integration/helpers/hosts.bash create mode 100644 tests/resources/local_hosts create mode 100644 tests/resources/local_integration_ssh create mode 100644 tests/resources/local_integration_ssh.pub diff --git a/Makefile b/Makefile index 022918e4..feb4874a 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,8 @@ vm-client-stop: sudo systemctl stop microvm@$(CLIENT_VM) vm-client-delete: vm-client-stop sudo rm -rf /var/lib/microvms/$(CLIENT_VM) +vm-client-connect: + kitten ssh abra@10.0.0.2 -i ./tests/resources/local_integration_ssh SERVER_VM := abra-server vm-server-status: @@ -114,8 +116,14 @@ vm-server-run: sudo microvm -f git+file://$$(pwd) -r $(SERVER_VM) vm-server-stop: sudo systemctl stop microvm@$(SERVER_VM) -vm-server-delete: vm-stop +vm-server-delete: vm-server-stop sudo rm -rf /var/lib/microvms/$(SERVER_VM) +vm-server-connect: + ssh abra@10.0.0.3 -i ./tests/resources/local_integration_ssh test-integration: - ssh-keygen -t ed25519 -f ./test-integration -q -N "" -C "abra integration test" + ssh-add ./tests/resources/local_integration_ssh + ./abra server add abra.local + ./abra app new traefik + ./abra app deploy traefik.abra.local + @bats -Tp tests/integration --verbose-run diff --git a/flake.nix b/flake.nix index 878081c8..9385e2e6 100644 --- a/flake.nix +++ b/flake.nix @@ -25,8 +25,18 @@ let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; - publicKey = builtins.readFile ./test-integration.pub; - privateKey = builtins.readFile ./test-integration; + publicKey = builtins.readFile ./tests/resources/local_integration_ssh.pub; + privateKey = builtins.readFile ./tests/resources/local_integration_ssh; + localDomainHosts = builtins.readFile ./tests/resources/local_hosts; + username = "abra"; + password = "abra"; + defaultDNS = [ + # Quad9.net + "9.9.9.9" + "149.112.112.112" + "2620:fe::fe" + "2620:fe::9" + ]; in { nixosConfigurations = { @@ -37,7 +47,16 @@ home-manager.nixosModules.home-manager ./nix/hosts/client/configuration.nix ]; - specialArgs = { inherit publicKey privateKey; }; + specialArgs = { + inherit + publicKey + privateKey + username + password + defaultDNS + localDomainHosts + ; + }; }; abra-server = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; @@ -45,11 +64,20 @@ microvm.nixosModules.microvm ./nix/hosts/server/configuration.nix ]; - specialArgs = { inherit publicKey privateKey; }; + specialArgs = { + inherit + publicKey + privateKey + username + password + defaultDNS + localDomainHosts + ; + }; }; }; packages = rec { - abra = pkgs.callPackage ./package.nix { }; + abra = pkgs.callPackage ./nix/package.nix { }; default = abra; }; apps = rec { diff --git a/nix/hosts/client/configuration.nix b/nix/hosts/client/configuration.nix index ccccd999..3b903994 100644 --- a/nix/hosts/client/configuration.nix +++ b/nix/hosts/client/configuration.nix @@ -3,6 +3,9 @@ pkgs, publicKey, privateKey, + username, + defaultDNS, + localDomainHosts, ... }: let @@ -11,6 +14,12 @@ let serverIp = "10.0.0.3"; in { + imports = [ + ../../modules/ssh.nix + ../../modules/user.nix + ../../modules/docker.nix + ]; + microvm = { vcpu = 4; mem = 2049; # see issue related in microvm repo with 2048, so add 1MB @@ -27,8 +36,8 @@ in tag = "repo"; # Source path can be absolute or relative # to /var/lib/microvms/$hostName - source = "/home/dev/Documents/abra"; - mountPoint = "/home/dev/abra"; + source = "/home/dev/Documents/kum/abra"; + mountPoint = "/home/${username}/abra"; } ]; }; @@ -77,13 +86,7 @@ in networkConfig = { # DNS servers no longer come from DHCP nor Router # Advertisements. Perhaps you want to change the defaults: - DNS = [ - # Quad9.net - "9.9.9.9" - "149.112.112.112" - "2620:fe::fe" - "2620:fe::9" - ]; + DNS = defaultDNS; }; }; @@ -91,10 +94,7 @@ in networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedUDPPorts = [ 22 ]; - networking.extraHosts = '' - ${serverIp} abra.local - ${serverIp} app_check_bats.abra.local - ''; + networking.extraHosts = localDomainHosts; environment.variables = { CGO_ENABLED = 0; @@ -102,32 +102,26 @@ in ABRA_DIR = "$HOME/.abra_test"; }; - users.users.dev = { - isNormalUser = true; - password = "test"; - home = "/home/dev"; - description = "Alice Foobar"; - extraGroups = [ - "wheel" - "networkmanager" - ]; - openssh.authorizedKeys.keys = [ - publicKey - ]; - }; - # ssh agent with askpass programs.ssh = { startAgent = true; + knownHostsFiles = [ + (pkgs.writeText "local.keys" '' + abra.local ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFD3rtSHGYWSrvVZe9VGQSa16EIawScFWmkBfGC0cebv + '') + ]; }; - services.openssh = { + programs.git = { enable = true; - settings = { - PasswordAuthentication = false; - PermitRootLogin = "no"; - AllowUsers = [ "dev" ]; - }; + # many recipe commands need a preset git user + config = [ + { + user = { + name = "abra dev"; + email = "helo@coopcloud.tech"; + }; + } + ]; }; - programs.git.enable = true; environment.systemPackages = with pkgs; [ # build dependencies, copied from flake.nix @@ -140,12 +134,13 @@ in p.bats-support ])) jq + wget ]; home-manager = { useGlobalPkgs = true; useUserPackages = true; - users.dev = + users."${username}" = { ... }: { imports = [ @@ -157,6 +152,7 @@ in publicKey = publicKey; privateKey = privateKey; serverIp = serverIp; + username = username; }; }; } diff --git a/nix/hosts/client/home.nix b/nix/hosts/client/home.nix index 905a22f8..1bf2433a 100644 --- a/nix/hosts/client/home.nix +++ b/nix/hosts/client/home.nix @@ -1,12 +1,13 @@ { serverIp, + username, ... }: { # Home Manager needs a bit of information about you and the # paths it should manage. - home.username = "dev"; - home.homeDirectory = "/home/dev"; + home.username = username; + home.homeDirectory = "/home/${username}"; # This value determines the Home Manager release that your # configuration is compatible with. This helps avoid breakage @@ -26,15 +27,15 @@ settings = { "abra.local" = { HostName = serverIp; - User = "dev"; + User = username; Port = 22; - IdentityFile = "/home/dev/abra/test-integration"; + IdentityFile = "/home/${username}/abra/tests/resources/local_integration_ssh"; }; "*.abra.local" = { HostName = serverIp; - User = "dev"; + User = username; Port = 22; - IdentityFile = "/home/dev/abra/test-integration"; + IdentityFile = "/home/${username}/abra/tests/resources/local_integration_sshn"; }; }; }; diff --git a/nix/hosts/server/configuration.nix b/nix/hosts/server/configuration.nix index e4a739fb..9c78500a 100644 --- a/nix/hosts/server/configuration.nix +++ b/nix/hosts/server/configuration.nix @@ -1,6 +1,6 @@ { lib, - publicKey, + defaultDNS, ... }: let @@ -9,9 +9,15 @@ let clientIp = "10.0.0.2"; in { + imports = [ + ../../modules/ssh.nix + ../../modules/user.nix + ../../modules/docker.nix + ]; + microvm = { - vcpu = 2; - mem = 2049; # see issue related in microvm repo with 2048, so add 1MB + vcpu = 4; + mem = 8097; # see issue related in microvm repo with 2048, so add 1MB interfaces = [ { id = "vm${toString index}"; @@ -23,7 +29,7 @@ in boot.tmp = { useTmpfs = true; - tmpfsSize = "2G"; + tmpfsSize = "8G"; }; networking = { @@ -65,13 +71,7 @@ in networkConfig = { # DNS servers no longer come from DHCP nor Router # Advertisements. Perhaps you want to change the defaults: - DNS = [ - # Quad9.net - "9.9.9.9" - "149.112.112.112" - "2620:fe::fe" - "2620:fe::9" - ]; + DNS = defaultDNS; }; }; @@ -80,37 +80,12 @@ in 22 80 443 + 1312 # deploy with udp and tcp on same port test ]; networking.firewall.allowedUDPPorts = [ 22 80 443 + 1312 # deploy with udp and tcp on same port test ]; - - users.users.dev = { - isNormalUser = true; - password = "test"; - home = "/home/dev"; - description = "Alice Foobar"; - extraGroups = [ - "wheel" - "networkmanager" - "docker" - ]; - openssh.authorizedKeys.keys = [ - publicKey - ]; - }; - services.openssh = { - enable = true; - settings = { - PasswordAuthentication = false; - PermitRootLogin = "no"; - AllowUsers = [ "dev" ]; - }; - }; - virtualisation.docker = { - enable = true; - liveRestore = false; - }; } diff --git a/nix/modules/docker.nix b/nix/modules/docker.nix new file mode 100644 index 00000000..d10cb8c0 --- /dev/null +++ b/nix/modules/docker.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + virtualisation.docker = { + enable = true; + liveRestore = false; + }; +} diff --git a/nix/modules/ssh.nix b/nix/modules/ssh.nix new file mode 100644 index 00000000..dfd39bf9 --- /dev/null +++ b/nix/modules/ssh.nix @@ -0,0 +1,33 @@ +{ + privateKey, + publicKey, + username, + ... +}: +{ + # default host key location + environment.etc."ssh/ssh_host_ed25519_key" = { + text = privateKey; + mode = "0600"; + }; + environment.etc."ssh/ssh_host_ed25519_key.pub" = { + text = publicKey; + mode = "0644"; + }; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; + AllowUsers = [ "${username}" ]; + }; + generateHostKeys = false; + hostKeys = [ + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + ]; + }; +} diff --git a/nix/modules/user.nix b/nix/modules/user.nix new file mode 100644 index 00000000..ec5c89f6 --- /dev/null +++ b/nix/modules/user.nix @@ -0,0 +1,22 @@ +{ + username, + password, + publicKey, + ... +}: +{ + users.users."${username}" = { + isNormalUser = true; + password = password; + home = "/home/${username}"; + description = "Abra server user"; + extraGroups = [ + "wheel" + "networkmanager" + "docker" + ]; + openssh.authorizedKeys.keys = [ + publicKey + ]; + }; +} diff --git a/package.nix b/nix/package.nix similarity index 100% rename from package.nix rename to nix/package.nix diff --git a/tests/integration/app_deploy.bats b/tests/integration/app_deploy.bats index be73a494..5137b38f 100644 --- a/tests/integration/app_deploy.bats +++ b/tests/integration/app_deploy.bats @@ -598,8 +598,7 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input assert_success - run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \ - $(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q) + _inspect assert_success assert_output --partial "WITH_COMMENT=foo" @@ -610,14 +609,13 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --force assert_success - run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \ - $(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q) + _inspect assert_success refute_output --partial "WITH_COMMENT=foo" assert_output --partial "WITH_COMMENT=bar" } -# bats test_tags=slow +# bats test_tags=slow,error @test "deploy with udp and tcp on same port" { run sed -i 's/TYPE=abra-test-recipe:.*/TYPE=git.coopcloud.tech\/p4u1\/abra-test-recipe:030e8a1cb1a0f17281847b3e55d829220ad32c50/g' \ "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" @@ -629,8 +627,14 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input assert_success - run docker service inspect --format '{{ range .Endpoint.Ports }}{{ .Protocol }}={{ .PublishedPort }}{{ end }}' \ + if _is_local; + then + run docker service inspect --format "{{ range .Endpoint.Ports }}{{ .Protocol }}={{ .PublishedPort }}{{ end }}" \ "${TEST_APP_DOMAIN//./_}_app" + else + run ssh "$TEST_SERVER" "docker service inspect --format '{{ range .Endpoint.Ports }}{{ .Protocol }}={{ .PublishedPort }}{{ end }}' ${TEST_APP_DOMAIN//./_}_app" + fi + assert_success assert_output --partial "tcp=1312" assert_output --partial "udp=1312" @@ -671,6 +675,9 @@ teardown(){ @test "unable to deploy borked tag" { _remove_tags + # can not tag without it + _set_git_author + run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag \ -a "2.4.8_1" -m "feat: completely borked tag" assert_success diff --git a/tests/integration/app_deploy_env_version.bats b/tests/integration/app_deploy_env_version.bats index e569e911..a57fd5b5 100644 --- a/tests/integration/app_deploy_env_version.bats +++ b/tests/integration/app_deploy_env_version.bats @@ -133,8 +133,7 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.0+1.20.0" --no-input assert_success - run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \ - $(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q) + _inspect assert_success assert_output --partial "$TEST_RECIIPE:0.1.0+1.20.0" } diff --git a/tests/integration/app_remove.bats b/tests/integration/app_remove.bats index f24e2ef4..021a214d 100644 --- a/tests/integration/app_remove.bats +++ b/tests/integration/app_remove.bats @@ -140,15 +140,22 @@ teardown(){ _undeploy_app sanitisedDomainName="${TEST_APP_DOMAIN//./_}" - run docker config create "${sanitisedDomainName}_test_conf_v99" "$ABRA_DIR/recipes/abra-test-recipe/abra.sh" - assert_success + remote_execute="" + if _is_local; + then + run docker config create "${sanitisedDomainName}_test_conf_v99" "$ABRA_DIR/recipes/abra-test-recipe/abra.sh" + else + remote_execute="ssh '$TEST_SERVER'" + run cat "$ABRA_DIR/recipes/abra-test-recipe/abra.sh" | ssh "$TEST_SERVER" docker config create "${sanitisedDomainName}_test_conf_v99 -" + assert_success + fi - assert bash -c "docker config ls | grep -q test_conf_v99" + assert bash -c "$remote_execute docker config ls | grep -q test_conf_v99" run $ABRA app rm "$TEST_APP_DOMAIN" --no-input assert_success - refute bash -c "docker config ls | grep -q test_conf_v99" + refute bash -c "$remote_execute docker config ls | grep -q test_conf_v99" } @test "remove .env file" { diff --git a/tests/integration/app_rollback_env_version.bats b/tests/integration/app_rollback_env_version.bats index b3bbcea1..de78d08c 100644 --- a/tests/integration/app_rollback_env_version.bats +++ b/tests/integration/app_rollback_env_version.bats @@ -54,8 +54,7 @@ teardown(){ --no-input assert_success - run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \ - $(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q) + _inspect assert_success assert_output --partial "$TEST_RECIIPE:0.1.0+1.20.0" } diff --git a/tests/integration/app_upgrade_env_version.bats b/tests/integration/app_upgrade_env_version.bats index 4d3e9bb4..5ca9f71b 100644 --- a/tests/integration/app_upgrade_env_version.bats +++ b/tests/integration/app_upgrade_env_version.bats @@ -53,8 +53,7 @@ teardown(){ run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" --no-input assert_success - run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' \ - $(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q) + _inspect assert_success - assert_output --partial "$TEST_RECIIPE:0.2.0+1.21.0" + assert_output --partial "$TEST_RECIPE:0.2.0+1.21.0" } diff --git a/tests/integration/helpers/common.bash b/tests/integration/helpers/common.bash index d528fc0c..37dca96c 100644 --- a/tests/integration/helpers/common.bash +++ b/tests/integration/helpers/common.bash @@ -31,9 +31,18 @@ _ensure_ssh_agent() { exit 1 fi - export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock" - if [ ! -S ~/.ssh/ssh_auth_sock ]; then - eval `ssh-agent` - ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock + # export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock" + # if [ ! -S ~/.ssh/ssh_auth_sock ]; then + # eval `ssh-agent` + # ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock + # fi +} + +_is_local() { + if [[ "$TEST_SERVER" == "default" ]]; + then + return 0 + else + return 1 fi } diff --git a/tests/integration/helpers/docker.bash b/tests/integration/helpers/docker.bash index a8304890..c1cd1ab2 100644 --- a/tests/integration/helpers/docker.bash +++ b/tests/integration/helpers/docker.bash @@ -1,13 +1,37 @@ #!/usr/bin/env bash _ensure_swarm() { - if [ "$(docker info | grep Swarm | sed 's/Swarm: //g' | tr -d ' ')" == "inactive" ]; then - run docker swarm init --advertise-addr 127.0.0.1:2377 - assert_success + if [ "$(docker info | grep Swarm | sed 's/Swarm: //g' | tr -d ' ')" == "inactive" ]; then + run docker swarm init --advertise-addr 127.0.0.1:2377 + assert_success fi - if ! $(docker network ls | grep -q 'proxy'); then - run docker network create -d overlay proxy - assert_success + if ! docker network ls | grep -q 'proxy'; then + run docker network create -d overlay proxy + assert_success fi + + if ! _is_local; + then + if [ "$(ssh "$TEST_SERVER" docker info | grep Swarm | sed 's/Swarm: //g' | tr -d ' ')" == "inactive" ]; then + run ssh "$TEST_SERVER" docker swarm init --advertise-addr 127.0.0.1:2377 + assert_success + fi + + if ! ssh "$TEST_SERVER" docker network ls | grep -q 'proxy'; then + run ssh "$TEST_SERVER" docker network create -d overlay proxy + assert_success + fi + fi +} + +_inspect() { + if _is_local; + then + containerId="$(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q)" + run docker inspect "$containerId" + else + containerId="$(ssh "$TEST_SERVER" docker ps -f name="$TEST_APP_DOMAIN" -q)" + run ssh "$TEST_SERVER" docker inspect "$containerId" + fi } diff --git a/tests/integration/helpers/hosts.bash b/tests/integration/helpers/hosts.bash new file mode 100755 index 00000000..39a395ff --- /dev/null +++ b/tests/integration/helpers/hosts.bash @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +echo "generating hosts file..." + +hosts_file_path="./tests/resources/local_hosts" + +echo "removing old file..." +rm $hosts_file_path + +# default entries +# the server +echo "10.0.0.3 abra.local" >> $hosts_file_path +# used to spin up traefik +echo "10.0.0.3 traefik.abra.local" >> $hosts_file_path +# used in integration tests +echo "10.0.0.3 gitea.abra.local" >> $hosts_file_path +echo "10.0.0.3 zammad.abra.local" >> $hosts_file_path +echo "10.0.0.3 custom-html.abra.local" >> $hosts_file_path +echo "10.0.0.3 foo.abra.local" >> $hosts_file_path +echo "10.0.0.3 foobar.abra.local" >> $hosts_file_path + +search_dir=./tests/integration +for entry in "$search_dir"/*.bats +do + base_name=$(basename "${entry}") + # converting file names to testing subdomains + subdomain=$(echo "$base_name" | tr . _) + echo "10.0.0.3 $subdomain.abra.local" >> $hosts_file_path +done + +echo "writing hosts success" diff --git a/tests/integration/recipe_upgrade.bats b/tests/integration/recipe_upgrade.bats index 527bb9d1..0570c88a 100644 --- a/tests/integration/recipe_upgrade.bats +++ b/tests/integration/recipe_upgrade.bats @@ -38,8 +38,6 @@ teardown(){ run $ABRA recipe upgrade "custom-html" --no-input assert_success - assert_output --partial 'can upgrade service: app' - assert_exists "$ABRA_DIR/recipes/custom-html" } diff --git a/tests/integration/server_add.bats b/tests/integration/server_add.bats index c1cd1bac..71683ce7 100644 --- a/tests/integration/server_add.bats +++ b/tests/integration/server_add.bats @@ -27,7 +27,7 @@ teardown(){ assert bash -c "docker context ls | grep -q $TEST_SERVER" server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers/$TEST_SERVER") - assert_equal $server_dir_perms "700" + assert_equal "$server_dir_perms" "700" } @test "error if using name and --local together" { @@ -43,8 +43,8 @@ teardown(){ assert bash -c "docker context ls | grep -q default" assert_output --partial 'local server successfully added' - server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers/$TEST_SERVER") - assert_equal $server_dir_perms "700" + server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers/default") + assert_equal "$server_dir_perms" "700" } @test "create local server fails when no docker swarm" { diff --git a/tests/resources/local_hosts b/tests/resources/local_hosts new file mode 100644 index 00000000..c7575f89 --- /dev/null +++ b/tests/resources/local_hosts @@ -0,0 +1,58 @@ +10.0.0.3 abra.local +10.0.0.3 traefik.abra.local +10.0.0.3 gitea.abra.local +10.0.0.3 zammad.abra.local +10.0.0.3 custom-html.abra.local +10.0.0.3 foo.abra.local +10.0.0.3 foobar.abra.local +10.0.0.3 app_check_bats.abra.local +10.0.0.3 app_cmd_bats.abra.local +10.0.0.3 app_config_bats.abra.local +10.0.0.3 app_cp_bats.abra.local +10.0.0.3 app_deploy_bats.abra.local +10.0.0.3 app_deploy_env_version_bats.abra.local +10.0.0.3 app_deploy_overview_bats.abra.local +10.0.0.3 app_deploy_remote_recipes_bats.abra.local +10.0.0.3 app_env_bats.abra.local +10.0.0.3 app_env_version_bats.abra.local +10.0.0.3 app_labels_bats.abra.local +10.0.0.3 app_list_bats.abra.local +10.0.0.3 app_logs_bats.abra.local +10.0.0.3 app_move_bats.abra.local +10.0.0.3 app_new_bats.abra.local +10.0.0.3 app_ps_bats.abra.local +10.0.0.3 app_remove_bats.abra.local +10.0.0.3 app_restart_bats.abra.local +10.0.0.3 app_rollback_bats.abra.local +10.0.0.3 app_rollback_env_version_bats.abra.local +10.0.0.3 app_rollback_overview_bats.abra.local +10.0.0.3 app_run_bats.abra.local +10.0.0.3 app_secret_bats.abra.local +10.0.0.3 app_secret_env_version_bats.abra.local +10.0.0.3 app_services_bats.abra.local +10.0.0.3 app_undeploy_bats.abra.local +10.0.0.3 app_undeploy_env_version_bats.abra.local +10.0.0.3 app_undeploy_overview_bats.abra.local +10.0.0.3 app_upgrade_bats.abra.local +10.0.0.3 app_upgrade_env_version_bats.abra.local +10.0.0.3 app_upgrade_overview_bats.abra.local +10.0.0.3 app_volume_bats.abra.local +10.0.0.3 autocomplete_bats.abra.local +10.0.0.3 catalogue_bats.abra.local +10.0.0.3 dirs_bats.abra.local +10.0.0.3 install_bats.abra.local +10.0.0.3 recipe_diff_bats.abra.local +10.0.0.3 recipe_fetch_bats.abra.local +10.0.0.3 recipe_lint_bats.abra.local +10.0.0.3 recipe_list_bats.abra.local +10.0.0.3 recipe_new_bats.abra.local +10.0.0.3 recipe_release_bats.abra.local +10.0.0.3 recipe_reset_bats.abra.local +10.0.0.3 recipe_upgrade_bats.abra.local +10.0.0.3 recipe_version_bats.abra.local +10.0.0.3 server_add_bats.abra.local +10.0.0.3 server_list_bats.abra.local +10.0.0.3 server_prune_bats.abra.local +10.0.0.3 server_remove_bats.abra.local +10.0.0.3 upgrade_bats.abra.local +10.0.0.3 version_bats.abra.local diff --git a/tests/resources/local_integration_ssh b/tests/resources/local_integration_ssh new file mode 100644 index 00000000..fcb7fe7c --- /dev/null +++ b/tests/resources/local_integration_ssh @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACBQ967UhxmFkq71WXvVRkEmtehCGsEnBVppAXxgtHHm7wAAAJhFGwTnRRsE +5wAAAAtzc2gtZWQyNTUxOQAAACBQ967UhxmFkq71WXvVRkEmtehCGsEnBVppAXxgtHHm7w +AAAEAnHEZcf2NeRQEcJC/aVgUWsdOz+vQgEG9ZY+3ErCeaKFD3rtSHGYWSrvVZe9VGQSa1 +6EIawScFWmkBfGC0cebvAAAAFWFicmEgaW50ZWdyYXRpb24gdGVzdA== +-----END OPENSSH PRIVATE KEY----- diff --git a/tests/resources/local_integration_ssh.pub b/tests/resources/local_integration_ssh.pub new file mode 100644 index 00000000..a04eea1f --- /dev/null +++ b/tests/resources/local_integration_ssh.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFD3rtSHGYWSrvVZe9VGQSa16EIawScFWmkBfGC0cebv abra integration test -- 2.54.0 From 0c0e16914aa28d0fa64b4a0d4e6de51fa78d2d9b Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 10:36:23 +0200 Subject: [PATCH 03/14] refactor: remove traefik deployment because it is not needed --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index feb4874a..2e166433 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,4 @@ vm-server-connect: test-integration: ssh-add ./tests/resources/local_integration_ssh - ./abra server add abra.local - ./abra app new traefik - ./abra app deploy traefik.abra.local @bats -Tp tests/integration --verbose-run -- 2.54.0 From beee7bd3f22ca2d128bb7bec92bc29f0ef2996fb Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 11:09:30 +0200 Subject: [PATCH 04/14] refactor: only export ssh auth socket when not existing --- tests/integration/helpers/common.bash | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/integration/helpers/common.bash b/tests/integration/helpers/common.bash index 37dca96c..e7ab16b8 100644 --- a/tests/integration/helpers/common.bash +++ b/tests/integration/helpers/common.bash @@ -31,11 +31,11 @@ _ensure_ssh_agent() { exit 1 fi - # export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock" - # if [ ! -S ~/.ssh/ssh_auth_sock ]; then - # eval `ssh-agent` - # ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock - # fi + if [[ ! -v SSH_AUTH_SOCK ]]; then + export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock" + eval `ssh-agent` + ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock + fi } _is_local() { -- 2.54.0 From b5e22790be2cb8da6cf597586464a3fe463be9eb Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 13:36:25 +0200 Subject: [PATCH 05/14] refactor: better name for inspect function --- tests/integration/app_deploy.bats | 9 +++------ tests/integration/app_deploy_env_version.bats | 2 +- tests/integration/app_rollback_env_version.bats | 2 +- tests/integration/app_upgrade_env_version.bats | 2 +- tests/integration/helpers/docker.bash | 6 +++--- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/integration/app_deploy.bats b/tests/integration/app_deploy.bats index 5137b38f..b987cede 100644 --- a/tests/integration/app_deploy.bats +++ b/tests/integration/app_deploy.bats @@ -598,7 +598,7 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input assert_success - _inspect + _inspect_env_test_app assert_success assert_output --partial "WITH_COMMENT=foo" @@ -609,13 +609,13 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --force assert_success - _inspect + _inspect_env_test_app assert_success refute_output --partial "WITH_COMMENT=foo" assert_output --partial "WITH_COMMENT=bar" } -# bats test_tags=slow,error +# bats test_tags=slow @test "deploy with udp and tcp on same port" { run sed -i 's/TYPE=abra-test-recipe:.*/TYPE=git.coopcloud.tech\/p4u1\/abra-test-recipe:030e8a1cb1a0f17281847b3e55d829220ad32c50/g' \ "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" @@ -675,9 +675,6 @@ teardown(){ @test "unable to deploy borked tag" { _remove_tags - # can not tag without it - _set_git_author - run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag \ -a "2.4.8_1" -m "feat: completely borked tag" assert_success diff --git a/tests/integration/app_deploy_env_version.bats b/tests/integration/app_deploy_env_version.bats index a57fd5b5..66b6a4a7 100644 --- a/tests/integration/app_deploy_env_version.bats +++ b/tests/integration/app_deploy_env_version.bats @@ -133,7 +133,7 @@ teardown(){ run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.0+1.20.0" --no-input assert_success - _inspect + _inspect_env_test_app assert_success assert_output --partial "$TEST_RECIIPE:0.1.0+1.20.0" } diff --git a/tests/integration/app_rollback_env_version.bats b/tests/integration/app_rollback_env_version.bats index de78d08c..8b7c6e34 100644 --- a/tests/integration/app_rollback_env_version.bats +++ b/tests/integration/app_rollback_env_version.bats @@ -54,7 +54,7 @@ teardown(){ --no-input assert_success - _inspect + _inspect_env_test_app assert_success assert_output --partial "$TEST_RECIIPE:0.1.0+1.20.0" } diff --git a/tests/integration/app_upgrade_env_version.bats b/tests/integration/app_upgrade_env_version.bats index 5ca9f71b..a503be4c 100644 --- a/tests/integration/app_upgrade_env_version.bats +++ b/tests/integration/app_upgrade_env_version.bats @@ -53,7 +53,7 @@ teardown(){ run $ABRA app upgrade "$TEST_APP_DOMAIN" "0.2.0+1.21.0" --no-input assert_success - _inspect + _inspect_env_test_app assert_success assert_output --partial "$TEST_RECIPE:0.2.0+1.21.0" } diff --git a/tests/integration/helpers/docker.bash b/tests/integration/helpers/docker.bash index c1cd1ab2..59572243 100644 --- a/tests/integration/helpers/docker.bash +++ b/tests/integration/helpers/docker.bash @@ -25,13 +25,13 @@ _ensure_swarm() { fi } -_inspect() { +_inspect_env_test_app() { if _is_local; then containerId="$(docker ps -f name="$TEST_APP_DOMAIN_$TEST_SERVER" -q)" - run docker inspect "$containerId" + run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' "$containerId" else containerId="$(ssh "$TEST_SERVER" docker ps -f name="$TEST_APP_DOMAIN" -q)" - run ssh "$TEST_SERVER" docker inspect "$containerId" + run ssh "$TEST_SERVER" "docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' '$containerId'" fi } -- 2.54.0 From 38d13eae73e4b32e1d0fd48d78b4d0c08f8d6c09 Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 13:42:22 +0200 Subject: [PATCH 06/14] refactor: better variable name --- tests/integration/app_remove.bats | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/app_remove.bats b/tests/integration/app_remove.bats index 021a214d..f31500c4 100644 --- a/tests/integration/app_remove.bats +++ b/tests/integration/app_remove.bats @@ -140,22 +140,22 @@ teardown(){ _undeploy_app sanitisedDomainName="${TEST_APP_DOMAIN//./_}" - remote_execute="" + remote_ssh_command="" if _is_local; then run docker config create "${sanitisedDomainName}_test_conf_v99" "$ABRA_DIR/recipes/abra-test-recipe/abra.sh" else - remote_execute="ssh '$TEST_SERVER'" + remote_ssh_command="ssh '$TEST_SERVER'" run cat "$ABRA_DIR/recipes/abra-test-recipe/abra.sh" | ssh "$TEST_SERVER" docker config create "${sanitisedDomainName}_test_conf_v99 -" assert_success fi - assert bash -c "$remote_execute docker config ls | grep -q test_conf_v99" + assert bash -c "$remote_ssh_command docker config ls | grep -q test_conf_v99" run $ABRA app rm "$TEST_APP_DOMAIN" --no-input assert_success - refute bash -c "$remote_execute docker config ls | grep -q test_conf_v99" + refute bash -c "$remote_ssh_command docker config ls | grep -q test_conf_v99" } @test "remove .env file" { -- 2.54.0 From 5e0dac6508fe839f895fbf5d231269fa413a7732 Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 14:11:00 +0200 Subject: [PATCH 07/14] refactor: adjusting hosts generation --- Makefile | 6 ++-- flake.nix | 6 ++-- nix/hosts/client/configuration.nix | 4 +-- scripts/tests/extra_hosts | 30 +++++++++++++++++++ tests/integration/helpers/hosts.bash | 31 -------------------- tests/resources/{local_hosts => extra_hosts} | 1 - 6 files changed, 39 insertions(+), 39 deletions(-) create mode 100755 scripts/tests/extra_hosts delete mode 100755 tests/integration/helpers/hosts.bash rename tests/resources/{local_hosts => extra_hosts} (98%) diff --git a/Makefile b/Makefile index 2e166433..a60279b8 100644 --- a/Makefile +++ b/Makefile @@ -88,11 +88,11 @@ release: CLIENT_VM := abra-client vm-client-status: sudo systemctl status microvm@$(CLIENT_VM).service -vm-client-create: +vm-client-create:test-integration-hosts sudo microvm -f git+file://$$(pwd) -c $(CLIENT_VM) vm-client-start: sudo systemctl start microvm@$(CLIENT_VM).service -vm-client-update: +vm-client-update:test-integration-hosts sudo microvm -R -f git+file://$$(pwd) -u $(CLIENT_VM) vm-client-run: sudo microvm -f git+file://$$(pwd) -r $(CLIENT_VM) @@ -121,6 +121,8 @@ vm-server-delete: vm-server-stop vm-server-connect: ssh abra@10.0.0.3 -i ./tests/resources/local_integration_ssh +test-integration-hosts: + ./scripts/tests/extra_hosts test-integration: ssh-add ./tests/resources/local_integration_ssh @bats -Tp tests/integration --verbose-run diff --git a/flake.nix b/flake.nix index 9385e2e6..f9127896 100644 --- a/flake.nix +++ b/flake.nix @@ -27,7 +27,8 @@ pkgs = nixpkgs.legacyPackages.${system}; publicKey = builtins.readFile ./tests/resources/local_integration_ssh.pub; privateKey = builtins.readFile ./tests/resources/local_integration_ssh; - localDomainHosts = builtins.readFile ./tests/resources/local_hosts; + # local DNS aliases for the server host + extraHosts = builtins.readFile ./tests/resources/extra_hosts; username = "abra"; password = "abra"; defaultDNS = [ @@ -54,7 +55,7 @@ username password defaultDNS - localDomainHosts + extraHosts ; }; }; @@ -71,7 +72,6 @@ username password defaultDNS - localDomainHosts ; }; }; diff --git a/nix/hosts/client/configuration.nix b/nix/hosts/client/configuration.nix index 3b903994..037b0686 100644 --- a/nix/hosts/client/configuration.nix +++ b/nix/hosts/client/configuration.nix @@ -5,7 +5,7 @@ privateKey, username, defaultDNS, - localDomainHosts, + extraHosts, ... }: let @@ -94,7 +94,7 @@ in networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedUDPPorts = [ 22 ]; - networking.extraHosts = localDomainHosts; + networking.extraHosts = extraHosts; environment.variables = { CGO_ENABLED = 0; diff --git a/scripts/tests/extra_hosts b/scripts/tests/extra_hosts new file mode 100755 index 00000000..0900674a --- /dev/null +++ b/scripts/tests/extra_hosts @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# This file generates local DNS aliases for the client VM for integration testing + +echo "generating hosts file..." +hosts_file_path="./tests/resources/extra_hosts" +echo "removing old file..." +rm -f $hosts_file_path + +# the server domain +server_ip="10.0.0.3" +domain="abra.local" +echo "$server_ip $domain" >> $hosts_file_path +# static subdomains used in integration tests +subdomains=("gitea" "zammad" "custom-html" "foo" "foobar") + +for subdomain in "${subdomains[@]}" +do + echo "$server_ip $subdomain.$domain" >> $hosts_file_path +done + +search_dir=./tests/integration +for entry in "$search_dir"/*.bats +do + file_name=$(basename "${entry}") + # converting file names to testing subdomains + subdomain=$(echo "$file_name" | tr . _) + echo "$server_ip $subdomain.$domain" >> $hosts_file_path +done + +echo "writing extra hosts success" diff --git a/tests/integration/helpers/hosts.bash b/tests/integration/helpers/hosts.bash deleted file mode 100755 index 39a395ff..00000000 --- a/tests/integration/helpers/hosts.bash +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -echo "generating hosts file..." - -hosts_file_path="./tests/resources/local_hosts" - -echo "removing old file..." -rm $hosts_file_path - -# default entries -# the server -echo "10.0.0.3 abra.local" >> $hosts_file_path -# used to spin up traefik -echo "10.0.0.3 traefik.abra.local" >> $hosts_file_path -# used in integration tests -echo "10.0.0.3 gitea.abra.local" >> $hosts_file_path -echo "10.0.0.3 zammad.abra.local" >> $hosts_file_path -echo "10.0.0.3 custom-html.abra.local" >> $hosts_file_path -echo "10.0.0.3 foo.abra.local" >> $hosts_file_path -echo "10.0.0.3 foobar.abra.local" >> $hosts_file_path - -search_dir=./tests/integration -for entry in "$search_dir"/*.bats -do - base_name=$(basename "${entry}") - # converting file names to testing subdomains - subdomain=$(echo "$base_name" | tr . _) - echo "10.0.0.3 $subdomain.abra.local" >> $hosts_file_path -done - -echo "writing hosts success" diff --git a/tests/resources/local_hosts b/tests/resources/extra_hosts similarity index 98% rename from tests/resources/local_hosts rename to tests/resources/extra_hosts index c7575f89..3df669c1 100644 --- a/tests/resources/local_hosts +++ b/tests/resources/extra_hosts @@ -1,5 +1,4 @@ 10.0.0.3 abra.local -10.0.0.3 traefik.abra.local 10.0.0.3 gitea.abra.local 10.0.0.3 zammad.abra.local 10.0.0.3 custom-html.abra.local -- 2.54.0 From 1ccbb31b7063478e6e960f51d71a7606ce18bd34 Mon Sep 17 00:00:00 2001 From: devydave Date: Fri, 7 Aug 2026 15:15:04 +0200 Subject: [PATCH 08/14] refactor: simplify config and remove hom-manager dependency --- flake.lock | 22 ---------------------- flake.nix | 6 ------ nix/hosts/client/configuration.nix | 28 +++++++--------------------- nix/modules/user.nix | 2 +- 4 files changed, 8 insertions(+), 50 deletions(-) diff --git a/flake.lock b/flake.lock index 57e2bd06..51acafa1 100644 --- a/flake.lock +++ b/flake.lock @@ -18,27 +18,6 @@ "type": "github" } }, - "home-manager": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1785119570, - "narHash": "sha256-Rgs2xKnGLFWQscxUaXX07oyZeuMDOHEbqDOsgliLFGM=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "d4fd24667c8cbef124bb70a20380cab75ec8474d", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "release-26.05", - "repo": "home-manager", - "type": "github" - } - }, "microvm": { "inputs": { "nixpkgs": [ @@ -79,7 +58,6 @@ "root": { "inputs": { "flake-utils": "flake-utils", - "home-manager": "home-manager", "microvm": "microvm", "nixpkgs": "nixpkgs" } diff --git a/flake.nix b/flake.nix index f9127896..3c621f0b 100644 --- a/flake.nix +++ b/flake.nix @@ -3,10 +3,6 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; - home-manager = { - url = "github:nix-community/home-manager/release-26.05"; - inputs.nixpkgs.follows = "nixpkgs"; - }; flake-utils.url = "github:numtide/flake-utils"; microvm = { url = "github:astro/microvm.nix"; @@ -19,7 +15,6 @@ self, nixpkgs, microvm, - home-manager, flake-utils, }: let @@ -45,7 +40,6 @@ system = "x86_64-linux"; modules = [ microvm.nixosModules.microvm - home-manager.nixosModules.home-manager ./nix/hosts/client/configuration.nix ]; specialArgs = { diff --git a/nix/hosts/client/configuration.nix b/nix/hosts/client/configuration.nix index 037b0686..d6fe693b 100644 --- a/nix/hosts/client/configuration.nix +++ b/nix/hosts/client/configuration.nix @@ -2,7 +2,6 @@ lib, pkgs, publicKey, - privateKey, username, defaultDNS, extraHosts, @@ -106,9 +105,15 @@ in startAgent = true; knownHostsFiles = [ (pkgs.writeText "local.keys" '' - abra.local ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFD3rtSHGYWSrvVZe9VGQSa16EIawScFWmkBfGC0cebv + abra.local ${publicKey} '') ]; + extraConfig = '' + Host abra.local + HostName abra.local + Port 22 + User ${username} + ''; }; programs.git = { enable = true; @@ -136,23 +141,4 @@ in jq wget ]; - - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - users."${username}" = - { ... }: - { - imports = [ - ./home.nix - ]; - }; - # pass args to home-manager - extraSpecialArgs = { - publicKey = publicKey; - privateKey = privateKey; - serverIp = serverIp; - username = username; - }; - }; } diff --git a/nix/modules/user.nix b/nix/modules/user.nix index ec5c89f6..edb13240 100644 --- a/nix/modules/user.nix +++ b/nix/modules/user.nix @@ -9,7 +9,7 @@ isNormalUser = true; password = password; home = "/home/${username}"; - description = "Abra server user"; + description = "Abra user"; extraGroups = [ "wheel" "networkmanager" -- 2.54.0 From 5766a25144bbc9b8a5660540c39267a24b896177 Mon Sep 17 00:00:00 2001 From: devydave Date: Wed, 12 Aug 2026 22:43:16 +0200 Subject: [PATCH 09/14] feat: adds host module --- flake.nix | 9 +++++++ nix/modules/host.nix | 59 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 nix/modules/host.nix diff --git a/flake.nix b/flake.nix index 3c621f0b..5e5333b5 100644 --- a/flake.nix +++ b/flake.nix @@ -70,6 +70,15 @@ }; }; }; + nixosModules = rec { + host = { + imports = [ + microvm.nixosModules.host + ./nix/modules/host.nix + ]; + }; + default = host; + }; packages = rec { abra = pkgs.callPackage ./nix/package.nix { }; default = abra; diff --git a/nix/modules/host.nix b/nix/modules/host.nix new file mode 100644 index 00000000..b288a682 --- /dev/null +++ b/nix/modules/host.nix @@ -0,0 +1,59 @@ +{ + lib, + config, + ... +}: +let + maxVMs = 3; +in +{ + options = { + abra.testing.enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable the abra integration testing framework"; + }; + abra.testing.externalInterface = lib.mkOption { + type = lib.types.str; + default = null; + description = "Change this to the interface with upstream Internet access"; + }; + }; + + config = lib.mkIf config.abra.testing.enable { + networking.useNetworkd = true; + systemd.network.wait-online.enable = false; + systemd.network.networks = builtins.listToAttrs ( + map (index: { + name = "30-vm${toString index}"; + value = { + matchConfig.Name = "vm${toString index}"; + # Host's addresses + address = [ + "10.0.0.0/32" + "fec0::/128" + ]; + # Setup routes to the VM + routes = [ + { + Destination = "10.0.0.${toString index}/32"; + } + { + Destination = "fec0::${lib.toHexString index}/128"; + } + ]; + # Enable routing + networkConfig = { + IPv4Forwarding = true; + IPv6Forwarding = true; + }; + }; + }) (lib.genList (i: i + 1) maxVMs) + ); + networking.nat = { + enable = true; + internalIPs = [ "10.0.0.0/24" ]; + externalInterface = config.abra.testing.externalInterface; + }; + }; +} -- 2.54.0 From a8c8df860416c7c71edae9181f51e6481390769e Mon Sep 17 00:00:00 2001 From: devydave Date: Wed, 12 Aug 2026 23:01:12 +0200 Subject: [PATCH 10/14] fix: remove personal terminal choice --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a60279b8..6cf65700 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ vm-client-stop: vm-client-delete: vm-client-stop sudo rm -rf /var/lib/microvms/$(CLIENT_VM) vm-client-connect: - kitten ssh abra@10.0.0.2 -i ./tests/resources/local_integration_ssh + ssh abra@10.0.0.2 -i ./tests/resources/local_integration_ssh SERVER_VM := abra-server vm-server-status: -- 2.54.0 From 02cbf7c014963828167f50fe4a8f260bc2634efe Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 13 Aug 2026 19:57:51 +0200 Subject: [PATCH 11/14] refactor: make path editable without nix and impure --- flake.nix | 2 ++ nix/hosts/client/configuration.nix | 3 ++- tests/resources/path_to_repo | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 tests/resources/path_to_repo diff --git a/flake.nix b/flake.nix index 5e5333b5..63f68abb 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,7 @@ pkgs = nixpkgs.legacyPackages.${system}; publicKey = builtins.readFile ./tests/resources/local_integration_ssh.pub; privateKey = builtins.readFile ./tests/resources/local_integration_ssh; + pathToRepo = builtins.readFile ./tests/resources/path_to_repo; # local DNS aliases for the server host extraHosts = builtins.readFile ./tests/resources/extra_hosts; username = "abra"; @@ -50,6 +51,7 @@ password defaultDNS extraHosts + pathToRepo ; }; }; diff --git a/nix/hosts/client/configuration.nix b/nix/hosts/client/configuration.nix index d6fe693b..83e8f0c3 100644 --- a/nix/hosts/client/configuration.nix +++ b/nix/hosts/client/configuration.nix @@ -3,6 +3,7 @@ pkgs, publicKey, username, + pathToRepo, defaultDNS, extraHosts, ... @@ -35,7 +36,7 @@ in tag = "repo"; # Source path can be absolute or relative # to /var/lib/microvms/$hostName - source = "/home/dev/Documents/kum/abra"; + source = "${lib.trim pathToRepo}"; mountPoint = "/home/${username}/abra"; } ]; diff --git a/tests/resources/path_to_repo b/tests/resources/path_to_repo new file mode 100644 index 00000000..7f63cd1e --- /dev/null +++ b/tests/resources/path_to_repo @@ -0,0 +1 @@ +/path/to/this/repo -- 2.54.0 From bb3c7576f8470dba5fe01f2431976fb340e5fc3f Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 13 Aug 2026 20:34:14 +0200 Subject: [PATCH 12/14] docs: add setup documentation --- nix/hosts/README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++ tests/README.md | 3 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 nix/hosts/README.md diff --git a/nix/hosts/README.md b/nix/hosts/README.md new file mode 100644 index 00000000..ee7b2448 --- /dev/null +++ b/nix/hosts/README.md @@ -0,0 +1,67 @@ +# Hosts +These hosts are VMs used for running the integration tests on your local machine. +The hosts contain a client where abra with the tests will be run and a server +to simulate a remote machine. + +## Prepare the host +For this setup to work you need a machine with NixOS and flakes enabled. + +1. Import the abra flake +The install example is based on the [using nix flakes wiki page](https://nixos.wiki/wiki/flakes#Using_nix_flakes_with_NixOS). +```nix +inputs = { + abra = { + url = "git+https://git.coopcloud.tech/toolshed/abra.git"; + }; +}; +``` +2. Add the host module to your configuration +Now add the host module to your configuration. At the toplevel of a flake it could look like this: +```nix +desktop = inputs.nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + abra.nixosModules.host + ./configuration.nix + ]; + specialArgs = inputs; +}; +``` +3. Adjust the required config +There are to options defined for +```nix +abra.testing = { + enable = true; # loads the required config, when set true + externalInterface = "eth1"; # adjust this to your network interface that has access to the internet +}; +``` +You can look up the interface with `ip link`. After that rebuild your system and you are read to go. + +## Get started +All commands are run on the repository root path. +1. Set path to repo +The VM will create a shared volume from the content of the file `tests/resources/path_to_repo`. +Set the content of the file to the path of your abra repository. +This will share the repository from your machine with the VM and you can edit files while testing without rebuiling +or restarting the VM. +2. Create the VMs +```sh +make vm-client-create +make vm-server-create +``` +3. Start the VMs +```sh +make vm-client-start +make vm-server-start +``` +After running that command you should be able to ping the machines. +The client runs on 10.0.0.2 and server 10.0.0.3 +4. Connect to the client +Running the following command will connect to the client VM via SSH. +```sh +make vm-client-connect +``` +5. Run the tests +```sh +make test-integration +``` diff --git a/tests/README.md b/tests/README.md index 73858fbc..8a7ccecd 100644 --- a/tests/README.md +++ b/tests/README.md @@ -7,4 +7,5 @@ * Integration tests are in `./tests/integration`. Please see [these docs](https://docs.coopcloud.tech/abra/hack/#integration-tests) for - instructions and tips on how to run them. + instructions and tips on how to run them. If you want to run it locally via nix, + read the [nix testing docs](../nix/hosts/README.md). -- 2.54.0 From 21dccc895ddb1b60733d71e3d6b862edd8383ff1 Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 13 Aug 2026 20:38:20 +0200 Subject: [PATCH 13/14] docs: formatting --- nix/hosts/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nix/hosts/README.md b/nix/hosts/README.md index ee7b2448..6065c474 100644 --- a/nix/hosts/README.md +++ b/nix/hosts/README.md @@ -7,6 +7,7 @@ to simulate a remote machine. For this setup to work you need a machine with NixOS and flakes enabled. 1. Import the abra flake + The install example is based on the [using nix flakes wiki page](https://nixos.wiki/wiki/flakes#Using_nix_flakes_with_NixOS). ```nix inputs = { @@ -16,6 +17,7 @@ inputs = { }; ``` 2. Add the host module to your configuration + Now add the host module to your configuration. At the toplevel of a flake it could look like this: ```nix desktop = inputs.nixpkgs.lib.nixosSystem { @@ -28,7 +30,6 @@ desktop = inputs.nixpkgs.lib.nixosSystem { }; ``` 3. Adjust the required config -There are to options defined for ```nix abra.testing = { enable = true; # loads the required config, when set true @@ -40,6 +41,7 @@ You can look up the interface with `ip link`. After that rebuild your system and ## Get started All commands are run on the repository root path. 1. Set path to repo + The VM will create a shared volume from the content of the file `tests/resources/path_to_repo`. Set the content of the file to the path of your abra repository. This will share the repository from your machine with the VM and you can edit files while testing without rebuiling @@ -57,6 +59,7 @@ make vm-server-start After running that command you should be able to ping the machines. The client runs on 10.0.0.2 and server 10.0.0.3 4. Connect to the client + Running the following command will connect to the client VM via SSH. ```sh make vm-client-connect -- 2.54.0 From a28cc7afcef9c165dc928951a3797ec12c0897ac Mon Sep 17 00:00:00 2001 From: devydave Date: Thu, 13 Aug 2026 20:41:04 +0200 Subject: [PATCH 14/14] docs: more formatting and typo --- nix/hosts/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nix/hosts/README.md b/nix/hosts/README.md index 6065c474..6e09bf58 100644 --- a/nix/hosts/README.md +++ b/nix/hosts/README.md @@ -36,7 +36,7 @@ abra.testing = { externalInterface = "eth1"; # adjust this to your network interface that has access to the internet }; ``` -You can look up the interface with `ip link`. After that rebuild your system and you are read to go. +You can look up the interface with `ip link`. After that rebuild your system and you are ready to go. ## Get started All commands are run on the repository root path. @@ -46,6 +46,7 @@ The VM will create a shared volume from the content of the file `tests/resources Set the content of the file to the path of your abra repository. This will share the repository from your machine with the VM and you can edit files while testing without rebuiling or restarting the VM. + 2. Create the VMs ```sh make vm-client-create @@ -58,6 +59,7 @@ make vm-server-start ``` After running that command you should be able to ping the machines. The client runs on 10.0.0.2 and server 10.0.0.3 + 4. Connect to the client Running the following command will connect to the client VM via SSH. -- 2.54.0