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 @@ 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. @@ -20,55 +20,114 @@ NixOS module system. -
- Warnings +
+ Defining Warnings and Assertions - This is an example of using warnings. + Both warnings and assertions can be defined using the option. Each assertion needs an attribute name, under which you have to define an enable condition using and a message using . Note that the enable condition is inverse 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 options to the module arguments and use ${options.path.to.option} to print a context-aware string representation of the option path. Here is an example showing how this can be done. - +
-
- Assertions +
+ Ignoring Warnings and Assertions - This example, extracted from the - - syslogd module shows how to use - assertions. 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. + 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 by using the attribute name of the definition, which is conveniently printed using [...] when the assertion is triggered. For above example, the evaluation output when the assertions are triggered looks as follows: - +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! + + + The [grafanaPassword] and [gpgSshAgent] strings tell you that these were defined under the grafanaPassword and gpgSshAgent attributes of respectively. With this knowledge you can adjust them to your liking: + + + +{ 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; +} + + + +
+
+ Warnings and Assertions in Submodules + + + Warnings and assertions can be defined within submodules in the same way. Here is an example: + + + +{ 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"; + }; + })); + }; + +} + + + + When this assertion is triggered, it shows both the submodule path along with the assertion attribute within that submodule, joined by a /. Note also how ${options.port} correctly shows the context of the option. + + + +trace: warning: [myServices.foo/portConflict] Port 80 defined using + myServices.foo.port is usually used for HTTP + + + + Therefore to disable such an assertion, you can do so by changing the option within the myServices.foo submodule: + + + +{ lib, ... }: { + myServices.foo._module.assertions.portConflict.enable = lib.mkForce false; +} + + + + + Assertions defined in submodules under types.listOf can't be ignored, since there's no way to change previously defined list items. + + +