inventory: make sure we always define all roles, even if we don't have machines

this makes write writing modules easier

add missing roles assertions
This commit is contained in:
Jörg Thalheim
2024-10-31 14:51:55 +01:00
parent 1bd3af310e
commit 9923bfee74
2 changed files with 33 additions and 25 deletions

View File

@@ -39,11 +39,9 @@ let
checkService =
serviceName:
let
frontmatter = clan-core.lib.modules.getFrontmatter serviceName;
in
if builtins.elem "inventory" frontmatter.features or [ ] then true else false;
builtins.elem "inventory" (clan-core.lib.modules.getFrontmatter serviceName).features or [ ];
trimExtension = name: builtins.substring 0 (builtins.stringLength name - 4) name;
/*
Returns a NixOS configuration for every machine in the inventory.
@@ -65,18 +63,29 @@ let
acc2: instanceName: serviceConfig:
let
resolvedRoles = builtins.mapAttrs (
roleName: members:
roles = lib.mapAttrsToList (name: _value: trimExtension name) (
lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (
builtins.readDir (
if clan-core.clanModules ? ${serviceName} then
clan-core.clanModules.${serviceName} + "/roles"
else
throw "ClanModule not found: '${serviceName}'. Make sure the module is added in the 'clanModules' attribute of clan-core."
)
)
);
resolvedRoles = lib.genAttrs roles (
roleName:
resolveTags {
members = serviceConfig.roles.${roleName} or { };
inherit
serviceName
instanceName
roleName
inventory
members
;
}
) serviceConfig.roles;
);
isInService = builtins.any (members: builtins.elem machineName members.machines) (
builtins.attrValues resolvedRoles
@@ -98,18 +107,12 @@ let
# TODO: maybe optimize this dont lookup the role in inverse roles. Imports are not lazy
roleModules = builtins.map (
role:
let
# Check the module exists
module =
clan-core.clanModules.${serviceName}
or (throw "ClanModule not found: '${serviceName}'. Make sure the module is added in the 'clanModules' attribute of clan-core.");
path = module + "/roles/${role}.nix";
in
if builtins.pathExists path then
path
if builtins.elem role roles && clan-core.clanModules ? ${serviceName} then
clan-core.clanModules.${serviceName} + "/roles/${role}.nix"
else
throw "Module doesn't have role: '${role}'. Role: ${role}.nix not found."
throw "Module ${serviceName} doesn't have role: '${role}'. Role: ${
clan-core.clanModules.${serviceName}
}/roles/${role}.nix not found."
) machineRoles;
roleServiceConfigs = builtins.filter (m: m != { }) (
@@ -119,8 +122,14 @@ let
extraModules = map (s: if builtins.typeOf s == "string" then "${directory}/${s}" else s) (
globalExtraModules ++ machineExtraModules ++ roleServiceExtraModules
);
nonExistingRoles = builtins.filter (role: !(builtins.elem role roles)) (
builtins.attrNames (serviceConfig.roles or { })
);
in
if !(serviceConfig.enabled or true) then
if (nonExistingRoles != [ ]) then
throw "Roles ${builtins.toString nonExistingRoles} are not defined in the service ${serviceName}."
else if !(serviceConfig.enabled or true) then
acc2
else if isInService then
acc2
@@ -139,14 +148,13 @@ let
);
}
)
{
config.clan.inventory.services.${serviceName}.${instanceName} = {
({
clan.inventory.services.${serviceName}.${instanceName} = {
roles = resolvedRoles;
# TODO: Add inverseRoles to the service config if needed
# inherit inverseRoles;
};
}
})
]
else
acc2

View File

@@ -171,7 +171,7 @@ in
expr = configs;
expectedError = {
type = "ThrownError";
msg = "Module doesn't have role.*";
msg = "Roles roleXYZ are not defined in the service borgbackup.";
};
};
test_inventory_tag_doesnt_exist =