Inventory: generate exact schema for validation & documentation

This commit is contained in:
Johannes Kirschbauer
2024-07-14 13:30:02 +02:00
parent 3034b9ef92
commit e54101165f
8 changed files with 209 additions and 205 deletions

View File

@@ -15,7 +15,7 @@ let
};
machineRef = lib.mkOptionType {
name = "machineRef";
name = "str";
description = "Machine :: [${builtins.concatStringsSep " | " (builtins.attrNames config.machines)}]";
check = v: lib.isString v && builtins.elem v (builtins.attrNames config.machines);
merge = lib.mergeEqualOption;
@@ -29,20 +29,85 @@ let
);
tagRef = lib.mkOptionType {
name = "tagRef";
name = "str";
description = "Tags :: [${builtins.concatStringsSep " | " allTags}]";
check = v: lib.isString v && builtins.elem v allTags;
merge = lib.mergeEqualOption;
};
moduleConfig = lib.mkOption {
default = { };
type = t.attrsOf t.anything;
};
in
{
options.assertions = lib.mkOption {
type = t.listOf t.unspecified;
internal = true;
default = [ ];
options = {
assertions = lib.mkOption {
type = t.listOf t.unspecified;
internal = true;
visible = false;
default = [ ];
};
meta = metaOptions;
machines = lib.mkOption {
default = { };
type = t.attrsOf (
t.submodule {
options = {
inherit (metaOptions) name description icon;
tags = lib.mkOption {
default = [ ];
apply = lib.unique;
type = t.listOf t.str;
};
system = lib.mkOption {
default = null;
type = t.nullOr t.str;
};
};
}
);
};
services = lib.mkOption {
default = { };
type = t.attrsOf (
t.attrsOf (
t.submodule {
options.meta = metaOptions;
options.config = moduleConfig;
options.machines = lib.mkOption {
default = { };
type = t.attrsOf (t.submodule { options.config = moduleConfig; });
};
options.roles = lib.mkOption {
default = { };
type = t.attrsOf (
t.submodule {
options.machines = lib.mkOption {
default = [ ];
type = t.listOf machineRef;
};
options.tags = lib.mkOption {
default = [ ];
apply = lib.unique;
type = t.listOf tagRef;
};
}
);
};
}
)
);
};
};
# Smoke validation of the inventory
config.assertions =
let
# Inventory assertions
# - All referenced machines must exist in the top-level machines
serviceAssertions = lib.foldlAttrs (
ass1: serviceName: c:
ass1
@@ -60,8 +125,11 @@ in
ass2 ++ assertions
) [ ] c
) [ ] config.services;
# Machine assertions
# - A machine must define their host system
machineAssertions = map (
{ name, value }:
{ name }:
{
assertion = true;
message = "Machine ${name} should define its host system in the inventory. ()";
@@ -69,68 +137,4 @@ in
) (lib.attrsToList (lib.filterAttrs (_n: v: v.system or null == null) config.machines));
in
machineAssertions ++ serviceAssertions;
options.meta = metaOptions;
options.machines = lib.mkOption {
default = { };
type = t.attrsOf (
t.submodule {
options = {
inherit (metaOptions) name description icon;
tags = lib.mkOption {
default = [ ];
apply = lib.unique;
type = t.listOf t.str;
};
system = lib.mkOption {
default = null;
type = t.nullOr t.str;
};
};
}
);
};
options.services = lib.mkOption {
default = { };
type = t.attrsOf (
t.attrsOf (
t.submodule {
options.meta = metaOptions;
options.config = lib.mkOption {
default = { };
type = t.anything;
};
options.machines = lib.mkOption {
default = { };
type = t.attrsOf (
t.submodule {
options.config = lib.mkOption {
default = { };
type = t.anything;
};
}
);
};
options.roles = lib.mkOption {
default = { };
type = t.attrsOf (
t.submodule {
options.machines = lib.mkOption {
default = [ ];
type = t.listOf machineRef;
};
options.tags = lib.mkOption {
default = [ ];
apply = lib.unique;
type = t.listOf tagRef;
};
}
);
};
}
)
);
};
}