From c64881b6da4779115e8ee36d7e4f6443d5283e5d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 18 Oct 2021 00:38:58 +0200 Subject: [PATCH] nixopsUnstable: Add test --- nixos/tests/all-tests.nix | 1 + nixos/tests/nixops/default.nix | 115 ++++++++++++++++++ .../nixops/legacy/base-configuration.nix | 31 +++++ nixos/tests/nixops/legacy/nixops.nix | 15 +++ .../networking/cluster/nixops/default.nix | 24 ++-- 5 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 nixos/tests/nixops/default.nix create mode 100644 nixos/tests/nixops/legacy/base-configuration.nix create mode 100644 nixos/tests/nixops/legacy/nixops.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index a6eb2c03258..12b67008291 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -311,6 +311,7 @@ in nitter = handleTest ./nitter.nix {}; nix-serve = handleTest ./nix-ssh-serve.nix {}; nix-ssh-serve = handleTest ./nix-ssh-serve.nix {}; + nixops = handleTest ./nixops/default.nix {}; nixos-generate-config = handleTest ./nixos-generate-config.nix {}; node-red = handleTest ./node-red.nix {}; nomad = handleTest ./nomad.nix {}; diff --git a/nixos/tests/nixops/default.nix b/nixos/tests/nixops/default.nix new file mode 100644 index 00000000000..4520b426849 --- /dev/null +++ b/nixos/tests/nixops/default.nix @@ -0,0 +1,115 @@ +{ pkgs, ... }: +let + inherit (pkgs) lib; + + tests = { + # TODO: uncomment stable + # - Blocked on https://github.com/NixOS/nixpkgs/issues/138584 which has a + # PR in staging: https://github.com/NixOS/nixpkgs/pull/139986 + # - Alternatively, blocked on a NixOps 2 release + # https://github.com/NixOS/nixops/issues/1242 + # stable = testsLegacyNetwork { nixopsPkg = pkgs.nixops; }; + unstable = testsForPackage { nixopsPkg = pkgs.nixopsUnstable; }; + + # inherit testsForPackage; + }; + + testsForPackage = lib.makeOverridable (args: lib.recurseIntoAttrs { + legacyNetwork = testLegacyNetwork args; + }); + + testLegacyNetwork = { nixopsPkg }: pkgs.nixosTest ({ + nodes = { + deployer = { config, lib, nodes, pkgs, ... }: { + imports = [ ../../modules/installer/cd-dvd/channel.nix ]; + environment.systemPackages = [ nixopsPkg ]; + nix.binaryCaches = lib.mkForce [ ]; + users.users.person.isNormalUser = true; + virtualisation.writableStore = true; + virtualisation.memorySize = 1024 /*MiB*/; + virtualisation.pathsInNixDB = [ + pkgs.hello + pkgs.figlet + + # This includes build dependencies all the way down. Not efficient, + # but we do need build deps to an *arbitrary* depth, which is hard to + # determine. + (allDrvOutputs nodes.server.config.system.build.toplevel) + ]; + }; + server = { lib, ... }: { + imports = [ ./legacy/base-configuration.nix ]; + }; + }; + + testScript = { nodes }: + let + deployerSetup = pkgs.writeScript "deployerSetup" '' + #!${pkgs.runtimeShell} + set -eux -o pipefail + cp --no-preserve=mode -r ${./legacy} unicorn + cp --no-preserve=mode ${../ssh-keys.nix} unicorn/ssh-keys.nix + mkdir -p ~/.ssh + cp ${snakeOilPrivateKey} ~/.ssh/id_ed25519 + chmod 0400 ~/.ssh/id_ed25519 + ''; + serverNetworkJSON = pkgs.writeText "server-network.json" + (builtins.toJSON nodes.server.config.system.build.networkConfig); + in + '' + import shlex + + def deployer_do(cmd): + cmd = shlex.quote(cmd) + return deployer.succeed(f"su person -l -c {cmd} &>/dev/console") + + start_all() + + deployer_do("cat /etc/hosts") + + deployer_do("${deployerSetup}") + deployer_do("cp ${serverNetworkJSON} unicorn/server-network.json") + + # Establish that ssh works, regardless of nixops + # Easy way to accept the server host key too. + server.wait_for_open_port(22) + deployer.wait_for_unit("network.target") + + # Put newlines on console, to flush the console reader's line buffer + # in case nixops' last output did not end in a newline, as is the case + # with a status line (if implemented?) + deployer.succeed("while sleep 60s; do echo [60s passed] >/dev/console; done &") + + deployer_do("cd ~/unicorn; ssh -oStrictHostKeyChecking=accept-new root@server echo hi") + + # Create and deploy + deployer_do("cd ~/unicorn; nixops create") + + deployer_do("cd ~/unicorn; nixops deploy --confirm") + + deployer_do("cd ~/unicorn; nixops ssh server 'hello | figlet'") + ''; + }); + + inherit (import ../ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; + + /* + Return a store path with a closure containing everything including + derivations and all build dependency outputs, all the way down. + */ + allDrvOutputs = pkg: + let name = lib.strings.sanitizeDerivationName "allDrvOutputs-${pkg.pname or pkg.name or "unknown"}"; + in + pkgs.runCommand name { refs = pkgs.writeReferencesToFile pkg.drvPath; } '' + touch $out + while read ref; do + case $ref in + *.drv) + cat $ref >>$out + ;; + esac + done <$refs + ''; + +in +tests diff --git a/nixos/tests/nixops/legacy/base-configuration.nix b/nixos/tests/nixops/legacy/base-configuration.nix new file mode 100644 index 00000000000..dba960f595c --- /dev/null +++ b/nixos/tests/nixops/legacy/base-configuration.nix @@ -0,0 +1,31 @@ +{ lib, modulesPath, pkgs, ... }: +let + ssh-keys = + if builtins.pathExists ../../ssh-keys.nix + then # Outside sandbox + ../../ssh-keys.nix + else # In sandbox + ./ssh-keys.nix; + + inherit (import ssh-keys pkgs) + snakeOilPrivateKey snakeOilPublicKey; +in +{ + imports = [ + (modulesPath + "/virtualisation/qemu-vm.nix") + (modulesPath + "/testing/test-instrumentation.nix") + ]; + virtualisation.writableStore = true; + nix.binaryCaches = lib.mkForce [ ]; + virtualisation.graphics = false; + documentation.enable = false; + services.qemuGuest.enable = true; + boot.loader.grub.enable = false; + + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keys = [ + snakeOilPublicKey + ]; + security.pam.services.sshd.limits = + [{ domain = "*"; item = "memlock"; type = "-"; value = 1024; }]; +} diff --git a/nixos/tests/nixops/legacy/nixops.nix b/nixos/tests/nixops/legacy/nixops.nix new file mode 100644 index 00000000000..795dc2a7182 --- /dev/null +++ b/nixos/tests/nixops/legacy/nixops.nix @@ -0,0 +1,15 @@ +{ + network = { + description = "Legacy Network using and legacy state."; + # NB this is not really what makes it a legacy network; lack of flakes is. + storage.legacy = { }; + }; + server = { lib, pkgs, ... }: { + deployment.targetEnv = "none"; + imports = [ + ./base-configuration.nix + (lib.modules.importJSON ./server-network.json) + ]; + environment.systemPackages = [ pkgs.hello pkgs.figlet ]; + }; +} diff --git a/pkgs/applications/networking/cluster/nixops/default.nix b/pkgs/applications/networking/cluster/nixops/default.nix index 91f5cb82668..4002f7478b3 100644 --- a/pkgs/applications/networking/cluster/nixops/default.nix +++ b/pkgs/applications/networking/cluster/nixops/default.nix @@ -1,4 +1,5 @@ -{ pkgs +{ nixosTests +, pkgs , poetry2nix , lib , overrides ? (self: super: {}) @@ -59,10 +60,17 @@ let } ).python; -in interpreter.pkgs.nixops.withPlugins(ps: [ - ps.nixops-encrypted-links - ps.nixops-virtd - ps.nixops-aws - ps.nixops-gcp - ps.nixopsvbox -]) + pkg = interpreter.pkgs.nixops.withPlugins(ps: [ + ps.nixops-encrypted-links + ps.nixops-virtd + ps.nixops-aws + ps.nixops-gcp + ps.nixopsvbox + ]) // rec { + # Workaround for https://github.com/NixOS/nixpkgs/issues/119407 + # TODO after #1199407: Use .overrideAttrs(pkg: old: { passthru.tests = .....; }) + tests = nixosTests.nixops.unstable.override { nixopsPkg = pkg; }; + # Not strictly necessary, but probably expected somewhere; part of the workaround: + passthru.tests = tests; + }; +in pkg