about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2024-02-01 20:15:26 +0100
committergithub-actions[bot] <github-actions[bot]@users.noreply.github.com>2024-02-05 18:27:19 +0000
commitf3bb1c767a54951e92c9e5ecec15df8dc4c233c9 (patch)
tree010d370292be81b8c311c20d9421af3c16e955ee /lib
parentfc819befe88a0b7737900164cdf8dff3298eb87a (diff)
lib.modules.doRename: Add condition parameter
This is to support single-to-multi service migrations, so that the
`to` (e.g. `foos.""`) isn't defined unconditionally. See test cases.

(cherry picked from commit 29c7665003cdcfe3319c969a9846f594dfeae550)
Diffstat (limited to 'lib')
-rw-r--r--lib/modules.nix6
-rwxr-xr-xlib/tests/modules.sh3
-rw-r--r--lib/tests/modules/doRename-condition-enable.nix10
-rw-r--r--lib/tests/modules/doRename-condition-migrated.nix10
-rw-r--r--lib/tests/modules/doRename-condition-no-enable.nix9
-rw-r--r--lib/tests/modules/doRename-condition.nix42
6 files changed, 77 insertions, 3 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index 4acbce39e94d1..65087e4ca70cb 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -1254,7 +1254,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;
@@ -1270,7 +1270,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}'.";
@@ -1278,7 +1278,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 ffef62cfddcab..cfd36bfff49bf 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -456,6 +456,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 0000000000000..e6eabfa6f89ae
--- /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 0000000000000..8d21610e8ec6a
--- /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 0000000000000..66ec004d31470
--- /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 0000000000000..c08b3035be6f7
--- /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.<name>` 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;
+    })
+  ];
+}