I’ve finally got around to fixing NixOS managing ZFS data sets with spaces in the name · Issue #29273 · NixOS/nixpkgs · GitHub and am trying to write a NixOS test for my patch.
I’m having trouble figuring out how I can modify the machine my test is running in while the test is running, as there is no /etc/nixos/configuration.nix.
My test script currently looks like this:
testScript = ‘’
$machine->succeed(“modprobe zfs”);
$machine->succeed(“zpool status”);
$machine->succeed("truncate -s 100M /test.img");
$machine->succeed("zpool create tank /test.img");
$machine->succeed("zfs create -o mountpoint=legacy tank/Foo\\ Bar");
# TODO: modify configuration.nix to include:
# fileSystems."/Foo Bar" = { device = "tank/Foo Bar"; fsType = "zfs"; };
# TODO: nixos-rebuild switch
# and ensure /etc/fstab is properly escaped
‘’;
Any help? Thank you.
@fpletz has some wizardry at offer IIRC
aszlig
October 28, 2018, 12:08am
3
I’m not sure what you mean by “dynamic”, but you can switch to another configuration. Here is an example test which is actually doing this:
users.users.bar.isNormalUser = true;
};
client2 = client1;
};
testScript = { nodes, ... }: let
cfg = nodes.server.config.services.taskserver;
portStr = toString cfg.listenPort;
newServerSystem = nodes.newServer.config.system.build.toplevel;
switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test";
in ''
sub su ($$) {
my ($user, $cmd) = @_;
my $esc = $cmd =~ s/'/'\\${"'"}'/gr;
return "su - $user -c '$esc'";
}
sub setupClientsFor ($$;$) {
my ($org, $user, $extraInit) = @_;
The idea here is to have two nodes defined, one for the initial configuration and another one for the configuration you want to switch to. You only start the initial configuration (via $initial->start
or anything implicitly triggering this) and afterwards you just query the toplevel
attribute for the configuration you want to switch to using the nodes
attribute and run switch-to-configuration test
.
Here is a shorter example:
import <nixpkgs/nixos/tests/make-test.nix> {
name = "foobar";
nodes = {
initial = { pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
};
new = {
services.openssh.enable = true;
};
};
testScript = { nodes, ... }: let
inherit (nodes.new.config.system.build) toplevel;
in ''
$initial->waitForUnit('multi-user.target');
$initial->succeed('hello');
$initial->fail('nc -z 127.0.0.1 22');
$initial->succeed('${toplevel}/bin/switch-to-configuration test');
$initial->fail('hello');
$initial->succeed('nc -z 127.0.0.1 22');
'';
}
Update 2023-11: Note that nowadays there is a better way to do this using the specialisation
option , here is a test that uses this option:
# Test configuration switching.
import ./make-test-python.nix ({ lib, pkgs, ...} : let
# Simple service that can either be socket-activated or that will
# listen on port 1234 if not socket-activated.
# A connection to the socket causes 'hello' to be written to the client.
socketTest = pkgs.writeScript "socket-test.py" /* python */ ''
#!${pkgs.python3}/bin/python3
from socketserver import TCPServer, StreamRequestHandler
import socket
import os
class Handler(StreamRequestHandler):
def handle(self):
self.wfile.write("hello".encode("utf-8"))
This file has been truncated. show original
2 Likes
aszlig,
That appears to be exactly what I’m looking for. Appreciate the very clear answer!