vars: new option prompts.<name>.createFile

This commit is contained in:
DavHau
2024-09-04 15:40:30 +02:00
parent 6597e9adf8
commit bd554ca392
3 changed files with 72 additions and 3 deletions

View File

@@ -4,13 +4,32 @@
pkgs, pkgs,
... ...
}: }:
let
inherit (lib)
attrNames
concatMapStrings
genAttrs
filterAttrs
makeBinPath
mkOptionDefault
optionalString
;
promptToFile = name: ''
cat "$prompts/${name}" > "$out/${name}"
'';
promptsToFilesScript = concatMapStrings promptToFile;
filePromptNames = attrNames (filterAttrs (_name: prompt: prompt.createFile) config.prompts);
in
{ {
finalScript = lib.mkOptionDefault '' finalScript = mkOptionDefault ''
set -eu -o pipefail set -eu -o pipefail
export PATH="${lib.makeBinPath config.runtimeInputs}:${pkgs.coreutils}/bin" export PATH="${makeBinPath config.runtimeInputs}:${pkgs.coreutils}/bin"
${lib.optionalString (pkgs.stdenv.hostPlatform.isLinux) '' ${optionalString (pkgs.stdenv.hostPlatform.isLinux) ''
# prepare sandbox user on platforms where this is supported # prepare sandbox user on platforms where this is supported
mkdir -p /etc mkdir -p /etc
@@ -31,6 +50,9 @@
::1 localhost ::1 localhost
EOF EOF
''} ''}
${promptsToFilesScript filePromptNames}
${config.script} ${config.script}
''; '';
files = genAttrs filePromptNames (_name: { });
} }

View File

@@ -120,6 +120,21 @@ in
type = attrsOf ( type = attrsOf (
submodule (prompt: { submodule (prompt: {
options = options { options = options {
createFile = {
description = ''
Whether the prompted value should be stored in a file with the same name as the prompt.
If enabled, the behavior is equivalent to the following configuration:
```nix
{
files.<name>.secret = true;
script = "cp $prompts/<name> $out/<name>";
}
```
'';
type = bool;
default = true;
};
description = { description = {
description = '' description = ''
The description of the prompted value The description of the prompted value
@@ -165,6 +180,7 @@ in
The script should produce the files specified in the 'files' attribute under $out. The script should produce the files specified in the 'files' attribute under $out.
''; '';
type = either str path; type = either str path;
default = "";
}; };
finalScript = { finalScript = {
description = '' description = ''

View File

@@ -314,6 +314,7 @@ def test_prompt(
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["files"]["my_value"]["secret"] = False my_generator["files"]["my_value"]["secret"] = False
my_generator["prompts"]["prompt1"]["description"] = "dream2nix" my_generator["prompts"]["prompt1"]["description"] = "dream2nix"
my_generator["prompts"]["prompt1"]["createFile"] = False
my_generator["prompts"]["prompt1"]["type"] = prompt_type my_generator["prompts"]["prompt1"]["type"] = prompt_type
my_generator["script"] = "cat $prompts/prompt1 > $out/my_value" my_generator["script"] = "cat $prompts/prompt1 > $out/my_value"
flake = generate_flake( flake = generate_flake(
@@ -378,3 +379,33 @@ def test_share_flag(
assert not in_repo_store.exists("shared_generator", "my_value", shared=False) assert not in_repo_store.exists("shared_generator", "my_value", shared=False)
assert in_repo_store.exists("unshared_generator", "my_value", shared=False) assert in_repo_store.exists("unshared_generator", "my_value", shared=False)
assert not in_repo_store.exists("unshared_generator", "my_value", shared=True) assert not in_repo_store.exists("unshared_generator", "my_value", shared=True)
@pytest.mark.impure
def test_prompt_create_file(
monkeypatch: pytest.MonkeyPatch,
temporary_home: Path,
sops_setup: SopsSetup,
) -> None:
"""
Test that the createFile flag in the prompt configuration works as expected
"""
config = nested_dict()
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
my_generator["prompts"]["prompt1"]["createFile"] = True
my_generator["prompts"]["prompt2"]["createFile"] = False
flake = generate_flake(
temporary_home,
flake_template=CLAN_CORE / "templates" / "minimal",
machine_configs={"my_machine": config},
)
monkeypatch.chdir(flake.path)
sops_setup.init()
monkeypatch.setattr("sys.stdin", StringIO("input1\ninput2\n"))
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
sops_store = sops.SecretStore(
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
)
assert sops_store.exists("my_generator", "prompt1")
assert not sops_store.exists("my_generator", "prompt2")
assert sops_store.get("my_generator", "prompt1").decode() == "input1"