revert Merge pull request 'Remove clanModules/*' (#4202) from remove-modules into main Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4202 See: https://git.clan.lol/clan/clan-core/issues/4365 Not all modules are migrated. If they are not migrated, we need to write migration docs and please display the link to the migration docs
174 lines
4.8 KiB
Nix
174 lines
4.8 KiB
Nix
{ lib, clanLib }:
|
|
let
|
|
# Trim the .nix extension from a filename
|
|
trimExtension = name: builtins.substring 0 (builtins.stringLength name - 4) name;
|
|
|
|
jsonWithoutHeader = clanLib.jsonschema {
|
|
includeDefaults = true;
|
|
header = { };
|
|
};
|
|
|
|
getModulesSchema =
|
|
{
|
|
modules,
|
|
clan-core,
|
|
pkgs,
|
|
}:
|
|
lib.mapAttrs
|
|
(
|
|
_moduleName: rolesOptions:
|
|
lib.mapAttrs (_roleName: options: jsonWithoutHeader.parseOptions options { }) rolesOptions
|
|
)
|
|
(
|
|
clanLib.evalClan.evalClanModulesWithRoles {
|
|
allModules = modules;
|
|
inherit pkgs clan-core;
|
|
}
|
|
);
|
|
|
|
evalFrontmatter =
|
|
{
|
|
moduleName,
|
|
instanceName,
|
|
resolvedRoles,
|
|
allModules,
|
|
}:
|
|
lib.evalModules {
|
|
modules = [
|
|
(getFrontmatter allModules.${moduleName} moduleName)
|
|
./interface.nix
|
|
{
|
|
constraints.imports = [
|
|
(lib.modules.importApply ../constraints {
|
|
inherit moduleName resolvedRoles instanceName;
|
|
allRoles = getRoles "inventory.modules" allModules moduleName;
|
|
})
|
|
];
|
|
}
|
|
];
|
|
};
|
|
|
|
# For Documentation purposes only
|
|
frontmatterOptions =
|
|
(lib.evalModules {
|
|
modules = [
|
|
./interface.nix
|
|
{
|
|
constraints.imports = [
|
|
(lib.modules.importApply ../constraints {
|
|
resolvedRoles = { };
|
|
moduleName = "{moduleName}";
|
|
instanceName = "{instanceName}";
|
|
allRoles = [ "{roleName}" ];
|
|
})
|
|
];
|
|
}
|
|
];
|
|
}).options;
|
|
|
|
migratedModules = [ "admin" ];
|
|
|
|
makeModuleNotFoundError =
|
|
serviceName:
|
|
if builtins.elem serviceName migratedModules then
|
|
''
|
|
(Legacy) ClanModule not found: '${serviceName}'.
|
|
|
|
Please update your configuration to use this module via 'inventory.instances'
|
|
See: https://docs.clan.lol/guides/clanServices/
|
|
''
|
|
else
|
|
''
|
|
(Legacy) ClanModule not found: '${serviceName}'.
|
|
|
|
Make sure the module is added to inventory.modules.${serviceName}
|
|
'';
|
|
# This is a legacy function
|
|
# Old modules needed to define their roles by directory
|
|
# This means if this function gets anything other than a string/path it will throw
|
|
getRoles =
|
|
_scope: allModules: serviceName:
|
|
let
|
|
module = allModules.${serviceName} or (throw (makeModuleNotFoundError serviceName));
|
|
moduleType = (lib.typeOf module);
|
|
checked =
|
|
if
|
|
builtins.elem moduleType [
|
|
"string"
|
|
"path"
|
|
]
|
|
then
|
|
true
|
|
else
|
|
throw "(Legacy) ClanModule must be a 'path' or 'string' pointing to a directory: Got 'typeOf inventory.modules.${serviceName}' => ${moduleType} ";
|
|
modulePath = lib.seq checked module + "/roles";
|
|
checkedPath =
|
|
if builtins.pathExists modulePath then
|
|
modulePath
|
|
else
|
|
throw ''
|
|
(Legacy) ClanModule must have a 'roles' directory'
|
|
|
|
Fixes:
|
|
- Provide a 'roles' subdirectory
|
|
- Use the newer 'clan.service' modules. (Recommended)
|
|
'';
|
|
in
|
|
lib.seq checkedPath lib.mapAttrsToList (name: _value: trimExtension name) (
|
|
lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (
|
|
builtins.readDir (checkedPath)
|
|
)
|
|
);
|
|
|
|
checkConstraints = args: (evalFrontmatter args).config.constraints.assertions;
|
|
|
|
getReadme =
|
|
modulepath: modulename:
|
|
let
|
|
readme = modulepath + "/README.md";
|
|
readmeContents =
|
|
if (builtins.pathExists readme) then
|
|
(builtins.readFile readme)
|
|
else
|
|
throw "No README.md found for module ${modulename} (expected at ${readme})";
|
|
in
|
|
readmeContents;
|
|
|
|
getFrontmatter =
|
|
modulepath: modulename:
|
|
let
|
|
content = getReadme modulepath modulename;
|
|
parts = lib.splitString "---" content;
|
|
# Partition the parts into the first part (the readme content) and the rest (the metadata)
|
|
parsed = builtins.partition ({ index, ... }: if index >= 2 then false else true) (
|
|
lib.filter ({ index, ... }: index != 0) (lib.imap0 (index: part: { inherit index part; }) parts)
|
|
);
|
|
meta = builtins.fromTOML (builtins.head parsed.right).part;
|
|
in
|
|
if (builtins.length parts >= 3) then
|
|
meta
|
|
else
|
|
throw ''
|
|
TOML Frontmatter not found in README.md for module ${modulename}
|
|
|
|
Please add the following to the top of your README.md:
|
|
|
|
---
|
|
description = "Your description here"
|
|
categories = [ "Your categories here" ]
|
|
features = [ "inventory" ]
|
|
---
|
|
...rest of your README.md...
|
|
'';
|
|
in
|
|
{
|
|
inherit
|
|
frontmatterOptions
|
|
getModulesSchema
|
|
getFrontmatter
|
|
|
|
checkConstraints
|
|
getRoles
|
|
;
|
|
}
|