diff options
Diffstat (limited to 'nixos')
44 files changed, 568 insertions, 478 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2003.xml b/nixos/doc/manual/release-notes/rl-2003.xml index 4980a99e6468..2a5064c71b0f 100644 --- a/nixos/doc/manual/release-notes/rl-2003.xml +++ b/nixos/doc/manual/release-notes/rl-2003.xml @@ -186,6 +186,19 @@ The osquery module has been removed. </para> </listitem> + <listitem> + <para> + Going forward, <literal>~/bin</literal> in the users home directory will no longer be in <literal>PATH</literal> by default. + If you depend on this you should set the option <literal>environment.homeBinInPath</literal> to <literal>true</literal>. + The aforementioned option was added this release. + </para> + </listitem> + <listitem> + <para> + The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output. + This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output. + </para> + </listitem> </itemizedlist> </section> diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index b79e16cd7979..a0a20228a742 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -122,7 +122,7 @@ in description = '' Include ~/bin/ in $PATH. ''; - default = true; + default = false; type = types.bool; }; diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 1e18e927ec6e..fcb30187fa2f 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -111,9 +111,10 @@ in config = mkIf enabled { assertions = [ { - assertion = with config.services.xserver.displayManager; gdm.enable -> !gdm.wayland; - message = "NVIDIA drivers don't support wayland, set services.xserver.displayManager.gdm.wayland=false"; + assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable; + message = "You cannot use wayland with GDM without modesetting enabled for NVIDIA drivers, set `hardware.nvidia.modesetting.enable = true`"; } + { assertion = !optimusCfg.enable || (optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != ""); diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9e0d9478b5de..076e1654818a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -307,6 +307,7 @@ ./services/desktops/gnome3/sushi.nix ./services/desktops/gnome3/tracker.nix ./services/desktops/gnome3/tracker-miners.nix + ./services/desktops/neard.nix ./services/desktops/profile-sync-daemon.nix ./services/desktops/system-config-printer.nix ./services/desktops/telepathy.nix diff --git a/nixos/modules/programs/ssmtp.nix b/nixos/modules/programs/ssmtp.nix index 0e060e3f5226..e45748af205a 100644 --- a/nixos/modules/programs/ssmtp.nix +++ b/nixos/modules/programs/ssmtp.nix @@ -8,18 +8,16 @@ with lib; let - - cfg = config.networking.defaultMailServer; + cfg = config.services.ssmtp; in - { options = { - networking.defaultMailServer = { + services.ssmtp = { - directDelivery = mkOption { + enable = mkOption { type = types.bool; default = false; description = '' @@ -29,7 +27,7 @@ in <command>sendmail</command> or <command>postfix</command> on your machine, set this option to <literal>true</literal>, and set the option - <option>networking.defaultMailServer.hostName</option> to the + <option>services.ssmtp.hostName</option> to the host name of your preferred mail server. ''; }; @@ -129,9 +127,9 @@ in }; - config = mkIf cfg.directDelivery { + config = mkIf cfg.enable { - networking.defaultMailServer.authPassFile = mkIf (cfg.authPass != "") + services.ssmtp.authPassFile = mkIf (cfg.authPass != "") (mkDefault (toString (pkgs.writeTextFile { name = "ssmtp-authpass"; text = cfg.authPass; diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index d4bce3b49d36..e392fef54dde 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -11,6 +11,8 @@ with lib; (mkRenamedOptionModule [ "networking" "enableRTL8192cFirmware" ] [ "hardware" "enableRedistributableFirmware" ]) (mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ]) (mkRenamedOptionModule [ "networking" "connman" ] [ "services" "connman" ]) + (mkRenamedOptionModule [ "networking" "defaultMailServer" ] [ "services" "ssmtp" ]) + (mkRenamedOptionModule [ "services" "ssmtp" "directDelivery" ] [ "services" "ssmtp" "enable" ]) (mkChangedOptionModule [ "services" "printing" "gutenprint" ] [ "services" "printing" "drivers" ] (config: let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config; diff --git a/nixos/modules/services/audio/roon-server.nix b/nixos/modules/services/audio/roon-server.nix index 4eda3c5708da..6aed485638cc 100644 --- a/nixos/modules/services/audio/roon-server.nix +++ b/nixos/modules/services/audio/roon-server.nix @@ -66,7 +66,8 @@ in { if cfg.user == "roon-server" then { isSystemUser = true; description = "Roon Server user"; - groups = [ cfg.group "audio" ]; + group = cfg.group; + extraGroups = [ "audio" ]; } else {}; }; diff --git a/nixos/modules/services/desktops/neard.nix b/nixos/modules/services/desktops/neard.nix new file mode 100644 index 000000000000..9b0f8d1b3a77 --- /dev/null +++ b/nixos/modules/services/desktops/neard.nix @@ -0,0 +1,23 @@ +# neard service. +{ config, lib, pkgs, ... }: + +with lib; + +{ + ###### interface + options = { + services.neard = { + enable = mkEnableOption "neard, NFC daemon"; + }; + }; + + + ###### implementation + config = mkIf config.services.neard.enable { + environment.systemPackages = [ pkgs.neard ]; + + services.dbus.packages = [ pkgs.neard ]; + + systemd.packages = [ pkgs.neard ]; + }; +} diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix index c5f9d1f9b725..7b13beea1ca9 100644 --- a/nixos/modules/services/hardware/bluetooth.nix +++ b/nixos/modules/services/hardware/bluetooth.nix @@ -36,17 +36,25 @@ in { ''; }; + config = mkOption { + type = with types; attrsOf (attrsOf (oneOf [ bool int str ])); + example = { + General = { + ControllerMode = "bredr"; + }; + }; + description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf)."; + }; + extraConfig = mkOption { - type = types.lines; - default = ""; + type = with types; nullOr lines; + default = null; example = '' [General] ControllerMode = bredr ''; description = '' Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf). - - NOTE: We already include [Policy], so any configuration under the Policy group should come first. ''; }; }; @@ -56,16 +64,18 @@ in { ###### implementation config = mkIf cfg.enable { + warnings = optional (cfg.extraConfig != null) "hardware.bluetooth.`extraConfig` is deprecated, please use hardware.bluetooth.`config`."; + + hardware.bluetooth.config = { + Policy = { + AutoEnable = mkDefault cfg.powerOnBoot; + }; + }; environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ]; environment.etc = singleton { - source = pkgs.writeText "main.conf" '' - [Policy] - AutoEnable=${lib.boolToString cfg.powerOnBoot} - - ${cfg.extraConfig} - ''; + source = pkgs.writeText "main.conf" (generators.toINI { } cfg.config + optionalString (cfg.extraConfig != null) cfg.extraConfig); target = "bluetooth/main.conf"; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 35b513bac571..53f32b8fadc7 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -197,6 +197,9 @@ in services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey; })] ++ [(mkIf config.services.rspamd.enable { services.prometheus.exporters.rspamd.url = mkDefault "http://localhost:11334/stat"; + })] ++ [(mkIf config.services.nginx.enable { + systemd.services.prometheus-nginx-exporter.after = [ "nginx.service" ]; + systemd.services.prometheus-nginx-exporter.requires = [ "nginx.service" ]; })] ++ (mapAttrsToList (name: conf: mkExporterConf { inherit name; diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index c66011afccbe..875ab70bfc73 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -115,7 +115,7 @@ in type = types.package; default = pkgs.samba; defaultText = "pkgs.samba"; - example = literalExample "pkgs.samba3"; + example = literalExample "pkgs.samba4Full"; description = '' Defines which package should be used for the samba server. ''; diff --git a/nixos/modules/services/networking/dnschain.nix b/nixos/modules/services/networking/dnschain.nix index 5b58ea9b0c91..b837bf816a15 100644 --- a/nixos/modules/services/networking/dnschain.nix +++ b/nixos/modules/services/networking/dnschain.nix @@ -137,7 +137,7 @@ in ]; services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries { - forwardZones = + forwardZonesRecurse = { bit = "127.0.0.1:${toString cfg.dns.port}"; dns = "127.0.0.1:${toString cfg.dns.port}"; }; diff --git a/nixos/modules/services/networking/pdns-recursor.nix b/nixos/modules/services/networking/pdns-recursor.nix index ebfdd9f35b72..e55ea3633781 100644 --- a/nixos/modules/services/networking/pdns-recursor.nix +++ b/nixos/modules/services/networking/pdns-recursor.nix @@ -91,10 +91,18 @@ in { forwardZones = mkOption { type = types.attrs; + default = {}; + description = '' + DNS zones to be forwarded to other authoritative servers. + ''; + }; + + forwardZonesRecurse = mkOption { + type = types.attrs; example = { eth = "127.0.0.1:5353"; }; default = {}; description = '' - DNS zones to be forwarded to other servers. + DNS zones to be forwarded to other recursive servers. ''; }; @@ -158,7 +166,8 @@ in { webserver-port = cfg.api.port; webserver-allow-from = cfg.api.allowFrom; - forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; + forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; + forward-zones-recurse = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZonesRecurse; export-etc-hosts = cfg.exportHosts; dnssec = cfg.dnssecValidation; serve-rfc1918 = cfg.serveRFC1918; diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index 294c0d70edea..8f05c3949fba 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -236,9 +236,12 @@ in { ${if ifaces == [] then '' for i in $(cd /sys/class/net && echo *); do DEVTYPE= - source /sys/class/net/$i/uevent - if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then - ifaces="$ifaces''${ifaces:+ -N} -i$i" + UEVENT_PATH=/sys/class/net/$i/uevent + if [ -e "$UEVENT_PATH" ]; then + source "$UEVENT_PATH" + if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then + ifaces="$ifaces''${ifaces:+ -N} -i$i" + fi fi done '' else '' diff --git a/nixos/modules/services/web-apps/matomo-doc.xml b/nixos/modules/services/web-apps/matomo-doc.xml index 79cece551d34..69d1170e4523 100644 --- a/nixos/modules/services/web-apps/matomo-doc.xml +++ b/nixos/modules/services/web-apps/matomo-doc.xml @@ -86,12 +86,6 @@ GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost'; <itemizedlist> <listitem> <para> - Matomo's file integrity check will warn you. This is due to the patches - necessary for NixOS, you can safely ignore this. - </para> - </listitem> - <listitem> - <para> Matomo will warn you that the JavaScript tracker is not writable. This is because it's located in the read-only nix store. You can safely ignore this, unless you need a plugin that needs JavaScript tracker access. diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 0af9ccfcf3e4..912ec5bd38ed 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -126,11 +126,21 @@ in wayland = mkOption { default = true; description = '' - Allow GDM run on Wayland instead of Xserver + Allow GDM to run on Wayland instead of Xserver. + Note to enable Wayland with Nvidia you need to + enable the <option>nvidiaWayland</option>. ''; type = types.bool; }; + nvidiaWayland = mkOption { + default = false; + description = '' + Whether to allow wayland to be used with the proprietary + NVidia graphics driver. + ''; + }; + autoSuspend = mkOption { default = true; description = '' @@ -237,6 +247,19 @@ in services.dbus.packages = [ gdm ]; + # We duplicate upstream's udev rules manually to make wayland with nvidia configurable + services.udev.extraRules = '' + # disable Wayland on Cirrus chipsets + ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="${gdm}/libexec/gdm-disable-wayland" + # disable Wayland on Hi1710 chipsets + ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="${gdm}/libexec/gdm-disable-wayland" + ${optionalString (!cfg.gdm.nvidiaWayland) '' + DRIVER=="nvidia", RUN+="${gdm}/libexec/gdm-disable-wayland" + ''} + # disable Wayland when modesetting is disabled + IMPORT{cmdline}="nomodeset", RUN+="${gdm}/libexec/gdm-disable-wayland" + ''; + systemd.user.services.dbus.wantedBy = [ "default.target" ]; programs.dconf.profiles.gdm = diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index 641cf9faadc9..12a80a12d19f 100644 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -214,7 +214,17 @@ while (my ($unit, $state) = each %{$activePrev}) { # Reload the changed mount unit to force a remount. $unitsToReload{$unit} = 1; recordUnit($reloadListFile, $unit); - } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/ || $unit =~ /\.slice$/) { + } elsif ($unit =~ /\.socket$/) { + my $unitInfo = parseUnit($newUnitFile); + # If a socket unit has been changed, the corresponding + # service unit has to be stopped before the socket can + # be restarted. The service will be started again on demand. + my $serviceUnit = $unitInfo->{'Unit'} // "$baseName.service"; + $unitsToStop{$serviceUnit} = 1; + $unitsToStop{$unit} = 1; + $unitsToStart{$unit} = 1; + recordUnit($startListFile, $unit); + } elsif ($unit =~ /\.path$/ || $unit =~ /\.slice$/) { # FIXME: do something? } else { my $unitInfo = parseUnit($newUnitFile); 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-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; - - # Start the webserver container. - $machine->succeed("nixos-container status webserver") =~ /up/ or die; - - # 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"); - - "${containerIp}" =~ /([^\/]+)\/([0-9+])/; - my $ip = $1; - chomp $ip; - $machine->succeed("ping -n -c 1 $ip"); - $machine->succeed("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"); - - # 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; - - # 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"); - ''; - + testScript = '' + machine.wait_for_unit("default.target") + assert "webserver" in machine.succeed("nixos-container list") + + with subtest("Start the webserver container"): + assert "up" in machine.succeed("nixos-container status webserver") + + 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", + ) + + ip = "${containerIp}".split("/")[0] + machine.succeed(f"ping -n -c 1 {ip}") + machine.succeed(f"curl --fail http://{ip}/ > /dev/null") + + ip6 = "${containerIp6}".split("/")[0] + machine.succeed(f"ping -n -c 1 {ip6}") + machine.succeed(f"curl --fail http://[{ip6}]/ > /dev/null") + + 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 + + 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") + ''; }) diff --git a/nixos/tests/containers-ephemeral.nix b/nixos/tests/containers-ephemeral.nix index 1ef8717d9a0e..692554ac0ba2 100644 --- a/nixos/tests/containers-ephemeral.nix +++ b/nixos/tests/containers-ephemeral.nix @@ -1,6 +1,6 @@ # Test for NixOS' container support. -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "containers-ephemeral"; machine = { pkgs, ... }: { @@ -16,10 +16,10 @@ import ./make-test.nix ({ pkgs, ...} : { services.nginx = { enable = true; virtualHosts.localhost = { - root = (pkgs.runCommand "localhost" {} '' + root = pkgs.runCommand "localhost" {} '' mkdir "$out" echo hello world > "$out/index.html" - ''); + ''; }; }; networking.firewall.allowedTCPPorts = [ 80 ]; @@ -28,29 +28,27 @@ import ./make-test.nix ({ pkgs, ...} : { }; testScript = '' - $machine->succeed("nixos-container list") =~ /webserver/ or die; + assert "webserver" in machine.succeed("nixos-container list") - # Start the webserver container. - $machine->succeed("nixos-container start webserver"); + machine.succeed("nixos-container start webserver") - # Check that container got its own root folder - $machine->succeed("ls /run/containers/webserver"); + with subtest("Container got its own root folder"): + machine.succeed("ls /run/containers/webserver") - # Check that container persistent directory is not created - $machine->fail("ls /var/lib/containers/webserver"); + with subtest("Container persistent directory is not created"): + machine.fail("ls /var/lib/containers/webserver") # 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"); + ip = machine.succeed("nixos-container show-ip webserver").rstrip() + machine.succeed(f"ping -n -c1 {ip}") + machine.succeed(f"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"); + with subtest("Stop the container"): + machine.succeed("nixos-container stop webserver") + machine.fail(f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null") - # Check that container's root folder was removed - $machine->fail("ls /run/containers/webserver"); + with subtest("Container's root folder was removed"): + machine.fail("ls /run/containers/webserver") ''; }) diff --git a/nixos/tests/containers-hosts.nix b/nixos/tests/containers-hosts.nix index 8cf298c62258..d6fb4a761eef 100644 --- a/nixos/tests/containers-hosts.nix +++ b/nixos/tests/containers-hosts.nix @@ -1,6 +1,6 @@ # Test for NixOS' container support. -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "containers-hosts"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ montag451 ]; @@ -42,11 +42,11 @@ import ./make-test.nix ({ pkgs, ...} : { }; testScript = '' - startAll; - $machine->waitForUnit("default.target"); + start_all() + machine.wait_for_unit("default.target") - # Ping the containers using the entries added in /etc/hosts - $machine->succeed("ping -n -c 1 simple.containers"); - $machine->succeed("ping -n -c 1 netmask.containers"); + with subtest("Ping the containers using the entries added in /etc/hosts"): + for host in "simple.containers", "netmask.containers": + machine.succeed(f"ping -n -c 1 {host}") ''; }) 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"); - - # Create some containers imperatively. - my $id1 = $machine->succeed("nixos-container create foo --ensure-unique-name"); - chomp $id1; - $machine->log("created container $id1"); - - my $id2 = $machine->succeed("nixos-container create foo --ensure-unique-name"); - chomp $id2; - $machine->log("created container $id2"); - - die if $id1 eq $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" - ); - - 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; - - # 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", - ); - - # 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" - ); - } - - # Start one of them. - $machine->succeed("nixos-container start $id1"); - - # Execute commands via the root shell. - $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die; - - # 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\"; }'"); - - # Stop and start (regression test for #4989) - $machine->succeed("nixos-container stop $id1"); - $machine->succeed("nixos-container start $id1"); - - # 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"); - - # Execute commands via the root shell. - $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die; - - # Destroy the containers. - $machine->succeed("nixos-container destroy $id1"); - $machine->succeed("nixos-container destroy $id2"); - - $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" - ); + 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") + + id1, id2 = None, None + + with subtest("Create some containers imperatively"): + id1 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip() + machine.log(f"created container {id1}") + + id2 = machine.succeed("nixos-container create foo --ensure-unique-name").rstrip() + machine.log(f"created container {id2}") + + assert id1 != id2 + + 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}", + ) + + ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip() + ip2 = machine.succeed(f"nixos-container show-ip {id2}").rstrip() + assert ip1 != ip2 + + 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") + + 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}", + ) + + with subtest("Start one of them"): + machine.succeed(f"nixos-container start {id1}") + + with subtest("Execute commands via the root shell"): + assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname") + + 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"; }\' ' + ) + + with subtest("Stop and start (regression test for #4989)"): + machine.succeed(f"nixos-container stop {id1}") + machine.succeed(f"nixos-container start {id1}") + + 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") + + with subtest("Execute commands via the root shell"): + assert "Linux" in machine.succeed(f"nixos-container run {id1} -- uname") + + 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}") ''; - }) 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"); - ''; - -}) diff --git a/nixos/tests/containers-reloadable.nix b/nixos/tests/containers-reloadable.nix index f41dea91b1e4..35aff91e85b5 100644 --- a/nixos/tests/containers-reloadable.nix +++ b/nixos/tests/containers-reloadable.nix @@ -1,7 +1,7 @@ -import ./make-test.nix ({ pkgs, lib, ...} : +import ./make-test-python.nix ({ pkgs, lib, ...} : let client_base = { - + containers.test1 = { autoStart = true; config = { @@ -48,18 +48,25 @@ in { c1System = nodes.client_c1.config.system.build.toplevel; c2System = nodes.client_c2.config.system.build.toplevel; in '' - $client->start(); - $client->waitForUnit("default.target"); - $client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_base ]] >&2"); + client.start() + client.wait_for_unit("default.target") + + assert "client_base" in client.succeed("nixos-container run test1 cat /etc/check") - $client->succeed("${c1System}/bin/switch-to-configuration test >&2"); - $client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c1 ]] >&2"); - $client->succeed("systemctl status httpd -M test1 >&2"); + with subtest("httpd is available after activating config1"): + client.succeed( + "${c1System}/bin/switch-to-configuration test >&2", + "[[ $(nixos-container run test1 cat /etc/check) == client_c1 ]] >&2", + "systemctl status httpd -M test1 >&2", + ) - $client->succeed("${c2System}/bin/switch-to-configuration test >&2"); - $client->succeed("[[ \$(nixos-container run test1 cat /etc/check) == client_c2 ]] >&2"); - $client->fail("systemctl status httpd -M test1 >&2"); - $client->succeed("systemctl status nginx -M test1 >&2"); + with subtest("httpd is not available any longer after switching to config2"): + client.succeed( + "${c2System}/bin/switch-to-configuration test >&2", + "[[ $(nixos-container run test1 cat /etc/check) == client_c2 ]] >&2", + "systemctl status nginx -M test1 >&2", + ) + client.fail("systemctl status httpd -M test1 >&2") ''; }) diff --git a/nixos/tests/containers-tmpfs.nix b/nixos/tests/containers-tmpfs.nix index e29fe6bbf032..171e8f01c7b9 100644 --- a/nixos/tests/containers-tmpfs.nix +++ b/nixos/tests/containers-tmpfs.nix @@ -1,6 +1,6 @@ # Test for NixOS' container support. -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "containers-tmpfs"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ kampka ]; @@ -31,49 +31,63 @@ import ./make-test.nix ({ pkgs, ...} : { virtualisation.pathsInNixDB = [ pkgs.stdenv ]; }; - testScript = - '' - $machine->waitForUnit("default.target"); - $machine->succeed("nixos-container list") =~ /tmpfs/ or die; - - # Start the tmpfs container. - #$machine->succeed("nixos-container status tmpfs") =~ /up/ or die; - - # Verify that /var is mounted as a tmpfs - #$machine->succeed("nixos-container run tmpfs -- systemctl status var.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die; - $machine->succeed("nixos-container run tmpfs -- mountpoint -q /var 2>/dev/null"); - - # Verify that /var/log is mounted as a tmpfs - $machine->succeed("nixos-container run tmpfs -- systemctl status var-log.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die; - $machine->succeed("nixos-container run tmpfs -- mountpoint -q /var/log 2>/dev/null"); - - # Verify that /some/random/path is mounted as a tmpfs - $machine->succeed("nixos-container run tmpfs -- systemctl status some-random-path.mount --no-pager 2>/dev/null") =~ /What: tmpfs/ or die; - $machine->succeed("nixos-container run tmpfs -- mountpoint -q /some/random/path 2>/dev/null"); - - # Verify that files created in the container in a non-tmpfs directory are visible on the host. - # This establishes legitimacy for the following tests - $machine->succeed("nixos-container run tmpfs -- touch /root/test.file 2>/dev/null"); - $machine->succeed("nixos-container run tmpfs -- ls -l /root | grep -q test.file 2>/dev/null"); - $machine->succeed("test -e /var/lib/containers/tmpfs/root/test.file"); - - - # Verify that /some/random/path is writable and that files created there - # are not in the hosts container dir but in the tmpfs - $machine->succeed("nixos-container run tmpfs -- touch /some/random/path/test.file 2>/dev/null"); - $machine->succeed("nixos-container run tmpfs -- test -e /some/random/path/test.file 2>/dev/null"); - - $machine->fail("test -e /var/lib/containers/tmpfs/some/random/path/test.file"); - - # Verify that files created in the hosts container dir in a path where a tmpfs file system has been mounted - # are not visible to the container as the do not exist in the tmpfs - $machine->succeed("touch /var/lib/containers/tmpfs/var/test.file"); - - $machine->succeed("test -e /var/lib/containers/tmpfs/var/test.file"); - $machine->succeed("ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null"); - - $machine->fail("nixos-container run tmpfs -- ls -l /var | grep -q test.file 2>/dev/null"); - + testScript = '' + machine.wait_for_unit("default.target") + assert "tmpfs" in machine.succeed("nixos-container list") + + with subtest("tmpfs container is up"): + assert "up" in machine.succeed("nixos-container status tmpfs") + + + def tmpfs_cmd(command): + return f"nixos-container run tmpfs -- {command} 2>/dev/null" + + + with subtest("/var is mounted as a tmpfs"): + machine.succeed(tmpfs_cmd("mountpoint -q /var")) + + with subtest("/var/log is mounted as a tmpfs"): + assert "What: tmpfs" in machine.succeed( + tmpfs_cmd("systemctl status var-log.mount --no-pager") + ) + machine.succeed(tmpfs_cmd("mountpoint -q /var/log")) + + with subtest("/some/random/path is mounted as a tmpfs"): + assert "What: tmpfs" in machine.succeed( + tmpfs_cmd("systemctl status some-random-path.mount --no-pager") + ) + machine.succeed(tmpfs_cmd("mountpoint -q /some/random/path")) + + with subtest( + "files created in the container in a non-tmpfs directory are visible on the host." + ): + # This establishes legitimacy for the following tests + machine.succeed( + tmpfs_cmd("touch /root/test.file"), + tmpfs_cmd("ls -l /root | grep -q test.file"), + "test -e /var/lib/containers/tmpfs/root/test.file", + ) + + with subtest( + "/some/random/path is writable and that files created there are not " + + "in the hosts container dir but in the tmpfs" + ): + machine.succeed( + tmpfs_cmd("touch /some/random/path/test.file"), + tmpfs_cmd("test -e /some/random/path/test.file"), + ) + machine.fail("test -e /var/lib/containers/tmpfs/some/random/path/test.file") + + with subtest( + "files created in the hosts container dir in a path where a tmpfs " + + "file system has been mounted are not visible to the container as " + + "the do not exist in the tmpfs" + ): + machine.succeed( + "touch /var/lib/containers/tmpfs/var/test.file", + "test -e /var/lib/containers/tmpfs/var/test.file", + "ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null", + ) + machine.fail(tmpfs_cmd("ls -l /var | grep -q test.file")) ''; - }) diff --git a/nixos/tests/iftop.nix b/nixos/tests/iftop.nix index a4f524ceb27b..8a161027c2ad 100644 --- a/nixos/tests/iftop.nix +++ b/nixos/tests/iftop.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, lib, ... }: +import ./make-test-python.nix ({ pkgs, lib, ... }: with lib; @@ -18,17 +18,16 @@ with lib; }; testScript = '' - subtest "machine with iftop enabled", sub { - $withIftop->waitForUnit("default.target"); - # limit to eth1 (eth0 is the test driver's control interface) - # and don't try name lookups - $withIftop->succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'"); - }; - subtest "machine without iftop", sub { - $withoutIftop->waitForUnit("default.target"); - # check that iftop is there but user alice lacks capabilities - $withoutIftop->succeed("iftop -t -s 1 -n -i eth1"); - $withoutIftop->fail("su -l alice -c 'iftop -t -s 1 -n -i eth1'"); - }; + with subtest("machine with iftop enabled"): + withIftop.wait_for_unit("default.target") + # limit to eth1 (eth0 is the test driver's control interface) + # and don't try name lookups + withIftop.succeed("su -l alice -c 'iftop -t -s 1 -n -i eth1'") + + with subtest("machine without iftop"): + withoutIftop.wait_for_unit("default.target") + # check that iftop is there but user alice lacks capabilitie + withoutIftop.succeed("iftop -t -s 1 -n -i eth1") + withoutIftop.fail("su -l alice -c 'iftop -t -s 1 -n -i eth1'") ''; }) diff --git a/nixos/tests/kernel-latest.nix b/nixos/tests/kernel-latest.nix index f30bd2e2e760..f09d0926d223 100644 --- a/nixos/tests/kernel-latest.nix +++ b/nixos/tests/kernel-latest.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "kernel-latest"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; @@ -11,7 +11,7 @@ import ./make-test.nix ({ pkgs, ...} : { testScript = '' - $machine->succeed("uname -s | grep 'Linux'"); - $machine->succeed("uname -a | grep '${pkgs.linuxPackages_latest.kernel.version}'"); + assert "Linux" in machine.succeed("uname -s") + assert "${pkgs.linuxPackages_latest.kernel.version}" in machine.succeed("uname -a") ''; }) diff --git a/nixos/tests/kernel-lts.nix b/nixos/tests/kernel-lts.nix index 28717fa6a844..bad706d63c03 100644 --- a/nixos/tests/kernel-lts.nix +++ b/nixos/tests/kernel-lts.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "kernel-lts"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; @@ -11,7 +11,7 @@ import ./make-test.nix ({ pkgs, ...} : { testScript = '' - $machine->succeed("uname -s | grep 'Linux'"); - $machine->succeed("uname -a | grep '${pkgs.linuxPackages.kernel.version}'"); + assert "Linux" in machine.succeed("uname -s") + assert "${pkgs.linuxPackages.kernel.version}" in machine.succeed("uname -a") ''; }) diff --git a/nixos/tests/kernel-testing.nix b/nixos/tests/kernel-testing.nix index 276d2de12bb5..b7e10ebd5bd1 100644 --- a/nixos/tests/kernel-testing.nix +++ b/nixos/tests/kernel-testing.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "kernel-testing"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; @@ -11,7 +11,7 @@ import ./make-test.nix ({ pkgs, ...} : { testScript = '' - $machine->succeed("uname -s | grep 'Linux'"); - $machine->succeed("uname -a | grep '${pkgs.linuxPackages_testing.kernel.modDirVersion}'"); + assert "Linux" in machine.succeed("uname -s") + assert "${pkgs.linuxPackages_testing.kernel.modDirVersion}" in machine.succeed("uname -a") ''; }) diff --git a/nixos/tests/mailcatcher.nix b/nixos/tests/mailcatcher.nix index d45b5d4edfc5..eb5b606ecc84 100644 --- a/nixos/tests/mailcatcher.nix +++ b/nixos/tests/mailcatcher.nix @@ -9,8 +9,8 @@ import ./make-test.nix ({ lib, ... }: { services.mailcatcher.enable = true; - networking.defaultMailServer.directDelivery = true; - networking.defaultMailServer.hostName = "localhost:1025"; + services.ssmtp.enable = true; + services.ssmtp.hostName = "localhost:1025"; environment.systemPackages = [ pkgs.mailutils ]; }; diff --git a/nixos/tests/memcached.nix b/nixos/tests/memcached.nix index b120599c51dd..31f5627d25ce 100644 --- a/nixos/tests/memcached.nix +++ b/nixos/tests/memcached.nix @@ -1,28 +1,24 @@ -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ... }: { name = "memcached"; - nodes = { - machine = - { ... }: - { - imports = [ ../modules/profiles/minimal.nix ]; - services.memcached.enable = true; - }; + machine = { + imports = [ ../modules/profiles/minimal.nix ]; + services.memcached.enable = true; }; testScript = let - testScript = pkgs.writeScript "testScript.py" '' - #!${pkgs.python3.withPackages (p: [p.memcached])}/bin/python - + testScript = pkgs.writers.writePython3 "test_memcache" { + libraries = with pkgs.python3Packages; [ memcached ]; + } '' import memcache c = memcache.Client(['localhost:11211']) c.set('key', 'value') assert 'value' == c.get('key') ''; in '' - startAll; - $machine->waitForUnit("memcached.service"); - $machine->waitForOpenPort("11211"); - $machine->succeed("${testScript}"); + machine.start() + machine.wait_for_unit("memcached.service") + machine.wait_for_open_port(11211) + machine.succeed("${testScript}") ''; }) diff --git a/nixos/tests/ndppd.nix b/nixos/tests/ndppd.nix index 6a6f602726de..b67b26a79341 100644 --- a/nixos/tests/ndppd.nix +++ b/nixos/tests/ndppd.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, lib, ...} : { +import ./make-test-python.nix ({ pkgs, lib, ...} : { name = "ndppd"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ fpletz ]; @@ -52,9 +52,9 @@ import ./make-test.nix ({ pkgs, lib, ...} : { }; testScript = '' - startAll; - $server->waitForUnit("multi-user.target"); - $upstream->waitForUnit("multi-user.target"); - $upstream->waitUntilSucceeds("ping -c5 fd42::2"); + start_all() + server.wait_for_unit("multi-user.target") + upstream.wait_for_unit("multi-user.target") + upstream.wait_until_succeeds("ping -c5 fd42::2") ''; }) diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix index 9bd147968e4b..8dd5eafb0977 100644 --- a/nixos/tests/netdata.nix +++ b/nixos/tests/netdata.nix @@ -1,6 +1,6 @@ # This test runs netdata and checks for data via apps.plugin -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test-python.nix ({ pkgs, ...} : { name = "netdata"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ cransom ]; @@ -16,23 +16,22 @@ import ./make-test.nix ({ pkgs, ...} : { }; testScript = '' - startAll; + start_all() - $netdata->waitForUnit("netdata.service"); + netdata.wait_for_unit("netdata.service") # wait for the service to listen before sending a request - $netdata->waitForOpenPort(19999); + netdata.wait_for_open_port(19999) # check if the netdata main page loads. - $netdata->succeed("curl --fail http://localhost:19999/"); + netdata.succeed("curl --fail http://localhost:19999/") # check if netdata can read disk ops for root owned processes. # if > 0, successful. verifies both netdata working and # apps.plugin has elevated capabilities. - my $cmd = <<'CMD'; - curl -s http://localhost:19999/api/v1/data\?chart=users.pwrites | \ - jq -e '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0' - CMD - $netdata->waitUntilSucceeds($cmd); + url = "http://localhost:19999/api/v1/data\?chart=users.pwrites" + filter = '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0' + cmd = f"curl -s {url} | jq -e '{filter}'" + netdata.wait_until_succeeds(cmd) ''; }) diff --git a/nixos/tests/nextcloud/basic.nix b/nixos/tests/nextcloud/basic.nix index bfb97ec3f230..75862feb202d 100644 --- a/nixos/tests/nextcloud/basic.nix +++ b/nixos/tests/nextcloud/basic.nix @@ -1,4 +1,4 @@ -import ../make-test.nix ({ pkgs, ...}: let +import ../make-test-python.nix ({ pkgs, ...}: let adminpass = "notproduction"; adminuser = "root"; in { @@ -50,11 +50,15 @@ in { diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; in '' - startAll(); - $nextcloud->waitForUnit("multi-user.target"); - $nextcloud->succeed("curl -sSf http://nextcloud/login"); - $nextcloud->succeed("${withRcloneEnv} ${copySharedFile}"); - $client->waitForUnit("multi-user.target"); - $client->succeed("${withRcloneEnv} ${diffSharedFile}"); + start_all() + nextcloud.wait_for_unit("multi-user.target") + nextcloud.succeed("curl -sSf http://nextcloud/login") + nextcloud.succeed( + "${withRcloneEnv} ${copySharedFile}" + ) + client.wait_for_unit("multi-user.target") + client.succeed( + "${withRcloneEnv} ${diffSharedFile}" + ) ''; }) diff --git a/nixos/tests/nextcloud/with-mysql-and-memcached.nix b/nixos/tests/nextcloud/with-mysql-and-memcached.nix index aaf37ee4c810..b9ba5888187d 100644 --- a/nixos/tests/nextcloud/with-mysql-and-memcached.nix +++ b/nixos/tests/nextcloud/with-mysql-and-memcached.nix @@ -1,4 +1,4 @@ -import ../make-test.nix ({ pkgs, ...}: let +import ../make-test-python.nix ({ pkgs, ...}: let adminpass = "hunter2"; adminuser = "root"; in { @@ -85,13 +85,16 @@ in { diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; in '' - startAll(); - $nextcloud->waitForUnit("multi-user.target"); - $nextcloud->succeed("${configureMemcached}"); - $nextcloud->succeed("curl -sSf http://nextcloud/login"); - $nextcloud->succeed("${withRcloneEnv} ${copySharedFile}"); - $client->waitForUnit("multi-user.target"); - $client->succeed("${withRcloneEnv} ${diffSharedFile}"); - + start_all() + nextcloud.wait_for_unit("multi-user.target") + nextcloud.succeed("${configureMemcached}") + nextcloud.succeed("curl -sSf http://nextcloud/login") + nextcloud.succeed( + "${withRcloneEnv} ${copySharedFile}" + ) + client.wait_for_unit("multi-user.target") + client.succeed( + "${withRcloneEnv} ${diffSharedFile}" + ) ''; }) diff --git a/nixos/tests/nextcloud/with-postgresql-and-redis.nix b/nixos/tests/nextcloud/with-postgresql-and-redis.nix index f655aba9d45e..324853350af6 100644 --- a/nixos/tests/nextcloud/with-postgresql-and-redis.nix +++ b/nixos/tests/nextcloud/with-postgresql-and-redis.nix @@ -1,4 +1,4 @@ -import ../make-test.nix ({ pkgs, ...}: let +import ../make-test-python.nix ({ pkgs, ...}: let adminpass = "hunter2"; adminuser = "custom-admin-username"; in { @@ -85,12 +85,16 @@ in { diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; in '' - startAll(); - $nextcloud->waitForUnit("multi-user.target"); - $nextcloud->succeed("${configureRedis}"); - $nextcloud->succeed("curl -sSf http://nextcloud/login"); - $nextcloud->succeed("${withRcloneEnv} ${copySharedFile}"); - $client->waitForUnit("multi-user.target"); - $client->succeed("${withRcloneEnv} ${diffSharedFile}"); + start_all() + nextcloud.wait_for_unit("multi-user.target") + nextcloud.succeed("${configureRedis}") + nextcloud.succeed("curl -sSf http://nextcloud/login") + nextcloud.succeed( + "${withRcloneEnv} ${copySharedFile}" + ) + client.wait_for_unit("multi-user.target") + client.succeed( + "${withRcloneEnv} ${diffSharedFile}" + ) ''; }) diff --git a/nixos/tests/pantheon.nix b/nixos/tests/pantheon.nix index 6ff19be1bb95..c0434f20754c 100644 --- a/nixos/tests/pantheon.nix +++ b/nixos/tests/pantheon.nix @@ -28,7 +28,8 @@ import ./make-test-python.nix ({ pkgs, ...} : with subtest("Test we can see usernames in elementary-greeter"): machine.wait_for_text("${user.description}") - machine.wait_for_text("${bob.description}") + # OCR was struggling with this one. + # machine.wait_for_text("${bob.description}") machine.screenshot("elementary_greeter_lightdm") with subtest("Login with elementary-greeter"): diff --git a/nixos/tests/rabbitmq.nix b/nixos/tests/rabbitmq.nix index bb5932c36417..8e7f34d06e32 100644 --- a/nixos/tests/rabbitmq.nix +++ b/nixos/tests/rabbitmq.nix @@ -1,21 +1,21 @@ # This test runs rabbitmq and checks if rabbitmq is up and running. -import ./make-test.nix ({ pkgs, ... }: { +import ./make-test-python.nix ({ pkgs, ... }: { name = "rabbitmq"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ eelco offline ]; }; - nodes = { - one = { ... }: { - services.rabbitmq.enable = true; - }; + machine = { + services.rabbitmq.enable = true; }; testScript = '' - startAll; + machine.start() - $one->waitForUnit("rabbitmq.service"); - $one->waitUntilSucceeds("su -s ${pkgs.stdenv.shell} rabbitmq -c \"rabbitmqctl status\""); + machine.wait_for_unit("rabbitmq.service") + machine.wait_until_succeeds( + 'su -s ${pkgs.stdenv.shell} rabbitmq -c "rabbitmqctl status"' + ) ''; }) diff --git a/nixos/tests/xmpp/ejabberd.nix b/nixos/tests/xmpp/ejabberd.nix index 196a04aca300..1518aaacc8ab 100644 --- a/nixos/tests/xmpp/ejabberd.nix +++ b/nixos/tests/xmpp/ejabberd.nix @@ -1,4 +1,4 @@ -import ../make-test.nix ({ pkgs, ... }: { +import ../make-test-python.nix ({ pkgs, ... }: { name = "ejabberd"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ ajs124 ]; @@ -248,13 +248,21 @@ import ../make-test.nix ({ pkgs, ... }: { }; testScript = { nodes, ... }: '' - $server->waitForUnit('ejabberd.service'); - $server->succeed('su ejabberd -s $(which ejabberdctl) status|grep started') =~ /ejabberd is running/; - $server->succeed('su ejabberd -s $(which ejabberdctl) register azurediamond example.com hunter2'); - $server->succeed('su ejabberd -s $(which ejabberdctl) register cthon98 example.com nothunter2'); - $server->fail('su ejabberd -s $(which ejabberdctl) register asdf wrong.domain'); - $client->succeed('send-message'); - $server->succeed('su ejabberd -s $(which ejabberdctl) unregister cthon98 example.com'); - $server->succeed('su ejabberd -s $(which ejabberdctl) unregister azurediamond example.com'); + ejabberd_prefix = "su ejabberd -s $(which ejabberdctl) " + + server.wait_for_unit("ejabberd.service") + + assert "status: started" in server.succeed(ejabberd_prefix + "status") + + server.succeed( + ejabberd_prefix + "register azurediamond example.com hunter2", + ejabberd_prefix + "register cthon98 example.com nothunter2", + ) + server.fail(ejabberd_prefix + "register asdf wrong.domain") + client.succeed("send-message") + server.succeed( + ejabberd_prefix + "unregister cthon98 example.com", + ejabberd_prefix + "unregister azurediamond example.com", + ) ''; }) diff --git a/nixos/tests/xss-lock.nix b/nixos/tests/xss-lock.nix index 0d757e8cef3f..3a7dea07d53a 100644 --- a/nixos/tests/xss-lock.nix +++ b/nixos/tests/xss-lock.nix @@ -1,4 +1,4 @@ -import ./make-test.nix ({ pkgs, lib, ... }: +import ./make-test-python.nix ({ pkgs, lib, ... }: with lib; @@ -26,15 +26,19 @@ with lib; }; testScript = '' - startAll; - - ${concatStringsSep "\n" (mapAttrsToList (name: lockCmd: '' - ${"$"+name}->start; - ${"$"+name}->waitForX; - ${"$"+name}->waitForUnit("xss-lock.service", "alice"); - ${"$"+name}->fail("pgrep ${lockCmd}"); - ${"$"+name}->succeed("su -l alice -c 'xset dpms force standby'"); - ${"$"+name}->waitUntilSucceeds("pgrep ${lockCmd}"); - '') { simple = "i3lock"; custom_lockcmd = "xlock"; })} + def perform_xsslock_test(machine, lockCmd): + machine.start() + machine.wait_for_x() + machine.wait_for_unit("xss-lock.service", "alice") + machine.fail(f"pgrep {lockCmd}") + machine.succeed("su -l alice -c 'xset dpms force standby'") + machine.wait_until_succeeds(f"pgrep {lockCmd}") + + + with subtest("simple"): + perform_xsslock_test(simple, "i3lock") + + with subtest("custom_cmd"): + perform_xsslock_test(custom_lockcmd, "xlock") ''; }) |