{ confDir, coreLib, corePkgs }: with coreLib; let machine = import ./machine { inherit confDir corePkgs coreLib findMetaConfig; }; findMetaConfig = { cluster, name }: cluster.${name}; makeMachine = { name, metaConfig, carrier ? null, alias ? null, clusterName ? null, extraModules ? [], buildAttribute ? null }: let ensuredClusterName = if isNull clusterName then name else clusterName; in { inherit name alias metaConfig carrier extraModules; clusterName = ensuredClusterName; build = { attribute = if isNull buildAttribute then metaConfig.buildAttribute else buildAttribute; toplevel = buildConfig { name = ensuredClusterName; inherit metaConfig; }; }; }; buildConfig = { name, metaConfig }: if !metaConfig.managed then null else if metaConfig.spin == "nixos" then machine.nixos { inherit name metaConfig; } else if metaConfig.spin == "vpsadminos" then machine.vpsadminos { inherit name metaConfig; } else null; expandCarriers = machineAttrs: flatten (mapAttrsToList (name: m: if m.metaConfig.carrier.enable then [ m ] ++ (expandCarrier machineAttrs m) else m ) machineAttrs); expandCarrier = machineAttrs: carrierMachine: map (cm: makeMachine { name = "${carrierMachine.name}#${if isNull cm.alias then cm.machine else cm.alias}"; alias = cm.alias; clusterName = cm.machine; carrier = carrierMachine.name; extraModules = cm.extraModules; buildAttribute = cm.buildAttribute; metaConfig = coreLib.updateManyAttrsByPath ([ { path = [ "labels" ]; update = old: old // cm.labels; } { path = [ "tags" ]; update = old: old ++ cm.tags; } ] ++ (generationUpdates cm)) machineAttrs.${cm.machine}.metaConfig; } ) carrierMachine.metaConfig.carrier.machines; generationUpdates = cm: flatten (map (generations: map (attr: { path = [ generations attr ]; update = old: let v = cm.${generations}.${attr}; in if isNull v then old else v; }) [ "min" "max" "maxAge" ] ) [ "buildGenerations" "hostGenerations" ]); in rec { inherit corePkgs coreLib; mkNetUdevRule = name: mac: '' ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*", KERNEL=="eth*", ATTR{address}=="${mac}", NAME="${name}" ''; mkNetUdevRules = rs: concatStringsSep "\n" (mapAttrsToList (name: mac: mkNetUdevRule name mac ) rs); inherit findMetaConfig; # Return all configured machines in a list getClusterMachines = cluster: let machineAttrs = mapAttrs (name: metaConfig: makeMachine { inherit name metaConfig; } ) cluster; in expandCarriers machineAttrs; # Get IP version addresses from all machines in a cluster getAllAddressesOf = cluster: v: let machines = getClusterMachines cluster; addresses = flatten (map (machine: map (addr: machine // addr) machine.metaConfig.addresses.${"v${toString v}"} ) machines); in addresses; mkOptions = { addresses = v: { config, ... }: { options = { address = mkOption { type = types.str; description = "IPv${toString v} address"; }; prefix = mkOption { type = types.ints.positive; description = "Prefix length"; }; string = mkOption { type = types.nullOr types.str; default = null; apply = v: if isNull v then "${config.address}/${toString config.prefix}" else v; description = "Address with prefix as string"; }; }; }; }; }