aboutsummaryrefslogtreecommitdiffstats
path: root/tests/scenarios.nix
blob: ad4617d33bd511e71ccd03cdb5bf344f5570993c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Test scenarios for krops, besides populate's, which run through
# pkgs.populate here: writeDeploy's arguments to nixos-rebuild, which a
# stand-in records.  The arguments are those of populate's builder.nix,
# and targets, which give the target of each kind for a path.
{ targets, ... }@args:

with import ../pkgs/populate/tests/builder.nix (removeAttrs args [ "targets" ]);

{

  # writeDeploy's arguments to nixos-rebuild, which a stand-in records.
  # flake is what gets deployed: nothing, or a flake from a file, git, or
  # flake source, or one whose inputs get drawn from a source, by rewriting
  # its lock file or through a generated flake.
  deploy = matrix "deploy" {
    flake = [ "none" "file" "git" "source" "rewrite" "generated" ];
    etcFlake = [ false true ];
    buildTarget = [ false true ];
  } (flags: ctx: let
    target = targets.${ctx.targetKind} ctx.path;
    buildTarget = targets.local "${ctx.path}-build";
    build = if flags.buildTarget then buildTarget else target;
    # Without a user, ssh decides.
    userHost = target:
      optionalString (target.user != null && target.user != "") "${target.user}@" +
      target.host;
    expected = [ "switch" ]
      ++ optionals flags.buildTarget [
        "--build-host" (userHost buildTarget)
        "--target-host" (userHost target)
      ]
      ++ optional (flags.buildTarget && target.sudo) "--use-remote-sudo";
    # The flake's directory, which gets deployed by its resolved path, as
    # path:, so no enclosing Git work tree captures it, or as the Git work
    # tree it is.
    flakeDir =
      if flags.flake == "generated" then ".populate/flakes/x" else "x";
    scheme = if flags.flake == "git" then "git+file" else "path";
  in
    # The local target can't have another build target.
    if flags.buildTarget && ctx.targetKind == "local" then null else {
      node = if flags.buildTarget then "deployer" else null;
      # /etc/nixos/flake.nix only matters if no flake gets deployed.
      exhaustive = flags.etcFlake && flags.flake != "none";
      # Each scenario creates or removes /etc/nixos/flake.nix.
      prepare = ''
        rm -f /tmp/nixos-rebuild.log
        ${if flags.etcFlake then ''
          mkdir -p /etc/nixos
          touch /etc/nixos/flake.nix
        '' else ''
          rm -f /etc/nixos/flake.nix
        ''}
      '';
      phases = twice {
        sources = {
          none.x.file = "/fixtures/alt";
          file.x.file = "/fixtures/alt";
          git.x.git = { url = gitUrl; ref = gitHead; };
        }.${flags.flake} or (alt // {
          x.flake = {
            url = "/fixtures/top";
            fetchOnTarget = ctx.targetKind == "sudo";
          } // drawInputs (if flags.flake == "source" then "none" else flags.flake) {
            dep.follows = "alt";
          };
        });
        deploy = {
          flake = if flags.flake == "none" then null else "x";
        } // optionalAttrs flags.buildTarget {
          inherit buildTarget;
        };
        check = ''
          expect_eq user "$(sed -n 1p /tmp/nixos-rebuild.log)" 0
          expect_eq NIX_PATH "$(sed -n 2p /tmp/nixos-rebuild.log)" ${build.path}
          expected=${lib.escapeShellArg (concatStringsSep " " expected)}
          ${if flags.flake == "none" then optionalString flags.etcFlake ''
            expected="$expected --no-flake"
          '' else ''
            expected="$expected --flake ${scheme}:$(readlink -f ${build.path}/${flakeDir})"
          ''}
          expect_eq arguments "$(sed -n 3p /tmp/nixos-rebuild.log)" "$expected"
        '';
      };
    })

  # writeDeploy with allocateTTY: nixos-rebuild's output is a terminal on
  # the local target.  ssh allocates one on remote targets only if its own
  # input is a terminal, which the tests' isn't.
  ++ map (targetKind: scenario {
    name = "deploy-${targetKind}-allocateTTY";
    inherit targetKind;
    prepare = ''
      rm -f /tmp/nixos-rebuild.log /etc/nixos/flake.nix
    '';
    phases = [{
      sources.x.file = "/fixtures/alt";
      deploy.allocateTTY = true;
      check = ''
        expect_eq arguments "$(sed -n 3p /tmp/nixos-rebuild.log)" switch
        expect_eq terminal "$(sed -n 4p /tmp/nixos-rebuild.log)" ${
          if targetKind == "local" then "terminal" else "'no terminal'"
        }
      '';
    }];
  }) targetKinds;

}