Loading nixos/modules/services/system/dbus.nix +2 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,8 @@ in config = mkIf cfg.enable (mkMerge [ { system.switch.inhibitors.dbus-implementation = cfg.implementation; environment.etc."dbus-1".source = configDir; environment.pathsToLink = [ Loading nixos/modules/system/activation/switchable-system.nix +79 −73 Original line number Diff line number Diff line Loading @@ -32,12 +32,12 @@ }; inhibitors = lib.mkOption { type = lib.types.listOf lib.types.pathInStore; default = [ ]; type = lib.types.attrsOf lib.types.str; default = { }; description = '' List of derivations that will prevent switching into a configuration when Attribute set of strings that will prevent switching into a configuration when they change. This can be manually overridden on the command line if required. The switch can be manually forced on the command line if required. ''; }; }; Loading Loading @@ -67,18 +67,15 @@ ln -s ${config.system.build.inhibitSwitch} $out/switch-inhibitors ''; build.inhibitSwitch = pkgs.writeTextFile { name = "switch-inhibitors"; text = lib.concatMapStringsSep "\n" (drv: drv.outPath) config.system.switch.inhibitors; }; build.inhibitSwitch = pkgs.writers.writeJSON "switch-inhibitors" config.system.switch.inhibitors; preSwitchChecks.switchInhibitors = let realpath = lib.getExe' pkgs.coreutils "realpath"; sha256sum = lib.getExe' pkgs.coreutils "sha256sum"; diff = lib.getExe' pkgs.diffutils "diff"; mktemp = lib.getExe' pkgs.coreutils "mktemp"; rm = lib.getExe' pkgs.coreutils "rm"; jq = lib.getExe' pkgs.jq "jq"; in lib.mkIf (lib.length config.system.switch.inhibitors > 0) # bash '' incoming="''${1-}" Loading @@ -91,45 +88,54 @@ echo -n "Checking switch inhibitors..." booted_inhibitors="$(${realpath} /run/booted-system)/switch-inhibitors" booted_inhibitors_sha="$( if [ -f "$booted_inhibitors" ]; then ${sha256sum} - < "$booted_inhibitors" else echo 'none' fi )" # Create a temporary file that we use in case a generation does not have # the switch-inhibitors file. empty="$(${mktemp} -t switch_inhibit.XXXX)" # shellcheck disable=SC2329 clean_up() { ${rm} -f "$empty" } trap clean_up EXIT echo "{}" > "$empty" if [ "$booted_inhibitors_sha" == "none" ]; then echo echo "The previous configuration did not specify switch inhibitors, nothing to check." exit current_inhibitors="$(${realpath} /run/current-system)/switch-inhibitors" if [ ! -f "$current_inhibitors" ]; then current_inhibitors="$empty" fi new_inhibitors="$(${realpath} "$incoming")/switch-inhibitors" new_inhibitors_sha="$( if [ -f "$new_inhibitors" ]; then ${sha256sum} - < "$new_inhibitors" else echo 'none' if [ ! -f "$new_inhibitors" ]; then new_inhibitors="$empty" fi )" if [ "$new_inhibitors_sha" == "none" ]; then echo echo "The new configuration does not specify switch inhibitors, nothing to check." exit fi diff="$( ${jq} \ --raw-output \ --null-input \ --rawfile current "$current_inhibitors" \ --rawfile newgen "$new_inhibitors" \ ' $current | try fromjson catch {} as $old | $newgen | try fromjson catch {} as $new | $old | to_entries | map( select(.key | in ($new)) | select(.value != $new.[.key]) | [ .key, ":", .value, "->", $new.[.key] ] | join(" ") ) | join("\n") ' \ )" if [ "$new_inhibitors_sha" != "$booted_inhibitors_sha" ]; then if [ -n "$diff" ]; then echo echo "Found diff in switch inhibitors:" echo "There are changes to critical components of the system:" echo ${diff} --color "$booted_inhibitors" "$new_inhibitors" echo "$diff" echo echo "The new configuration contains changes to packages that were" echo "listed as switch inhibitors." echo "You probably want to run 'nixos-rebuild boot' and reboot your system." echo "Switching into this system is not recommended." echo "You probably want to run 'nixos-rebuild boot' and reboot your system instead." echo echo "If you really want to switch into this configuration directly, then" echo "you can set NIXOS_NO_CHECK=1 to ignore pre-switch checks." Loading nixos/tests/switch-test.nix +36 −0 Original line number Diff line number Diff line Loading @@ -646,6 +646,23 @@ in EOF ''; }; no_inhibitors.configuration.system.switch.inhibitors = lib.mkForce { }; inhibitors.configuration.system.switch.inhibitors = lib.mkForce { foo = "bar"; quz = "bor"; }; inhibitors_changed.configuration.system.switch.inhibitors = lib.mkForce { foo = "baz"; quz = "boz"; }; inhibitors_new.configuration.system.switch.inhibitors = lib.mkForce { foo = "bar"; qux = "baz"; }; }; }; Loading @@ -658,6 +675,7 @@ in echo "this should succeed (config: $config, action: $action)" [ "$action" == "check" ] || [ "$action" == "test" ] ''; boot.loader.grub.enable = false; specialisation.failingCheck.configuration.system.preSwitchChecks.failEveryTime = '' echo this will fail false Loading Loading @@ -745,6 +763,24 @@ in out = switch_to_specialisation("${otherSystem}", "failingCheck", action="check", fail=True) assert_contains(out, "this will fail") with subtest("switch inhibitors"): # Start without any inhibitors switch_to_specialisation("${machine}", "no_inhibitors", action="switch") # Check that we can switch into a generation with inhibitors from one that doesn't have any switch_to_specialisation("${machine}", "inhibitors", action="switch") # Check that we cannot switch into a generation that has a different value for an existing inhibitor out = switch_to_specialisation("${machine}", "inhibitors_changed", action="switch", fail=True) assert_contains(out, "There are changes to critical components of the system") assert_contains(out, "foo") assert_contains(out, "bar") assert_contains(out, "baz") # Confirm that we can set that same generation as the new boot default switch_to_specialisation("${machine}", "inhibitors_changed", action="boot") # Check that we can switch into a new generation with new inhibitors, but same values for existing ones switch_to_specialisation("${machine}", "inhibitors_new", action="switch") # Check that we can switch back into a generation without inhibitors switch_to_specialisation("${machine}", "no_inhibitors", action="switch") with subtest("actions"): # boot action out = switch_to_specialisation("${machine}", "simpleService", action="boot") Loading Loading
nixos/modules/services/system/dbus.nix +2 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,8 @@ in config = mkIf cfg.enable (mkMerge [ { system.switch.inhibitors.dbus-implementation = cfg.implementation; environment.etc."dbus-1".source = configDir; environment.pathsToLink = [ Loading
nixos/modules/system/activation/switchable-system.nix +79 −73 Original line number Diff line number Diff line Loading @@ -32,12 +32,12 @@ }; inhibitors = lib.mkOption { type = lib.types.listOf lib.types.pathInStore; default = [ ]; type = lib.types.attrsOf lib.types.str; default = { }; description = '' List of derivations that will prevent switching into a configuration when Attribute set of strings that will prevent switching into a configuration when they change. This can be manually overridden on the command line if required. The switch can be manually forced on the command line if required. ''; }; }; Loading Loading @@ -67,18 +67,15 @@ ln -s ${config.system.build.inhibitSwitch} $out/switch-inhibitors ''; build.inhibitSwitch = pkgs.writeTextFile { name = "switch-inhibitors"; text = lib.concatMapStringsSep "\n" (drv: drv.outPath) config.system.switch.inhibitors; }; build.inhibitSwitch = pkgs.writers.writeJSON "switch-inhibitors" config.system.switch.inhibitors; preSwitchChecks.switchInhibitors = let realpath = lib.getExe' pkgs.coreutils "realpath"; sha256sum = lib.getExe' pkgs.coreutils "sha256sum"; diff = lib.getExe' pkgs.diffutils "diff"; mktemp = lib.getExe' pkgs.coreutils "mktemp"; rm = lib.getExe' pkgs.coreutils "rm"; jq = lib.getExe' pkgs.jq "jq"; in lib.mkIf (lib.length config.system.switch.inhibitors > 0) # bash '' incoming="''${1-}" Loading @@ -91,45 +88,54 @@ echo -n "Checking switch inhibitors..." booted_inhibitors="$(${realpath} /run/booted-system)/switch-inhibitors" booted_inhibitors_sha="$( if [ -f "$booted_inhibitors" ]; then ${sha256sum} - < "$booted_inhibitors" else echo 'none' fi )" # Create a temporary file that we use in case a generation does not have # the switch-inhibitors file. empty="$(${mktemp} -t switch_inhibit.XXXX)" # shellcheck disable=SC2329 clean_up() { ${rm} -f "$empty" } trap clean_up EXIT echo "{}" > "$empty" if [ "$booted_inhibitors_sha" == "none" ]; then echo echo "The previous configuration did not specify switch inhibitors, nothing to check." exit current_inhibitors="$(${realpath} /run/current-system)/switch-inhibitors" if [ ! -f "$current_inhibitors" ]; then current_inhibitors="$empty" fi new_inhibitors="$(${realpath} "$incoming")/switch-inhibitors" new_inhibitors_sha="$( if [ -f "$new_inhibitors" ]; then ${sha256sum} - < "$new_inhibitors" else echo 'none' if [ ! -f "$new_inhibitors" ]; then new_inhibitors="$empty" fi )" if [ "$new_inhibitors_sha" == "none" ]; then echo echo "The new configuration does not specify switch inhibitors, nothing to check." exit fi diff="$( ${jq} \ --raw-output \ --null-input \ --rawfile current "$current_inhibitors" \ --rawfile newgen "$new_inhibitors" \ ' $current | try fromjson catch {} as $old | $newgen | try fromjson catch {} as $new | $old | to_entries | map( select(.key | in ($new)) | select(.value != $new.[.key]) | [ .key, ":", .value, "->", $new.[.key] ] | join(" ") ) | join("\n") ' \ )" if [ "$new_inhibitors_sha" != "$booted_inhibitors_sha" ]; then if [ -n "$diff" ]; then echo echo "Found diff in switch inhibitors:" echo "There are changes to critical components of the system:" echo ${diff} --color "$booted_inhibitors" "$new_inhibitors" echo "$diff" echo echo "The new configuration contains changes to packages that were" echo "listed as switch inhibitors." echo "You probably want to run 'nixos-rebuild boot' and reboot your system." echo "Switching into this system is not recommended." echo "You probably want to run 'nixos-rebuild boot' and reboot your system instead." echo echo "If you really want to switch into this configuration directly, then" echo "you can set NIXOS_NO_CHECK=1 to ignore pre-switch checks." Loading
nixos/tests/switch-test.nix +36 −0 Original line number Diff line number Diff line Loading @@ -646,6 +646,23 @@ in EOF ''; }; no_inhibitors.configuration.system.switch.inhibitors = lib.mkForce { }; inhibitors.configuration.system.switch.inhibitors = lib.mkForce { foo = "bar"; quz = "bor"; }; inhibitors_changed.configuration.system.switch.inhibitors = lib.mkForce { foo = "baz"; quz = "boz"; }; inhibitors_new.configuration.system.switch.inhibitors = lib.mkForce { foo = "bar"; qux = "baz"; }; }; }; Loading @@ -658,6 +675,7 @@ in echo "this should succeed (config: $config, action: $action)" [ "$action" == "check" ] || [ "$action" == "test" ] ''; boot.loader.grub.enable = false; specialisation.failingCheck.configuration.system.preSwitchChecks.failEveryTime = '' echo this will fail false Loading Loading @@ -745,6 +763,24 @@ in out = switch_to_specialisation("${otherSystem}", "failingCheck", action="check", fail=True) assert_contains(out, "this will fail") with subtest("switch inhibitors"): # Start without any inhibitors switch_to_specialisation("${machine}", "no_inhibitors", action="switch") # Check that we can switch into a generation with inhibitors from one that doesn't have any switch_to_specialisation("${machine}", "inhibitors", action="switch") # Check that we cannot switch into a generation that has a different value for an existing inhibitor out = switch_to_specialisation("${machine}", "inhibitors_changed", action="switch", fail=True) assert_contains(out, "There are changes to critical components of the system") assert_contains(out, "foo") assert_contains(out, "bar") assert_contains(out, "baz") # Confirm that we can set that same generation as the new boot default switch_to_specialisation("${machine}", "inhibitors_changed", action="boot") # Check that we can switch into a new generation with new inhibitors, but same values for existing ones switch_to_specialisation("${machine}", "inhibitors_new", action="switch") # Check that we can switch back into a generation without inhibitors switch_to_specialisation("${machine}", "no_inhibitors", action="switch") with subtest("actions"): # boot action out = switch_to_specialisation("${machine}", "simpleService", action="boot") Loading