From ec2d28e3233c4c04fe6afe13e828691d099167ae Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Thu, 5 Mar 2020 17:07:20 -0500 Subject: [PATCH] specialisation: replace nesting with named configurations Co-authored-by: worldofpeace --- .../installing-behind-a-proxy.xml | 2 +- nixos/doc/manual/release-notes/rl-2009.xml | 44 +++++++++ nixos/modules/system/activation/no-clone.nix | 3 +- nixos/modules/system/activation/top-level.nix | 65 +++++++------ .../system/boot/loader/grub/install-grub.pl | 5 +- .../loader/init-script/init-script-builder.sh | 2 +- nixos/tests/acme.nix | 94 +++++++++---------- nixos/tests/all-tests.nix | 2 +- nixos/tests/caddy.nix | 44 +++++---- nixos/tests/installer.nix | 20 ++-- nixos/tests/nesting.nix | 44 --------- nixos/tests/nginx-etag.nix | 4 +- nixos/tests/nginx.nix | 47 +++++----- nixos/tests/specialisation.nix | 43 +++++++++ 14 files changed, 230 insertions(+), 189 deletions(-) delete mode 100644 nixos/tests/nesting.nix create mode 100644 nixos/tests/specialisation.nix diff --git a/nixos/doc/manual/installation/installing-behind-a-proxy.xml b/nixos/doc/manual/installation/installing-behind-a-proxy.xml index 8f9baff44b51..c1ef638e876e 100644 --- a/nixos/doc/manual/installation/installing-behind-a-proxy.xml +++ b/nixos/doc/manual/installation/installing-behind-a-proxy.xml @@ -40,7 +40,7 @@ networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; If you are switching networks with different proxy configurations, use the - nesting.clone option in + specialisation option in configuration.nix to switch proxies at runtime. Refer to for more information. diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index cf7946ffb807..4965f9c36297 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -203,6 +203,50 @@ environment.systemPackages = [ here. + + + + The NixOS options nesting.clone and + nesting.children have been deleted, and + replaced with named + configurations. + + + + Replace a nesting.clone entry with: + +{ +specialisation.example-sub-configuration = { + configuration = { + ... + }; +}; + + + + Replace a nesting.children entry with: + +{ +specialisation.example-sub-configuration = { + inheritParentConfig = false; + configuration = { + ... + }; +}; + + + + To switch to a specialised configuration at runtime you need to + run: + +# sudo /run/current-system/specialisation/example-sub-configuration/bin/switch-to-configuration test + + Before you would have used: + +# sudo /run/current-system/fine-tune/child-1/bin/switch-to-configuration test + + + diff --git a/nixos/modules/system/activation/no-clone.nix b/nixos/modules/system/activation/no-clone.nix index 7f4584435266..912420347dc0 100644 --- a/nixos/modules/system/activation/no-clone.nix +++ b/nixos/modules/system/activation/no-clone.nix @@ -4,6 +4,5 @@ with lib; { boot.loader.grub.device = mkOverride 0 "nodev"; - nesting.children = mkOverride 0 []; - nesting.clone = mkOverride 0 []; + specialisation = mkOverride 0 {}; } diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 49693b6f1be0..f6739977fa4f 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -11,21 +11,16 @@ let # you can provide an easy way to boot the same configuration # as you use, but with another kernel # !!! fix this - cloner = inheritParent: list: - map (childConfig: + children = mapAttrs (childName: childConfig: (import ../../../lib/eval-config.nix { inherit baseModules; system = config.nixpkgs.initialSystem; modules = - (optionals inheritParent modules) + (optionals childConfig.inheritParentConfig modules) ++ [ ./no-clone.nix ] - ++ [ childConfig ]; + ++ [ childConfig.configuration ]; }).config.system.build.toplevel - ) list; - - children = - cloner false config.nesting.children - ++ cloner true config.nesting.clone; + ) config.specialisation; systemBuilder = let @@ -77,12 +72,9 @@ let echo -n "$nixosLabel" > $out/nixos-version echo -n "${config.boot.kernelPackages.stdenv.hostPlatform.system}" > $out/system - mkdir $out/fine-tune - childCount=0 - for i in $children; do - childCount=$(( childCount + 1 )) - ln -s $i $out/fine-tune/child-$childCount - done + mkdir $out/specialisation + ${concatStringsSep "\n" + (mapAttrsToList (name: path: "ln -s ${path} $out/specialisation/${name}") children)} mkdir $out/bin export localeArchive="${config.i18n.glibcLocales}/lib/locale/locale-archive" @@ -112,7 +104,6 @@ let shell = "${pkgs.bash}/bin/sh"; su = "${pkgs.shadow.su}/bin/su"; - inherit children; kernelParams = config.boot.kernelParams; installBootLoader = config.system.build.installBootLoader @@ -143,6 +134,11 @@ let in { + imports = [ + (mkRemovedOptionModule [ "nesting" "clone" ] "Use `specialisation.«name» = { inheritParentConfig = true; configuration = { ... }; }` instead.") + (mkRemovedOptionModule [ "nesting" "children" ] "Use `specialisation.«name».configuration = { ... }` instead.") + ]; + options = { system.build = mkOption { @@ -154,26 +150,35 @@ in ''; }; - nesting.children = mkOption { - default = []; + specialisation = mkOption { + default = {}; + example = lib.literalExample "{ fewJobsManyCores.configuration = { nix.buildCores = 0; nix.maxJobs = 1; }; }"; description = '' - Additional configurations to build. - ''; - }; + Additional configurations to build. If + inheritParentConfig is true, the system + will be based on the overall system configuration. - nesting.clone = mkOption { - default = []; - description = '' - Additional configurations to build based on the current - configuration which then has a lower priority. - - To switch to a cloned configuration (e.g. child-1) - at runtime, run + To switch to a specialised configuration + (e.g. fewJobsManyCores) at runtime, run: - # sudo /run/current-system/fine-tune/child-1/bin/switch-to-configuration test + # sudo /run/current-system/specialisation/fewJobsManyCores/bin/switch-to-configuration test ''; + 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 { diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index ca0fb0248e0e..8df18cbd9013 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -409,7 +409,7 @@ $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS; # Find all the children of the current default configuration # Do not search for grand children -my @links = sort (glob "$defaultConfig/fine-tune/*"); +my @links = sort (glob "$defaultConfig/specialisation/*"); foreach my $link (@links) { my $entryName = ""; @@ -425,7 +425,8 @@ foreach my $link (@links) { if ($cfgName) { $entryName = $cfgName; } else { - $entryName = "($date - $version)"; + my $linkname = basename($link); + $entryName = "($linkname - $date - $version)"; } addEntry("NixOS - $entryName", $link); } diff --git a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh b/nixos/modules/system/boot/loader/init-script/init-script-builder.sh index 08d4ab14c9ca..6f48d2539ace 100644 --- a/nixos/modules/system/boot/loader/init-script/init-script-builder.sh +++ b/nixos/modules/system/boot/loader/init-script/init-script-builder.sh @@ -69,7 +69,7 @@ addEntry "NixOS - Default" $defaultConfig "" # Add all generations of the system profile to the menu, in reverse # (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/\..*//') addEntry "NixOS - variation" $link "" done diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix index e045f3415fa0..638601cd75f3 100644 --- a/nixos/tests/acme.nix +++ b/nixos/tests/acme.nix @@ -91,52 +91,50 @@ in import ./make-test-python.nix { security.acme.server = "https://acme-v02.api.letsencrypt.org/dir"; - nesting.clone = [ - ({pkgs, ...}: { - systemd.targets."acme-finished-b.example.com" = {}; - systemd.services."acme-b.example.com" = { - wants = [ "acme-finished-b.example.com.target" ]; - before = [ "acme-finished-b.example.com.target" ]; - after = [ "nginx.service" ]; - }; - services.nginx.virtualHosts."b.example.com" = { - enableACME = true; - forceSSL = true; - locations."/".root = pkgs.runCommand "docroot" {} '' - mkdir -p "$out" - echo hello world > "$out/index.html" - ''; - }; - }) - ({pkgs, config, nodes, lib, ...}: { - security.acme.certs."example.com" = { - domain = "*.example.com"; - dnsProvider = "exec"; - dnsPropagationCheck = false; - credentialsFile = with pkgs; writeText "wildcard.env" '' - EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }} - ''; - user = config.services.nginx.user; - group = config.services.nginx.group; - }; - systemd.targets."acme-finished-example.com" = {}; - systemd.services."acme-example.com" = { - wants = [ "acme-finished-example.com.target" ]; - before = [ "acme-finished-example.com.target" "nginx.service" ]; - wantedBy = [ "nginx.service" ]; - }; - services.nginx.virtualHosts."c.example.com" = { - forceSSL = true; - sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem"; - sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem"; - sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem"; - locations."/".root = pkgs.runCommand "docroot" {} '' - mkdir -p "$out" - echo hello world > "$out/index.html" - ''; - }; - }) - ]; + specialisation.second-cert.configuration = {pkgs, ...}: { + systemd.targets."acme-finished-b.example.com" = {}; + systemd.services."acme-b.example.com" = { + wants = [ "acme-finished-b.example.com.target" ]; + before = [ "acme-finished-b.example.com.target" ]; + after = [ "nginx.service" ]; + }; + services.nginx.virtualHosts."b.example.com" = { + enableACME = true; + forceSSL = true; + locations."/".root = pkgs.runCommand "docroot" {} '' + mkdir -p "$out" + echo hello world > "$out/index.html" + ''; + }; + }; + specialisation.dns-01.configuration = {pkgs, config, nodes, lib, ...}: { + security.acme.certs."example.com" = { + domain = "*.example.com"; + dnsProvider = "exec"; + dnsPropagationCheck = false; + credentialsFile = with pkgs; writeText "wildcard.env" '' + EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }} + ''; + user = config.services.nginx.user; + group = config.services.nginx.group; + }; + systemd.targets."acme-finished-example.com" = {}; + systemd.services."acme-example.com" = { + wants = [ "acme-finished-example.com.target" ]; + before = [ "acme-finished-example.com.target" "nginx.service" ]; + wantedBy = [ "nginx.service" ]; + }; + services.nginx.virtualHosts."c.example.com" = { + forceSSL = true; + sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem"; + sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem"; + sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem"; + locations."/".root = pkgs.runCommand "docroot" {} '' + mkdir -p "$out" + echo hello world > "$out/index.html" + ''; + }; + }; }; client = {nodes, lib, ...}: { @@ -196,7 +194,7 @@ in import ./make-test-python.nix { with subtest("Can add another certificate for nginx service"): 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") client.succeed( @@ -208,7 +206,7 @@ in import ./make-test-python.nix { "${switchToNewServer}" ) 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") client.succeed( diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 76ca49416170..5819879b30e9 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -202,7 +202,7 @@ in nat.standalone = handleTest ./nat.nix { withFirewall = false; }; ndppd = handleTest ./ndppd.nix {}; neo4j = handleTest ./neo4j.nix {}; - nesting = handleTest ./nesting.nix {}; + specialisation = handleTest ./specialisation.nix {}; netdata = handleTest ./netdata.nix {}; networking.networkd = handleTest ./networking.nix { networkd = true; }; networking.scripted = handleTest ./networking.nix { networkd = false; }; diff --git a/nixos/tests/caddy.nix b/nixos/tests/caddy.nix index fc10df0c79b5..144d83179a16 100644 --- a/nixos/tests/caddy.nix +++ b/nixos/tests/caddy.nix @@ -20,35 +20,33 @@ import ./make-test-python.nix ({ pkgs, ... }: { } ''; - nesting.clone = [ - { - services.caddy.config = lib.mkForce '' - http://localhost { - gzip + specialisation.etag.configuration = { + services.caddy.config = lib.mkForce '' + http://localhost { + gzip - root ${ - pkgs.runCommand "testdir2" {} '' - mkdir "$out" - echo changed > "$out/example.html" - '' - } + root ${ + pkgs.runCommand "testdir2" {} '' + mkdir "$out" + echo changed > "$out/example.html" + '' } - ''; - } + } + ''; + }; - { - services.caddy.config = '' - http://localhost:8080 { - } - ''; - } - ]; + specialisation.config-reload.configuration = { + services.caddy.config = '' + http://localhost:8080 { + } + ''; + }; }; }; testScript = { nodes, ... }: let - etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1"; - justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2"; + etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag"; + justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload"; in '' url = "http://localhost/example.html" 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( old_etag, new_etag ) - + with subtest("config is reloaded on nixos-rebuild switch"): webserver.succeed( "${justReloadSystem}/bin/switch-to-configuration test >&2" diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index babde4126c4c..c5abd458ec9a 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -65,7 +65,7 @@ let # partitions and filesystems. testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi , grubIdentifier, preBootCommands, extraConfig - , testCloneConfig + , testSpecialisationConfig }: let iface = if grubVersion == 1 then "ide" else "virtio"; isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); @@ -220,7 +220,7 @@ let # Tests for validating clone configuration entries in grub menu '' - + optionalString testCloneConfig '' + + optionalString testSpecialisationConfig '' # Reboot Machine machine = create_machine_named("clone-default-config") ${preBootCommands} @@ -262,7 +262,7 @@ let , bootLoader ? "grub" # either "grub" or "systemd-boot" , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false , enableOCR ? false, meta ? {} - , testCloneConfig ? false + , testSpecialisationConfig ? false }: makeTest { inherit enableOCR; @@ -337,7 +337,7 @@ let testScript = testScriptFun { inherit bootLoader createPartitions preBootCommands grubVersion grubDevice grubIdentifier grubUseEfi extraConfig - testCloneConfig; + testSpecialisationConfig; }; }; @@ -411,11 +411,11 @@ let grubUseEfi = true; }; - clone-test-extraconfig = { + specialisation-test-extraconfig = { extraConfig = '' environment.systemPackages = [ pkgs.grub2 ]; boot.loader.grub.configurationName = "Home"; - nesting.clone = [ { + specialisation.work.configuration = { boot.loader.grub.configurationName = lib.mkForce "Work"; environment.etc = { @@ -424,9 +424,9 @@ let gitproxy = none for work.com "; }; - } ]; + }; ''; - testCloneConfig = true; + testSpecialisationConfig = true; }; @@ -440,7 +440,7 @@ in { simple = makeInstallerTest "simple" simple-test-config; # 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 simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" { @@ -467,7 +467,7 @@ in { simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config; # 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. separateBoot = makeInstallerTest "separateBoot" { diff --git a/nixos/tests/nesting.nix b/nixos/tests/nesting.nix deleted file mode 100644 index a75806b24ff6..000000000000 --- a/nixos/tests/nesting.nix +++ /dev/null @@ -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") - ''; -} diff --git a/nixos/tests/nginx-etag.nix b/nixos/tests/nginx-etag.nix index e357309d166a..63ab2e0c6c27 100644 --- a/nixos/tests/nginx-etag.nix +++ b/nixos/tests/nginx-etag.nix @@ -19,7 +19,7 @@ import ./make-test-python.nix { ''; }; - nesting.clone = lib.singleton { + specialisation.pass-checks.configuration = { services.nginx.virtualHosts.server = { root = lib.mkForce (pkgs.runCommandLocal "testdir2" {} '' mkdir "$out" @@ -70,7 +70,7 @@ import ./make-test-python.nix { testScript = { nodes, ... }: let inherit (nodes.server.config.system.build) toplevel; - newSystem = "${toplevel}/fine-tune/child-1"; + newSystem = "${toplevel}/specialisation/pass-checks"; in '' start_all() diff --git a/nixos/tests/nginx.nix b/nixos/tests/nginx.nix index 7358800a6763..18822f095688 100644 --- a/nixos/tests/nginx.nix +++ b/nixos/tests/nginx.nix @@ -42,38 +42,35 @@ import ./make-test-python.nix ({ pkgs, ... }: { services.nginx.enableReload = true; - nesting.clone = [ - { - services.nginx.virtualHosts.localhost = { - root = lib.mkForce (pkgs.runCommand "testdir2" {} '' - mkdir "$out" - echo content changed > "$out/index.html" - ''); - }; - } + specialisation.etagSystem.configuration = { + services.nginx.virtualHosts.localhost = { + root = lib.mkForce (pkgs.runCommand "testdir2" {} '' + mkdir "$out" + echo content changed > "$out/index.html" + ''); + }; + }; - { - services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }]; - } + specialisation.justReloadSystem.configuration = { + services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }]; + }; - { - services.nginx.package = pkgs.nginxUnstable; - } + specialisation.reloadRestartSystem.configuration = { + services.nginx.package = pkgs.nginxUnstable; + }; - { - services.nginx.package = pkgs.nginxUnstable; - services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;"; - } - ]; + specialisation.reloadWithErrorsSystem.configuration = { + services.nginx.package = pkgs.nginxUnstable; + services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;"; + }; }; - }; testScript = { nodes, ... }: let - etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1"; - justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2"; - reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-3"; - reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-4"; + etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etagSystem"; + justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/justReloadSystem"; + reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadRestartSystem"; + reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadWithErrorsSystem"; in '' url = "http://localhost/index.html" diff --git a/nixos/tests/specialisation.nix b/nixos/tests/specialisation.nix new file mode 100644 index 000000000000..b8d4b8279f4d --- /dev/null +++ b/nixos/tests/specialisation.nix @@ -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") + ''; +}