diff options
author | Robert Hensing <roberth@users.noreply.github.com> | 2020-08-15 12:13:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-15 12:13:58 +0200 |
commit | 6d0a85fe528e020eb7d8eb78d33ee87055c01c74 (patch) | |
tree | cd0e99185243f514ba6a4004d8697e019681db55 /nixos | |
parent | 375611df00b01c668fd82fc0632cd8aec826b5ec (diff) | |
parent | 25d75155f39d293d16ecd6aab70024a8740e0baa (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.xml | 68 | ||||
-rw-r--r-- | nixos/doc/manual/development/settings-options.xml | 41 | ||||
-rw-r--r-- | nixos/doc/manual/development/writing-modules.xml | 1 |
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 <link xlink:href="https://example.com/docs/foo"/> - 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 + <link xlink:href="https://example.com/docs/foo"/> + 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> |