diff options
author | Silvan Mosberger <contact@infinisil.com> | 2020-09-02 19:23:39 +0200 |
---|---|---|
committer | Silvan Mosberger <contact@infinisil.com> | 2020-11-30 23:51:23 +0100 |
commit | c4fb54e92a10f04bb70b31b397a50fdbc203bc66 (patch) | |
tree | 6a9e43f0d1c685f2daa1875eb6d230c76fddf093 | |
parent | 3759a77fcda2e33f89023b8c6b1476e8fa413a8e (diff) | |
download | nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar.gz nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar.bz2 nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar.lz nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar.xz nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.tar.zst nixpkgs-c4fb54e92a10f04bb70b31b397a50fdbc203bc66.zip |
nixos/docs: Update assertion docs for new module-builtin ones
-rw-r--r-- | nixos/doc/manual/development/assertions.xml | 129 |
1 files changed, 94 insertions, 35 deletions
diff --git a/nixos/doc/manual/development/assertions.xml b/nixos/doc/manual/development/assertions.xml index 32f90cf2e7c..91506ba65a1 100644 --- a/nixos/doc/manual/development/assertions.xml +++ b/nixos/doc/manual/development/assertions.xml @@ -8,7 +8,7 @@ <para> When configuration problems are detectable in a module, it is a good idea to write an assertion or warning. Doing so provides clear feedback to the user - and prevents errors after the build. + and can prevent errors before the build. </para> <para> @@ -20,55 +20,114 @@ NixOS module system. </para> - <section xml:id="sec-assertions-warnings"> - <title>Warnings</title> + <section xml:id="sec-assertions-define"> + <title>Defining Warnings and Assertions</title> <para> - This is an example of using <literal>warnings</literal>. + Both warnings and assertions can be defined using the <xref linkend="opt-_module.assertions"/> option. Each assertion needs an attribute name, under which you have to define an enable condition using <xref linkend="opt-_module.assertions._name_.enable"/> and a message using <xref linkend="opt-_module.assertions._name_.message"/>. Note that the enable condition is <emphasis>inverse</emphasis> of what an assertion would be: To assert a value being true, the enable condition should be false in that case, so that it isn't triggered. For the assertion message, you can add <literal>options</literal> to the module arguments and use <literal>${options.path.to.option}</literal> to print a context-aware string representation of the option path. Here is an example showing how this can be done. </para> <programlisting> -<![CDATA[ -{ config, lib, ... }: -{ - config = lib.mkIf config.services.foo.enable { - warnings = - if config.services.foo.bar - then [ ''You have enabled the bar feature of the foo service. - This is known to cause some specific problems in certain situations. - '' ] - else []; - } +{ config, options, ... }: { + _module.assertions.gpgSshAgent = { + enable = config.programs.gnupg.agent.enableSSHSupport && config.programs.ssh.startAgent; + message = "You can't enable both ${options.programs.ssh.startAgent}" + + " and ${options.programs.gnupg.agent.enableSSHSupport}!"; + }; + + _module.assertions.grafanaPassword = { + enable = config.services.grafana.database.password != ""; + message = "The grafana password defined with ${options.services.grafana.database.password}" + + " will be stored as plaintext in the Nix store!"; + # This is a non-fatal warning + type = "warning"; + }; } -]]> </programlisting> + </section> - <section xml:id="sec-assertions-assertions"> - <title>Assertions</title> + <section xml:id="sec-assertions-ignoring"> + <title>Ignoring Warnings and Assertions</title> + + <para> + Sometimes you can get warnings or assertions that don't apply to your specific case and you wish to ignore them, or at least make assertions non-fatal. You can do so for all assertions defined using <xref linkend="opt-_module.assertions"/> by using the attribute name of the definition, which is conveniently printed using <literal>[...]</literal> when the assertion is triggered. For above example, the evaluation output when the assertions are triggered looks as follows: + </para> + +<programlisting> +trace: warning: [grafanaPassword] The grafana password defined with + services.grafana.database.password will be stored as plaintext in the Nix store! +error: Failed assertions: +- [gpgSshAgent] You can't enable both programs.ssh.startAgent and + programs.gnupg.agent.enableSSHSupport! +</programlisting> <para> - This example, extracted from the - <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-17.09/nixos/modules/services/logging/syslogd.nix"> - <literal>syslogd</literal> module </link> shows how to use - <literal>assertions</literal>. Since there can only be one active syslog - daemon at a time, an assertion is useful to prevent such a broken system - from being built. + The <literal>[grafanaPassword]</literal> and <literal>[gpgSshAgent]</literal> strings tell you that these were defined under the <literal>grafanaPassword</literal> and <literal>gpgSshAgent</literal> attributes of <xref linkend="opt-_module.assertions"/> respectively. With this knowledge you can adjust them to your liking: </para> <programlisting> -<![CDATA[ -{ config, lib, ... }: -{ - config = lib.mkIf config.services.syslogd.enable { - assertions = - [ { assertion = !config.services.rsyslogd.enable; - message = "rsyslogd conflicts with syslogd"; - } - ]; - } +{ lib, ... }: { + # Change the assertion into a non-fatal warning + _module.assertions.gpgSshAgent.type = "warning"; + + # We don't care about this warning, disable it + _module.assertions.grafanaPassword.enable = lib.mkForce false; } -]]> </programlisting> + + + </section> + <section xml:id="sec-assertions-submodules"> + <title>Warnings and Assertions in Submodules</title> + + <para> + Warnings and assertions can be defined within submodules in the same way. Here is an example: + </para> + +<programlisting> +{ lib, ... }: { + + options.myServices = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({ config, options, ... }: { + options.port = lib.mkOption {}; + + config._module.assertions.portConflict = { + enable = config.port == 80; + message = "Port ${toString config.port} defined using" + + " ${options.port} is usually used for HTTP"; + type = "warning"; + }; + })); + }; + +} +</programlisting> + + <para> + When this assertion is triggered, it shows both the submodule path along with the assertion attribute within that submodule, joined by a <literal>/</literal>. Note also how <literal>${options.port}</literal> correctly shows the context of the option. + </para> + +<programlisting> +trace: warning: [myServices.foo/portConflict] Port 80 defined using + myServices.foo.port is usually used for HTTP +</programlisting> + + <para> + Therefore to disable such an assertion, you can do so by changing the <xref linkend="opt-_module.assertions"/> option within the <literal>myServices.foo</literal> submodule: + </para> + +<programlisting> +{ lib, ... }: { + myServices.foo._module.assertions.portConflict.enable = lib.mkForce false; +} +</programlisting> + +<note> + <para> + Assertions defined in submodules under <literal>types.listOf</literal> can't be ignored, since there's no way to change previously defined list items. + </para> +</note> + </section> </section> |