summaryrefslogtreecommitdiffstats
path: root/nixos
diff options
context:
space:
mode:
authorRobert Hensing <roberth@users.noreply.github.com>2020-08-15 12:13:58 +0200
committerGitHub <noreply@github.com>2020-08-15 12:13:58 +0200
commit6d0a85fe528e020eb7d8eb78d33ee87055c01c74 (patch)
treecd0e99185243f514ba6a4004d8697e019681db55 /nixos
parent375611df00b01c668fd82fc0632cd8aec826b5ec (diff)
parent25d75155f39d293d16ecd6aab70024a8740e0baa (diff)
Merge pull request #82743 from Infinisil/partially-typed-v2
Freeform modules
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/freeform-modules.xml68
-rw-r--r--nixos/doc/manual/development/settings-options.xml41
-rw-r--r--nixos/doc/manual/development/writing-modules.xml1
3 files changed, 108 insertions, 2 deletions
diff --git a/nixos/doc/manual/development/freeform-modules.xml b/nixos/doc/manual/development/freeform-modules.xml
new file mode 100644
index 000000000000..257e6b11bf01
--- /dev/null
+++ b/nixos/doc/manual/development/freeform-modules.xml
@@ -0,0 +1,68 @@
+<section xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="sec-freeform-modules">
+ <title>Freeform modules</title>
+ <para>
+ Freeform modules allow you to define values for option paths that have not been declared explicitly. This can be used to add attribute-specific types to what would otherwise have to be <literal>attrsOf</literal> options in order to accept all attribute names.
+ </para>
+ <para>
+ This feature can be enabled by using the attribute <literal>freeformType</literal> to define a freeform type. By doing this, all assignments without an associated option will be merged using the freeform type and combined into the resulting <literal>config</literal> set. Since this feature nullifies name checking for entire option trees, it is only recommended for use in submodules.
+ </para>
+ <example xml:id="ex-freeform-module">
+ <title>Freeform submodule</title>
+ <para>
+ The following shows a submodule assigning a freeform type that allows arbitrary attributes with <literal>str</literal> values below <literal>settings</literal>, but also declares an option for the <literal>settings.port</literal> attribute to have it type-checked and assign a default value. See <xref linkend="ex-settings-typed-attrs"/> for a more complete example.
+ </para>
+ <programlisting>
+{ lib, config, ... }: {
+
+ options.settings = lib.mkOption {
+ type = lib.types.submodule {
+
+ freeformType = with lib.types; attrsOf str;
+
+ # We want this attribute to be checked for the correct type
+ options.port = lib.mkOption {
+ type = lib.types.port;
+ # Declaring the option also allows defining a default value
+ default = 8080;
+ };
+
+ };
+ };
+}
+ </programlisting>
+ <para>
+ And the following shows what such a module then allows
+ </para>
+ <programlisting>
+{
+ # Not a declared option, but the freeform type allows this
+ settings.logLevel = "debug";
+
+ # Not allowed because the the freeform type only allows strings
+ # settings.enable = true;
+
+ # Allowed because there is a port option declared
+ settings.port = 80;
+
+ # Not allowed because the port option doesn't allow strings
+ # settings.port = "443";
+}
+ </programlisting>
+ </example>
+ <note>
+ <para>
+ Freeform attributes cannot depend on other attributes of the same set without infinite recursion:
+<programlisting>
+{
+ # This throws infinite recursion encountered
+ settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
+}
+</programlisting>
+ To prevent this, declare options for all attributes that need to depend on others. For above example this means to declare <literal>logLevel</literal> to be an option.
+ </para>
+ </note>
+</section>
diff --git a/nixos/doc/manual/development/settings-options.xml b/nixos/doc/manual/development/settings-options.xml
index 84895adb444d..c99c3af92f89 100644
--- a/nixos/doc/manual/development/settings-options.xml
+++ b/nixos/doc/manual/development/settings-options.xml
@@ -137,7 +137,7 @@ in {
description = ''
Configuration for foo, see
&lt;link xlink:href="https://example.com/docs/foo"/&gt;
- for supported values.
+ for supported settings.
'';
};
};
@@ -167,13 +167,50 @@ in {
# We know that the `user` attribute exists because we set a default value
# for it above, allowing us to use it without worries here
- users.users.${cfg.settings.user} = {}
+ users.users.${cfg.settings.user} = {};
# ...
};
}
</programlisting>
</example>
+ <section xml:id="sec-settings-attrs-options">
+ <title>Option declarations for attributes</title>
+ <para>
+ Some <literal>settings</literal> attributes may deserve some extra care. They may need a different type, default or merging behavior, or they are essential options that should show their documentation in the manual. This can be done using <xref linkend='sec-freeform-modules'/>.
+ <example xml:id="ex-settings-typed-attrs">
+ <title>Declaring a type-checked <literal>settings</literal> attribute</title>
+ <para>
+ We extend above example using freeform modules to declare an option for the port, which will enforce it to be a valid integer and make it show up in the manual.
+ </para>
+<programlisting>
+settings = lib.mkOption {
+ type = lib.types.submodule {
+
+ freeformType = settingsFormat.type;
+
+ # Declare an option for the port such that the type is checked and this option
+ # is shown in the manual.
+ options.port = lib.mkOption {
+ type = lib.types.port;
+ default = 8080;
+ description = ''
+ Which port this service should listen on.
+ '';
+ };
+
+ };
+ default = {};
+ description = ''
+ Configuration for Foo, see
+ &lt;link xlink:href="https://example.com/docs/foo"/&gt;
+ for supported values.
+ '';
+};
+</programlisting>
+ </example>
+ </para>
+ </section>
</section>
</section>
diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml
index 602f134f9cbf..d244356dbed1 100644
--- a/nixos/doc/manual/development/writing-modules.xml
+++ b/nixos/doc/manual/development/writing-modules.xml
@@ -183,5 +183,6 @@ in {
<xi:include href="meta-attributes.xml" />
<xi:include href="importing-modules.xml" />
<xi:include href="replace-modules.xml" />
+ <xi:include href="freeform-modules.xml" />
<xi:include href="settings-options.xml" />
</chapter>