diff --git a/lib/build-clan/default.nix b/lib/build-clan/default.nix index 86f5b4da1..0696a7c7c 100644 --- a/lib/build-clan/default.nix +++ b/lib/build-clan/default.nix @@ -35,5 +35,6 @@ eval { rest # implementation ./module.nix + ./imports.nix ]; } diff --git a/lib/build-clan/imports.nix b/lib/build-clan/imports.nix new file mode 100644 index 000000000..4a459bbce --- /dev/null +++ b/lib/build-clan/imports.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + ... +}: +################################## +# # +# Handle the "imports" directory # +# # +################################## + +let + inherit (config) + directory + ; + + # Check if the imports directory exists + # If it does, check if the files in the directory are allowed + importsDir = + if builtins.pathExists "${directory}/imports" then + ( + let + allowedFiles = [ + "inventory" + ]; + invalidImports = lib.filter (name: !(lib.elem name allowedFiles)) ( + builtins.attrNames (builtins.readDir "${directory}/imports") + ); + in + if invalidImports != [ ] then + builtins.throw '' + Invalid file imports/{${lib.concatStringsSep ", " invalidImports}}. + Allowed are imports/{${lib.concatStringsSep ", " allowedFiles}} + '' + else + "${directory}/imports" + ) + else + "${directory}/imports"; + + # Get the directory names in the inventory/imports directory + inventoryImportNames = + if builtins.pathExists "${importsDir}/inventory" then + let + inventoryEntries = builtins.readDir "${importsDir}/inventory"; + invalidFiles = builtins.attrNames (lib.filterAttrs (_: type: type == "regular") inventoryEntries); + in + if invalidFiles != [ ] then + builtins.throw '' + Invalid file(s) in imports/inventory/{${lib.concatStringsSep ", " invalidFiles}} + Only directories are allowed. + '' + else + builtins.attrNames (lib.filterAttrs (_: type: type == "directory") inventoryEntries) + else + [ ]; + + # Check if the roles directory exists in each inventory import + inventoryImportAttrsetWithCheck = lib.genAttrs inventoryImportNames ( + name: + let + rolesDir = "${directory}/imports/inventory/${name}/roles"; + in + if builtins.pathExists rolesDir then + rolesDir + else + builtins.throw "The module ${name} is not inventory compatible because the roles directory does not exist at ${rolesDir}" + ); +in +{ + inventory.modules = inventoryImportAttrsetWithCheck; +} diff --git a/lib/build-clan/module.nix b/lib/build-clan/module.nix index 42411857d..12128c2b6 100644 --- a/lib/build-clan/module.nix +++ b/lib/build-clan/module.nix @@ -167,6 +167,7 @@ let (builtins.fromJSON (builtins.readFile inventoryFile)) else { }; + in { imports = [ @@ -189,7 +190,9 @@ in inventory.machines = lib.mapAttrs (_n: _: { }) config.machines; } # Merge the meta attributes from the buildClan function - { inventory.modules = clan-core.clanModules; } + { + inventory.modules = clan-core.clanModules; + } # config.inventory.meta <- config.meta { inventory.meta = config.meta; } # Set default for computed tags