specialisation: replace nesting with named configurations

Co-authored-by: worldofpeace <worldofpeace@protonmail.ch>
This commit is contained in:
Graham Christensen 2020-03-05 17:07:20 -05:00
parent 807ca93fad
commit ec2d28e323
No known key found for this signature in database
GPG key ID: FE918C3A98C1030F
14 changed files with 230 additions and 189 deletions

View file

@ -40,7 +40,7 @@ networking.proxy.noProxy = &quot;127.0.0.1,localhost,internal.domain&quot;;
<note> <note>
<para> <para>
If you are switching networks with different proxy configurations, use the If you are switching networks with different proxy configurations, use the
<literal>nesting.clone</literal> option in <literal>specialisation</literal> option in
<literal>configuration.nix</literal> to switch proxies at runtime. Refer to <literal>configuration.nix</literal> to switch proxies at runtime. Refer to
<xref linkend="ch-options" /> for more information. <xref linkend="ch-options" /> for more information.
</para> </para>

View file

@ -203,6 +203,50 @@ environment.systemPackages = [
<link xlink:href="https://github.com/gollum/gollum/wiki/5.0-release-notes#migrating-your-wiki">here</link>. <link xlink:href="https://github.com/gollum/gollum/wiki/5.0-release-notes#migrating-your-wiki">here</link>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The NixOS options <literal>nesting.clone</literal> and
<literal>nesting.children</literal> have been deleted, and
replaced with named <xref linkend="opt-specialisation"/>
configurations.
</para>
<para>
Replace a <literal>nesting.clone</literal> entry with:
<programlisting>{
<link xlink:href="#opt-specialisation">specialisation.example-sub-configuration</link> = {
<link xlink:href="#opt-specialisation._name_.configuration">configuration</link> = {
...
};
};</programlisting>
</para>
<para>
Replace a <literal>nesting.children</literal> entry with:
<programlisting>{
<link xlink:href="#opt-specialisation">specialisation.example-sub-configuration</link> = {
<link xlink:href="#opt-specialisation._name_.inheritParentConfig">inheritParentConfig</link> = false;
<link xlink:href="#opt-specialisation._name_.configuration">configuration</link> = {
...
};
};</programlisting>
</para>
<para>
To switch to a specialised configuration at runtime you need to
run:
<programlisting>
# sudo /run/current-system/specialisation/example-sub-configuration/bin/switch-to-configuration test
</programlisting>
Before you would have used:
<programlisting>
# sudo /run/current-system/fine-tune/child-1/bin/switch-to-configuration test
</programlisting>
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View file

@ -4,6 +4,5 @@ with lib;
{ {
boot.loader.grub.device = mkOverride 0 "nodev"; boot.loader.grub.device = mkOverride 0 "nodev";
nesting.children = mkOverride 0 []; specialisation = mkOverride 0 {};
nesting.clone = mkOverride 0 [];
} }

View file

@ -11,21 +11,16 @@ let
# you can provide an easy way to boot the same configuration # you can provide an easy way to boot the same configuration
# as you use, but with another kernel # as you use, but with another kernel
# !!! fix this # !!! fix this
cloner = inheritParent: list: children = mapAttrs (childName: childConfig:
map (childConfig:
(import ../../../lib/eval-config.nix { (import ../../../lib/eval-config.nix {
inherit baseModules; inherit baseModules;
system = config.nixpkgs.initialSystem; system = config.nixpkgs.initialSystem;
modules = modules =
(optionals inheritParent modules) (optionals childConfig.inheritParentConfig modules)
++ [ ./no-clone.nix ] ++ [ ./no-clone.nix ]
++ [ childConfig ]; ++ [ childConfig.configuration ];
}).config.system.build.toplevel }).config.system.build.toplevel
) list; ) config.specialisation;
children =
cloner false config.nesting.children
++ cloner true config.nesting.clone;
systemBuilder = systemBuilder =
let let
@ -77,12 +72,9 @@ let
echo -n "$nixosLabel" > $out/nixos-version echo -n "$nixosLabel" > $out/nixos-version
echo -n "${config.boot.kernelPackages.stdenv.hostPlatform.system}" > $out/system echo -n "${config.boot.kernelPackages.stdenv.hostPlatform.system}" > $out/system
mkdir $out/fine-tune mkdir $out/specialisation
childCount=0 ${concatStringsSep "\n"
for i in $children; do (mapAttrsToList (name: path: "ln -s ${path} $out/specialisation/${name}") children)}
childCount=$(( childCount + 1 ))
ln -s $i $out/fine-tune/child-$childCount
done
mkdir $out/bin mkdir $out/bin
export localeArchive="${config.i18n.glibcLocales}/lib/locale/locale-archive" export localeArchive="${config.i18n.glibcLocales}/lib/locale/locale-archive"
@ -112,7 +104,6 @@ let
shell = "${pkgs.bash}/bin/sh"; shell = "${pkgs.bash}/bin/sh";
su = "${pkgs.shadow.su}/bin/su"; su = "${pkgs.shadow.su}/bin/su";
inherit children;
kernelParams = config.boot.kernelParams; kernelParams = config.boot.kernelParams;
installBootLoader = installBootLoader =
config.system.build.installBootLoader config.system.build.installBootLoader
@ -143,6 +134,11 @@ let
in in
{ {
imports = [
(mkRemovedOptionModule [ "nesting" "clone" ] "Use `specialisation.«name» = { inheritParentConfig = true; configuration = { ... }; }` instead.")
(mkRemovedOptionModule [ "nesting" "children" ] "Use `specialisation.«name».configuration = { ... }` instead.")
];
options = { options = {
system.build = mkOption { system.build = mkOption {
@ -154,26 +150,35 @@ in
''; '';
}; };
nesting.children = mkOption { specialisation = mkOption {
default = []; default = {};
example = lib.literalExample "{ fewJobsManyCores.configuration = { nix.buildCores = 0; nix.maxJobs = 1; }; }";
description = '' description = ''
Additional configurations to build. Additional configurations to build. If
''; <literal>inheritParentConfig</literal> is true, the system
}; will be based on the overall system configuration.
nesting.clone = mkOption { To switch to a specialised configuration
default = []; (e.g. <literal>fewJobsManyCores</literal>) at runtime, run:
description = ''
Additional configurations to build based on the current
configuration which then has a lower priority.
To switch to a cloned configuration (e.g. <literal>child-1</literal>)
at runtime, run
<programlisting> <programlisting>
# sudo /run/current-system/fine-tune/child-1/bin/switch-to-configuration test # sudo /run/current-system/specialisation/fewJobsManyCores/bin/switch-to-configuration test
</programlisting> </programlisting>
''; '';
type = types.attrsOf (types.submodule (
{ ... }: {
options.inheritParentConfig = mkOption {
type = types.bool;
default = true;
description = "Include the entire system's configuration. Set to false to make a completely differently configured system.";
};
options.configuration = mkOption {
default = {};
description = "Arbitrary NixOS configuration options.";
};
})
);
}; };
system.boot.loader.id = mkOption { system.boot.loader.id = mkOption {

View file

@ -409,7 +409,7 @@ $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
# Find all the children of the current default configuration # Find all the children of the current default configuration
# Do not search for grand children # Do not search for grand children
my @links = sort (glob "$defaultConfig/fine-tune/*"); my @links = sort (glob "$defaultConfig/specialisation/*");
foreach my $link (@links) { foreach my $link (@links) {
my $entryName = ""; my $entryName = "";
@ -425,7 +425,8 @@ foreach my $link (@links) {
if ($cfgName) { if ($cfgName) {
$entryName = $cfgName; $entryName = $cfgName;
} else { } else {
$entryName = "($date - $version)"; my $linkname = basename($link);
$entryName = "($linkname - $date - $version)";
} }
addEntry("NixOS - $entryName", $link); addEntry("NixOS - $entryName", $link);
} }

View file

@ -69,7 +69,7 @@ addEntry "NixOS - Default" $defaultConfig ""
# Add all generations of the system profile to the menu, in reverse # Add all generations of the system profile to the menu, in reverse
# (most recent to least recent) order. # (most recent to least recent) order.
for link in $((ls -d $defaultConfig/fine-tune/* ) | sort -n); do for link in $((ls -d $defaultConfig/specialisation/* ) | sort -n); do
date=$(stat --printf="%y\n" $link | sed 's/\..*//') date=$(stat --printf="%y\n" $link | sed 's/\..*//')
addEntry "NixOS - variation" $link "" addEntry "NixOS - variation" $link ""
done done

View file

@ -91,52 +91,50 @@ in import ./make-test-python.nix {
security.acme.server = "https://acme-v02.api.letsencrypt.org/dir"; security.acme.server = "https://acme-v02.api.letsencrypt.org/dir";
nesting.clone = [ specialisation.second-cert.configuration = {pkgs, ...}: {
({pkgs, ...}: { systemd.targets."acme-finished-b.example.com" = {};
systemd.targets."acme-finished-b.example.com" = {}; systemd.services."acme-b.example.com" = {
systemd.services."acme-b.example.com" = { wants = [ "acme-finished-b.example.com.target" ];
wants = [ "acme-finished-b.example.com.target" ]; before = [ "acme-finished-b.example.com.target" ];
before = [ "acme-finished-b.example.com.target" ]; after = [ "nginx.service" ];
after = [ "nginx.service" ]; };
}; services.nginx.virtualHosts."b.example.com" = {
services.nginx.virtualHosts."b.example.com" = { enableACME = true;
enableACME = true; forceSSL = true;
forceSSL = true; locations."/".root = pkgs.runCommand "docroot" {} ''
locations."/".root = pkgs.runCommand "docroot" {} '' mkdir -p "$out"
mkdir -p "$out" echo hello world > "$out/index.html"
echo hello world > "$out/index.html" '';
''; };
}; };
}) specialisation.dns-01.configuration = {pkgs, config, nodes, lib, ...}: {
({pkgs, config, nodes, lib, ...}: { security.acme.certs."example.com" = {
security.acme.certs."example.com" = { domain = "*.example.com";
domain = "*.example.com"; dnsProvider = "exec";
dnsProvider = "exec"; dnsPropagationCheck = false;
dnsPropagationCheck = false; credentialsFile = with pkgs; writeText "wildcard.env" ''
credentialsFile = with pkgs; writeText "wildcard.env" '' EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }}
EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }} '';
''; user = config.services.nginx.user;
user = config.services.nginx.user; group = config.services.nginx.group;
group = config.services.nginx.group; };
}; systemd.targets."acme-finished-example.com" = {};
systemd.targets."acme-finished-example.com" = {}; systemd.services."acme-example.com" = {
systemd.services."acme-example.com" = { wants = [ "acme-finished-example.com.target" ];
wants = [ "acme-finished-example.com.target" ]; before = [ "acme-finished-example.com.target" "nginx.service" ];
before = [ "acme-finished-example.com.target" "nginx.service" ]; wantedBy = [ "nginx.service" ];
wantedBy = [ "nginx.service" ]; };
}; services.nginx.virtualHosts."c.example.com" = {
services.nginx.virtualHosts."c.example.com" = { forceSSL = true;
forceSSL = true; sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem";
sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem"; sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem";
sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem"; sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem";
sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem"; locations."/".root = pkgs.runCommand "docroot" {} ''
locations."/".root = pkgs.runCommand "docroot" {} '' mkdir -p "$out"
mkdir -p "$out" echo hello world > "$out/index.html"
echo hello world > "$out/index.html" '';
''; };
}; };
})
];
}; };
client = {nodes, lib, ...}: { client = {nodes, lib, ...}: {
@ -196,7 +194,7 @@ in import ./make-test-python.nix {
with subtest("Can add another certificate for nginx service"): with subtest("Can add another certificate for nginx service"):
webserver.succeed( webserver.succeed(
"/run/current-system/fine-tune/child-1/bin/switch-to-configuration test" "/run/current-system/specialisation/second-cert/bin/switch-to-configuration test"
) )
webserver.wait_for_unit("acme-finished-b.example.com.target") webserver.wait_for_unit("acme-finished-b.example.com.target")
client.succeed( client.succeed(
@ -208,7 +206,7 @@ in import ./make-test-python.nix {
"${switchToNewServer}" "${switchToNewServer}"
) )
webserver.succeed( webserver.succeed(
"/run/current-system/fine-tune/child-2/bin/switch-to-configuration test" "/run/current-system/specialisation/dns-01/bin/switch-to-configuration test"
) )
webserver.wait_for_unit("acme-finished-example.com.target") webserver.wait_for_unit("acme-finished-example.com.target")
client.succeed( client.succeed(

View file

@ -202,7 +202,7 @@ in
nat.standalone = handleTest ./nat.nix { withFirewall = false; }; nat.standalone = handleTest ./nat.nix { withFirewall = false; };
ndppd = handleTest ./ndppd.nix {}; ndppd = handleTest ./ndppd.nix {};
neo4j = handleTest ./neo4j.nix {}; neo4j = handleTest ./neo4j.nix {};
nesting = handleTest ./nesting.nix {}; specialisation = handleTest ./specialisation.nix {};
netdata = handleTest ./netdata.nix {}; netdata = handleTest ./netdata.nix {};
networking.networkd = handleTest ./networking.nix { networkd = true; }; networking.networkd = handleTest ./networking.nix { networkd = true; };
networking.scripted = handleTest ./networking.nix { networkd = false; }; networking.scripted = handleTest ./networking.nix { networkd = false; };

View file

@ -20,35 +20,33 @@ import ./make-test-python.nix ({ pkgs, ... }: {
} }
''; '';
nesting.clone = [ specialisation.etag.configuration = {
{ services.caddy.config = lib.mkForce ''
services.caddy.config = lib.mkForce '' http://localhost {
http://localhost { gzip
gzip
root ${ root ${
pkgs.runCommand "testdir2" {} '' pkgs.runCommand "testdir2" {} ''
mkdir "$out" mkdir "$out"
echo changed > "$out/example.html" echo changed > "$out/example.html"
'' ''
}
} }
''; }
} '';
};
{ specialisation.config-reload.configuration = {
services.caddy.config = '' services.caddy.config = ''
http://localhost:8080 { http://localhost:8080 {
} }
''; '';
} };
];
}; };
}; };
testScript = { nodes, ... }: let testScript = { nodes, ... }: let
etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1"; etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag";
justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2"; justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload";
in '' in ''
url = "http://localhost/example.html" url = "http://localhost/example.html"
webserver.wait_for_unit("caddy") webserver.wait_for_unit("caddy")
@ -77,7 +75,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
assert old_etag != new_etag, "Old ETag {} is the same as {}".format( assert old_etag != new_etag, "Old ETag {} is the same as {}".format(
old_etag, new_etag old_etag, new_etag
) )
with subtest("config is reloaded on nixos-rebuild switch"): with subtest("config is reloaded on nixos-rebuild switch"):
webserver.succeed( webserver.succeed(
"${justReloadSystem}/bin/switch-to-configuration test >&2" "${justReloadSystem}/bin/switch-to-configuration test >&2"

View file

@ -65,7 +65,7 @@ let
# partitions and filesystems. # partitions and filesystems.
testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi
, grubIdentifier, preBootCommands, extraConfig , grubIdentifier, preBootCommands, extraConfig
, testCloneConfig , testSpecialisationConfig
}: }:
let iface = if grubVersion == 1 then "ide" else "virtio"; let iface = if grubVersion == 1 then "ide" else "virtio";
isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
@ -220,7 +220,7 @@ let
# Tests for validating clone configuration entries in grub menu # Tests for validating clone configuration entries in grub menu
'' ''
+ optionalString testCloneConfig '' + optionalString testSpecialisationConfig ''
# Reboot Machine # Reboot Machine
machine = create_machine_named("clone-default-config") machine = create_machine_named("clone-default-config")
${preBootCommands} ${preBootCommands}
@ -262,7 +262,7 @@ let
, bootLoader ? "grub" # either "grub" or "systemd-boot" , bootLoader ? "grub" # either "grub" or "systemd-boot"
, grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false
, enableOCR ? false, meta ? {} , enableOCR ? false, meta ? {}
, testCloneConfig ? false , testSpecialisationConfig ? false
}: }:
makeTest { makeTest {
inherit enableOCR; inherit enableOCR;
@ -337,7 +337,7 @@ let
testScript = testScriptFun { testScript = testScriptFun {
inherit bootLoader createPartitions preBootCommands inherit bootLoader createPartitions preBootCommands
grubVersion grubDevice grubIdentifier grubUseEfi extraConfig grubVersion grubDevice grubIdentifier grubUseEfi extraConfig
testCloneConfig; testSpecialisationConfig;
}; };
}; };
@ -411,11 +411,11 @@ let
grubUseEfi = true; grubUseEfi = true;
}; };
clone-test-extraconfig = { specialisation-test-extraconfig = {
extraConfig = '' extraConfig = ''
environment.systemPackages = [ pkgs.grub2 ]; environment.systemPackages = [ pkgs.grub2 ];
boot.loader.grub.configurationName = "Home"; boot.loader.grub.configurationName = "Home";
nesting.clone = [ { specialisation.work.configuration = {
boot.loader.grub.configurationName = lib.mkForce "Work"; boot.loader.grub.configurationName = lib.mkForce "Work";
environment.etc = { environment.etc = {
@ -424,9 +424,9 @@ let
gitproxy = none for work.com gitproxy = none for work.com
"; ";
}; };
} ]; };
''; '';
testCloneConfig = true; testSpecialisationConfig = true;
}; };
@ -440,7 +440,7 @@ in {
simple = makeInstallerTest "simple" simple-test-config; simple = makeInstallerTest "simple" simple-test-config;
# Test cloned configurations with the simple grub configuration # Test cloned configurations with the simple grub configuration
simpleClone = makeInstallerTest "simpleClone" (simple-test-config // clone-test-extraconfig); simpleSpecialised = makeInstallerTest "simpleSpecialised" (simple-test-config // specialisation-test-extraconfig);
# Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem
simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" { simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" {
@ -467,7 +467,7 @@ in {
simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config; simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config;
# Test cloned configurations with the uefi grub configuration # Test cloned configurations with the uefi grub configuration
simpleUefiGrubClone = makeInstallerTest "simpleUefiGrubClone" (simple-uefi-grub-config // clone-test-extraconfig); simpleUefiGrubSpecialisation = makeInstallerTest "simpleUefiGrubSpecialisation" (simple-uefi-grub-config // specialisation-test-extraconfig);
# Same as the previous, but now with a separate /boot partition. # Same as the previous, but now with a separate /boot partition.
separateBoot = makeInstallerTest "separateBoot" { separateBoot = makeInstallerTest "separateBoot" {

View file

@ -1,44 +0,0 @@
import ./make-test-python.nix {
name = "nesting";
nodes = {
clone = { pkgs, ... }: {
environment.systemPackages = [ pkgs.cowsay ];
nesting.clone = [
({ pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
})
];
};
children = { pkgs, ... }: {
environment.systemPackages = [ pkgs.cowsay ];
nesting.children = [
({ pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
})
];
};
};
testScript = ''
clone.wait_for_unit("default.target")
clone.succeed("cowsay hey")
clone.fail("hello")
with subtest("Nested clones do inherit from parent"):
clone.succeed(
"/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
)
clone.succeed("cowsay hey")
clone.succeed("hello")
children.wait_for_unit("default.target")
children.succeed("cowsay hey")
children.fail("hello")
with subtest("Nested children do not inherit from parent"):
children.succeed(
"/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
)
children.fail("cowsay hey")
children.succeed("hello")
'';
}

View file

@ -19,7 +19,7 @@ import ./make-test-python.nix {
''; '';
}; };
nesting.clone = lib.singleton { specialisation.pass-checks.configuration = {
services.nginx.virtualHosts.server = { services.nginx.virtualHosts.server = {
root = lib.mkForce (pkgs.runCommandLocal "testdir2" {} '' root = lib.mkForce (pkgs.runCommandLocal "testdir2" {} ''
mkdir "$out" mkdir "$out"
@ -70,7 +70,7 @@ import ./make-test-python.nix {
testScript = { nodes, ... }: let testScript = { nodes, ... }: let
inherit (nodes.server.config.system.build) toplevel; inherit (nodes.server.config.system.build) toplevel;
newSystem = "${toplevel}/fine-tune/child-1"; newSystem = "${toplevel}/specialisation/pass-checks";
in '' in ''
start_all() start_all()

View file

@ -42,38 +42,35 @@ import ./make-test-python.nix ({ pkgs, ... }: {
services.nginx.enableReload = true; services.nginx.enableReload = true;
nesting.clone = [ specialisation.etagSystem.configuration = {
{ services.nginx.virtualHosts.localhost = {
services.nginx.virtualHosts.localhost = { root = lib.mkForce (pkgs.runCommand "testdir2" {} ''
root = lib.mkForce (pkgs.runCommand "testdir2" {} '' mkdir "$out"
mkdir "$out" echo content changed > "$out/index.html"
echo content changed > "$out/index.html" '');
''); };
}; };
}
{ specialisation.justReloadSystem.configuration = {
services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }]; services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }];
} };
{ specialisation.reloadRestartSystem.configuration = {
services.nginx.package = pkgs.nginxUnstable; services.nginx.package = pkgs.nginxUnstable;
} };
{ specialisation.reloadWithErrorsSystem.configuration = {
services.nginx.package = pkgs.nginxUnstable; services.nginx.package = pkgs.nginxUnstable;
services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;"; services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
} };
];
}; };
}; };
testScript = { nodes, ... }: let testScript = { nodes, ... }: let
etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1"; etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etagSystem";
justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2"; justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/justReloadSystem";
reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-3"; reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadRestartSystem";
reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-4"; reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadWithErrorsSystem";
in '' in ''
url = "http://localhost/index.html" url = "http://localhost/index.html"

View file

@ -0,0 +1,43 @@
import ./make-test-python.nix {
name = "specialisation";
nodes = {
inheritconf = { pkgs, ... }: {
environment.systemPackages = [ pkgs.cowsay ];
specialisation.inheritconf.configuration = { pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
};
};
noinheritconf = { pkgs, ... }: {
environment.systemPackages = [ pkgs.cowsay ];
specialisation.noinheritconf = {
inheritParentConfig = false;
configuration = { pkgs, ... }: {
environment.systemPackages = [ pkgs.hello ];
};
};
};
};
testScript = ''
inheritconf.wait_for_unit("default.target")
inheritconf.succeed("cowsay hey")
inheritconf.fail("hello")
with subtest("Nested clones do inherit from parent"):
inheritconf.succeed(
"/run/current-system/specialisation/inheritconf/bin/switch-to-configuration test"
)
inheritconf.succeed("cowsay hey")
inheritconf.succeed("hello")
noinheritconf.wait_for_unit("default.target")
noinheritconf.succeed("cowsay hey")
noinheritconf.fail("hello")
with subtest("Nested children do not inherit from parent"):
noinheritconf.succeed(
"/run/current-system/specialisation/noinheritconf/bin/switch-to-configuration test"
)
noinheritconf.fail("cowsay hey")
noinheritconf.succeed("hello")
'';
}