1import ./make-test-python.nix ({ pkgs, lib, ... }: {
2 name = "containers-imperative";
3 meta = {
4 maintainers = with lib.maintainers; [ aristid aszlig eelco kampfschlaefer ];
5 };
6
7 nodes.machine =
8 { config, pkgs, lib, ... }:
9 { imports = [ ../modules/installer/cd-dvd/channel.nix ];
10
11 # XXX: Sandbox setup fails while trying to hardlink files from the host's
12 # store file system into the prepared chroot directory.
13 nix.settings.sandbox = false;
14 nix.settings.substituters = []; # don't try to access cache.nixos.org
15
16 virtualisation.writableStore = true;
17 # Make sure we always have all the required dependencies for creating a
18 # container available within the VM, because we don't have network access.
19 virtualisation.additionalPaths = let
20 emptyContainer = import ../lib/eval-config.nix {
21 modules = lib.singleton {
22 nixpkgs = { inherit (config.nixpkgs) localSystem; };
23
24 containers.foo.config = {
25 system.stateVersion = "18.03";
26 };
27 };
28
29 # The system is inherited from the host above.
30 # Set it to null, to remove the "legacy" entrypoint's non-hermetic default.
31 system = null;
32 };
33 in with pkgs; [
34 stdenv stdenvNoCC emptyContainer.config.containers.foo.path
35 libxslt desktop-file-utils texinfo docbook5 libxml2
36 docbook_xsl_ns xorg.lndir documentation-highlighter
37 ];
38 };
39
40 testScript = let
41 tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" ''
42 {
43 systemd.tmpfiles.rules = [ "d /foo - - - - -" ];
44 systemd.services.foo = {
45 serviceConfig.Type = "oneshot";
46 script = "ls -al /foo";
47 wantedBy = [ "multi-user.target" ];
48 };
49 }
50 '';
51 brokenCfg = pkgs.writeText "broken.nix" ''
52 {
53 assertions = [
54 { assertion = false;
55 message = "I never evaluate";
56 }
57 ];
58 }
59 '';
60 in ''
61 with subtest("Make sure we have a NixOS tree (required by ‘nixos-container create’)"):
62 machine.succeed("PAGER=cat nix-env -qa -A nixos.hello >&2")
63
64 id1, id2 = None, None
65
66 with subtest("Create some containers imperatively"):
67 id1 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip()
68 machine.log(f"created container {id1}")
69
70 id2 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip()
71 machine.log(f"created container {id2}")
72
73 assert id1 != id2
74
75 with subtest(f"Put the root of {id2} into a bind mount"):
76 machine.succeed(
77 f"mv /var/lib/nixos-containers/{id2} /id2-bindmount",
78 f"mount --bind /id2-bindmount /var/lib/nixos-containers/{id1}",
79 )
80
81 ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip()
82 ip2 = machine.succeed(f"nixos-container show-ip {id2}").rstrip()
83 assert ip1 != ip2
84
85 with subtest(
86 "Create a directory and a file we can later check if it still exists "
87 + "after destruction of the container"
88 ):
89 machine.succeed("mkdir /nested-bindmount")
90 machine.succeed("echo important data > /nested-bindmount/dummy")
91
92 with subtest(
93 "Create a directory with a dummy file and bind-mount it into both containers."
94 ):
95 for id in id1, id2:
96 important_path = f"/var/lib/nixos-containers/{id}/very/important/data"
97 machine.succeed(
98 f"mkdir -p {important_path}",
99 f"mount --bind /nested-bindmount {important_path}",
100 )
101
102 with subtest("Start one of them"):
103 machine.succeed(f"nixos-container start {id1}")
104
105 with subtest("Execute commands via the root shell"):
106 assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
107
108 with subtest("Execute a nix command via the root shell. (regression test for #40355)"):
109 machine.succeed(
110 f"nixos-container run {id1} -- nix-instantiate -E "
111 + '\'derivation { name = "empty"; builder = "false"; system = "false"; }\' '
112 )
113
114 with subtest("Stop and start (regression test for #4989)"):
115 machine.succeed(f"nixos-container stop {id1}")
116 machine.succeed(f"nixos-container start {id1}")
117
118 # clear serial backlog for next tests
119 machine.succeed("logger eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d")
120 machine.wait_for_console_text(
121 "eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d"
122 )
123
124 with subtest("Stop a container early"):
125 machine.succeed(f"nixos-container stop {id1}")
126 machine.succeed(f"nixos-container start {id1} >&2 &")
127 machine.wait_for_console_text("Stage 2")
128 machine.succeed(f"nixos-container stop {id1}")
129 machine.wait_for_console_text(f"Container {id1} exited successfully")
130 machine.succeed(f"nixos-container start {id1}")
131
132 with subtest("Stop a container without machined (regression test for #109695)"):
133 machine.systemctl("stop systemd-machined")
134 machine.succeed(f"nixos-container stop {id1}")
135 machine.wait_for_console_text(f"Container {id1} has been shut down")
136 machine.succeed(f"nixos-container start {id1}")
137
138 with subtest("tmpfiles are present"):
139 machine.log("creating container tmpfiles")
140 machine.succeed(
141 "nixos-container create tmpfiles --config-file ${tmpfilesContainerConfig}"
142 )
143 machine.log("created, starting…")
144 machine.succeed("nixos-container start tmpfiles")
145 machine.log("done starting, investigating…")
146 machine.succeed(
147 "echo $(nixos-container run tmpfiles -- systemctl is-active foo.service) | grep -q active;"
148 )
149 machine.succeed("nixos-container destroy tmpfiles")
150
151 with subtest("Execute commands via the root shell"):
152 assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname")
153
154 with subtest("Destroy the containers"):
155 for id in id1, id2:
156 machine.succeed(f"nixos-container destroy {id}")
157
158 with subtest("Check whether destruction of any container has killed important data"):
159 machine.succeed("grep -qF 'important data' /nested-bindmount/dummy")
160
161 with subtest("Ensure that the container path is gone"):
162 print(machine.succeed("ls -lsa /var/lib/nixos-containers"))
163 machine.succeed(f"test ! -e /var/lib/nixos-containers/{id1}")
164
165 with subtest("Ensure that a failed container creation doesn'leave any state"):
166 machine.fail(
167 "nixos-container create b0rk --config-file ${brokenCfg}"
168 )
169 machine.succeed("test ! -e /var/lib/nixos-containers/b0rk")
170 '';
171})