-
-
Notifications
You must be signed in to change notification settings - Fork 17.9k
WIP: implement a secret vars store in nixpkgs #370444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -621,6 +621,24 @@ in { | |||||
|
|
||||||
| config = mkIf cfg.enable { | ||||||
|
|
||||||
| vars.generators.syncthing = { | ||||||
|
||||||
| files."cert.pem" = {}; | ||||||
| files."key.pem" = {}; | ||||||
| files."syncthing.pub".secret = false; | ||||||
| runtimeInputs = [ | ||||||
| pkgs.coreutils | ||||||
| pkgs.gnugrep | ||||||
| pkgs.syncthing | ||||||
| ]; | ||||||
| script = '' | ||||||
| syncthing generate --config "$out" | ||||||
| < "$out"/config.xml grep -oP '(?<=<device id=")[^"]+' | uniq > "$out"/syncthing.pub | ||||||
|
||||||
| < "$out"/config.xml grep -oP '(?<=<device id=")[^"]+' | uniq > "$out"/syncthing.pub | |
| < "$out"/config.xml grep -m 1 -oP '(?<=<device id=")[^"]+' > "$out"/syncthing.pub |
should guarantee that it can yield no more than 1 id (uniq could still yield multiple, different ids). Due to the regex match not applying to empty strings, grep will already return rc 1 if no id is found, so the set -e in the reference backend should fetch it.
Might be a good idea to explicitly define that scripts are supposed to be run with set -e. :)
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,140 @@ | ||||||||||
| # we use this vars backend as an example backend. | ||||||||||
| # this generates a script which creates the values at the expected path. | ||||||||||
| # this script has to be run manually (I guess after updating the system) to generate the required vars. | ||||||||||
| { | ||||||||||
| pkgs, | ||||||||||
| lib, | ||||||||||
| config, | ||||||||||
| ... | ||||||||||
| }: | ||||||||||
| let | ||||||||||
| cfg = config.vars.settings.on-machine; | ||||||||||
| sortedGenerators = | ||||||||||
| (lib.toposort (a: b: builtins.elem a.name b.dependencies) (lib.attrValues config.vars.generators)) | ||||||||||
| .result; | ||||||||||
|
|
||||||||||
| promptCmd = { | ||||||||||
| hidden = "read -sr prompt_value"; | ||||||||||
| line = "read -r prompt_value"; | ||||||||||
| multiline = '' | ||||||||||
| echo 'press control-d to finish' | ||||||||||
| prompt_value=$(cat) | ||||||||||
| ''; | ||||||||||
| }; | ||||||||||
| generate-vars = pkgs.writeShellApplication { | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly, this script may be run on the deployer host, which can be a different platform.
Suggested change
It is then up to the caller to pass a suitable EDIT: this is of course not the complete solution because the script contents still refer to
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a test case, you could add
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. usually we overwrite pkgs of the system where the vars are defined if the caller architecture is different from the target systems architecture, since this also supports string context references to pkgs and the vars definitons want to live next to the service definitions.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recommend against that. It blurs the line too much.
Explicit is good. By making this a proper parameter, readers and module authors have at least an idea of what's going on, and you don't rely on the overriding magic to never hit them in the face. |
||||||||||
| name = "generate-vars"; | ||||||||||
| text = '' | ||||||||||
| set -efuo pipefail | ||||||||||
|
|
||||||||||
| PATH=${lib.makeBinPath [ pkgs.coreutils ]} | ||||||||||
|
|
||||||||||
| # make the output directory overridable | ||||||||||
| OUT_DIR=''${OUT_DIR:-${cfg.fileLocation}} | ||||||||||
|
|
||||||||||
| # check if all files are present or all files are missing | ||||||||||
| # if not, they are in an inconsistent state and we bail out | ||||||||||
| ${lib.concatMapStringsSep "\n" (gen: '' | ||||||||||
| all_files_missing=true | ||||||||||
| all_files_present=true | ||||||||||
| ${lib.concatMapStringsSep "\n" (file: '' | ||||||||||
| if test -e ${lib.escapeShellArg file.path} ; then | ||||||||||
| all_files_missing=false | ||||||||||
| else | ||||||||||
| all_files_present=false | ||||||||||
| fi | ||||||||||
| '') (lib.attrValues gen.files)} | ||||||||||
|
|
||||||||||
| if [ $all_files_missing = false ] && [ $all_files_present = false ] ; then | ||||||||||
| echo "Inconsistent state for generator: {gen.name}" | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(unless this some ultra-obscure bash syntax i am not aware of ;)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I sadly think that "Inconsistent state for generator: ${gen.name}" is a pretty bad error message here. I think it should at least try to communicate to the user what exactly is wrong, i.e. which file was found / not found. Ideally it would communicate something actionable as well, i.e:
I understand that it's annoying to implement in bash, but I am not sure that bash is the right choice of language here in the first place tbh. |
||||||||||
| exit 1 | ||||||||||
| fi | ||||||||||
| if [ $all_files_present = true ] ; then | ||||||||||
| echo "All secrets for ${gen.name} are present" | ||||||||||
| elif [ $all_files_missing = true ] ; then | ||||||||||
|
|
||||||||||
| # prompts | ||||||||||
| prompts=$(mktemp -d) | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should slap |
||||||||||
| trap 'rm -rf $prompts' EXIT | ||||||||||
| export prompts | ||||||||||
| mkdir -p "$prompts" | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||
| ${lib.concatMapStringsSep "\n" (prompt: '' | ||||||||||
| echo ${lib.escapeShellArg prompt.description} | ||||||||||
| ${promptCmd.${prompt.type}} | ||||||||||
|
||||||||||
| echo -n "$prompt_value" > "$prompts"/${prompt.name} | ||||||||||
| '') (lib.attrValues gen.prompts)} | ||||||||||
| echo "Generating vars for ${gen.name}" | ||||||||||
|
||||||||||
|
|
||||||||||
| # dependencies | ||||||||||
| in=$(mktemp -d) | ||||||||||
| trap 'rm -rf $in' EXIT | ||||||||||
| export in | ||||||||||
| mkdir -p "$in" | ||||||||||
| ${lib.concatMapStringsSep "\n" (input: '' | ||||||||||
| mkdir -p "$in"/${input} | ||||||||||
| ${lib.concatMapStringsSep "\n" (file: '' | ||||||||||
| cp "$OUT_DIR"/${ | ||||||||||
| if file.secret then "secret" else "public" | ||||||||||
| }/${input}/${file.name} "$in"/${input}/${file.name} | ||||||||||
| '') (lib.attrValues config.vars.generators.${input}.files)} | ||||||||||
| '') gen.dependencies} | ||||||||||
|
|
||||||||||
| # outputs | ||||||||||
| out=$(mktemp -d) | ||||||||||
| trap 'rm -rf $out' EXIT | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Traps override each other. Confer The way it stands, unless the script exits prematurely, only the very final One possible solution would be to spawn a subshell for each generator, e.g.:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's also possible to have an array of cleanup function: https://github.com/Mic92/dotfiles/blob/4ce52e794985cf159e69e259e8b63d2f7cadfa22/pkgs/merge-when-green/script.sh#L10 |
||||||||||
| export out | ||||||||||
| mkdir -p "$out" | ||||||||||
|
|
||||||||||
| ( | ||||||||||
| # prepare PATH | ||||||||||
| unset PATH | ||||||||||
| ${lib.optionalString (gen.runtimeInputs != [ ]) '' | ||||||||||
| PATH=${lib.makeBinPath gen.runtimeInputs} | ||||||||||
| export PATH | ||||||||||
| ''} | ||||||||||
|
|
||||||||||
| # actually run the generator | ||||||||||
| ${gen.script} | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| # check if all files got generated | ||||||||||
| ${lib.concatMapStringsSep "\n" (file: '' | ||||||||||
| if ! test -e "$out"/${file.name} ; then | ||||||||||
| echo 'generator ${gen.name} failed to generate ${file.name}' | ||||||||||
| exit 1 | ||||||||||
| fi | ||||||||||
| '') (lib.attrValues gen.files)} | ||||||||||
|
|
||||||||||
| # move the files to the correct location | ||||||||||
| ${lib.concatMapStringsSep "\n" (file: '' | ||||||||||
| OUT_FILE="$OUT_DIR"/${if file.secret then "secret" else "public"}/${file.generator}/${file.name} | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we somehow reuse |
||||||||||
| mkdir -p "$(dirname "$OUT_FILE")" | ||||||||||
| mv "$out"/${file.name} "$OUT_FILE" | ||||||||||
| '') (lib.attrValues gen.files)} | ||||||||||
| rm -rf "$out" | ||||||||||
|
||||||||||
| fi | ||||||||||
| '') sortedGenerators} | ||||||||||
| ''; | ||||||||||
| }; | ||||||||||
| in | ||||||||||
| { | ||||||||||
| options.vars.settings.on-machine = { | ||||||||||
| enable = lib.mkEnableOption "Enable on-machine vars backend"; | ||||||||||
| fileLocation = lib.mkOption { | ||||||||||
|
||||||||||
| type = lib.types.str; | ||||||||||
| default = "/etc/vars"; | ||||||||||
| }; | ||||||||||
| }; | ||||||||||
| config = lib.mkIf cfg.enable { | ||||||||||
| vars.settings.fileModule = file: { | ||||||||||
| path = | ||||||||||
| if file.config.secret then | ||||||||||
| "${cfg.fileLocation}/secret/${file.config.generator}/${file.config.name}" | ||||||||||
| else | ||||||||||
| "${cfg.fileLocation}/public/${file.config.generator}/${file.config.name}"; | ||||||||||
Mic92 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| }; | ||||||||||
| environment.systemPackages = [ | ||||||||||
| generate-vars | ||||||||||
| ]; | ||||||||||
| system.build.generate-vars = generate-vars; | ||||||||||
| }; | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,185 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| lib, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| config, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| pkgs, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ... | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| options.vars = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| settings = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not RFC 42. What's the thought behind this name?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand it's the provider-specific settings, similar in spirit to how SelfHostBlocks does it, except here it's (IMO correctly) in terms of modules. |
||||||||||||||||||||||||||||||||||||||||||||||||||
| fileModule = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.deferredModule; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| internal = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A module to be imported in every vars.files.<name> submodule. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Used by backends to define the `path` attribute. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Takes the file as an argument and returns maybe an attrset which should at least contain the `path` attribute. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Can be used to set other file attributes as well, like `value`. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = { }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| generators = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This contains both generators (executables), as well as their target files (calls of those executables).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that you have an insofar unnamed domain entity for groups of files that are generated together, and perhaps its name should be put here.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, the idea was, that one generator can create many files, so the files are below the generators in the hierarchy. Files belong to a generator in that they need to be generated by one, not sure where else in the option tree they could live |
||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A set of generators that can be used to generate files. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Generators are scripts that produce files based on the values of other generators and user input. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Each generator is expected to produce a set of files under a directory. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = { }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.attrsOf ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| lib.types.submodule (generator: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| options = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
Lassulus marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| name = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.strMatching "[a-zA-Z0-9:_\\.-]*"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The name of the generator. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| This name will be used to refer to the generator in other generators. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| readOnly = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = generator.config._module.args.name; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "Name of the generator"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| dependencies = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A list of other generators that this generator depends on. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The output values of these generators will be available to the generator script as files. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| For example, the file 'file1' of a dependency named 'dep1' will be available via $in/dep1/file1. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.listOf lib.types.str; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = [ ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| files = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A set of files to generate. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The generator 'script' is expected to produce exactly these files under $out. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "attrs of files"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not sure. |
||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.attrsOf ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| lib.types.submodule (file: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| imports = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| config.vars.settings.fileModule | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| options = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.strMatching "[a-zA-Z0-9:_\\.-]*"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name of the generated file | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| readOnly = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = file.config._module.args.name; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+60
to
+71
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This seems to be a much more idiomatic way of writing it. That piece of code had confused the hell out of me, but maybe I'm just used to different things.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only changing it to |
||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "Name of the file"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| generator = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The generator that produces the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| This is the name of another generator. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.strMatching "[a-zA-Z0-9:_\\.-]*"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| readOnly = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| internal = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = generator.config.name; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "Name of the generator"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| deploy = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Whether the file should be deployed to the target machine. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Disable this if the generated file is only used as an input to other generators. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.bool; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| secret = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Whether the file should be treated as a secret. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.bool; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| path = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The path to the file containing the content of the generated value. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| This will be set automatically | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.nullOr lib.types.str; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| prompts = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A set of prompts to ask the user for values. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Prompts are available to the generator script as files. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| For example, a prompt named 'prompt1' will be available via $prompts/prompt1 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = { }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.attrsOf ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| lib.types.submodule (prompt: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| options = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The name of the prompt. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| This name will be used to refer to the prompt in the generator script. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.strMatching "[a-zA-Z0-9:_\\.-]*"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = prompt.config._module.args.name; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "Name of the prompt"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The description of the prompted value | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.str; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| example = "SSH private key"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = prompt.config._module.args.name; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultText = "Name of the prompt"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The input type of the prompt. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The following types are available: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - hidden: A hidden text (e.g. password) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - line: A single line of text | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - multiline: A multiline text | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.enum [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "hidden" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "line" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "multiline" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = "line"; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| runtimeInputs = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A list of packages that the generator script requires. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| These packages will be available in the PATH when the script is run. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.listOf lib.types.package; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = [ pkgs.coreutils ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| script = lib.mkOption { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| description = '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The script to run to generate the files. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The script will be run with the following environment variables: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - $in: The directory containing the output values of all declared dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - $out: The output directory to put the generated files | ||||||||||||||||||||||||||||||||||||||||||||||||||
| - $prompts: The directory containing the prompted values as files | ||||||||||||||||||||||||||||||||||||||||||||||||||
| The script should produce the files specified in the 'files' attribute under $out. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| type = lib.types.either lib.types.str lib.types.path; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| default = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1132,6 +1132,7 @@ in { | |
| user-home-mode = handleTest ./user-home-mode.nix {}; | ||
| ustreamer = handleTest ./ustreamer.nix {}; | ||
| uwsgi = handleTest ./uwsgi.nix {}; | ||
| vars = handleTest ./vars.nix {}; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This placed seemed pretty ordered until this line got added. Or is |
||
| v2ray = handleTest ./v2ray.nix {}; | ||
| varnish60 = handleTest ./varnish.nix { package = pkgs.varnish60; }; | ||
| varnish75 = handleTest ./varnish.nix { package = pkgs.varnish75; }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without an accompanying section in the NixOS manual, you're kind of leaving me guessing here, so I hope my comments make sense.