Merge staging-nixos into master (nix security update) (#516623)

This commit is contained in:
Jörg Thalheim
2026-05-04 20:33:49 +00:00
committed by GitHub
62 changed files with 404 additions and 277 deletions
@@ -160,6 +160,8 @@
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
- `systemd.coredump.extraConfig` has been removed in favor of the structured [](#opt-systemd.coredump.settings.Coredump) option. Use `systemd.coredump.settings.Coredump` to set any `coredump.conf(5)` option directly. For example, replace `systemd.coredump.extraConfig = "Storage=journal";` with `systemd.coredump.settings.Coredump.Storage = "journal";`.
- `opentrack`, `slushload`, `synthesia`, `vtfedit`, `winbox`, `wineasio`, and `yabridge` use wineWow64Packages instead of wineWowPackages as wine versions >= 11.0 have deprecated wineWowPackages. As such, the prefixes for these packages are NOT backwards compatible and need to be regenerated with potential for data loss.
- []{#sec-release-26.05-incompatibilities-profiles-hardened-removed} `profiles/hardened` has been removed, because:
-1
View File
@@ -8,7 +8,6 @@ version = "0.0.0"
[project.scripts]
nixos-test-driver = "test_driver:main"
generate-driver-symbols = "test_driver:generate_driver_symbols"
[tool.setuptools.packages]
find = {}
@@ -6,9 +6,10 @@ import warnings
from pathlib import Path
import ptpython.ipython
from colorama import Fore, Style
from test_driver.debug import Debug, DebugAbstract, DebugNop
from test_driver.driver import Driver, DriverConfiguration, load_driver_configuration
from test_driver.driver import Driver, load_driver_configuration
from test_driver.logger import (
CompositeLogger,
JunitXMLLogger,
@@ -55,6 +56,29 @@ def writeable_dir(arg: str) -> Path:
return path
def formatwarning(
message: Warning | str,
category: type[Warning],
filename: str,
lineno: int,
line: str | None = None,
) -> str:
return (
Style.BRIGHT
+ Fore.YELLOW
+ f"??? Warning ({category.__name__}): " # ty: ignore[unsupported-operator]
+ Style.NORMAL
+ str(message)
+ "\n"
+ f' File "{filename}", line {lineno}\n'
+ (f" {line}\n" if line is not None else "")
+ Style.RESET_ALL
)
warnings.formatwarning = formatwarning # ty:ignore[invalid-assignment]
def main() -> None:
arg_parser = argparse.ArgumentParser(prog="nixos-test-driver")
arg_parser.add_argument(
@@ -159,30 +183,3 @@ def main() -> None:
driver.run_tests()
toc = time.time()
logger.info(f"test script finished in {(toc - tic):.2f}s")
def generate_driver_symbols() -> None:
"""
This generates a file with symbols of the test-driver code that can be used
in user's test scripts. That list is then used by pyflakes to lint those
scripts.
"""
d = Driver(
config=DriverConfiguration(
vms=dict(),
containers=dict(),
vlans=[],
global_timeout=0,
enable_ssh_backdoor=False,
test_script=(
Path("testScriptWithTypes")
if (Path("testScriptWithTypes").is_file())
else Path("testScriptFile")
),
),
out_dir=Path(),
logger=CompositeLogger([]),
)
test_symbols = d.test_symbols()
with open("driver-symbols", "w") as fp:
fp.write(",".join(test_symbols.keys()))
@@ -7,7 +7,7 @@ import sys
import tempfile
import threading
import traceback
from collections.abc import Callable, Iterator
from collections.abc import Callable, Generator, Iterator
from contextlib import AbstractContextManager, contextmanager
from dataclasses import dataclass
from pathlib import Path
@@ -22,6 +22,7 @@ from test_driver.errors import MachineError, RequestedAssertionFailed
from test_driver.logger import AbstractLogger
from test_driver.machine import (
BaseMachine,
MachineDeprecationWrapper,
NspawnMachine,
QemuMachine,
retry,
@@ -299,7 +300,7 @@ class Driver:
f"Error during cleanup of vhost-device-vsock process: {e}"
)
def subtest(self, name: str) -> Iterator[None]:
def subtest(self, name: str) -> Generator[None]:
"""Group logs under a given test name"""
with self.logger.subtest(name):
try:
@@ -338,11 +339,17 @@ class Driver:
debug=self.debug,
dump_machine_ssh=self.dump_machine_ssh,
)
machine_symbols = {pythonize_name(m.name): m for m in self.machines}
machine_symbols: dict[
str, QemuMachine | NspawnMachine | MachineDeprecationWrapper
] = {pythonize_name(m.name): m for m in self.machines}
# If there's exactly one machine, make it available under the name
# "machine", even if it's not called that.
if len(self.machines) == 1:
(machine_symbols["machine"],) = self.machines
if len(self.machines) == 1 and "machine" not in machine_symbols:
only_machine_name = next(iter(machine_symbols))
machine_symbols["machine"] = MachineDeprecationWrapper(
f"It's deprecated to use the `machine` variable when the only machine is called {only_machine_name}. This behavior will no longer work in NixOS 27.05.",
self.machines[0],
)
vlan_symbols = {
f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans)
}
@@ -1710,3 +1710,18 @@ class NspawnMachine(BaseMachine):
with self.nested("waiting for the container to power off"):
self.process.wait()
self.process = None
class MachineDeprecationWrapper:
def __init__(self, msg: str, machine: QemuMachine | NspawnMachine):
self.msg = msg
self.machine = machine
def __getattribute__(self, name: str):
if name in ("msg", "machine"):
return object.__getattribute__(self, name)
typename = self.machine.__class__.__name__
warnings.warn(
f"invoking '{typename}.{name}' is deprecated: {self.msg}",
)
return self.machine.__getattribute__(name)
+110 -39
View File
@@ -1,19 +1,31 @@
# This file contains type hints that can be prepended to Nix test scripts so they can be type
# checked.
from test_driver.debug import DebugAbstract
from test_driver.driver import Driver
from test_driver.vlan import VLan
from test_driver.machine import BaseMachine, NspawnMachine, QemuMachine
from test_driver.logger import AbstractLogger
from typing import Callable, Iterator, ContextManager, Optional, List, Dict, Any, Union
from typing_extensions import Protocol
from pathlib import Path
from contextlib import contextmanager
from typing import Any, Callable, ContextManager, Generator, List, Optional, Union
from unittest import TestCase
from test_driver.debug import DebugAbstract, DebugNop
from test_driver.driver import Driver
from test_driver.logger import AbstractLogger, CompositeLogger
from typing_extensions import Protocol
class RetryProtocol(Protocol):
def __call__(self, fn: Callable, timeout_seconds: int = 900) -> None:
from test_driver.machine import BaseMachine, NspawnMachine, QemuMachine
from test_driver.vlan import VLan
# Protocols
class CreateMachineProtocol(Protocol):
def __call__(
self,
start_command: str | dict,
*,
name: Optional[str] = None,
keep_machine_state: bool = False,
**kwargs: Any, # to allow usage of deprecated keep_vm_state
) -> QemuMachine:
raise Exception("This is just type information for the Nix test driver")
@@ -28,34 +40,93 @@ class PollingConditionProtocol(Protocol):
raise Exception("This is just type information for the Nix test driver")
class CreateMachineProtocol(Protocol):
def __call__(
self,
start_command: str | dict,
*,
name: Optional[str] = None,
keep_machine_state: bool = False,
**kwargs: Any, # to allow usage of deprecated keep_vm_state
) -> QemuMachine:
raise Exception("This is just type information for the Nix test driver")
# Classes
start_all: Callable[[], None]
subtest: Callable[[str], ContextManager[None]]
retry: RetryProtocol
test_script: Callable[[], None]
machines: List[BaseMachine]
machines_qemu: List[QemuMachine]
machines_nspawn: List[NspawnMachine]
vlans: List[VLan]
driver: Driver
log: AbstractLogger
create_machine: CreateMachineProtocol
run_tests: Callable[[], None]
join_all: Callable[[], None]
serial_stdout_off: Callable[[], None]
serial_stdout_on: Callable[[], None]
polling_condition: PollingConditionProtocol
debug: DebugAbstract
t: TestCase
dump_machine_ssh: Callable[[], None]
class AssertionTester(TestCase):
pass
# Global Variables
debug: DebugAbstract = DebugNop()
machines: List[BaseMachine] = []
machines_nspawn: List[NspawnMachine] = []
machines_qemu: List[QemuMachine] = []
t = AssertionTester()
vlans: List[VLan] = []
def create_fake_driver() -> Driver:
raise Exception("fake driver")
driver = create_fake_driver()
# Functions
# these are going to be called by the testScriptWithTypes in driver.nix
def create_fake_qemu_machine() -> QemuMachine:
raise Exception("fake qemu machine")
def create_fake_nspawn_machine() -> NspawnMachine:
raise Exception("fake nspawn machine")
def create_fake_vlan() -> VLan:
raise Exception("fake vlan")
def create_machine(
start_command: str, name: str | None = None, keep_machine_state: bool = False
) -> QemuMachine:
raise Exception("fake machine")
def dump_machine_ssh() -> None:
return None
def join_all() -> None:
return None
log: AbstractLogger = CompositeLogger([])
def polling_condition(
fun: Callable | None, seconds_interval: float = 0.0, description: str | None = None
):
pass
def retry(fn: Callable, timeout_seconds: int = 900) -> None:
pass
def run_tests() -> None:
return
def serial_stdout_off() -> None:
return None
def serial_stdout_on() -> None:
return None
def start_all() -> None:
return
def test_script() -> None:
return
@contextmanager
def subtest(str: str) -> Generator[None, None, None]:
yield
+46 -50
View File
@@ -19,34 +19,38 @@ let
enableNspawn = config.containers != { };
};
pythonizeName =
name:
typeHints =
let
head = lib.substring 0 1 name;
tail = lib.substring 1 (-1) name;
pythonizeName =
name:
let
head = lib.substring 0 1 name;
tail = lib.substring 1 (-1) name;
in
(if builtins.match "[A-z_]" head == null then "_" else head)
+ lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
vmMachineNames = lib.attrNames config.driverConfiguration.vms;
containerMachineNames = lib.attrNames config.driverConfiguration.containers;
theOnlyMachine =
let
exactlyOneMachine = lib.length (lib.attrValues config.nodes) == 1;
allMachineNames = lib.attrNames config.allMachines;
in
lib.optional (exactlyOneMachine && !lib.elem "machine" allMachineNames) "machine";
vmMachineTypeHints = map (name: "${pythonizeName name} = create_fake_qemu_machine()") (
vmMachineNames ++ theOnlyMachine
);
containerMachineTypeHints = map (
name: "${pythonizeName name} = create_fake_nspawn_machine()"
) containerMachineNames;
vlanTypeHints = map (i: "vlan${toString i} = create_fake_vlan()") config.driverConfiguration.vlans;
in
(if builtins.match "[A-z_]" head == null then "_" else head)
+ lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
vlanTypeHints = lib.strings.concatMapStringsSep "\n" (
i: "vlan${toString i}: VLan"
) config.driverConfiguration.vlans;
vmMachineNames = lib.attrNames config.driverConfiguration.vms;
containerMachineNames = lib.attrNames config.driverConfiguration.containers;
theOnlyMachine =
let
exactlyOneMachine = lib.length (lib.attrValues config.nodes) == 1;
allMachineNames = map (c: c.system.name) (lib.attrValues config.allMachines);
in
lib.optional (exactlyOneMachine && !lib.elem "machine" allMachineNames) "machine";
pythonizedVmNames = map pythonizeName (vmMachineNames ++ theOnlyMachine);
vmMachineTypeHints = map (name: "${name}: QemuMachine;") pythonizedVmNames;
pythonizedContainerNames = map pythonizeName containerMachineNames;
containerMachineTypeHints = map (name: "${name}: NspawnMachine;") pythonizedContainerNames;
lib.strings.concatStringsSep "\n" (
vlanTypeHints ++ vmMachineTypeHints ++ containerMachineTypeHints
);
withChecks = lib.warnIf config.skipLint "Linting is disabled";
@@ -57,7 +61,8 @@ let
nativeBuildInputs = [
hostPkgs.makeWrapper
]
++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ];
++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.ty ]
++ lib.optionals (!config.skipLint) [ hostPkgs.ruff ];
buildInputs = [ testDriver ];
testScript = config.testScriptString;
preferLocalBuild = true;
@@ -69,43 +74,34 @@ let
''
mkdir -p $out/bin
${lib.optionalString (!config.skipTypeCheck) ''
# prepend type hints so the test script can be type checked with mypy
${lib.optionalString (!config.skipTypeCheck || !config.skipLint) ''
# prepend type hints so the test script can be type checked with ty
cat "${../test-script-prepend.py}" >> testScriptWithTypes
echo "${toString vmMachineTypeHints}" >> testScriptWithTypes
echo "${toString containerMachineTypeHints}" >> testScriptWithTypes
echo "${toString vlanTypeHints}" >> testScriptWithTypes
echo "${toString typeHints}" >> testScriptWithTypes
echo -n "$testScript" >> testScriptWithTypes
''}
${lib.optionalString (!config.skipTypeCheck) ''
echo "Running type check (enable/disable: config.skipTypeCheck)"
echo "See https://nixos.org/manual/nixos/stable/#test-opt-skipTypeCheck"
mypy --no-implicit-optional \
--pretty \
--no-color-output \
testScriptWithTypes
ty check testScriptWithTypes
''}
echo -n "$testScript" > testScriptFile
cp "${config.driverConfiguration.test_script}" $out/test-script
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
${testDriver}/bin/generate-driver-symbols
${lib.optionalString (!config.skipLint) ''
echo "Linting test script (enable/disable: config.skipLint)"
echo "See https://nixos.org/manual/nixos/stable/#test-opt-skipLint"
PYFLAKES_BUILTINS="$(
echo -n ${
lib.escapeShellArg (lib.concatStringsSep "," (pythonizedVmNames ++ pythonizedContainerNames))
},
cat ${lib.escapeShellArg "driver-symbols"}
)" ${hostPkgs.python3Packages.pyflakes}/bin/pyflakes $out/test-script
# F are the "(py)flakes" checks.
# we can't go with the defaults because these include
# code style/formatting
ruff check --select F testScriptWithTypes
''}
cp "${config.driverConfiguration.test_script}" $out/test-script
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
wrapProgram $out/bin/nixos-test-driver \
--add-flags "--config ${config.driverConfigurationFile}" \
--add-flags "--log-level ${config.logLevel}" \
+19 -14
View File
@@ -72,20 +72,25 @@ in
{
inherit (config.boot.kernelPackages.kernel) configfile;
}
''
mmap_rnd_bits_max=$(grep "^CONFIG_ARCH_MMAP_RND_BITS_MAX=" $configfile | grep --only-matching "[0-9]*$")
if [[ -z "$mmap_rnd_bits_max" ]]; then
echo "Unable to determine mmap_rnd_bits_max. Check your kernel configfile is valid."
exit 1
fi
mmap_rnd_compat_bits_max=$(grep "^CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=" $configfile | grep --only-matching "[0-9]*$")
if [[ -z "$mmap_rnd_compat_bits_max" ]]; then
echo "Unable to determine mmap_rnd_compat_bits_max. Check your kernel configfile is valid."
exit 1
fi
echo "vm.mmap_rnd_bits=$mmap_rnd_bits_max" >> $out
echo "vm.mmap_rnd_compat_bits=$mmap_rnd_compat_bits_max" >> $out
'';
(
''
mmap_rnd_bits_max=$(grep "^CONFIG_ARCH_MMAP_RND_BITS_MAX=" $configfile | grep --only-matching "[0-9]*$")
if [[ -z "$mmap_rnd_bits_max" ]]; then
echo "Unable to determine mmap_rnd_bits_max. Check your kernel configfile is valid."
exit 1
fi
echo "vm.mmap_rnd_bits=$mmap_rnd_bits_max" >> $out
''
# HAVE_ARCH_MMAP_RND_COMPAT_BITS is not defined for LoongArch64
+ lib.optionalString (!pkgs.stdenv.hostPlatform.isLoongArch64) ''
mmap_rnd_compat_bits_max=$(grep "^CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=" $configfile | grep --only-matching "[0-9]*$")
if [[ -z "$mmap_rnd_compat_bits_max" ]]; then
echo "Unable to determine mmap_rnd_compat_bits_max. Check your kernel configfile is valid."
exit 1
fi
echo "vm.mmap_rnd_compat_bits=$mmap_rnd_compat_bits_max" >> $out
''
);
"sysctl.d/60-nixos.conf".text = lib.concatStrings (
lib.mapAttrsToList (
n: v: lib.optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n"
@@ -1,8 +1,8 @@
{
x86_64-linux = "/nix/store/q7f0d4m54yj98fcjmbkscw83j82fypnd-nix-2.34.6";
i686-linux = "/nix/store/mlv349bmjjx34p50idp54rg0wsm44hws-nix-2.34.6";
aarch64-linux = "/nix/store/wlcv2ymswfgwv1cj1q29p26rh26xj3nd-nix-2.34.6";
riscv64-linux = "/nix/store/000b0vjlhw359rl82p8pld00g6363c78-nix-riscv64-unknown-linux-gnu-2.34.6";
x86_64-darwin = "/nix/store/mqvv503c5l9kgjvc7vyxj3rdx5a71c11-nix-2.34.6";
aarch64-darwin = "/nix/store/hcgga2smfm8lqirshrbfpk5j1my1wh4j-nix-2.34.6";
x86_64-linux = "/nix/store/6qpfa1c19q4idpjij6s6yywkfvhp820s-nix-2.34.7";
i686-linux = "/nix/store/npdbf892fhicd1pw8flpywzbvhcdx469-nix-2.34.7";
aarch64-linux = "/nix/store/5i60qiqjx9bjkcy31fwvnx28ijljlbs3-nix-2.34.7";
riscv64-linux = "/nix/store/xvl2f539v978jwflp2d9r7znk35br00i-nix-riscv64-unknown-linux-gnu-2.34.7";
x86_64-darwin = "/nix/store/j9rh0z3zy9rq00lz9ckcsa1g1hn35cyw-nix-2.34.7";
aarch64-darwin = "/nix/store/yxgyagiaffxkbrff4d7mrg718wdj3llj-nix-2.34.7";
}
+1
View File
@@ -12,6 +12,7 @@
"virtio_scsi"
"9p"
"9pnet_virtio"
"virtiofs"
];
boot.initrd.kernelModules = [
"virtio_balloon"
+25 -18
View File
@@ -6,17 +6,23 @@
...
}:
with lib;
let
cfg = config.systemd.coredump;
systemd = config.systemd.package;
in
{
imports = [
(lib.mkRemovedOptionModule [
"systemd"
"coredump"
"extraConfig"
] "Use systemd.coredump.settings.Coredump instead.")
];
options = {
systemd.coredump.enable = mkOption {
systemd.coredump.enable = lib.mkOption {
default = true;
type = types.bool;
type = lib.types.bool;
description = ''
Whether core dumps should be processed by
{command}`systemd-coredump`. If disabled, core dumps
@@ -24,30 +30,31 @@ in
'';
};
systemd.coredump.extraConfig = mkOption {
default = "";
type = types.lines;
example = "Storage=journal";
systemd.coredump.settings.Coredump = lib.mkOption {
default = { };
type = lib.types.submodule {
freeformType = lib.types.attrsOf utils.systemdUtils.unitOptions.unitOption;
};
example = {
Storage = "journal";
};
description = ''
Extra config options for systemd-coredump. See {manpage}`coredump.conf(5)` man page
for available options.
Settings for systemd-coredump. See {manpage}`coredump.conf(5)` for
available options.
'';
};
};
config = mkMerge [
config = lib.mkMerge [
(mkIf cfg.enable {
(lib.mkIf cfg.enable {
systemd.additionalUpstreamSystemUnits = [
"systemd-coredump.socket"
"systemd-coredump@.service"
];
environment.etc = {
"systemd/coredump.conf".text = ''
[Coredump]
${cfg.extraConfig}
'';
"systemd/coredump.conf".text = utils.systemdUtils.lib.settingsToSections cfg.settings;
# install provided sysctl snippets
"sysctl.d/50-coredump.conf".source =
@@ -76,8 +83,8 @@ in
users.groups.systemd-coredump = { };
})
(mkIf (!cfg.enable) {
boot.kernel.sysctl."kernel.core_pattern" = mkDefault "core";
(lib.mkIf (!cfg.enable) {
boot.kernel.sysctl."kernel.core_pattern" = lib.mkDefault "core";
})
];
+1 -1
View File
@@ -15,7 +15,7 @@
meta = with lib.maintainers; {
maintainers = [ urbas ];
};
nodes.machine = {
nodes.unnamed = {
imports = [
../modules/profiles/headless.nix
../modules/virtualisation/amazon-init.nix
+1 -1
View File
@@ -32,7 +32,7 @@ in
in
''
start_all()
machine.wait_for_unit("multi-user.target")
benchexec.wait_for_unit("multi-user.target")
benchexec.succeed(''''\
systemd-run \
--property='StandardOutput=file:${stdout}' \
+1 -1
View File
@@ -27,7 +27,7 @@ in
illustris
];
nodes.machine2 =
nodes.unnamed =
{ ... }:
{
virtualisation.qemu.options = [
+1 -1
View File
@@ -60,7 +60,7 @@ in
lewo
illustris
];
nodes.machine = {
nodes.unnamed = {
virtualisation.qemu.options = [
"-cdrom"
"${metadataDrive}/metadata.iso"
+1 -1
View File
@@ -140,7 +140,7 @@
machine.succeed(f"pkill {gui_app}", timeout=5)
machine.succeed("echo 'test completed succeessfully' > /${testName}", timeout=5)
machine.copy_from_vm('/${testName}')
machine.copy_from_machine('/${testName}')
machine.shutdown()
'';
+1 -1
View File
@@ -36,7 +36,7 @@
# wait until the pdf files are completely produced and readable by alice
machine.wait_until_succeeds(f"su - alice -c 'pdfinfo /var/spool/cups-pdf-{name}/users/alice/*.pdf'")
machine.succeed(f"cp /var/spool/cups-pdf-{name}/users/alice/*.pdf /tmp/{name}.pdf")
machine.copy_from_vm(f"/tmp/{name}.pdf", "")
machine.copy_from_machine(f"/tmp/{name}.pdf", "")
run(f"${lib.getExe hostPkgs.imagemagickBig} -density 300 $out/{name}.pdf $out/{name}.jpeg", shell=True, check=True)
assert text.encode() in run(f"${lib.getExe hostPkgs.tesseract} $out/{name}.jpeg stdout", shell=True, check=True, capture_output=True).stdout
'';
+2
View File
@@ -49,6 +49,8 @@ let
enableOCR = true;
testScript = ''
machine = ${name}
@polling_condition
def drawterm_running():
machine.succeed("pgrep drawterm")
+1 -1
View File
@@ -91,7 +91,7 @@
"${exe} file://${pkgs.sound-theme-freedesktop}/share/sounds/freedesktop/stereo/phone-incoming-call.oga >&2 &"
)
wait_for_sound(machine)
machine.copy_from_vm("/tmp/record.wav")
machine.copy_from_machine("/tmp/record.wav")
with subtest("Close sound test tab"):
machine.execute("xdotool key ctrl+w")
+1 -1
View File
@@ -270,7 +270,7 @@ let
server.succeed("${serverSystem}/specialisation/dump/bin/switch-to-configuration test")
server.systemctl("start forgejo-dump")
assert "Zstandard compressed data" in server.succeed("file ${dumpFile}")
server.copy_from_vm("${dumpFile}")
server.copy_from_machine("${dumpFile}")
'';
};
in
+1
View File
@@ -41,6 +41,7 @@ let
testScript = ''
start_all()
machine = ${name}
machine.wait_for_unit('graphical.target')
machine.wait_for_text('Your Subscription list is currently empty')
machine.send_key("ctrl-r")
+1
View File
@@ -54,6 +54,7 @@
};
testScript = ''
import os
# prepare certificates
+1
View File
@@ -48,6 +48,7 @@
};
testScript = ''
import os
# prepare certificates
+2
View File
@@ -69,6 +69,8 @@
};
};
testScript = ''
import os
# Helpers
def cmd(command):
print(f"+{command}")
-2
View File
@@ -43,8 +43,6 @@ let
''
start_all()
machine = ${hostName}
machine.systemctl("start network-online.target")
machine.wait_for_unit("network-online.target")
+1 -1
View File
@@ -59,7 +59,7 @@
lib.pipe nodes [
builtins.attrNames
(map (node: ''
${node}.copy_from_vm(
${node}.copy_from_machine(
${node}.succeed("readlink -f /etc/locale.conf").strip(),
"${node}"
)
+5 -1
View File
@@ -81,7 +81,11 @@
machine.wait_until_succeeds(f"[ `{cmd} | wc -l` -eq 1 ]")
output = machine.succeed(cmd)
ip = re.search(r"inet6 ([0-9a-f:]{2,})/", output).group(1)
matches: re.Match | None = re.search(r"inet6 ([0-9a-f:]{2,})/", output)
if matches is None:
raise Exception(f"Can't match IP out of output: {output}")
ip = matches.group(1)
if temporary:
scope = scope + " temporary"
+1 -1
View File
@@ -80,6 +80,6 @@ in
'LOCALE': 'en_US',
})
machine.succeed(f"curl 'localhost:${toString port}/process?{query}' -o ./audio.wav")
machine.copy_from_vm("./audio.wav")
machine.copy_from_machine("./audio.wav")
'';
}
+1 -1
View File
@@ -223,7 +223,7 @@ in
appservice.wait_for_open_port(11111)
with subtest("copy the registration file"):
appservice.copy_from_vm("/var/lib/matrix-appservice-irc/registration.yml")
appservice.copy_from_machine("/var/lib/matrix-appservice-irc/registration.yml")
homeserver.copy_from_host(
str(pathlib.Path(os.environ.get("out", os.getcwd())) / "registration.yml"), "/"
)
+2 -2
View File
@@ -114,7 +114,7 @@
machine.wait_for_text("alice@machine")
machine.send_chars("test-wayland\n")
machine.wait_for_file("/tmp/test-wayland-exit-ok")
machine.copy_from_vm("/tmp/test-wayland.out")
machine.copy_from_machine("/tmp/test-wayland.out")
machine.screenshot("foot_wayland_info")
# please actually register that we want to close the window
@@ -135,7 +135,7 @@
machine.wait_for_text("alice@machine")
machine.send_chars("test-x11\n")
machine.wait_for_file("/tmp/test-x11-exit-ok")
machine.copy_from_vm("/tmp/test-x11.out")
machine.copy_from_machine("/tmp/test-x11.out")
machine.screenshot("alacritty_glinfo")
# please actually register that we want to close the window
+2 -2
View File
@@ -108,7 +108,7 @@
machine.wait_for_text(r"(alice|machine)")
machine.send_chars("test-wayland\n")
machine.wait_for_file("/tmp/test-wayland-exit-ok")
machine.copy_from_vm("/tmp/test-wayland.out")
machine.copy_from_machine("/tmp/test-wayland.out")
machine.screenshot("foot_wayland_info")
# please actually register that we want to close the window
@@ -128,7 +128,7 @@
machine.wait_for_text(r"(alice|machine)")
machine.send_chars("test-x11\n")
machine.wait_for_file("/tmp/test-x11-exit-ok")
machine.copy_from_vm("/tmp/test-x11.out")
machine.copy_from_machine("/tmp/test-x11.out")
machine.screenshot("alacritty_glinfo")
# please actually register that we want to close the window
+2 -2
View File
@@ -140,7 +140,7 @@ in
# to perform the following test:
client.fail(f"{mpc} -h serverPulseAudio status")
# For inspecting these files
serverALSA.copy_from_vm("/run/mpd/mpd.conf", "ALSA")
serverPulseAudio.copy_from_vm("/run/mpd/mpd.conf", "PulseAudio")
serverALSA.copy_from_machine("/run/mpd/mpd.conf", "ALSA")
serverPulseAudio.copy_from_machine("/run/mpd/mpd.conf", "PulseAudio")
'';
}
+1 -1
View File
@@ -95,6 +95,6 @@ in
## Check that it contains the title of the score
machine.succeed('pdfgrep "Untitled score" "/root/Untitled score.pdf"')
machine.copy_from_vm("/root/Untitled score.pdf")
machine.copy_from_machine("/root/Untitled score.pdf")
'';
}
+3 -3
View File
@@ -15,14 +15,14 @@
testScript = ''
start_all();
machine.wait_for_unit("mympd.service");
mympd.wait_for_unit("mympd.service");
# Ensure that mympd can connect to mpd
machine.wait_until_succeeds(
mympd.wait_until_succeeds(
"journalctl -eu mympd -o cat | grep 'Connected to MPD'"
)
# Ensure that the web server is working
machine.succeed("curl http://localhost:8081 --compressed | grep -o myMPD")
mympd.succeed("curl http://localhost:8081 --compressed | grep -o myMPD")
'';
}
+1 -1
View File
@@ -96,7 +96,7 @@ in
webserver.succeed("mkdir -p /var/web")
webserver.succeed("chown nginx:nginx /var/web")
webserver.succeed("$(curl -vvv http://sandbox.test/test2-write)")
assert "404 Not Found" in machine.succeed(
assert "404 Not Found" in webserver.succeed(
"curl -vvv -s http://sandbox.test/test2-read/bar.txt"
)
'';
+2 -2
View File
@@ -14,8 +14,8 @@
testScript = ''
start_all()
machine.systemctl("start network-online.target")
machine.wait_for_unit("network-online.target")
serviceEmptyConf.systemctl("start network-online.target")
serviceEmptyConf.wait_for_unit("network-online.target")
with subtest("empty/default config test"):
serviceEmptyConf.wait_for_unit("paisa.service")
+1
View File
@@ -83,6 +83,7 @@ import ../make-test-python.nix (
};
testScript = ''
import os
import shlex
+5 -5
View File
@@ -75,18 +75,18 @@ in
)
with subtest("verify UI installed"):
machine.succeed("curl -sSf http://127.0.0.1:7280/ui/")
server.succeed("curl -sSf http://127.0.0.1:7280/ui/")
with subtest("injest and query data"):
import json
# Test CLI ingestion
print(machine.succeed('${pkgs.quickwit}/bin/quickwit index create --index-config ${pkgs.writeText "index.yaml" index_yaml}'))
print(server.succeed('${pkgs.quickwit}/bin/quickwit index create --index-config ${pkgs.writeText "index.yaml" index_yaml}'))
# Important to use `--wait`, otherwise the queries below race with index processing.
print(machine.succeed('${pkgs.quickwit}/bin/quickwit index ingest --index example_server_logs --input-path ${pkgs.writeText "exampleDocs.json" exampleDocs} --wait'))
print(server.succeed('${pkgs.quickwit}/bin/quickwit index ingest --index example_server_logs --input-path ${pkgs.writeText "exampleDocs.json" exampleDocs} --wait'))
# Test CLI query
cli_query_output = machine.succeed('${pkgs.quickwit}/bin/quickwit index search --index example_server_logs --query "exception"')
cli_query_output = server.succeed('${pkgs.quickwit}/bin/quickwit index search --index example_server_logs --query "exception"')
print(cli_query_output)
# Assert query result is as expected.
@@ -94,7 +94,7 @@ in
assert num_hits == 3, f"cli_query_output contains unexpected number of results: {num_hits}"
# Test API query
api_query_output = machine.succeed('curl --fail http://127.0.0.1:7280/api/v1/example_server_logs/search?query=exception')
api_query_output = server.succeed('curl --fail http://127.0.0.1:7280/api/v1/example_server_logs/search?query=exception')
print(api_query_output)
quickwit.log(quickwit.succeed(
+2 -2
View File
@@ -78,11 +78,11 @@ in
with subtest("debugging: /dev/video0 works"):
machine.succeed("v4l2-ctl --all >&2")
machine.succeed("fswebcam --no-banner /tmp/webcam.jpg")
machine.copy_from_vm("/tmp/webcam.jpg", "webcam")
machine.copy_from_machine("/tmp/webcam.jpg", "webcam")
# scan with the webcam
machine.succeed("scanimage -o /tmp/scan.png >&2")
machine.copy_from_vm("/tmp/scan.png", "scan")
machine.copy_from_machine("/tmp/scan.png", "scan")
# the image should contain "${text}"
output = machine.succeed("tesseract /tmp/scan.png -")
@@ -140,28 +140,27 @@ in
in
# python
''
# List of AS instances
machines = [scion01, scion02, scion03, scion04, scion05]
vms = [scion01, scion02, scion03, scion04, scion05]
# Functions to avoid many for loops
def start(allow_reboot=False):
for i in machines:
for i in vms:
i.start(allow_reboot=allow_reboot)
def wait_for_unit(service_name):
for i in machines:
for i in vms:
i.wait_for_unit(service_name)
def succeed(command):
for i in machines:
for i in vms:
i.succeed(command)
def reboot():
for i in machines:
for i in vms:
i.reboot()
def crash():
for i in machines:
for i in vms:
i.crash()
# Start all machines, allowing reboot for later
+1 -1
View File
@@ -79,7 +79,7 @@
with subtest("Environment variables have been substituted"):
base.succeed("grep -q somesecret /run/searx/settings.yml")
base.copy_from_vm("/run/searx/settings.yml")
base.copy_from_machine("/run/searx/settings.yml")
with subtest("Basic setup is working"):
base.wait_for_open_port(8080)
+2 -2
View File
@@ -17,8 +17,8 @@
testScript = ''
start_all();
machine.wait_for_unit("snmpd.service")
machine.succeed("snmpwalk -v 2c -c public localhost | grep SNMPv2-MIB::sysName.0");
snmpd.wait_for_unit("snmpd.service")
snmpd.succeed("snmpwalk -v 2c -c public localhost | grep SNMPv2-MIB::sysName.0");
'';
}
+2 -2
View File
@@ -148,7 +148,7 @@
machine.send_chars("test-x11\n")
machine.wait_for_file("/tmp/test-x11-exit-ok")
print(machine.succeed("cat /tmp/test-x11.out"))
machine.copy_from_vm("/tmp/test-x11.out")
machine.copy_from_machine("/tmp/test-x11.out")
machine.screenshot("alacritty_glinfo")
machine.succeed("pkill alacritty")
@@ -160,7 +160,7 @@
machine.send_chars("test-wayland\n")
machine.wait_for_file("/tmp/test-wayland-exit-ok")
print(machine.succeed("cat /tmp/test-wayland.out"))
machine.copy_from_vm("/tmp/test-wayland.out")
machine.copy_from_machine("/tmp/test-wayland.out")
machine.screenshot("foot_wayland_info")
machine.send_key("alt-shift-q")
machine.wait_until_fails("pgrep foot")
+2 -2
View File
@@ -149,7 +149,7 @@
machine.send_chars("test-x11\n")
machine.wait_for_file("/tmp/test-x11-exit-ok")
print(machine.succeed("cat /tmp/test-x11.out"))
machine.copy_from_vm("/tmp/test-x11.out")
machine.copy_from_machine("/tmp/test-x11.out")
machine.screenshot("alacritty_glinfo")
machine.succeed("pkill alacritty")
@@ -161,7 +161,7 @@
machine.send_chars("test-wayland\n")
machine.wait_for_file("/tmp/test-wayland-exit-ok")
print(machine.succeed("cat /tmp/test-wayland.out"))
machine.copy_from_vm("/tmp/test-wayland.out")
machine.copy_from_machine("/tmp/test-wayland.out")
machine.screenshot("foot_wayland_info")
machine.send_key("alt-shift-q")
machine.wait_until_fails("pgrep foot")
+3 -3
View File
@@ -227,7 +227,7 @@ in
})
+ ''
# Useful for debugging later
machine.copy_from_vm("${configPath}", "before")
machine.copy_from_machine("${configPath}", "before")
machine.systemctl("restart syncthing-init.service")
machine.wait_for_unit("syncthing-init.service")
@@ -237,13 +237,13 @@ in
})
+ ''
# Useful for debugging later
machine.copy_from_vm("${configPath}", "after")
machine.copy_from_machine("${configPath}", "after")
# Copy the systemd unit's bash script, to inspect it for debugging.
mergeScript = machine.succeed(
"systemctl cat syncthing-init.service | "
"${pkgs.initool}/bin/initool g - Service ExecStart --value-only"
).strip() # strip from new lines
machine.copy_from_vm(mergeScript, "")
machine.copy_from_machine(mergeScript, "")
'';
}
+2 -2
View File
@@ -44,7 +44,7 @@
# We copy the main graph into the $out (toplevel), and we also copy
# the entire output directory with additional data
with subtest("Copying the resulting data into $out"):
machine.copy_from_vm("systemd-analyze/", "")
machine.copy_from_vm("systemd-analyze/systemd-analyze.svg", "")
machine.copy_from_machine("systemd-analyze/", "")
machine.copy_from_machine("systemd-analyze/systemd-analyze.svg", "")
'';
}
+1 -1
View File
@@ -37,7 +37,7 @@
with subtest("interactive shell with terminal in capsule"):
hello_output = machine.succeed("systemd-run -t --capsule=alice /run/current-system/sw/bin/bash -i -c 'hello | tee ~/hello'")
assert hello_output == "Hello, world!\r\n"
machine.copy_from_vm("/var/lib/capsules/alice/hello")
machine.copy_from_machine("/var/lib/capsules/alice/hello")
with subtest("capsule cleanup"):
machine.succeed("systemctl --capsule=alice stop sleeptest.service")
+16 -2
View File
@@ -21,10 +21,19 @@ in
maintainers = [ ];
};
nodes.machine1 = { pkgs, lib, ... }: commonConfig;
nodes.machine1 =
{ pkgs, lib, ... }:
{
imports = [ commonConfig ];
systemd.coredump.settings.Coredump = {
Storage = "journal";
ProcessSizeMax = "0";
};
};
nodes.machine2 =
{ pkgs, lib, ... }:
lib.recursiveUpdate commonConfig {
{
imports = [ commonConfig ];
systemd.coredump.enable = false;
systemd.package = pkgs.systemd.override {
withCoredump = false;
@@ -39,6 +48,11 @@ in
machine1.wait_until_succeeds("coredumpctl list | grep crasher", timeout=10)
machine1.fail("stat /var/lib/crasher/core*")
with subtest("settings.Coredump renders coredump.conf"):
machine1.succeed("grep -F '[Coredump]' /etc/systemd/coredump.conf")
machine1.succeed("grep -F 'Storage=journal' /etc/systemd/coredump.conf")
machine1.succeed("grep -F 'ProcessSizeMax=0' /etc/systemd/coredump.conf")
with subtest("systemd-coredump disabled"):
machine2.systemctl("start crasher");
machine2.wait_until_succeeds("stat /var/lib/crasher/core*", timeout=10)
+3 -3
View File
@@ -45,11 +45,11 @@
client.wait_for_unit("multi-user.target")
def copy_pem(file: str):
machine.copy_from_host(source=f"{tmpdir}/{file}", target=f"/run/secrets/{file}")
machine.succeed(f"chmod 600 /run/secrets/{file} && chown systemd-journal-gateway /run/secrets/{file}")
client.copy_from_host(source=f"{tmpdir}/{file}", target=f"/run/secrets/{file}")
client.succeed(f"chmod 600 /run/secrets/{file} && chown systemd-journal-gateway /run/secrets/{file}")
with subtest("Copying keys and certificates"):
machine.succeed("mkdir -p /run/secrets/{client,server}")
client.succeed("mkdir -p /run/secrets/{client,server}")
copy_pem("server/cert.pem")
copy_pem("server/key.pem")
copy_pem("client/cert.pem")
-4
View File
@@ -75,10 +75,6 @@ let
# improvement: move following profile to ../modules/profiles/vmspawn-guest.nix
profile-guest-vmspawn = {
imports = [ ../modules/profiles/qemu-guest.nix ];
# improvement: move following configuration to qemu-guest.nix
boot.initrd.availableKernelModules = [
"virtiofs"
];
boot.initrd.systemd.enable = true;
# root is defined by systemd-vmspawn
+23 -23
View File
@@ -48,44 +48,44 @@
};
testScript = ''
start_all()
machine.wait_for_unit("sockets.target")
server.wait_for_unit("sockets.target")
with subtest("Check keys are generated"):
machine.wait_until_succeeds("curl -v http://127.0.0.1:7654/adv")
key = machine.wait_until_succeeds("tang-show-keys 7654")
server.wait_until_succeeds("curl -v http://127.0.0.1:7654/adv")
key = server.wait_until_succeeds("tang-show-keys 7654")
with subtest("Check systemd access list"):
machine.succeed("ping -c 3 192.168.0.1")
machine.fail("curl -v --connect-timeout 3 http://192.168.0.1:7654/adv")
server.succeed("ping -c 3 192.168.0.1")
server.fail("curl -v --connect-timeout 3 http://192.168.0.1:7654/adv")
with subtest("Check basic encrypt and decrypt message"):
machine.wait_until_succeeds(f"""echo 'Hello World' | clevis encrypt tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}"}}' > /tmp/encrypted""")
decrypted = machine.wait_until_succeeds("clevis decrypt < /tmp/encrypted")
server.wait_until_succeeds(f"""echo 'Hello World' | clevis encrypt tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}"}}' > /tmp/encrypted""")
decrypted = server.wait_until_succeeds("clevis decrypt < /tmp/encrypted")
assert decrypted.strip() == "Hello World"
machine.wait_until_succeeds("tang-show-keys 7654")
server.wait_until_succeeds("tang-show-keys 7654")
with subtest("Check encrypt and decrypt disk"):
machine.succeed("cryptsetup luksFormat --force-password --batch-mode /dev/vdb <<<'password'")
machine.succeed(f"""clevis luks bind -s1 -y -f -d /dev/vdb tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}" }}' <<< 'password' """)
clevis_luks = machine.succeed("clevis luks list -d /dev/vdb")
server.succeed("cryptsetup luksFormat --force-password --batch-mode /dev/vdb <<<'password'")
server.succeed(f"""clevis luks bind -s1 -y -f -d /dev/vdb tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}" }}' <<< 'password' """)
clevis_luks = server.succeed("clevis luks list -d /dev/vdb")
assert clevis_luks.strip() == """1: tang '{"url":"http://127.0.0.1:7654"}'"""
machine.succeed("clevis luks unlock -d /dev/vdb")
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
machine.succeed("clevis luks unlock -d /dev/vdb")
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
server.succeed("clevis luks unlock -d /dev/vdb")
server.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
server.succeed("clevis luks unlock -d /dev/vdb")
server.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
# without tang available, unlock should fail
machine.succeed("systemctl stop tangd.socket")
machine.fail("clevis luks unlock -d /dev/vdb")
machine.succeed("systemctl start tangd.socket")
server.succeed("systemctl stop tangd.socket")
server.fail("clevis luks unlock -d /dev/vdb")
server.succeed("systemctl start tangd.socket")
with subtest("Rotate server keys"):
machine.succeed("${pkgs.tang}/libexec/tangd-rotate-keys -d /var/lib/tang")
machine.succeed("clevis luks unlock -d /dev/vdb")
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
server.succeed("${pkgs.tang}/libexec/tangd-rotate-keys -d /var/lib/tang")
server.succeed("clevis luks unlock -d /dev/vdb")
server.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
with subtest("Test systemd service security"):
output = machine.succeed("systemd-analyze security tangd@.service")
machine.log(output)
output = server.succeed("systemd-analyze security tangd@.service")
server.log(output)
assert output[-9:-1] == "SAFE :-}"
'';
}
+2 -2
View File
@@ -41,7 +41,7 @@
client.succeed("task sync")
# Useful for debugging
client.copy_from_vm("/root/.task", "client")
server.copy_from_vm("${cfg.dataDir}", "server")
client.copy_from_machine("/root/.task", "client")
server.copy_from_machine("${cfg.dataDir}", "server")
'';
}
+2 -2
View File
@@ -55,13 +55,13 @@
# Make a screenshot and save the result:
machine.screenshot("tinywl_foot")
print(machine.succeed("cat /tmp/test-wayland.out"))
machine.copy_from_vm("/tmp/test-wayland.out")
machine.copy_from_machine("/tmp/test-wayland.out")
# Terminate cleanly:
machine.send_key("alt-esc")
machine.wait_until_fails("pgrep foot")
machine.wait_until_fails("pgrep tinywl")
machine.wait_for_file("/tmp/tinywl-exit-ok")
machine.copy_from_vm("/tmp/tinywl.log")
machine.copy_from_machine("/tmp/tinywl.log")
'';
}
+4 -4
View File
@@ -146,10 +146,10 @@
machine.succeed("scrot --display :0 /tmp/glxgears.png")
# Copy files down.
machine.copy_from_vm("/tmp/glxgears.png")
machine.copy_from_vm("/tmp/glxgears.stdout")
machine.copy_from_vm("/tmp/Xvnc.stdout")
machine.copy_from_vm("/tmp/Xvnc.stderr")
machine.copy_from_machine("/tmp/glxgears.png")
machine.copy_from_machine("/tmp/glxgears.stdout")
machine.copy_from_machine("/tmp/Xvnc.stdout")
machine.copy_from_machine("/tmp/Xvnc.stderr")
'';
}
+2
View File
@@ -51,6 +51,8 @@ let
enableOCR = true;
testScript = ''
machine = ${name}
@polling_condition
def codium_running():
machine.succeed('pgrep -x codium')
+1 -1
View File
@@ -113,7 +113,7 @@ in
machine.succeed("run-goupile-test")
out_dir = os.environ.get("out", os.getcwd())
machine.copy_from_vm("/tmp/videos", out_dir)
machine.copy_from_machine("/tmp/videos", out_dir)
'';
# Debug interactively with:
+7 -7
View File
@@ -52,12 +52,12 @@
start_all()
def get_users():
response = machine.succeed("http --check-status http://strichliste.local/api/user")
response = server.succeed("http --check-status http://strichliste.local/api/user")
users = json.loads(response)["users"]
return users
def get_user(uid: int):
response = machine.succeed(f"http --check-status http://strichliste.local/api/user/{uid}")
response = server.succeed(f"http --check-status http://strichliste.local/api/user/{uid}")
user = json.loads(response)["user"]
return user
@@ -67,7 +67,7 @@
t.assertEqual(len(users), 0, "Strichliste must not have users.")
with subtest("Create user"):
machine.succeed("http --check-status post http://strichliste.local/api/user name=Alice")
server.succeed("http --check-status post http://strichliste.local/api/user name=Alice")
users = get_users()
t.assertEqual(len(users), 1, "Strichliste must have exactly one user.")
@@ -77,19 +77,19 @@
t.assertEqual(user["balance"], 0, "New users should have a balance of 0")
with subtest("Deposit money"):
machine.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=500")
server.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=500")
user = get_user(1)
t.assertEqual(user["balance"], 500, "Balance must be 500 after depositing 500")
with subtest("Dispense money"):
machine.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=-1000")
server.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=-1000")
user = get_user(1)
t.assertEqual(user["balance"], -500, "Balance must be -500 after dispensing 1000")
with subtest("Undo transaction"):
response = machine.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=7500")
response = server.succeed("http --check-status post http://strichliste.local/api/user/1/transaction amount=7500")
transaction = json.loads(response)["transaction"]
machine.succeed(f"http --check-status delete http://strichliste.local/api/user/1/transaction/{transaction['id']}")
server.succeed(f"http --check-status delete http://strichliste.local/api/user/1/transaction/{transaction['id']}")
server.wait_for_unit("phpfpm-strichliste.service")
+1 -1
View File
@@ -53,7 +53,7 @@
# NOTE; Wait a couple of seconds for all windmill components to finalise their database migration flow. This prevents race conditions on schema constraints.
time.sleep(10) # seconds
windmill.succeed("curl --silent --fail http://windmill:8001")
t.assertIn("v${pkgs.windmill.version}", machine.succeed("curl --silent --fail http://windmill:8001/api/version"), "Mismatched version response")
t.assertIn("v${pkgs.windmill.version}", windmill.succeed("curl --silent --fail http://windmill:8001/api/version"), "Mismatched version response")
with subtest("Validation"):
windmill.succeed("integration-test --language python3 --script ${./python3.script} --input ${./python3.input}")
+2 -2
View File
@@ -137,7 +137,7 @@ let
testScript = ''
# save hostapd config file for manual inspection
machine.wait_for_unit("hostapd.service")
machine.copy_from_vm("/run/hostapd/wlan0.hostapd.conf")
machine.copy_from_machine("/run/hostapd/wlan0.hostapd.conf")
${extraTestScript}
'';
@@ -257,7 +257,7 @@ in
machine.succeed("wpa_cli -i wlan0 list_networks | grep -q test2")
# save file for manual inspection
machine.copy_from_vm(config_file)
machine.copy_from_machine(config_file)
# check hardening options
machine.succeed("systemd-analyze security wpa_supplicant >&2")
+3 -3
View File
@@ -14,14 +14,14 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "ty";
version = "0.0.33";
version = "0.0.34";
src = fetchFromGitHub {
owner = "astral-sh";
repo = "ty";
tag = finalAttrs.version;
fetchSubmodules = true;
hash = "sha256-cc/1piasUlv3wwYsXdJaKc8Ck9KF1/FjAjHv6XL6E7o=";
hash = "sha256-pLe25JRy6xrFVuNCQKwp9k3Mvc4pfYKF6Xi17yMgSzw=";
};
# For Darwin platforms, remove the integration test for file notifications,
@@ -35,7 +35,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
cargoBuildFlags = [ "--package=ty" ];
cargoHash = "sha256-8DaJWHFBoVzpbkd9QmJ72a5NeKuX99lfDq3uUp+wd5I=";
cargoHash = "sha256-A/oJeFIY/+Pu9jYp3hwGwkSAXfF0VLTHKGP48wsnheo=";
nativeBuildInputs = [ installShellFiles ];
@@ -90,6 +90,12 @@ stdenv.mkDerivation rec {
excludes = [ "networking/httpd_ratelimit_cgi.c" ]; # New since release.
hash = "sha256-Msm9sDZrVx7ofunnvnTS73SPKUUpR3Tv5xZ/wBd+rts=";
})
# syslogd: fix writing to local log file
# https://lists.busybox.net/pipermail/busybox/2024-October/090969.html
(fetchpatch {
url = "https://hg.slitaz.org/wok/raw-file/1cba565dc2a9/busybox/stuff/busybox-1.37-fix-syslogd.patch";
hash = "sha256-NZRctLv1CpTfnR6+CA890YY8ljBQLGkkselyP5/TnsQ=";
})
# https://lists.busybox.net/pipermail/busybox/2026-March/092010.html
./build-system-buffer-overflow.patch
]
@@ -155,8 +155,8 @@ lib.makeExtensible (
(
{
nix_2_28 = commonMeson {
version = "2.28.6";
hash = "sha256-jg2YDTFt8CY4kMg4ha3UK5C+mQY+Zg67nwNy+CmTk5w=";
version = "2.28.7";
hash = "sha256-Fq4+7uYz6bdE1HvPqn+qZcYX1rNilVKT7YAAPLA8170=";
self_attribute_name = "nix_2_28";
patches = patches_common ++ [
lowdown30PatchOld
@@ -165,14 +165,14 @@ lib.makeExtensible (
nixComponents_2_30 =
(nixDependencies.callPackage ./modular/packages.nix rec {
version = "2.30.4";
version = "2.30.5";
inherit teams;
otherSplices = generateSplicesForNixComponents "nixComponents_2_30";
src = fetchFromGitHub {
owner = "NixOS";
repo = "nix";
tag = version;
hash = "sha256-cJ96IBZCYoX0Tdlo5Q7qDSAKfL6QcUq/4Kr1UplH50E=";
hash = "sha256-tGiV71RxtCNcUNX86ZwmOIghG4pLwm5nlRKd89er7Gk=";
};
}).appendPatches
(patches_common ++ [ lowdown30PatchOld ]);
@@ -181,14 +181,14 @@ lib.makeExtensible (
nixComponents_2_31 =
(nixDependencies.callPackage ./modular/packages.nix rec {
version = "2.31.4";
version = "2.31.5";
inherit teams;
otherSplices = generateSplicesForNixComponents "nixComponents_2_31";
src = fetchFromGitHub {
owner = "NixOS";
repo = "nix";
tag = version;
hash = "sha256-f/haYfcI+9IiYVH+g6cjhF8cK7QWHAFfcPtF+57ujZ0=";
hash = "sha256-b7fhCXxl9qKTNPQvG8T/+nOxB95kalt9/aSY+ZSRctk=";
};
}).appendPatches
[ ];
@@ -197,14 +197,14 @@ lib.makeExtensible (
nixComponents_2_34 =
(nixDependencies.callPackage ./modular/packages.nix rec {
version = "2.34.6";
version = "2.34.7";
inherit teams;
otherSplices = generateSplicesForNixComponents "nixComponents_2_34";
src = fetchFromGitHub {
owner = "NixOS";
repo = "nix";
tag = version;
hash = "sha256-kHMyhuzhLtH3f+wAcNvAL62ct2kmwZOp2B54SHkMMo0=";
hash = "sha256-uj5KNW8Vdm60FCUxD2KsrCVH/WwoemvczWmmrb3Gvlo=";
};
}).appendPatches
patches_common;