{ lib, self, ... }: { includeDefaults ? true, }: let optionsFromModule = mName: let eval = self.lib.evalClanModules [ mName ]; in if (eval.options.clan ? "${mName}") then eval.options.clan.${mName} else { }; modulesSchema = lib.mapAttrs ( moduleName: _: jsonLib'.parseOptions (optionsFromModule moduleName) { } ) self.clanModules; jsonLib = self.lib.jsonschema { inherit includeDefaults; }; jsonLib' = self.lib.jsonschema { inherit includeDefaults; header = { }; }; inventorySchema = jsonLib.parseModule (import ./build-inventory/interface.nix); getRoles = modulePath: let rolesDir = "${modulePath}/roles"; in if builtins.pathExists rolesDir then lib.pipe rolesDir [ builtins.readDir (lib.filterAttrs (_n: v: v == "regular")) lib.attrNames (map (fileName: lib.removeSuffix ".nix" fileName)) ] else null; # The actual schema for the inventory # !!! We cannot import the module into the interface.nix, because it would cause evaluation overhead. # Modifies: # - service...config = moduleSchema # - service...machine..config = moduleSchema # - service...roles = acutalRoles schema = let moduleToService = moduleName: moduleSchema: { type = "object"; additionalProperties = { type = "object"; additionalProperties = false; properties = { meta = inventorySchema.properties.services.additionalProperties.additionalProperties.properties.meta; config = moduleSchema; roles = { type = "object"; additionalProperties = false; required = [ ]; properties = lib.listToAttrs ( map (role: { name = role; value = inventorySchema.properties.services.additionalProperties.additionalProperties.properties.roles.additionalProperties; }) (rolesOf moduleName) ); }; machines = lib.recursiveUpdate inventorySchema.properties.services.additionalProperties.additionalProperties.properties.machines { additionalProperties.properties.config = moduleSchema; }; }; }; }; rolesOf = moduleName: let roles = getRoles self.clanModules.${moduleName}; in if roles == null then [ ] else roles; moduleServices = lib.mapAttrs moduleToService ( lib.filterAttrs (n: _v: rolesOf n != [ ]) modulesSchema ); in inventorySchema // { properties = inventorySchema.properties // { services = { type = "object"; additionalProperties = false; properties = moduleServices; }; }; }; in schema