I’d like to set a “global” option from within a submodule, but the config
I return is grafted into the “global” under the submodule “path” rather than at the root… any idea if it’s somehow possible?
Er… I guess I didn’t make a great job at explaining what I want to do… Some code will hopefully help.
In mymodule.nix
I have:
{ lib, config, ... }: {
options.myoption = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (
import ./mysubmodule.nix
));
};
}
and mysubmodule.nix
is:
{ name, lib, config, ... }: {
options.mysubmoduleoption = {
type = lib.types.str;
};
config = {
# here I want to set a "global" option, say "systemd.mounts"
# based on the value of "mymodule.name.mysubmoduleoption"
# but it seems I can only set values under "mymodule.name"
};
}
Your module only defines the option inside
types.submodule
- I’d (ideally, to better organize the code) want to also put theconfig
section in the submodule.Ie. your code is structured similar to:
options = { fileSystems = mkOption { type = types.attrsOf (types.submodule { options = { # bla bla }; }; }; }; config = { # set options here };
while what I would like to do is more like
options = { fileSystems = mkOption { type = types.attrsOf (types.submodule { options = { # bla bla }; config = { # set options here }; }; };
The reason why I’m trying to do so is purely to restructure my code (which right now does has the
config
logic at the module, rather than submodule, level) in order to make it more readable/manageable, since it currently has jems like:config.services.restic.backups = builtins.listToAttrs ( builtins.concatLists (lib.attrsets.mapAttrsToList (v-name: v-cfg: ( builtins.concatLists (lib.attrsets.mapAttrsToList (s-name: s-cfg: ( builtins.concatLists (lib.attrsets.mapAttrsToList (r-name: r-cfg: (
I know I can restructure the code in other ways (eg.
let .. in
) - I just wanted to put the options definitions together with the code that uses them.It doesn’t work like that. Submodules are for defining the type, so the only thing you get is interface (
options
), not implementation.Do that.
Also be aware that some use-cases might be covered by library functions such as
lib.flatMap
orlib.pipe
.You do get a functional
config
in submodules… try this (it doesn’t do anything so you can just import into anyconfiguration.nix
):{ config, lib, pkgs, modulesPath, specialArgs, options, ... }: { options.mynamespace = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule ({name, config, ...}:{ options = { option1 = lib.mkOption { type = lib.types.str; default = ""; }; option2 = lib.mkOption { type = lib.types.str; default = ""; }; }; config = { option2 = "derived from value of option1: '${config.option1}'"; }; })); }; config = { mynamespace.submodule1.option1 = "value of option1"; fileSystems = builtins.trace (builtins.toJSON config.mynamespace) {}; }; }