lib.values: init getPrio

This function can be used to get the priority of all values within a module
This commit is contained in:
Johannes Kirschbauer
2024-12-04 17:37:01 +01:00
parent 493e158d3c
commit de78a85324
5 changed files with 327 additions and 0 deletions

View File

@@ -15,6 +15,7 @@ in
buildClan = import ./build-clan { inherit lib nixpkgs clan-core; }; buildClan = import ./build-clan { inherit lib nixpkgs clan-core; };
facts = import ./facts.nix { inherit lib; }; facts = import ./facts.nix { inherit lib; };
inventory = import ./inventory { inherit lib clan-core; }; inventory = import ./inventory { inherit lib clan-core; };
values = import ./values { inherit lib; };
jsonschema = import ./jsonschema { inherit lib; }; jsonschema = import ./jsonschema { inherit lib; };
modules = import ./frontmatter { modules = import ./frontmatter {
inherit lib; inherit lib;

View File

@@ -9,6 +9,7 @@
./jsonschema/flake-module.nix ./jsonschema/flake-module.nix
./inventory/flake-module.nix ./inventory/flake-module.nix
./build-clan/flake-module.nix ./build-clan/flake-module.nix
./values/flake-module.nix
]; ];
flake.lib = import ./default.nix { flake.lib = import ./default.nix {
inherit lib inputs; inherit lib inputs;

90
lib/values/default.nix Normal file
View File

@@ -0,0 +1,90 @@
{
lib ? import <nixpkgs/lib>,
}:
let
filterOptions = lib.filterAttrs (
name: _:
!builtins.elem name [
"_module"
"_freeformOptions"
]
);
getPrios =
{
options,
}:
let
filteredOptions = filterOptions options;
in
lib.mapAttrs (
_: opt:
let
prio = {
__prio = opt.highestPrio;
};
subOptions = opt.type.getSubOptions opt.loc;
attrDefinitions = (lib.modules.mergeAttrDefinitionsWithPrio opt);
zipDefs = builtins.zipAttrsWith (_ns: vs: vs);
defs = zipDefs opt.definitions;
prioPerValue =
{ type, defs }:
lib.mapAttrs (
attrName: prioSet:
let
# Evaluate the submodule
options = filterOptions subOptions;
modules = (
[
{ inherit options; }
]
++ map (config: { inherit config; }) defs.${attrName}
);
submoduleEval = lib.evalModules {
inherit modules;
};
in
(lib.optionalAttrs (prioSet ? highestPrio) {
__prio = prioSet.highestPrio;
# inherit defs options;
})
// (
if type.nestedTypes.elemType.name == "submodule" then
getPrios { options = submoduleEval.options; }
else
# Nested attrsOf
(lib.optionalAttrs (type.nestedTypes.elemType.name == "attrsOf") (
prioPerValue {
type = type.nestedTypes.elemType;
defs = zipDefs defs.${attrName};
} prioSet.value
))
)
);
attributePrios = prioPerValue {
type = opt.type;
inherit defs;
} attrDefinitions;
in
if opt ? type && opt.type.name == "submodule" then
prio // (getPrios { options = subOptions; })
else if opt ? type && opt.type.name == "attrsOf" then
# prio // attributePrios
# else if
# opt ? type && opt.type.name == "attrsOf" && opt.type.nestedTypes.elemType.name == "attrsOf"
# then
# prio // attributePrios
# else if opt ? type && opt.type.name == "attrsOf" then
prio // attributePrios
else if opt ? type && opt._type == "option" then
prio
else
getPrios { options = opt; }
) filteredOptions;
in
{
inherit getPrios;
}

View File

@@ -0,0 +1,24 @@
{ self, inputs, ... }:
let
inputOverrides = builtins.concatStringsSep " " (
builtins.map (input: " --override-input ${input} ${inputs.${input}}") (builtins.attrNames inputs)
);
in
{
perSystem =
{ pkgs, system, ... }:
{
checks = {
lib-values-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-inventory
touch $out
'';
};
};
}

211
lib/values/test.nix Normal file
View File

@@ -0,0 +1,211 @@
# tests for the nixos options to jsonschema converter
# run these tests via `nix-unit ./test.nix`
{
lib ? (import <nixpkgs> { }).lib,
slib ? (import ./. { inherit lib; }),
}:
let
eval =
modules:
let
evaledConfig = lib.evalModules {
inherit modules;
};
in
evaledConfig;
in
{
test_default = {
expr = slib.getPrios {
options =
(eval [
{
options.foo.bar = lib.mkOption {
type = lib.types.bool;
description = "Test Description";
default = true;
};
}
]).options;
};
expected = {
foo.bar = {
__prio = 1500;
};
};
};
test_no_default = {
expr = slib.getPrios {
options =
(eval [
{
options.foo.bar = lib.mkOption {
type = lib.types.bool;
};
}
]).options;
};
expected = {
foo.bar = {
__prio = 9999;
};
};
};
test_submodule = {
expr = slib.getPrios {
options =
(eval [
{
options.foo = lib.mkOption {
type = lib.types.submodule {
options = {
bar = lib.mkOption {
type = lib.types.bool;
};
};
};
};
}
]).options;
};
expected = {
foo = {
# Prio of the submodule itself
__prio = 9999;
# Prio of the bar option within the submodule
bar.__prio = 9999;
};
};
};
# TODO(@hsjobeki): Cover this edge case
# test_freeform =
# let
# evaluated = (
# eval [
# {
# freeformType = with lib.types; attrsOf (int);
# options = {
# foo = lib.mkOption {
# type = lib.types.int;
# default = 0;
# };
# };
# }
# {
# bar = lib.mkForce 123;
# baz = 1;
# }
# {
# bar = 10;
# }
# ]
# );
# in
# {
# inherit evaluated;
# expr = slib.getPrios {
# options = evaluated.options;
# };
# expected = {
# };
# };
test_attrsOf_submodule =
let
evaluated = eval [
{
options.foo = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
bar = lib.mkOption {
type = lib.types.int;
default = 0;
};
};
}
);
};
config.foo = {
"nested" = {
"bar" = 2; # <- 100 prio ?
};
"other" = {
"bar" = lib.mkForce 2; # <- 50 prio ?
};
};
}
];
in
{
expr = slib.getPrios { options = evaluated.options; };
expected = {
foo.__prio = 100;
foo.nested.__prio = 100;
foo.other.__prio = 100;
foo.nested.bar.__prio = 100;
foo.other.bar.__prio = 50;
};
};
test_attrsOf_attrsOf_submodule =
let
evaluated = eval [
{
options.foo = lib.mkOption {
type = lib.types.attrsOf (
lib.types.attrsOf (
lib.types.submodule {
options = {
bar = lib.mkOption {
type = lib.types.int;
default = 0;
};
};
}
)
);
};
config.foo = {
a.b = {
bar = 1;
};
a.c = {
bar = 1;
};
x.y = {
bar = 1;
};
x.z = {
bar = 1;
};
};
}
];
in
{
inherit evaluated;
expr = slib.getPrios { options = evaluated.options; };
expected = {
foo.__prio = 100;
# Sub A
foo.a.__prio = 100;
# a.b doesnt have a prio
# a.c doesnt have a prio
foo.a.b.bar.__prio = 100;
foo.a.c.bar.__prio = 100;
# Sub X
foo.x.__prio = 100;
# x.y doesnt have a prio
# x.z doesnt have a prio
foo.x.y.bar.__prio = 100;
foo.x.z.bar.__prio = 100;
};
};
}