diff --git a/lib/modules.nix b/lib/modules.nix index 64939a1eae81..0c484fa684aa 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1256,7 +1256,7 @@ let (opt.highestPrio or defaultOverridePriority) (f opt.value); - doRename = { from, to, visible, warn, use, withPriority ? true }: + doRename = { from, to, visible, warn, use, withPriority ? true, condition ? true }: { config, options, ... }: let fromOpt = getAttrFromPath from options; @@ -1272,7 +1272,7 @@ let } // optionalAttrs (toType != null) { type = toType; }); - config = mkMerge [ + config = mkIf condition (mkMerge [ (optionalAttrs (options ? warnings) { warnings = optional (warn && fromOpt.isDefined) "The option `${showOption from}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption to}'."; @@ -1280,7 +1280,7 @@ let (if withPriority then mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt else mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt) - ]; + ]); }; /* Use this function to import a JSON file as NixOS configuration. diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 0755670c5987..072b92b38365 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -465,6 +465,9 @@ checkConfigOutput '^1234$' config.c.d.e ./doRename-basic.nix checkConfigOutput '^"The option `a\.b. defined in `.*/doRename-warnings\.nix. has been renamed to `c\.d\.e.\."$' \ config.result \ ./doRename-warnings.nix +checkConfigOutput "^true$" config.result ./doRename-condition.nix ./doRename-condition-enable.nix +checkConfigOutput "^true$" config.result ./doRename-condition.nix ./doRename-condition-no-enable.nix +checkConfigOutput "^true$" config.result ./doRename-condition.nix ./doRename-condition-migrated.nix # Anonymous modules get deduplicated by key checkConfigOutput '^"pear"$' config.once.raw ./merge-module-with-key.nix diff --git a/lib/tests/modules/doRename-condition-enable.nix b/lib/tests/modules/doRename-condition-enable.nix new file mode 100644 index 000000000000..e6eabfa6f89a --- /dev/null +++ b/lib/tests/modules/doRename-condition-enable.nix @@ -0,0 +1,10 @@ +{ config, lib, ... }: +{ + config = { + services.foo.enable = true; + services.foo.bar = "baz"; + result = + assert config.services.foos == { "" = { bar = "baz"; }; }; + true; + }; +} diff --git a/lib/tests/modules/doRename-condition-migrated.nix b/lib/tests/modules/doRename-condition-migrated.nix new file mode 100644 index 000000000000..8d21610e8ec6 --- /dev/null +++ b/lib/tests/modules/doRename-condition-migrated.nix @@ -0,0 +1,10 @@ +{ config, lib, ... }: +{ + config = { + services.foos."".bar = "baz"; + result = + assert config.services.foos == { "" = { bar = "baz"; }; }; + assert config.services.foo.bar == "baz"; + true; + }; +} diff --git a/lib/tests/modules/doRename-condition-no-enable.nix b/lib/tests/modules/doRename-condition-no-enable.nix new file mode 100644 index 000000000000..66ec004d3147 --- /dev/null +++ b/lib/tests/modules/doRename-condition-no-enable.nix @@ -0,0 +1,9 @@ +{ config, lib, options, ... }: +{ + config = { + result = + assert config.services.foos == { }; + assert ! options.services.foo.bar.isDefined; + true; + }; +} diff --git a/lib/tests/modules/doRename-condition.nix b/lib/tests/modules/doRename-condition.nix new file mode 100644 index 000000000000..c08b3035be6f --- /dev/null +++ b/lib/tests/modules/doRename-condition.nix @@ -0,0 +1,42 @@ +/* + Simulate a migration from a single-instance `services.foo` to a multi instance + `services.foos.` module, where `name = ""` serves as the legacy / + compatibility instance. + + - No instances must exist, unless one is defined in the multi-instance module, + or if the legacy enable option is set to true. + - The legacy instance options must be renamed to the new instance, if it exists. + + The relevant scenarios are tested in separate files: + - ./doRename-condition-enable.nix + - ./doRename-condition-no-enable.nix + */ +{ config, lib, ... }: +let + inherit (lib) mkOption mkEnableOption types doRename; +in +{ + options = { + services.foo.enable = mkEnableOption "foo"; + services.foos = mkOption { + type = types.attrsOf (types.submodule { + options = { + bar = mkOption { type = types.str; }; + }; + }); + default = { }; + }; + result = mkOption {}; + }; + imports = [ + (doRename { + from = [ "services" "foo" "bar" ]; + to = [ "services" "foos" "" "bar" ]; + visible = true; + warn = false; + use = x: x; + withPriority = true; + condition = config.services.foo.enable; + }) + ]; +}