From 2e55028a1b12e6d8e8659bee7a3749133af5b4a3 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Thu, 30 Oct 2025 11:48:13 +0100 Subject: [PATCH] services: move into clan submodule --- .../all-services-wrapper.nix | 3 +- .../distributed-service/inventory-adapter.nix | 4 +- modules/clan/default.nix | 1 + modules/clan/distributed-services.nix | 163 ++++++++++++++++++ modules/clan/module.nix | 16 +- modules/inventoryClass/default.nix | 3 - 6 files changed, 168 insertions(+), 22 deletions(-) create mode 100644 modules/clan/distributed-services.nix diff --git a/lib/inventory/distributed-service/all-services-wrapper.nix b/lib/inventory/distributed-service/all-services-wrapper.nix index 381f4c555..65cd40fb4 100644 --- a/lib/inventory/distributed-service/all-services-wrapper.nix +++ b/lib/inventory/distributed-service/all-services-wrapper.nix @@ -28,16 +28,15 @@ in elemType = submoduleWith { class = "clan.service"; specialArgs = { - exports = config.exports; directory = directory; clanLib = specialArgs.clanLib; + exports = config.exports; }; modules = [ ( { name, ... }: { _module.args._ctx = [ name ]; - } ) ./service-module.nix diff --git a/lib/inventory/distributed-service/inventory-adapter.nix b/lib/inventory/distributed-service/inventory-adapter.nix index 7c19997b3..9f4f65d0b 100644 --- a/lib/inventory/distributed-service/inventory-adapter.nix +++ b/lib/inventory/distributed-service/inventory-adapter.nix @@ -159,10 +159,10 @@ { inherit servicesEval - importedModuleWithInstances + allMachines # Exposed for testing grouped - allMachines + importedModuleWithInstances ; }; } diff --git a/modules/clan/default.nix b/modules/clan/default.nix index f35ca8b2e..10392376a 100644 --- a/modules/clan/default.nix +++ b/modules/clan/default.nix @@ -19,6 +19,7 @@ imports = [ ./top-level-interface.nix ./module.nix + ./distributed-services.nix ./checks.nix ]; } diff --git a/modules/clan/distributed-services.nix b/modules/clan/distributed-services.nix new file mode 100644 index 000000000..adcff5cca --- /dev/null +++ b/modules/clan/distributed-services.nix @@ -0,0 +1,163 @@ +{ + lib, + clanLib, + config, + clan-core, + ... +}: +let + inherit (lib) mkOption types; + # Keep a reference to top-level + clanConfig = config; + + inventory = clanConfig.inventory; + flakeInputs = clanConfig.self.inputs; + clanCoreModules = clan-core.clan.modules; + + grouped = lib.foldlAttrs ( + acc: instanceName: instance: + let + inputName = if instance.module.input == null then "" else instance.module.input; + id = inputName + "-" + instance.module.name; + in + acc + // { + ${id} = acc.${id} or [ ] ++ [ + { + inherit instanceName instance; + } + ]; + } + ) { } importedModuleWithInstances; + + importedModuleWithInstances = lib.mapAttrs ( + instanceName: instance: + let + resolvedModule = clanLib.resolveModule { + moduleSpec = instance.module; + inherit flakeInputs clanCoreModules; + }; + + # Every instance includes machines via roles + # :: { client :: ... } + instanceRoles = lib.mapAttrs ( + roleName: role: + let + resolvedMachines = clanLib.inventory.resolveTags { + members = { + # Explicit members + machines = lib.attrNames role.machines; + # Resolved Members + tags = lib.attrNames role.tags; + }; + inherit (inventory) machines; + inherit instanceName roleName; + }; + in + # instances..roles. = + # Remove "tags", they are resolved into "machines" + (removeAttrs role [ "tags" ]) + // { + machines = lib.genAttrs resolvedMachines.machines ( + machineName: + let + machineSettings = instance.roles.${roleName}.machines.${machineName}.settings or { }; + in + # TODO: tag settings + # Wait for this feature until option introspection for 'settings' is done. + # This might get too complex to handle otherwise. + # settingsViaTags = lib.filterAttrs ( + # tagName: _: machineHasTag machineName tagName + # ) instance.roles.${roleName}.tags; + { + # TODO: Do we want to wrap settings with + # setDefaultModuleLocation "inventory.instances.${instanceName}.roles.${roleName}.tags.${tagName}"; + settings = { + imports = [ + machineSettings + ]; # ++ lib.attrValues (lib.mapAttrs (_tagName: v: v.settings) settingsViaTags); + }; + } + ); + } + ) instance.roles; + in + { + inherit (instance) module; + inherit resolvedModule instanceRoles; + } + ) inventory.instances or { }; +in +{ + _class = "clan"; + options._services = mkOption { + visible = false; + description = '' + All service instances + + !!! Danger "Internal API" + Do not rely on this API yet. + + - Will be renamed to just 'services' in the future. + Once the name can be claimed again. + - Structure will change. + + API will be declared as public after beeing simplified. + ''; + type = types.submoduleWith { + # TODO: Remove specialArgs + specialArgs = { + inherit clanLib; + }; + modules = [ + (import ../../lib/inventory/distributed-service/all-services-wrapper.nix { + inherit (clanConfig) directory; + }) + # Dependencies + { + exportsModule = clanConfig.exportsModule; + } + { + # TODO: Rename to "allServices" + # All services + mappedServices = lib.mapAttrs (_module_ident: instances: { + imports = [ + # Import the resolved module. + # i.e. clan.modules.admin + { + options.module = lib.mkOption { + type = lib.types.raw; + default = (builtins.head instances).instance.module; + }; + } + (builtins.head instances).instance.resolvedModule + ] # Include all the instances that correlate to the resolved module + ++ (builtins.map (v: { + instances.${v.instanceName}.roles = v.instance.instanceRoles; + }) instances); + }) grouped; + } + ]; + }; + default = { }; + }; + options._allMachines = mkOption { + internal = true; + type = types.raw; + default = lib.mapAttrs (machineName: _: { + # This is the list of nixosModules for each machine + machineImports = lib.foldlAttrs ( + acc: _module_ident: serviceModule: + acc ++ [ serviceModule.result.final.${machineName}.nixosModule or { } ] + ) [ ] config._services.mappedServices; + }) inventory.machines or { }; + }; + + config = { + clanInternals.inventoryClass.machines = config._allMachines; + # clanInternals.inventoryClass.distributedServices = config._services; + + # Exports from distributed services + exports = config._services.exports; + }; +} diff --git a/modules/clan/module.nix b/modules/clan/module.nix index ab433b68a..26739055c 100644 --- a/modules/clan/module.nix +++ b/modules/clan/module.nix @@ -219,8 +219,6 @@ in inherit nixosConfigurations; inherit darwinConfigurations; - exports = config.clanInternals.inventoryClass.distributedServices.servicesEval.config.exports; - clanInternals = { inventoryClass = let @@ -254,21 +252,9 @@ in exportsModule = config.exportsModule; } ( - { config, ... }: + { ... }: { staticModules = clan-core.clan.modules; - - distributedServices = clanLib.inventory.mapInstances { - inherit (config) - inventory - directory - flakeInputs - exportsModule - ; - clanCoreModules = clan-core.clan.modules; - prefix = [ "distributedServices" ]; - }; - machines = config.distributedServices.allMachines; } ) ]; diff --git a/modules/inventoryClass/default.nix b/modules/inventoryClass/default.nix index 20893aaa6..f355e9533 100644 --- a/modules/inventoryClass/default.nix +++ b/modules/inventoryClass/default.nix @@ -67,9 +67,6 @@ in type = types.raw; }; - distributedServices = mkOption { - type = types.raw; - }; inventory = mkOption { type = types.raw; };