{ lib, config, pkgs, ... }: let inherit (import ./constants.nix) targetMachines pathToRoot; escapedJson = v: lib.replaceStrings [ "\"" ] [ "\\\\\"" ] (lib.strings.toJSON v); in { _class = "nixosTest"; imports = [ ./options.nix ]; name = "deployment-model"; sourceFileset = lib.fileset.unions [ ../../data-model.nix ../../function.nix ./constants.nix ./deployment.nix ]; nodes.deployer = { pkgs, ... }: { environment.systemPackages = with pkgs; [ jq ]; system.extraDependenciesFromModule = { pkgs, ... }: { environment.systemPackages = with pkgs; [ hello ]; }; }; extraTestScript = '' ${lib.concatStringsSep "\n" ( lib.lists.map ( nodeName: let deployment-config = { inherit (config) enableAcme; acmeNodeIP = if config.enableAcme then config.nodes.acme.networking.primaryIPAddress else null; host = nodeName; }; inherit ((import ./deployment.nix { inherit (pkgs) system; config = deployment-config; }).ssh-host.ssh ) host username key-file ; in '' with subtest("Check the status before deployment"): ${nodeName}.fail("${nodeName} 1>&2") with subtest("Run the deployment for ${nodeName}"): deployer.succeed(""" set -euo pipefail # INSTANTIATE command=(nix-instantiate --show-trace --expr ' let system = "${pkgs.system}"; # FIXME: what system are we deploying to? in import ${pathToRoot}/deployment/nixos.nix { inherit system; configuration = ( import ${pathToRoot}/deployment/check/data-model/deployment.nix { inherit system; config = builtins.fromJSON "${escapedJson deployment-config}"; } ).ssh-host.nixos-configuration; } ') # DEPLOY host="${lib.defaultTo "root" username}@${host}" sshOpts=( ${if key-file == null then "" else "-i ${key-file}"} -o StrictHostKeyChecking=no -o "ConnectTimeout=1" -o "ServerAliveInterval=1" ) # instantiate the config in /nix/store "''${command[@]}" --show-trace -A out_path # get the realized derivation to deploy outPath=$(nix-store --realize "$("''${command[@]}" --show-trace --eval --strict --json | jq -r '.drv_path')") # deploy the config by nix-copy-closure NIX_SSHOPTS="''${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes # switch the remote host to the config output=$(ssh "''${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; nohup $outPath/bin/switch-to-configuration switch &" 2>&1) || echo "status code: $?" echo "output: $output" if [[ $output != *"Timeout, server ${nodeName} not responding"* ]]; then echo "non-timeout error: $output" exit 1 else exit 0 fi """) ${nodeName}.wait_for_unit("multi-user.target") ${nodeName}.succeed("su - operator -c ${nodeName} 1>&2") '' ) targetMachines )} ''; }