From 70a2c545274cda238c5eda28b60cfa9dbc6f7ed6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 30 Oct 2013 15:33:20 +0100 Subject: [PATCH] Strictly check the arguments to mkOption And fix various instances of bad arguments. --- lib/options.nix | 23 ++++++++-------- lib/types.nix | 3 +++ nixos/modules/config/fonts/fontconfig.nix | 1 + nixos/modules/services/games/ghost-one.nix | 3 ++- nixos/modules/services/networking/bitlbee.nix | 2 +- .../modules/services/networking/minidlna.nix | 2 +- .../modules/services/networking/ssh/sshd.nix | 2 +- .../system/boot/systemd-unit-options.nix | 26 ++++++++++--------- nixos/modules/system/upstart/upstart.nix | 22 +++++++--------- 9 files changed, 45 insertions(+), 39 deletions(-) diff --git a/lib/options.nix b/lib/options.nix index 5a05775e8c25..d1a161cf7633 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -11,17 +11,18 @@ with import ./strings.nix; rec { isOption = lib.isType "option"; - mkOption = attrs: attrs // { - _type = "option"; - # name (this is the name of the attributem it is automatically generated by the traversal) - # default (value used when no definition exists) - # example (documentation) - # description (documentation) - # type (option type, provide a default merge function and ensure type correctness) - # merge (function used to merge definitions into one definition: [ /type/ ] -> /type/) - # apply (convert the option value to ease the manipulation of the option result) - # options (set of sub-options declarations & definitions) - }; + mkOption = + { default ? null # Default value used when no definition is given in the configuration. + , defaultText ? null # Textual representation of the default, for in the manual. + , example ? null # Example value used in the manual. + , description ? null # String describing the option. + , type ? null # Option type, providing type-checking and value merging. + , apply ? null # Function that converts the option value to something else. + , internal ? null # Whether the option is for NixOS developers only. + , visible ? null # Whether the option shows up in the manual. + , options ? null # Obsolete, used by types.optionSet. + } @ attrs: + attrs // { _type = "option"; }; mkEnableOption = name: mkOption { default = false; diff --git a/lib/types.nix b/lib/types.nix index cf8eef008337..2b3aa23df2f1 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -201,6 +201,9 @@ rec { name = /* builtins.trace "types.optionSet is deprecated; use types.submodule instead" */ "option set"; }; + # Augment the given type with an additional type check function. + addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; }; + }; } diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix index 6e0fdaf4b748..987bb1088c0d 100644 --- a/nixos/modules/config/fonts/fontconfig.nix +++ b/nixos/modules/config/fonts/fontconfig.nix @@ -9,6 +9,7 @@ with pkgs.lib; fonts = { enableFontConfig = mkOption { # !!! should be enableFontconfig + type = types.bool; default = true; description = '' If enabled, a Fontconfig configuration file will be built diff --git a/nixos/modules/services/games/ghost-one.nix b/nixos/modules/services/games/ghost-one.nix index 815118be1c63..92c9112eeb6c 100644 --- a/nixos/modules/services/games/ghost-one.nix +++ b/nixos/modules/services/games/ghost-one.nix @@ -21,7 +21,8 @@ in language = mkOption { default = "English"; - check = lang: elem lang [ "English" "Spanish" "Russian" "Serbian" "Turkish" ]; + type = types.addCheck types.str + (lang: elem lang [ "English" "Spanish" "Russian" "Serbian" "Turkish" ]); description = "The language of bot messages: English, Spanish, Russian, Serbian or Turkish."; }; diff --git a/nixos/modules/services/networking/bitlbee.nix b/nixos/modules/services/networking/bitlbee.nix index 82e875f5aae0..fe37e8ea0120 100644 --- a/nixos/modules/services/networking/bitlbee.nix +++ b/nixos/modules/services/networking/bitlbee.nix @@ -64,7 +64,7 @@ in authMode = mkOption { default = "Open"; - check = authModeCheck; + type = types.addCheck types.str authModeCheck; description = '' The following authentication modes are available: Open -- Accept connections from anyone, use NickServ for user authentication. diff --git a/nixos/modules/services/networking/minidlna.nix b/nixos/modules/services/networking/minidlna.nix index ea5bc8514f1c..e31d77f13fed 100644 --- a/nixos/modules/services/networking/minidlna.nix +++ b/nixos/modules/services/networking/minidlna.nix @@ -32,7 +32,7 @@ in services.minidlna.mediaDirs = mkOption { type = types.listOf types.string; default = []; - examples = [ "/data/media" "V,/home/alice/video" ]; + example = [ "/data/media" "V,/home/alice/video" ]; description = '' Directories to be scanned for media files. The prefixes diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index f5670ccdcbfa..360c745f3627 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -102,7 +102,7 @@ in permitRootLogin = mkOption { default = "without-password"; - check = permitRootLoginCheck; + type = types.addCheck types.str permitRootLoginCheck; description = '' Whether the root user can login using ssh. Valid values are yes, without-password, diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index ac9e636fe1e3..a1faea886f98 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -2,7 +2,19 @@ with pkgs.lib; -rec { +let + + checkService = v: + let assertValueOneOf = name: values: attr: + let val = getAttr name attr; + in optional ( hasAttr name attr && !elem val values) "Systemd service field `${name}' cannot have value `${val}'."; + checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"]; + checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"]; + errors = concatMap (c: c v) [checkType checkRestart]; + in if errors == [] then true + else builtins.trace (concatStringsSep "\n" errors) false; + +in rec { unitOptions = { @@ -147,23 +159,13 @@ rec { { StartLimitInterval = 10; RestartSec = 5; }; - type = types.attrs; + type = types.addCheck types.attrs checkService; description = '' Each attribute in this set specifies an option in the [Service] section of the unit. See systemd.service 5 for details. ''; - - check = v: - let assertValueOneOf = name: values: attr: - let val = getAttr name attr; - in optional ( hasAttr name attr && !elem val values) "${name} ${val} not known to systemd"; - checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"]; - checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"]; - errors = concatMap (c: c v) [checkType checkRestart]; - in if errors == [] then true - else builtins.trace (concatStringsSep "\n" errors) false; }; script = mkOption { diff --git a/nixos/modules/system/upstart/upstart.nix b/nixos/modules/system/upstart/upstart.nix index 58523652864c..464041ebe6b2 100644 --- a/nixos/modules/system/upstart/upstart.nix +++ b/nixos/modules/system/upstart/upstart.nix @@ -104,7 +104,7 @@ let name = mkOption { # !!! The type should ensure that this could be a filename. - type = types.string; + type = types.str; example = "sshd"; description = '' Name of the Upstart job. @@ -113,7 +113,7 @@ let startOn = mkOption { # !!! Re-enable this once we're on Upstart >= 0.6. - #type = types.string; + #type = types.str; default = ""; description = '' The Upstart event that triggers this job to be started. @@ -122,7 +122,7 @@ let }; stopOn = mkOption { - type = types.string; + type = types.str; default = "starting shutdown"; description = '' The Upstart event that triggers this job to be stopped. @@ -130,7 +130,7 @@ let }; postStart = mkOption { - type = types.string; + type = types.lines; default = ""; description = '' Shell commands executed after the job is started (i.e. after @@ -140,7 +140,7 @@ let }; preStop = mkOption { - type = types.string; + type = types.lines; default = ""; description = '' Shell commands executed before the job is stopped @@ -150,7 +150,7 @@ let }; postStop = mkOption { - type = types.string; + type = types.lines; default = ""; description = '' Shell commands executed after the job has stopped @@ -159,7 +159,7 @@ let }; exec = mkOption { - type = types.string; + type = types.str; default = ""; description = '' Command to start the job's main process. If empty, the @@ -189,7 +189,7 @@ let }; daemonType = mkOption { - type = types.string; + type = types.str; default = "none"; description = '' Determines how Upstart detects when a daemon should be @@ -203,8 +203,7 @@ let }; setuid = mkOption { - type = types.string; - check = userExists; + type = types.addCheck types.str userExists; default = ""; description = '' Run the daemon as a different user. @@ -212,8 +211,7 @@ let }; setgid = mkOption { - type = types.string; - check = groupExists; + type = types.addCheck types.str groupExists; default = ""; description = '' Run the daemon as a different group.