diff --git a/lib/inventory/build-inventory/interface.nix b/lib/inventory/build-inventory/interface.nix index cd7cc628a..f65ea230d 100644 --- a/lib/inventory/build-inventory/interface.nix +++ b/lib/inventory/build-inventory/interface.nix @@ -410,6 +410,48 @@ in default = { }; type = clanLib.types.uniqueDeferredSerializableModule; }; + extraModules = lib.mkOption { + description = '' + List of additionally imported `.nix` expressions. + + Supported types: + + - **Strings**: Interpreted relative to the 'directory' passed to buildClan. + - **Paths**: should be relative to the current file. + - **Any**: Nix expression must be serializable to JSON. + + !!! Note + **The import only happens if the machine is part of the service or role.** + + Other types are passed through to the nixos configuration. + + ???+ Example + To import the `special.nix` file + + ``` + . Clan Directory + ├── flake.nix + ... + └── modules + ├── special.nix + └── ... + ``` + + ```nix + { + extraModules = [ "modules/special.nix" ]; + } + ``` + ''; + apply = value: if lib.isString value then value else builtins.seq (builtins.toJSON value) value; + default = [ ]; + type = types.listOf ( + types.oneOf [ + types.str + types.anything + ] + ); + }; }; } ); diff --git a/lib/inventory/distributed-service/inventory-adapter.nix b/lib/inventory/distributed-service/inventory-adapter.nix index 1aa157b6a..a5645f217 100644 --- a/lib/inventory/distributed-service/inventory-adapter.nix +++ b/lib/inventory/distributed-service/inventory-adapter.nix @@ -188,7 +188,7 @@ in # This is the list of nixosModules for each machine machineImports = lib.foldlAttrs ( acc: _module_ident: eval: - acc ++ [ eval.config.result.final.${machineName}.nixosModule or {}] + acc ++ [ eval.config.result.final.${machineName}.nixosModule or { } ] ) [ ] importedModulesEvaluated; }) inventory.machines; in diff --git a/lib/inventory/distributed-service/service-module.nix b/lib/inventory/distributed-service/service-module.nix index e92b53da1..efdd5fe93 100644 --- a/lib/inventory/distributed-service/service-module.nix +++ b/lib/inventory/distributed-service/service-module.nix @@ -214,6 +214,11 @@ in description = "Settings of 'role': ${name}"; default = { }; }; + + options.extraModules = lib.mkOption { + default = [ ]; + type = types.listOf (types.deferredModule); + }; } ) ]; @@ -405,12 +410,43 @@ in # Intermediate result by mapping over the 'roles', 'instances', and 'machines'. # During this step the 'perMachine' and 'perInstance' are applied. # The result-set for a single machine can then be found by collecting all 'nixosModules' recursively. + + /** + allRoles :: { + :: { + allInstances :: { + :: { + allMachines :: { + :: { + nixosModule :: NixOSModule; + services :: { }; # TODO: nested services + }; + }; + }; + }; + }; + } + */ result.allRoles = mkOption { readOnly = true; default = lib.mapAttrs (roleName: roleCfg: { allInstances = lib.mapAttrs (instanceName: instanceCfg: { allMachines = lib.mapAttrs ( - machineName: _machineCfg: roleCfg.perInstance instanceName machineName + machineName: _machineCfg: + let + instanceRes = roleCfg.perInstance instanceName machineName; + in + { + nixosModule = { + imports = [ + # Result of the applied 'perInstance = {...}: { nixosModule = { ... }; }' + instanceRes.nixosModule + ] ++ instanceCfg.roles.${roleName}.extraModules; + }; + # TODO: nested services + services = { }; + } + ) instanceCfg.roles.${roleName}.machines or { }; }) config.instances; }) config.roles; @@ -434,6 +470,9 @@ in ) [ ] instance.roles ); # The service machines are defined by collecting all instance machines + # returns "allMachines" that are part of the service in the form: + # serviceMachines :: { ${machineName} :: MachineOrigin; } + # MachineOrigin :: { instances :: [ string ]; roles :: [ string ]; } serviceMachines = lib.foldlAttrs ( acc: instanceName: instance: acc @@ -470,8 +509,6 @@ in default = lib.mapAttrs ( machineName: machineResult: let - # config.result.allRoles.client.allInstances.bar.allMachines.test - # instanceResults = config.result.allRoles.client.allInstances.bar.allMachines.${machineName}; instanceResults = lib.foldlAttrs ( acc: roleName: role: acc