lib.types: Add deferredModule
This commit is contained in:
parent
9ef09e0680
commit
4746f6d03e
5 changed files with 118 additions and 0 deletions
|
@ -194,6 +194,9 @@ checkConfigOutput '^"submodule"$' options.submodule.type.description ./declare-s
|
|||
## Paths should be allowed as values and work as expected
|
||||
checkConfigOutput '^true$' config.submodule.enable ./declare-submoduleWith-path.nix
|
||||
|
||||
## Deferred module
|
||||
checkConfigOutput '"beta"' config.nodes.foo.settingsDict.c ./deferred-module.nix
|
||||
|
||||
# Check the file location information is propagated into submodules
|
||||
checkConfigOutput the-file.nix config.submodule.internalFiles.0 ./submoduleFiles.nix
|
||||
|
||||
|
|
54
lib/tests/modules/deferred-module.nix
Normal file
54
lib/tests/modules/deferred-module.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types mkOption setDefaultModuleLocation;
|
||||
inherit (types) deferredModule lazyAttrsOf submodule str raw;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# generic module, declaring submodules:
|
||||
# - nodes.<name>
|
||||
# - default
|
||||
# where all nodes include the default
|
||||
({ config, ... }: {
|
||||
_file = "generic.nix";
|
||||
options.nodes = mkOption {
|
||||
type = lazyAttrsOf (submodule { imports = config.default; });
|
||||
default = {};
|
||||
};
|
||||
options.default = mkOption {
|
||||
type = deferredModule;
|
||||
default = { };
|
||||
description = ''
|
||||
Module that is included in all nodes.
|
||||
'';
|
||||
};
|
||||
})
|
||||
|
||||
{
|
||||
_file = "default-1.nix";
|
||||
default = { config, ... }: {
|
||||
options.settingsDict = lib.mkOption { type = lazyAttrsOf str; default = {}; };
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
_file = "default-a-is-b.nix";
|
||||
default = { config, ... }: {
|
||||
settingsDict.a = config.settingsDict.b;
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
_file = "nodes-foo.nix";
|
||||
nodes.foo.settingsDict.b = "beta";
|
||||
}
|
||||
|
||||
{
|
||||
_file = "nodes-foo-c-is-a.nix";
|
||||
nodes.foo = { config, ... }: {
|
||||
settingsDict.c = config.settingsDict.a;
|
||||
};
|
||||
}
|
||||
|
||||
];
|
||||
}
|
|
@ -539,6 +539,14 @@ rec {
|
|||
modules = toList modules;
|
||||
};
|
||||
|
||||
# A module to be imported in some other part of the configuration.
|
||||
deferredModule = mkOptionType {
|
||||
name = "deferredModule";
|
||||
description = "module";
|
||||
check = t: isAttrs t || isFunction t;
|
||||
merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs;
|
||||
};
|
||||
|
||||
# The type of a type!
|
||||
optionType = mkOptionType {
|
||||
name = "optionType";
|
||||
|
|
|
@ -220,6 +220,25 @@ Value types are types that take a value parameter.
|
|||
requires using a function:
|
||||
`the-submodule = { ... }: { options = { ... }; }`.
|
||||
|
||||
`types.deferredModule`
|
||||
|
||||
: Whereas `submodule` represents an option tree, `deferredModule` represents
|
||||
a module value, such as a module file or a configuration.
|
||||
|
||||
It can be set multiple times.
|
||||
|
||||
Module authors can use its value, which is always a list of module values,
|
||||
in `imports` or in `submoduleWith`'s `modules` parameter.
|
||||
Note that `imports` must be evaluated before the module fixpoint. Because
|
||||
of this, deferred modules can only be imported into "other" fixpoints, such
|
||||
as submodules.
|
||||
|
||||
One use case for this type is the type of a "default" module that allow the
|
||||
user to affect all submodules in an `attrsOf submodule` at once. This is
|
||||
more convenient and discoverable than expecting the module user to
|
||||
type-merge with the `attrsOf submodule` option. NixOps uses this type in
|
||||
`network.defaults`.
|
||||
|
||||
## Composed Types {#sec-option-types-composed}
|
||||
|
||||
Composed types are types that take a type as parameter. `listOf
|
||||
|
|
|
@ -427,6 +427,40 @@
|
|||
</itemizedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>types.deferredModule</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Whereas <literal>submodule</literal> represents an option
|
||||
tree, <literal>deferredModule</literal> represents a module
|
||||
value, such as a module file or a configuration.
|
||||
</para>
|
||||
<para>
|
||||
It can be set multiple times.
|
||||
</para>
|
||||
<para>
|
||||
Module authors can use its value, which is always a list of
|
||||
module values, in <literal>imports</literal> or in
|
||||
<literal>submoduleWith</literal>’s
|
||||
<literal>modules</literal> parameter. Note that
|
||||
<literal>imports</literal> must be evaluated before the
|
||||
module fixpoint. Because of this, deferred modules can only
|
||||
be imported into <quote>other</quote> fixpoints, such as
|
||||
submodules.
|
||||
</para>
|
||||
<para>
|
||||
One use case for this type is the type of a
|
||||
<quote>default</quote> module that allow the user to affect
|
||||
all submodules in an <literal>attrsOf submodule</literal> at
|
||||
once. This is more convenient and discoverable than
|
||||
expecting the module user to type-merge with the
|
||||
<literal>attrsOf submodule</literal> option. NixOps uses
|
||||
this type in <literal>network.defaults</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</section>
|
||||
<section xml:id="sec-option-types-composed">
|
||||
|
|
Loading…
Reference in a new issue