Remove clanModules

- Removes clanModules in favor of the new clanServices
- Adds a warning and link to the migration guide
This commit is contained in:
pinpox
2025-07-04 15:54:44 +02:00
parent e4949755d7
commit 35e5f4a42a
141 changed files with 83 additions and 5332 deletions

View File

@@ -158,8 +158,6 @@ in
};
config = {
inventory.modules = clan-core.clanModules;
inventory._legacyModules = clan-core.clanModules;
inventory.meta = config.meta;
outputs.moduleForMachine = lib.mkMerge [
@@ -266,7 +264,6 @@ in
# TODO: unify this interface
# We should have only clan.modules. (consistent with clan.templates)
inherit (clan-core) clanModules;
# Statically export the predefined clan modules
templates = clan-core.clan.templates;

View File

@@ -21,7 +21,6 @@ in
../../../../flakeModules
../../../../lib
../../../../nixosModules/clanCore
../../../../clanModules/borgbackup
../../../../machines
../../../../inventory.json
];

View File

@@ -32,7 +32,7 @@ let
let
inventory = evalInventory inventoryModule;
flakeInputsFixture = {
self.clan.modules = inventory.modules;
self.clan.modules = inventoryModule.modules or { };
# Example upstream module
upstream.clan.modules = {
uzzi = {
@@ -167,7 +167,7 @@ in
instances."instance_zaza" = {
module = {
name = "B";
input = "self";
input = null;
};
};
};
@@ -193,7 +193,7 @@ in
_class = "clan.service";
manifest = {
name = "network";
input = "self";
input = null;
};
# Define a role without special behavior
roles.peer = { };
@@ -222,7 +222,7 @@ in
instances."instance_zaza" = {
module = {
name = "B";
input = "self";
input = null;
};
roles.peer.tags.all = { };
};
@@ -274,7 +274,7 @@ in
instances."instance_zaza" = {
module = {
name = "B";
input = "self";
input = null;
};
roles.peer.tags.all = { };
};

View File

@@ -88,6 +88,7 @@ let
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
};

View File

@@ -65,7 +65,7 @@ let
instances."instance_zaza" = {
module = {
name = "B";
input = "self";
input = null;
};
roles.peer.tags.all = { };
};

View File

@@ -78,7 +78,6 @@ in
../../../flakeModules
../../../lib
../../../nixosModules/clanCore
../../../clanModules/borgbackup
../../../machines
../../../inventory.json
];

View File

@@ -66,7 +66,7 @@ let
];
}).options;
migratedModules = [ "admin" ];
migratedModules = [ ];
makeModuleNotFoundError =
serviceName:
@@ -121,45 +121,7 @@ let
);
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...
'';
getFrontmatter = _modulepath: _modulename: "clanModules are removed!";
in
{
inherit

View File

@@ -62,135 +62,6 @@ in
expr = eval.config.clanInternals.inventoryClass.machines;
expected = { };
};
test_inventory_role_resolve =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
roles.server.machines = [ "backup_server" ];
roles.client.machines = [
"client_1_machine"
"client_2_machine"
];
};
};
machines = {
"backup_server" = { };
"client_1_machine" = { };
"client_2_machine" = { };
};
};
};
in
{
expr = {
m1 =
(eval.config.clanInternals.inventoryClass.machines."backup_server")
.compiledServices.borgbackup.matchedRoles;
m2 =
(eval.config.clanInternals.inventoryClass.machines."client_1_machine")
.compiledServices.borgbackup.matchedRoles;
m3 =
(eval.config.clanInternals.inventoryClass.machines."client_2_machine")
.compiledServices.borgbackup.matchedRoles;
inherit
((eval.config.clanInternals.inventoryClass.machines."client_2_machine").compiledServices.borgbackup)
resolvedRolesPerInstance
;
};
expected = {
m1 = [
"server"
];
m2 = [
"client"
];
m3 = [
"client"
];
resolvedRolesPerInstance = {
instance_1 = {
client = {
machines = [
"client_1_machine"
"client_2_machine"
];
};
server = {
machines = [ "backup_server" ];
};
};
};
};
};
test_inventory_tag_resolve =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
roles.client.tags = [ "backup" ];
};
};
machines = {
"not_used_machine" = { };
"client_1_machine" = {
tags = [ "backup" ];
};
"client_2_machine" = {
tags = [ "backup" ];
};
};
};
};
in
{
expr =
eval.config.clanInternals.inventoryClass.machines.client_1_machine.compiledServices.borgbackup.resolvedRolesPerInstance;
expected = {
instance_1 = {
client = {
machines = [
"client_1_machine"
"client_2_machine"
];
};
server = {
machines = [ ];
};
};
};
};
test_inventory_multiple_roles =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
roles.client.machines = [ "machine_1" ];
roles.server.machines = [ "machine_1" ];
};
};
machines = {
"machine_1" = { };
};
};
};
in
{
expr =
eval.config.clanInternals.inventoryClass.machines.machine_1.compiledServices.borgbackup.matchedRoles;
expected = [
"client"
"server"
];
};
test_inventory_module_doesnt_exist =
let
@@ -216,84 +87,4 @@ in
msg = "ClanModule not found*";
};
};
test_inventory_role_doesnt_exist =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
roles.roleXYZ.machines = [ "machine_1" ];
};
};
machines = {
"machine_1" = { };
};
};
};
in
{
inherit eval;
expr = eval.config.clanInternals.inventoryClass.machines.machine_1.machineImports;
expectedError = {
type = "ThrownError";
msg = ''Roles \["roleXYZ"\] are not defined in the service borgbackup'';
};
};
# Needs NIX_ABORT_ON_WARN=1
# So the lib.warn is turned into abort
test_inventory_tag_doesnt_exist =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
roles.client.machines = [ "machine_1" ];
roles.client.tags = [ "tagXYZ" ];
};
};
machines = {
"machine_1" = {
tags = [ "tagABC" ];
};
};
};
};
in
{
expr = eval.config.clanInternals.inventoryClass.machines.machine_1.machineImports;
expectedError = {
type = "Error";
# TODO: Add warning matching in nix-unit
msg = ".*";
};
};
test_inventory_disabled_service =
let
eval = clan {
directory = ./.;
inventory = {
services = {
borgbackup.instance_1 = {
enabled = false;
roles.client.machines = [ "machine_1" ];
};
};
machines = {
"machine_1" = {
};
};
};
};
in
{
inherit eval;
expr = builtins.filter (
v: v != { } && !v.clan.inventory.assertions ? "alive.assertion.inventory"
) eval.config.clanInternals.inventoryClass.machines.machine_1.machineImports;
expected = [ ];
};
}

View File

@@ -104,11 +104,6 @@ in
internal = true;
visible = false;
};
_legacyModules = lib.mkOption {
internal = true;
visible = false;
default = { };
};
noInstanceOptions = lib.mkOption {
type = types.bool;
internal = true;
@@ -142,7 +137,7 @@ in
- The module MUST have at least `features = [ "inventory" ]` in the frontmatter section.
- The module MUST have a subfolder `roles` with at least one `{roleName}.nix` file.
For further information see: [Module Authoring Guide](../../guides/services/community.md).
For further information see: [Module Authoring Guide](../../guides/authoring/clanServices/index.md).
???+ example
```nix
@@ -161,26 +156,7 @@ in
```
'';
apply =
moduleSet:
let
allowedNames = lib.attrNames config._legacyModules;
in
if builtins.all (moduleName: builtins.elem moduleName allowedNames) (lib.attrNames moduleSet) then
moduleSet
else
lib.warn ''
`inventory.modules` will be deprecated soon.
Please migrate the following modules into `clan.service` modules
and register them in `clan.modules`
${lib.concatStringsSep "\n" (
map (m: "'${m}'") (lib.attrNames (lib.filterAttrs (n: _v: !builtins.elem n allowedNames) moduleSet))
)}
See: https://docs.clan.lol/guides/services/community/
'' moduleSet;
apply = _: { };
};
assertions = lib.mkOption {