diff --git a/flakeModules/clan.nix b/flakeModules/clan.nix index f8a60d1fb..45f5e382f 100644 --- a/flakeModules/clan.nix +++ b/flakeModules/clan.nix @@ -4,125 +4,34 @@ clan-core: lib, flake-parts-lib, inputs, - self, ... }: let inherit (lib) mkOption types; - buildClan = import ../lib/build-clan { - inherit lib clan-core; - inherit (inputs) nixpkgs; - }; - cfg = config.clan; in { - imports = [ - # TODO: figure out how to print the deprecation warning - # "${inputs.nixpkgs}/nixos/modules/misc/assertions.nix" - (lib.mkRenamedOptionModule - [ - "clan" - "clanName" - ] - [ - "clan" - "meta" - "name" - ] - ) - (lib.mkRenamedOptionModule - [ - "clan" - "clanIcon" - ] - [ - "clan" - "meta" - "icon" - ] - ) - ]; - options.clan = { - directory = mkOption { - type = types.path; - description = "The directory containing the clan subdirectory"; - default = self; # default to the directory of the flake - }; - specialArgs = mkOption { - type = types.attrsOf types.raw; - default = { }; - description = "Extra arguments to pass to nixosSystem i.e. useful to make self available"; - }; - machines = mkOption { - type = types.attrsOf types.raw; - default = { }; - description = "Allows to include machine-specific modules i.e. machines.\${name} = { ... }"; - }; - inventory = mkOption { - #type = types.submodule { imports = [ ../lib/inventory/build-inventory/interface.nix ]; }; - type = types.attrsOf types.raw; - default = { }; - description = '' - An abstract service layer for consistently configuring distributed services across machine boundaries. - See https://docs.clan.lol/concepts/inventory/ for more details. - ''; - }; - - # Checks are performed in 'buildClan' - # Not everyone uses flake-parts - meta = { - name = lib.mkOption { - type = types.nullOr types.str; - default = null; - description = "Needs to be (globally) unique, as this determines the folder name where the flake gets downloaded to."; + options.clan = lib.mkOption { + type = types.submoduleWith { + # _module.args = { + # }; + specialArgs = { + inherit clan-core; + inherit (inputs) nixpkgs; }; - icon = mkOption { - type = types.nullOr types.path; - default = null; - description = "A path to an icon to be used for the clan in the GUI"; - }; - description = mkOption { - type = types.nullOr types.str; - default = null; - description = "A short description of the clan"; - }; - }; - - pkgsForSystem = mkOption { - type = types.functionTo types.raw; - default = _system: null; - description = "A map from arch to pkgs, if specified this nixpkgs will be only imported once for each system."; + modules = [ + ../lib/build-clan/interface.nix + ../lib/build-clan/module.nix + ]; }; }; - options.flake = flake-parts-lib.mkSubmoduleOptions { - clanInternals = lib.mkOption { - type = lib.types.submodule { - options = { - inventory = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - inventoryFile = lib.mkOption { type = lib.types.unspecified; }; - clanModules = lib.mkOption { type = lib.types.attrsOf lib.types.path; }; - source = lib.mkOption { type = lib.types.path; }; - meta = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - all-machines-json = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - machines = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); }; - machinesFunc = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); }; - }; - }; - }; + options.flake = flake-parts-lib.mkSubmoduleOptions { + clanInternals = lib.mkOption { type = types.raw; }; }; config = { - flake = buildClan { - inherit (cfg) - directory - specialArgs - machines - pkgsForSystem - meta - inventory - ; - }; + flake.clanInternals = config.clan.clanInternals; + flake.nixosConfigurations = config.clan.nixosConfigurations; }; _file = __curPos.file; } diff --git a/lib/build-clan/flake-module.nix b/lib/build-clan/flake-module.nix index 87dfa7c92..13310663a 100644 --- a/lib/build-clan/flake-module.nix +++ b/lib/build-clan/flake-module.nix @@ -26,7 +26,7 @@ in buildClan = self.lib.buildClan; }; checks = { - lib-inventory-eval = pkgs.runCommand "tests" { nativeBuildInputs = [ pkgs.nix-unit ]; } '' + lib-build-clan-eval = pkgs.runCommand "tests" { nativeBuildInputs = [ pkgs.nix-unit ]; } '' export HOME="$(realpath .)" nix-unit --eval-store "$HOME" \ diff --git a/lib/build-clan/interface.nix b/lib/build-clan/interface.nix index 169a0bb6f..275aa1664 100644 --- a/lib/build-clan/interface.nix +++ b/lib/build-clan/interface.nix @@ -4,6 +4,27 @@ let in { options = { + # Required options + directory = lib.mkOption { + type = types.path; + description = "The directory containing the clan subdirectory"; + }; + + specialArgs = lib.mkOption { + type = types.attrsOf types.raw; + default = { }; + description = "Extra arguments to pass to nixosSystem i.e. useful to make self available"; + }; + + # Optional + machines = lib.mkOption { + type = types.attrsOf types.deferredModule; + default = { }; + }; + inventory = lib.mkOption { + type = types.submodule { imports = [ ../inventory/build-inventory/interface.nix ]; }; + }; + # Meta meta = { name = lib.mkOption { @@ -23,44 +44,32 @@ in }; }; - # Required options - directory = lib.mkOption { - type = types.path; - description = "The directory containing the clan subdirectory"; - }; - specialArgs = lib.mkOption { - type = types.attrsOf types.raw; - default = { }; - description = "Extra arguments to pass to nixosSystem i.e. useful to make self available"; - }; - - # Optional - machines = lib.mkOption { - type = types.attrsOf types.deferredModule; - default = { }; - }; pkgsForSystem = lib.mkOption { type = types.functionTo (types.nullOr types.attrs); default = _: null; }; - inventory = lib.mkOption { - type = types.submodule { imports = [ ../inventory/build-inventory/interface.nix ]; }; - }; # Outputs + nixosConfigurations = lib.mkOption { + type = types.lazyAttrsOf types.raw; + default = { }; + }; # flake.clanInternals clanInternals = lib.mkOption { + # type = types.raw; + # ClanInternals type = types.submodule { options = { # Those options are interfaced by the CLI - inventory = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - inventoryFile = lib.mkOption { type = lib.types.unspecified; }; - clanModules = lib.mkOption { type = lib.types.attrsOf lib.types.path; }; - source = lib.mkOption { type = lib.types.path; }; - meta = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - all-machines-json = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; }; - machines = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); }; - machinesFunc = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); }; + # We don't speficy the type here, for better performance. + inventory = lib.mkOption { type = lib.types.raw; }; + inventoryFile = lib.mkOption { type = lib.types.raw; }; + clanModules = lib.mkOption { type = lib.types.raw; }; + source = lib.mkOption { type = lib.types.raw; }; + meta = lib.mkOption { type = lib.types.raw; }; + all-machines-json = lib.mkOption { type = lib.types.raw; }; + machines = lib.mkOption { type = lib.types.raw; }; + machinesFunc = lib.mkOption { type = lib.types.raw; }; }; }; }; diff --git a/lib/build-clan/module.nix b/lib/build-clan/module.nix index b868230bb..e0e6d3473 100644 --- a/lib/build-clan/module.nix +++ b/lib/build-clan/module.nix @@ -3,11 +3,15 @@ clan-core, nixpkgs, lib, - specialArgs ? { }, ... }: let - inherit (config) directory machines pkgsForSystem; + inherit (config) + directory + machines + pkgsForSystem + specialArgs + ; # Final inventory inherit (config.clanInternals) inventory; @@ -165,10 +169,7 @@ in { imports = [ # Merge the inventory file - { clanInternals.inventory = inventoryLoaded; } - { clanInternals.inventory = config.inventory; } - # Derived meta from the merged inventory - { clanInternals.meta = config.clanInternals.inventory.meta; } + { inventory = inventoryLoaded; } ]; inherit nixosConfigurations; @@ -176,6 +177,8 @@ in clanInternals = { inherit (clan-core) clanModules; inherit inventoryFile; + inventory = config.inventory; + meta = config.inventory.meta; source = "${clan-core}"; diff --git a/lib/build-clan/old_default.nix b/lib/build-clan/old_default.nix deleted file mode 100644 index 01808d6db..000000000 --- a/lib/build-clan/old_default.nix +++ /dev/null @@ -1,306 +0,0 @@ -{ - clan-core, - nixpkgs, - lib, -}: -{ - directory, # The directory containing the machines subdirectory - specialArgs ? { }, # Extra arguments to pass to nixosSystem i.e. useful to make self available - machines ? { }, # allows to include machine-specific modules i.e. machines.${name} = { ... } - # DEPRECATED: use meta.name instead - clanName ? null, # Needs to be (globally) unique, as this determines the folder name where the flake gets downloaded to. - # DEPRECATED: use meta.icon instead - clanIcon ? null, # A path to an icon to be used for the clan, should be the same for all machines - meta ? { }, # A set containing clan meta: name :: string, icon :: string, description :: string - # A map from arch to pkgs, if specified this nixpkgs will be only imported once for each system. - # This improves performance, but all nipxkgs.* options will be ignored. - pkgsForSystem ? (_system: null), - /* - Low level inventory configuration. - Overrides the services configuration. - */ - inventory ? { }, -}: -let - # Internal inventory, this is the result of merging all potential inventory sources: - # - Default instances configured via 'services' - # - The inventory overrides - # - Machines that exist in inventory.machines - # - Machines explicitly configured via 'machines' argument - # - Machines that exist in the machines directory - # Checks on the module level: - # - Each service role must reference a valid machine after all machines are merged - - clanToInventory = - config: - { clanPath, inventoryPath }: - let - v = lib.attrByPath clanPath null config; - in - lib.optionalAttrs (v != null) (lib.setAttrByPath inventoryPath v); - - mergedInventory = - (lib.evalModules { - modules = [ - clan-core.lib.inventory.interface - { inherit meta; } - ( - if - builtins.pathExists "${directory}/inventory.json" - # Is recursively applied. Any explicit nix will override. - then - (builtins.fromJSON (builtins.readFile "${directory}/inventory.json")) - else - { } - ) - inventory - # Machines explicitly configured via 'machines' argument - { - # { ${name} :: meta // { name, tags } } - machines = lib.mapAttrs ( - name: machineConfig: - (lib.attrByPath [ - "clan" - "meta" - ] { } machineConfig) - // { - # meta.name default is the attribute name of the machine - name = lib.mkDefault ( - lib.attrByPath [ - "clan" - "meta" - "name" - ] name machineConfig - ); - } - # tags - // (clanToInventory machineConfig { - clanPath = [ - "clan" - "tags" - ]; - inventoryPath = [ "tags" ]; - }) - # system - // (clanToInventory machineConfig { - clanPath = [ - "nixpkgs" - "hostPlatform" - ]; - inventoryPath = [ "system" ]; - }) - # deploy.targetHost - // (clanToInventory machineConfig { - clanPath = [ - "clan" - "core" - "networking" - "targetHost" - ]; - inventoryPath = [ - "deploy" - "targetHost" - ]; - }) - ) machines; - } - - # Will be deprecated - { - machines = - lib.mapAttrs - ( - name: _: - # Use mkForce to make sure users migrate to the inventory system. - # When the settings.json exists the evaluation will print the deprecation warning. - lib.mkForce { - inherit name; - system = (machineSettings name).nixpkgs.hostSystem or null; - } - ) - ( - lib.filterAttrs ( - machineName: _: builtins.pathExists "${directory}/machines/${machineName}/settings.json" - ) machinesDirs - ); - } - - # Deprecated interface - (if clanName != null then { meta.name = clanName; } else { }) - (if clanIcon != null then { meta.icon = clanIcon; } else { }) - ]; - }).config; - - inherit (clan-core.lib.inventory) buildInventory; - - # map from machine name to service configuration - # { ${machineName} :: Config } - serviceConfigs = buildInventory { - inventory = mergedInventory; - inherit directory; - }; - - machinesDirs = lib.optionalAttrs (builtins.pathExists "${directory}/machines") ( - builtins.readDir (directory + /machines) - ); - - machineSettings = - machineName: - let - warn = lib.warn '' - The use of ./machines//settings.json is deprecated. - If your settings.json is empty, you can safely remove it. - !!! Consider using the inventory system. !!! - - File: ${directory + /machines/${machineName}/settings.json} - - If there are still features missing in the inventory system, please open an issue on the clan-core repository. - ''; - in - # CLAN_MACHINE_SETTINGS_FILE allows to override the settings file temporarily - # This is useful for doing a dry-run before writing changes into the settings.json - # Using CLAN_MACHINE_SETTINGS_FILE requires passing --impure to nix eval - if builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE" != "" then - warn (builtins.fromJSON (builtins.readFile (builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE"))) - else - lib.optionalAttrs (builtins.pathExists "${directory}/machines/${machineName}/settings.json") ( - warn (builtins.fromJSON (builtins.readFile (directory + /machines/${machineName}/settings.json))) - ); - - machineImports = - machineSettings: map (module: clan-core.clanModules.${module}) (machineSettings.clanImports or [ ]); - - deprecationWarnings = [ - (lib.warnIf ( - clanName != null - ) "clanName in buildClan is deprecated, please use meta.name instead." null) - (lib.warnIf (clanIcon != null) "clanIcon is deprecated, please use meta.icon instead" null) - ]; - - # TODO: remove default system once we have a hardware-config mechanism - nixosConfiguration = - { - system ? "x86_64-linux", - name, - pkgs ? null, - extraConfig ? { }, - }: - nixpkgs.lib.nixosSystem { - modules = - let - settings = machineSettings name; - in - (machineImports settings) - ++ [ - { - # Autoinclude configuration.nix and hardware-configuration.nix - imports = builtins.filter (p: builtins.pathExists p) [ - "${directory}/machines/${name}/configuration.nix" - "${directory}/machines/${name}/hardware-configuration.nix" - ]; - } - settings - clan-core.nixosModules.clanCore - extraConfig - (machines.${name} or { }) - # Inherit the inventory assertions ? - { inherit (mergedInventory) assertions; } - { imports = serviceConfigs.${name} or { }; } - ( - { - # Settings - clan.core.clanDir = directory; - # Inherited from clan wide settings - clan.core.clanName = meta.name or clanName; - clan.core.clanIcon = meta.icon or clanIcon; - - # Machine specific settings - clan.core.machineName = name; - networking.hostName = lib.mkDefault name; - nixpkgs.hostPlatform = lib.mkDefault system; - - # speeds up nix commands by using the nixpkgs from the host system (especially useful in VMs) - nix.registry.nixpkgs.to = { - type = "path"; - path = lib.mkDefault nixpkgs; - }; - } - // lib.optionalAttrs (pkgs != null) { nixpkgs.pkgs = lib.mkForce pkgs; } - ) - ]; - specialArgs = { - inherit clan-core; - } // specialArgs; - }; - - allMachines = mergedInventory.machines or { }; - - supportedSystems = [ - "x86_64-linux" - "aarch64-linux" - "riscv64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; - - nixosConfigurations = lib.mapAttrs (name: _: nixosConfiguration { inherit name; }) allMachines; - - # This instantiates nixos for each system that we support: - # configPerSystem = ..nixosConfiguration - # We need this to build nixos secret generators for each system - configsPerSystem = builtins.listToAttrs ( - builtins.map ( - system: - lib.nameValuePair system ( - lib.mapAttrs ( - name: _: - nixosConfiguration { - inherit name system; - pkgs = pkgsForSystem system; - } - ) allMachines - ) - ) supportedSystems - ); - - configsFuncPerSystem = builtins.listToAttrs ( - builtins.map ( - system: - lib.nameValuePair system ( - lib.mapAttrs ( - name: _: args: - nixosConfiguration ( - args - // { - inherit name system; - pkgs = pkgsForSystem system; - } - ) - ) allMachines - ) - ) supportedSystems - ); -in -builtins.deepSeq deprecationWarnings { - inherit nixosConfigurations; - - clanInternals = { - inherit (clan-core) clanModules; - source = "${clan-core}"; - - meta = mergedInventory.meta; - inventory = mergedInventory; - - inventoryFile = "${directory}/inventory.json"; - - # machine specifics - machines = configsPerSystem; - machinesFunc = configsFuncPerSystem; - all-machines-json = lib.mapAttrs ( - system: configs: - nixpkgs.legacyPackages.${system}.writers.writeJSON "machines.json" ( - lib.mapAttrs (_: m: m.config.system.clan.deployment.data) configs - ) - ) configsPerSystem; - }; -} diff --git a/lib/build-clan/tests.nix b/lib/build-clan/tests.nix index 366e795be..2d78f42b3 100644 --- a/lib/build-clan/tests.nix +++ b/lib/build-clan/tests.nix @@ -49,7 +49,6 @@ in inventory.meta.name = "test"; } - # Build-clan implementation ./module.nix # Explicit output, usually defined by flake-parts { options.nixosConfigurations = lib.mkOption { type = lib.types.raw; }; }