From 4e89f75ca6970549e5bfcd89fd41e239b6d83480 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Tue, 26 Nov 2019 00:43:52 +0100 Subject: [PATCH 1/3] nixos/containers-bridge: Port test to python --- nixos/tests/containers-bridge.nix | 65 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/nixos/tests/containers-bridge.nix b/nixos/tests/containers-bridge.nix index 38db64eb7931..2c8e8fa5370f 100644 --- a/nixos/tests/containers-bridge.nix +++ b/nixos/tests/containers-bridge.nix @@ -7,7 +7,7 @@ let containerIp6 = "fc00::2/7"; in -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "containers-bridge"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ aristid aszlig eelco kampfschlaefer ]; @@ -61,43 +61,42 @@ import ./make-test.nix ({ pkgs, ...} : { virtualisation.pathsInNixDB = [ pkgs.stdenv ]; }; - testScript = - '' - $machine->waitForUnit("default.target"); - $machine->succeed("nixos-container list") =~ /webserver/ or die; + testScript = '' + machine.wait_for_unit("default.target") + assert "webserver" in machine.succeed("nixos-container list") - # Start the webserver container. - $machine->succeed("nixos-container status webserver") =~ /up/ or die; + with subtest("Start the webserver container"): + assert "up" in machine.succeed("nixos-container status webserver") - # Check if bridges exist inside containers - $machine->succeed("nixos-container run webserver -- ip link show eth0"); - $machine->succeed("nixos-container run web-noip -- ip link show eth0"); + with subtest("Bridges exist inside containers"): + machine.succeed( + "nixos-container run webserver -- ip link show eth0", + "nixos-container run web-noip -- ip link show eth0", + ) - "${containerIp}" =~ /([^\/]+)\/([0-9+])/; - my $ip = $1; - chomp $ip; - $machine->succeed("ping -n -c 1 $ip"); - $machine->succeed("curl --fail http://$ip/ > /dev/null"); + ip = "${containerIp}".split("/")[0] + machine.succeed(f"ping -n -c 1 {ip}") + machine.succeed(f"curl --fail http://{ip}/ > /dev/null") - "${containerIp6}" =~ /([^\/]+)\/([0-9+])/; - my $ip6 = $1; - chomp $ip6; - $machine->succeed("ping -n -c 1 $ip6"); - $machine->succeed("curl --fail http://[$ip6]/ > /dev/null"); + ip6 = "${containerIp6}".split("/")[0] + machine.succeed(f"ping -n -c 1 {ip6}") + machine.succeed(f"curl --fail http://[{ip6}]/ > /dev/null") - # Check that nixos-container show-ip works in case of an ipv4 address with - # subnetmask in CIDR notation. - my $result = $machine->succeed("nixos-container show-ip webserver"); - chomp $result; - $result eq $ip or die; + with subtest( + "nixos-container show-ip works in case of an ipv4 address " + + "with subnetmask in CIDR notation." + ): + result = machine.succeed("nixos-container show-ip webserver").rstrip() + assert result == ip - # Stop the container. - $machine->succeed("nixos-container stop webserver"); - $machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null"); - $machine->fail("curl --fail --connect-timeout 2 http://[$ip6]/ > /dev/null"); - - # Destroying a declarative container should fail. - $machine->fail("nixos-container destroy webserver"); - ''; + with subtest("Stop the container"): + machine.succeed("nixos-container stop webserver") + machine.fail( + f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null", + f"curl --fail --connect-timeout 2 http://[{ip6}]/ > /dev/null", + ) + # Destroying a declarative container should fail. + machine.fail("nixos-container destroy webserver") + ''; }) From 07802f4d204c8cb5e9a8e6ff1ea25063f823798c Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Tue, 26 Nov 2019 00:44:12 +0100 Subject: [PATCH 2/3] nixos/containers-ip: Test both ipv4 and ipv6 in the same script --- nixos/release-combined.nix | 3 +- nixos/release-small.nix | 3 +- nixos/tests/all-tests.nix | 3 +- nixos/tests/containers-ip.nix | 77 +++++++++++++++++++++++++++++++++ nixos/tests/containers-ipv4.nix | 55 ----------------------- nixos/tests/containers-ipv6.nix | 60 ------------------------- 6 files changed, 80 insertions(+), 121 deletions(-) create mode 100644 nixos/tests/containers-ip.nix delete mode 100644 nixos/tests/containers-ipv4.nix delete mode 100644 nixos/tests/containers-ipv6.nix diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index 689f881cbea9..678ce3c28800 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -63,8 +63,7 @@ in rec { #(all nixos.tests.containers) (all nixos.tests.containers-imperative) - (all nixos.tests.containers-ipv4) - (all nixos.tests.containers-ipv6) + (all nixos.tests.containers-ip) nixos.tests.chromium.x86_64-linux or [] (all nixos.tests.firefox) (all nixos.tests.firewall) diff --git a/nixos/release-small.nix b/nixos/release-small.nix index 84af457801a1..74c16e990f35 100644 --- a/nixos/release-small.nix +++ b/nixos/release-small.nix @@ -32,8 +32,7 @@ in rec { tests = { inherit (nixos'.tests) containers-imperative - containers-ipv4 - containers-ipv6 + containers-ip firewall ipv6 login diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7945a239f6a0..df65ef249e8a 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -53,8 +53,7 @@ in containers-extra_veth = handleTest ./containers-extra_veth.nix {}; containers-hosts = handleTest ./containers-hosts.nix {}; containers-imperative = handleTest ./containers-imperative.nix {}; - containers-ipv4 = handleTest ./containers-ipv4.nix {}; - containers-ipv6 = handleTest ./containers-ipv6.nix {}; + containers-ip = handleTest ./containers-ip.nix {}; containers-macvlans = handleTest ./containers-macvlans.nix {}; containers-physical_interfaces = handleTest ./containers-physical_interfaces.nix {}; containers-restart_networking = handleTest ./containers-restart_networking.nix {}; diff --git a/nixos/tests/containers-ip.nix b/nixos/tests/containers-ip.nix new file mode 100644 index 000000000000..8583a08c6258 --- /dev/null +++ b/nixos/tests/containers-ip.nix @@ -0,0 +1,77 @@ +# Test for NixOS' container support. + +let + webserverFor = hostAddress: localAddress: { + inherit hostAddress localAddress; + privateNetwork = true; + config = { + services.httpd = { + enable = true; + adminAddr = "foo@example.org"; + }; + networking.firewall.allowedTCPPorts = [ 80 ]; + }; + }; + +in import ./make-test-python.nix ({ pkgs, ...} : { + name = "containers-ipv4-ipv6"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ aristid aszlig eelco kampfschlaefer ]; + }; + + machine = + { pkgs, ... }: { + imports = [ ../modules/installer/cd-dvd/channel.nix ]; + virtualisation = { + writableStore = true; + memorySize = 768; + }; + + containers.webserver4 = webserverFor "10.231.136.1" "10.231.136.2"; + containers.webserver6 = webserverFor "fc00::2" "fc00::1"; + virtualisation.pathsInNixDB = [ pkgs.stdenv ]; + }; + + testScript = { nodes, ... }: '' + import time + + + def curl_host(ip): + # put [] around ipv6 addresses for curl + host = ip if ":" not in ip else f"[{ip}]" + return f"curl --fail --connect-timeout 2 http://{host}/ > /dev/null" + + + def get_ip(container): + # need to distinguish because show-ip won't work for ipv6 + if container == "webserver4": + ip = machine.succeed(f"nixos-container show-ip {container}").rstrip() + assert ip == "${nodes.machine.config.containers.webserver4.localAddress}" + return ip + return "${nodes.machine.config.containers.webserver6.localAddress}" + + + for container in "webserver4", "webserver6": + assert container in machine.succeed("nixos-container list") + + with subtest(f"Start container {container}"): + machine.succeed(f"nixos-container start {container}") + # wait 2s for container to start and network to be up + time.sleep(2) + + # Since "start" returns after the container has reached + # multi-user.target, we should now be able to access it. + + ip = get_ip(container) + with subtest(f"{container} reacts to pings and HTTP requests"): + machine.succeed(f"ping -n -c1 {ip}") + machine.succeed(curl_host(ip)) + + with subtest(f"Stop container {container}"): + machine.succeed(f"nixos-container stop {container}") + machine.fail(curl_host(ip)) + + # Destroying a declarative container should fail. + machine.fail(f"nixos-container destroy {container}") + ''; +}) diff --git a/nixos/tests/containers-ipv4.nix b/nixos/tests/containers-ipv4.nix deleted file mode 100644 index ace68ff2df8b..000000000000 --- a/nixos/tests/containers-ipv4.nix +++ /dev/null @@ -1,55 +0,0 @@ -# Test for NixOS' container support. - -import ./make-test.nix ({ pkgs, ...} : { - name = "containers-ipv4"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ aristid aszlig eelco kampfschlaefer ]; - }; - - machine = - { pkgs, ... }: - { imports = [ ../modules/installer/cd-dvd/channel.nix ]; - virtualisation.writableStore = true; - virtualisation.memorySize = 768; - - containers.webserver = - { privateNetwork = true; - hostAddress = "10.231.136.1"; - localAddress = "10.231.136.2"; - config = - { services.httpd.enable = true; - services.httpd.adminAddr = "foo@example.org"; - networking.firewall.allowedTCPPorts = [ 80 ]; - system.stateVersion = "18.03"; - }; - }; - - virtualisation.pathsInNixDB = [ pkgs.stdenv ]; - }; - - testScript = - '' - $machine->succeed("nixos-container list") =~ /webserver/ or die; - - # Start the webserver container. - $machine->succeed("nixos-container start webserver"); - - # wait two seconds for the container to start and the network to be up - sleep 2; - - # Since "start" returns after the container has reached - # multi-user.target, we should now be able to access it. - my $ip = $machine->succeed("nixos-container show-ip webserver"); - chomp $ip; - $machine->succeed("ping -n -c1 $ip"); - $machine->succeed("curl --fail http://$ip/ > /dev/null"); - - # Stop the container. - $machine->succeed("nixos-container stop webserver"); - $machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null"); - - # Destroying a declarative container should fail. - $machine->fail("nixos-container destroy webserver"); - ''; - -}) diff --git a/nixos/tests/containers-ipv6.nix b/nixos/tests/containers-ipv6.nix deleted file mode 100644 index a9499d192bd4..000000000000 --- a/nixos/tests/containers-ipv6.nix +++ /dev/null @@ -1,60 +0,0 @@ -# Test for NixOS' container support. - -let - hostIp = "fc00::2"; - localIp = "fc00::1"; -in - -import ./make-test.nix ({ pkgs, ...} : { - name = "containers-ipv6"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ aristid aszlig eelco kampfschlaefer ]; - }; - - machine = - { pkgs, ... }: - { imports = [ ../modules/installer/cd-dvd/channel.nix ]; - virtualisation.writableStore = true; - virtualisation.memorySize = 768; - - containers.webserver = - { privateNetwork = true; - hostAddress6 = hostIp; - localAddress6 = localIp; - config = - { services.httpd.enable = true; - services.httpd.adminAddr = "foo@example.org"; - networking.firewall.allowedTCPPorts = [ 80 ]; - }; - }; - - virtualisation.pathsInNixDB = [ pkgs.stdenv ]; - }; - - testScript = - '' - $machine->waitForUnit("default.target"); - $machine->succeed("nixos-container list") =~ /webserver/ or die; - - # Start the webserver container. - $machine->succeed("nixos-container start webserver"); - - # wait two seconds for the container to start and the network to be up - sleep 2; - - # Since "start" returns after the container has reached - # multi-user.target, we should now be able to access it. - my $ip = "${localIp}"; - chomp $ip; - $machine->succeed("ping -n -c 1 $ip"); - $machine->succeed("curl --fail http://[$ip]/ > /dev/null"); - - # Stop the container. - $machine->succeed("nixos-container stop webserver"); - $machine->fail("curl --fail --connect-timeout 2 http://[$ip]/ > /dev/null"); - - # Destroying a declarative container should fail. - $machine->fail("nixos-container destroy webserver"); - ''; - -}) From 9de0a8a7b3d15c8a0d0f561589b3c31572e8aebd Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Tue, 26 Nov 2019 09:11:30 +0100 Subject: [PATCH 3/3] nixos/containers-imperative: Port test to python --- nixos/tests/containers-imperative.nix | 156 +++++++++++++------------- 1 file changed, 80 insertions(+), 76 deletions(-) diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix index 2e7e4b2f1d69..61df74042cb3 100644 --- a/nixos/tests/containers-imperative.nix +++ b/nixos/tests/containers-imperative.nix @@ -1,6 +1,6 @@ # Test for NixOS' container support. -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "containers-imperative"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ aristid aszlig eelco kampfschlaefer ]; @@ -36,95 +36,99 @@ import ./make-test.nix ({ pkgs, ...} : { }; testScript = let - tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" '' - { - systemd.tmpfiles.rules = [ "d /foo - - - - -" ]; - systemd.services.foo = { - serviceConfig.Type = "oneshot"; - script = "ls -al /foo"; - wantedBy = [ "multi-user.target" ]; - }; - } - ''; in - '' - # Make sure we have a NixOS tree (required by ‘nixos-container create’). - $machine->succeed("PAGER=cat nix-env -qa -A nixos.hello >&2"); + tmpfilesContainerConfig = pkgs.writeText "container-config-tmpfiles" '' + { + systemd.tmpfiles.rules = [ "d /foo - - - - -" ]; + systemd.services.foo = { + serviceConfig.Type = "oneshot"; + script = "ls -al /foo"; + wantedBy = [ "multi-user.target" ]; + }; + } + ''; + in '' + with subtest("Make sure we have a NixOS tree (required by ‘nixos-container create’)"): + machine.succeed("PAGER=cat nix-env -qa -A nixos.hello >&2") - # Create some containers imperatively. - my $id1 = $machine->succeed("nixos-container create foo --ensure-unique-name"); - chomp $id1; - $machine->log("created container $id1"); + id1, id2 = None, None - my $id2 = $machine->succeed("nixos-container create foo --ensure-unique-name"); - chomp $id2; - $machine->log("created container $id2"); + with subtest("Create some containers imperatively"): + id1 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip() + machine.log(f"created container {id1}") - die if $id1 eq $id2; + id2 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip() + machine.log(f"created container {id2}") - # Put the root of $id2 into a bind mount. - $machine->succeed( - "mv /var/lib/containers/$id2 /id2-bindmount", - "mount --bind /id2-bindmount /var/lib/containers/$id1" - ); + assert id1 != id2 - my $ip1 = $machine->succeed("nixos-container show-ip $id1"); - chomp $ip1; - my $ip2 = $machine->succeed("nixos-container show-ip $id2"); - chomp $ip2; - die if $ip1 eq $ip2; + with subtest(f"Put the root of {id2} into a bind mount"): + machine.succeed( + f"mv /var/lib/containers/{id2} /id2-bindmount", + f"mount --bind /id2-bindmount /var/lib/containers/{id1}", + ) - # Create a directory and a file we can later check if it still exists - # after destruction of the container. - $machine->succeed( - "mkdir /nested-bindmount", - "echo important data > /nested-bindmount/dummy", - ); + ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip() + ip2 = machine.succeed(f"nixos-container show-ip {id2}").rstrip() + assert ip1 != ip2 - # Create a directory with a dummy file and bind-mount it into both - # containers. - foreach ($id1, $id2) { - my $importantPath = "/var/lib/containers/$_/very/important/data"; - $machine->succeed( - "mkdir -p $importantPath", - "mount --bind /nested-bindmount $importantPath" - ); - } + with subtest( + "Create a directory and a file we can later check if it still exists " + + "after destruction of the container" + ): + machine.succeed("mkdir /nested-bindmount") + machine.succeed("echo important data > /nested-bindmount/dummy") - # Start one of them. - $machine->succeed("nixos-container start $id1"); + with subtest( + "Create a directory with a dummy file and bind-mount it into both containers." + ): + for id in id1, id2: + important_path = f"/var/lib/containers/{id}/very/important/data" + machine.succeed( + f"mkdir -p {important_path}", + f"mount --bind /nested-bindmount {important_path}", + ) - # Execute commands via the root shell. - $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die; + with subtest("Start one of them"): + machine.succeed(f"nixos-container start {id1}") - # Execute a nix command via the root shell. (regression test for #40355) - $machine->succeed("nixos-container run $id1 -- nix-instantiate -E 'derivation { name = \"empty\"; builder = \"false\"; system = \"false\"; }'"); + with subtest("Execute commands via the root shell"): + assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname") - # Stop and start (regression test for #4989) - $machine->succeed("nixos-container stop $id1"); - $machine->succeed("nixos-container start $id1"); + with subtest("Execute a nix command via the root shell. (regression test for #40355)"): + machine.succeed( + f"nixos-container run {id1} -- nix-instantiate -E " + + '\'derivation { name = "empty"; builder = "false"; system = "false"; }\' ' + ) - # Ensure tmpfiles are present - $machine->log("creating container tmpfiles"); - $machine->succeed("nixos-container create tmpfiles --config-file ${tmpfilesContainerConfig}"); - $machine->log("created, starting…"); - $machine->succeed("nixos-container start tmpfiles"); - $machine->log("done starting, investigating…"); - $machine->succeed("echo \$(nixos-container run tmpfiles -- systemctl is-active foo.service) | grep -q active;"); - $machine->succeed("nixos-container destroy tmpfiles"); + with subtest("Stop and start (regression test for #4989)"): + machine.succeed(f"nixos-container stop {id1}") + machine.succeed(f"nixos-container start {id1}") - # Execute commands via the root shell. - $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die; + with subtest("tmpfiles are present"): + machine.log("creating container tmpfiles") + machine.succeed( + "nixos-container create tmpfiles --config-file ${tmpfilesContainerConfig}" + ) + machine.log("created, starting…") + machine.succeed("nixos-container start tmpfiles") + machine.log("done starting, investigating…") + machine.succeed( + "echo $(nixos-container run tmpfiles -- systemctl is-active foo.service) | grep -q active;" + ) + machine.succeed("nixos-container destroy tmpfiles") - # Destroy the containers. - $machine->succeed("nixos-container destroy $id1"); - $machine->succeed("nixos-container destroy $id2"); + with subtest("Execute commands via the root shell"): + assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname") - $machine->succeed( - # Check whether destruction of any container has killed important data - "grep -qF 'important data' /nested-bindmount/dummy", - # Ensure that the container path is gone - "test ! -e /var/lib/containers/$id1" - ); + with subtest("Destroy the containers"): + for id in id1, id2: + machine.succeed(f"nixos-container destroy {id}") + + with subtest("Check whether destruction of any container has killed important data"): + machine.succeed("grep -qF 'important data' /nested-bindmount/dummy") + + with subtest("Ensure that the container path is gone"): + print(machine.succeed("ls -lsa /var/lib/containers")) + machine.succeed(f"test ! -e /var/lib/containers/{id1}") ''; - })