forked from clan/clan-core
vars: init
- init eval tests - init basic interface
This commit is contained in:
parent
d4f2f7944c
commit
5668bc561d
@ -26,6 +26,7 @@
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
select-shell
|
||||
pkgs.nix-unit
|
||||
pkgs.tea
|
||||
# Better error messages than nix 2.18
|
||||
pkgs.nixVersions.latest
|
||||
|
@ -51,6 +51,7 @@
|
||||
./formatter.nix
|
||||
./lib/flake-module.nix
|
||||
./nixosModules/flake-module.nix
|
||||
./nixosModules/clanCore/vars/flake-module.nix
|
||||
./pkgs/flake-module.nix
|
||||
./templates/flake-module.nix
|
||||
];
|
||||
|
@ -30,7 +30,7 @@ in
|
||||
};
|
||||
|
||||
# Run: nix-unit --extra-experimental-features flakes --flake .#legacyPackages.x86_64-linux.evalTests
|
||||
legacyPackages.evalTests = import ./tests {
|
||||
legacyPackages.evalTests-inventory = import ./tests {
|
||||
inherit buildInventory;
|
||||
clan-core = self;
|
||||
};
|
||||
@ -42,7 +42,7 @@ in
|
||||
nix-unit --eval-store "$HOME" \
|
||||
--extra-experimental-features flakes \
|
||||
${inputOverrides} \
|
||||
--flake ${self}#legacyPackages.${system}.evalTests
|
||||
--flake ${self}#legacyPackages.${system}.evalTests-inventory
|
||||
|
||||
touch $out
|
||||
'';
|
||||
|
16
nixosModules/clanCore/vars/default.nix
Normal file
16
nixosModules/clanCore/vars/default.nix
Normal file
@ -0,0 +1,16 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.clan.core.vars = lib.mkOption {
|
||||
internal = true;
|
||||
description = ''
|
||||
Generated Variables
|
||||
|
||||
Define generators that prompt for or generate variables like facts and secrets to store, deploy, and rotate them easily.
|
||||
For example, generators can be used to:
|
||||
- prompt the user for input, like passwords or host names
|
||||
- generate secrets like private keys automatically when they are needed
|
||||
- output multiple values like private and public keys simultaneously
|
||||
'';
|
||||
type = lib.types.submoduleWith { modules = [ ./interface.nix ]; };
|
||||
};
|
||||
}
|
50
nixosModules/clanCore/vars/eval-tests/default.nix
Normal file
50
nixosModules/clanCore/vars/eval-tests/default.nix
Normal file
@ -0,0 +1,50 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
eval =
|
||||
module:
|
||||
(lib.evalModules {
|
||||
modules = [
|
||||
../default.nix
|
||||
module
|
||||
];
|
||||
}).config;
|
||||
in
|
||||
{
|
||||
single_file_single_prompt =
|
||||
let
|
||||
config = eval {
|
||||
clan.core.vars.generators.my_secret = {
|
||||
files.password = { };
|
||||
files.username.secret = false;
|
||||
prompts.prompt1 = { };
|
||||
script = ''
|
||||
cp $prompts/prompt1 $files/password
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
test_file_secret_by_default = {
|
||||
expr = config.clan.core.vars.generators.my_secret.files.password.secret;
|
||||
expected = true;
|
||||
};
|
||||
test_secret_value_access_raises_error = {
|
||||
expr = config.clan.core.vars.generators.my_secret.files.password.value;
|
||||
expectedError.type = "ThrownError";
|
||||
expectedError.msg = "Cannot access value of secret file";
|
||||
};
|
||||
test_public_value_access = {
|
||||
expr = config.clan.core.vars.generators.my_secret.files.username ? value;
|
||||
expected = true;
|
||||
};
|
||||
# both secret and public values must provide a path
|
||||
test_secret_has_path = {
|
||||
expr = config.clan.core.vars.generators.my_secret.files.password ? path;
|
||||
expected = true;
|
||||
};
|
||||
test_public_var_has_path = {
|
||||
expr = config.clan.core.vars.generators.my_secret.files.username ? path;
|
||||
expected = true;
|
||||
};
|
||||
};
|
||||
}
|
31
nixosModules/clanCore/vars/flake-module.nix
Normal file
31
nixosModules/clanCore/vars/flake-module.nix
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
self,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inputOverrides = builtins.concatStringsSep " " (
|
||||
builtins.map (input: " --override-input ${input} ${inputs.${input}}") (builtins.attrNames inputs)
|
||||
);
|
||||
in
|
||||
{
|
||||
perSystem =
|
||||
{ system, pkgs, ... }:
|
||||
{
|
||||
legacyPackages.evalTests-module-clan-vars = import ./eval-tests {
|
||||
inherit lib;
|
||||
clan-core = self;
|
||||
};
|
||||
checks.module-clan-vars-eval = pkgs.runCommand "tests" { nativeBuildInputs = [ pkgs.nix-unit ]; } ''
|
||||
export HOME="$(realpath .)"
|
||||
|
||||
nix-unit --eval-store "$HOME" \
|
||||
--extra-experimental-features flakes \
|
||||
${inputOverrides} \
|
||||
--flake ${self}#legacyPackages.${system}.evalTests-module-clan-vars
|
||||
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
}
|
105
nixosModules/clanCore/vars/interface.nix
Normal file
105
nixosModules/clanCore/vars/interface.nix
Normal file
@ -0,0 +1,105 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
bool
|
||||
enum
|
||||
listOf
|
||||
str
|
||||
submodule
|
||||
;
|
||||
options = lib.mapAttrs (_: mkOption);
|
||||
subOptions = opts: submodule { options = options opts; };
|
||||
in
|
||||
{
|
||||
options = options {
|
||||
generators = {
|
||||
type = attrsOf (subOptions {
|
||||
dependencies = {
|
||||
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 $dependencies/dep1/file1.
|
||||
'';
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
files = {
|
||||
description = ''
|
||||
A set of files to generate.
|
||||
The generator 'script' is expected to produce exactly these files under $out.
|
||||
'';
|
||||
type = attrsOf (subOptions {
|
||||
secret = {
|
||||
description = ''
|
||||
Whether the file should be treated as a secret.
|
||||
'';
|
||||
type = bool;
|
||||
default = true;
|
||||
};
|
||||
path = {
|
||||
description = ''
|
||||
The path to the file containing the content of the generated value.
|
||||
This will be set automatically
|
||||
'';
|
||||
type = str;
|
||||
readOnly = true;
|
||||
};
|
||||
value = {
|
||||
description = ''
|
||||
The content of the generated value.
|
||||
Only available if the file is not secret.
|
||||
'';
|
||||
type = str;
|
||||
default = throw "Cannot access value of secret file";
|
||||
defaultText = "Throws error because the value of a secret file is not accessible";
|
||||
};
|
||||
});
|
||||
};
|
||||
prompts = {
|
||||
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
|
||||
'';
|
||||
type = attrsOf (subOptions {
|
||||
description = {
|
||||
description = ''
|
||||
The description of the prompted value
|
||||
'';
|
||||
type = str;
|
||||
example = "SSH private key";
|
||||
};
|
||||
type = {
|
||||
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 = enum [
|
||||
"hidden"
|
||||
"line"
|
||||
"multiline"
|
||||
];
|
||||
default = "line";
|
||||
};
|
||||
});
|
||||
};
|
||||
script = {
|
||||
description = ''
|
||||
The script to run to generate the files.
|
||||
The script will be run with the following environment variables:
|
||||
- $dependencies: 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 = str;
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user