Adding mkip.
This commit is contained in:
parent
633a9c1856
commit
551b401efa
2 changed files with 571 additions and 0 deletions
139
flake.nix
Normal file
139
flake.nix
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
{
|
||||||
|
description = "Metanix static flake: meta.nix → addressing, deploy-rs, disko, nixos-anywhere";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||||
|
deploy-rs.url = "github:serokell/deploy-rs";
|
||||||
|
disko.url = "github:nix-community/disko";
|
||||||
|
nixos-anywhere.url = "github:numtide/nixos-anywhere";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, deploy-rs, disko, nixos-anywhere, ... }:
|
||||||
|
let
|
||||||
|
# Default architecture if meta.nix doesn't say otherwise
|
||||||
|
system = "x86_64-linux";
|
||||||
|
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
|
||||||
|
lib = pkgs.lib;
|
||||||
|
|
||||||
|
# Your mkIp / mkHostsFromSpec / mkSubnetsFromSpec, etc.
|
||||||
|
# This expects: lib/addressing/default.nix
|
||||||
|
addressing = import ./lib/addressing {
|
||||||
|
inherit lib;
|
||||||
|
};
|
||||||
|
|
||||||
|
# User-provided world model.
|
||||||
|
meta = import ./meta.nix;
|
||||||
|
|
||||||
|
# Uses your rewritten mkNetworkFromSpec that understands meta.nix shape.
|
||||||
|
network = addressing.mkNetworkFromSpec meta;
|
||||||
|
|
||||||
|
# Optional: meta.systems = { hostName = { system = "..."; modules = [ ... ]; ... }; ...; }
|
||||||
|
systemsFromMeta = meta.systems or { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
#######################
|
||||||
|
# Library-style exports
|
||||||
|
#######################
|
||||||
|
lib = {
|
||||||
|
metanix = {
|
||||||
|
inherit meta network addressing;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# Per-host NixOS configs
|
||||||
|
#
|
||||||
|
# Driven by meta.systems if present. Shape example:
|
||||||
|
# meta.systems = {
|
||||||
|
# deimos = {
|
||||||
|
# system = "x86_64-linux";
|
||||||
|
# modules = [ ./hosts/deimos.nix ];
|
||||||
|
# diskoConfig = ./disko/deimos.nix; # optional
|
||||||
|
# deployHost = "deimos.kasear.net"; # optional
|
||||||
|
# deployUser = "root"; # optional
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
#############################
|
||||||
|
nixosConfigurations =
|
||||||
|
lib.mapAttrs
|
||||||
|
(name: sysCfg:
|
||||||
|
let
|
||||||
|
systemForHost = sysCfg.system or system;
|
||||||
|
|
||||||
|
pkgsForHost = import nixpkgs {
|
||||||
|
inherit systemForHost;
|
||||||
|
};
|
||||||
|
|
||||||
|
hostLib = pkgsForHost.lib;
|
||||||
|
|
||||||
|
# Optional disko module wiring if sysCfg.diskoConfig exists.
|
||||||
|
diskoModule =
|
||||||
|
if sysCfg ? diskoConfig then
|
||||||
|
{ imports = [ disko.nixosModules.disko sysCfg.diskoConfig ]; }
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
in
|
||||||
|
hostLib.nixosSystem {
|
||||||
|
system = systemForHost;
|
||||||
|
modules =
|
||||||
|
(sysCfg.modules or [ ]) ++ [
|
||||||
|
diskoModule
|
||||||
|
({ ... }: {
|
||||||
|
_module.args = {
|
||||||
|
inherit meta network addressing;
|
||||||
|
hostName = name;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
})
|
||||||
|
systemsFromMeta;
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# deploy-rs integration
|
||||||
|
#
|
||||||
|
# Builds deploy.nodes using meta.systems + addressing.
|
||||||
|
########################################
|
||||||
|
deploy = {
|
||||||
|
nodes =
|
||||||
|
lib.mapAttrs
|
||||||
|
(name: sysCfg:
|
||||||
|
let
|
||||||
|
hasNetworkHost = builtins.hasAttr name network.hosts;
|
||||||
|
hostInfo = if hasNetworkHost then network.hosts.${name} else null;
|
||||||
|
|
||||||
|
defaultHostname =
|
||||||
|
if hasNetworkHost then hostInfo.fqdn else "${name}.${meta.domain}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
hostname = sysCfg.deployHost or defaultHostname;
|
||||||
|
|
||||||
|
profiles.system = {
|
||||||
|
user = sysCfg.deployUser or "root";
|
||||||
|
path =
|
||||||
|
deploy-rs.lib.${system}.activate.nixos
|
||||||
|
self.nixosConfigurations.${name};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
systemsFromMeta;
|
||||||
|
};
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# deploy-rs sanity checks
|
||||||
|
########################################
|
||||||
|
checks.${system}.deploy =
|
||||||
|
deploy-rs.lib.${system}.deployChecks self.deploy;
|
||||||
|
|
||||||
|
########################################
|
||||||
|
# nixos-anywhere convenience app
|
||||||
|
########################################
|
||||||
|
apps.${system}.nixos-anywhere = {
|
||||||
|
type = "app";
|
||||||
|
program =
|
||||||
|
"${nixos-anywhere.packages.${system}.nixos-anywhere}/bin/nixos-anywhere";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
432
lib/addressing/default.nix
Normal file
432
lib/addressing/default.nix
Normal file
|
|
@ -0,0 +1,432 @@
|
||||||
|
{ lib ? import <nixpkgs/lib> { } }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
assertMsg
|
||||||
|
attrNames
|
||||||
|
concatMapAttrs
|
||||||
|
concatStringsSep
|
||||||
|
listToAttrs
|
||||||
|
nameValuePair
|
||||||
|
optionalAttrs
|
||||||
|
imap1
|
||||||
|
mapAttrs'
|
||||||
|
imap0
|
||||||
|
length
|
||||||
|
filter
|
||||||
|
findFirst
|
||||||
|
toLower;#
|
||||||
|
|
||||||
|
|
||||||
|
mkInitials =
|
||||||
|
name:
|
||||||
|
let
|
||||||
|
lower = toLower name; # was builtins.toLower
|
||||||
|
noApos = builtins.replaceStrings [ "'" ] [ " " ] lower;
|
||||||
|
words = filter (w: w != "") (builtins.split " +" noApos);
|
||||||
|
letters =
|
||||||
|
concatStringsSep ""
|
||||||
|
(builtins.map (w: builtins.substring 0 1 w) words);
|
||||||
|
in
|
||||||
|
if letters == "" then "loc" else builtins.substring 0 3 letters;
|
||||||
|
|
||||||
|
mkLocationCode =
|
||||||
|
name:
|
||||||
|
let
|
||||||
|
base = mkInitials name;
|
||||||
|
hash = builtins.substring 0 4 (builtins.hashString "sha256" name);
|
||||||
|
in
|
||||||
|
"${base}-${hash}";
|
||||||
|
|
||||||
|
# Manual elemIndex so we don't care what nixpkgs version you're on
|
||||||
|
elemIndex =
|
||||||
|
name: list:
|
||||||
|
let
|
||||||
|
idxs = imap0 (i: v: if v == name then i else null) list;
|
||||||
|
in
|
||||||
|
findFirst (i: i != null) null idxs;
|
||||||
|
|
||||||
|
subnetTypes = {
|
||||||
|
dmz = 0;
|
||||||
|
main = 1;
|
||||||
|
guest = 2;
|
||||||
|
iot = 3;
|
||||||
|
storage = 4;
|
||||||
|
management = 5;
|
||||||
|
infra = 6;
|
||||||
|
lab = 7;
|
||||||
|
};
|
||||||
|
|
||||||
|
roles = {
|
||||||
|
coreServer = 0;
|
||||||
|
router = 1;
|
||||||
|
infraDevice = 2;
|
||||||
|
server = 3;
|
||||||
|
workstation = 4;
|
||||||
|
thinClient = 5;
|
||||||
|
printer = 6;
|
||||||
|
nas = 7;
|
||||||
|
phone = 8;
|
||||||
|
camera = 9;
|
||||||
|
mobile = 10;
|
||||||
|
guestClient = 11;
|
||||||
|
appliance = 12;
|
||||||
|
automation = 13;
|
||||||
|
oobMgmt = 14;
|
||||||
|
hypervisor = 15;
|
||||||
|
containerHost = 16;
|
||||||
|
monitoring = 17;
|
||||||
|
logging = 18;
|
||||||
|
identity = 19;
|
||||||
|
labDevice = 20;
|
||||||
|
adminWorkstation = 21;
|
||||||
|
repoMirror = 22;
|
||||||
|
ci = 23;
|
||||||
|
media = 24;
|
||||||
|
homeAutomation = 25;
|
||||||
|
pool = 31;
|
||||||
|
};
|
||||||
|
|
||||||
|
subnetSlugs = {
|
||||||
|
dmz = "dmz";
|
||||||
|
main = "main";
|
||||||
|
guest = "guest";
|
||||||
|
iot = "iot";
|
||||||
|
storage = "storage";
|
||||||
|
management = "mgmt";
|
||||||
|
infra = "infra";
|
||||||
|
lab = "lab";
|
||||||
|
};
|
||||||
|
|
||||||
|
roleSlugs = {
|
||||||
|
coreServer = "core";
|
||||||
|
router = "router";
|
||||||
|
infraDevice = "infra-dev";
|
||||||
|
server = "server";
|
||||||
|
workstation = "ws";
|
||||||
|
thinClient = "thin";
|
||||||
|
printer = "printer";
|
||||||
|
nas = "nas";
|
||||||
|
phone = "phone";
|
||||||
|
camera = "camera";
|
||||||
|
mobile = "mobile";
|
||||||
|
guestClient = "guest";
|
||||||
|
appliance = "appliance";
|
||||||
|
automation = "automation";
|
||||||
|
oobMgmt = "oobm";
|
||||||
|
hypervisor = "hypervisor";
|
||||||
|
containerHost = "container";
|
||||||
|
monitoring = "monitoring";
|
||||||
|
logging = "logging";
|
||||||
|
identity = "identity";
|
||||||
|
labDevice = "lab-dev";
|
||||||
|
adminWorkstation = "admin-ws";
|
||||||
|
repoMirror = "mirror";
|
||||||
|
ci = "ci";
|
||||||
|
media = "media";
|
||||||
|
homeAutomation = "home-auto";
|
||||||
|
pool = "dhcp-pool";
|
||||||
|
};
|
||||||
|
|
||||||
|
thirdOctet =
|
||||||
|
{ type, role }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (type >= 0 && type <= 7)
|
||||||
|
"metatron-addressing: type must be in 0..7, got ${toString type}";
|
||||||
|
__ = assertMsg (role >= 0 && role <= 31)
|
||||||
|
"metatron-addressing: role must be in 0..31, got ${toString role}";
|
||||||
|
in
|
||||||
|
type * 32 + role;
|
||||||
|
|
||||||
|
decodeThirdOctet =
|
||||||
|
octet:
|
||||||
|
let
|
||||||
|
_ = assertMsg (octet >= 0 && octet <= 255)
|
||||||
|
"metatron-addressing: octet must be in 0..255, got ${toString octet}";
|
||||||
|
type = builtins.div octet 32;
|
||||||
|
role = octet - (type * 32);
|
||||||
|
in
|
||||||
|
{ inherit type role; };
|
||||||
|
|
||||||
|
mkIp =
|
||||||
|
{ location, type, role, host }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (location >= 0 && location <= 255)
|
||||||
|
"metatron-addressing: location must be in 0..255, got ${toString location}";
|
||||||
|
__ = assertMsg (host >= 0 && host <= 255)
|
||||||
|
"metatron-addressing: host must be in 0..255, got ${toString host}";
|
||||||
|
oct3 = thirdOctet { inherit type role; };
|
||||||
|
in
|
||||||
|
"10.${toString location}.${toString oct3}.${toString host}";
|
||||||
|
|
||||||
|
mkRoleRange =
|
||||||
|
{ location, type, role }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (location >= 0 && location <= 255)
|
||||||
|
"metatron-addressing: location must be in 0..255, got ${toString location}";
|
||||||
|
__ = assertMsg (type >= 0 && type <= 7)
|
||||||
|
"metatron-addressing: type must be in 0..7, got ${toString type}";
|
||||||
|
___ = assertMsg (role >= 0 && role <= 31)
|
||||||
|
"metatron-addressing: role must be in 0..31, got ${toString role}";
|
||||||
|
|
||||||
|
oct3 = thirdOctet { inherit type role; };
|
||||||
|
base = "10.${toString location}.${toString oct3}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
start = "${base}.0";
|
||||||
|
end = "${base}.255";
|
||||||
|
};
|
||||||
|
|
||||||
|
mkRoleRangeNamed =
|
||||||
|
{ location, typeName, roleName }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (subnetTypes ? typeName)
|
||||||
|
"metatron-addressing: unknown subnet type '${typeName}'";
|
||||||
|
__ = assertMsg (roles ? roleName)
|
||||||
|
"metatron-addressing: unknown role '${roleName}'";
|
||||||
|
|
||||||
|
type = subnetTypes.${typeName};
|
||||||
|
role = roles.${roleName};
|
||||||
|
in
|
||||||
|
mkRoleRange { inherit location type role; };
|
||||||
|
|
||||||
|
mkIpNamed =
|
||||||
|
{ location, typeName, roleName, host }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (subnetTypes ? typeName)
|
||||||
|
"metatron-addressing: unknown subnet type '${typeName}'";
|
||||||
|
__ = assertMsg (roles ? roleName)
|
||||||
|
"metatron-addressing: unknown role '${roleName}'";
|
||||||
|
|
||||||
|
type = subnetTypes.${typeName};
|
||||||
|
role = roles.${roleName};
|
||||||
|
in
|
||||||
|
mkIp { inherit location host type role; };
|
||||||
|
|
||||||
|
mkSubnet =
|
||||||
|
{ location, type }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (location >= 0 && location <= 255)
|
||||||
|
"metatron-addressing: location must be in 0..255, got ${toString location}";
|
||||||
|
__ = assertMsg (type >= 0 && type <= 7)
|
||||||
|
"metatron-addressing: type must be in 0..7, got ${toString type}";
|
||||||
|
oct3 = type * 32;
|
||||||
|
in
|
||||||
|
"10.${toString location}.${toString oct3}.0/19";
|
||||||
|
|
||||||
|
mkSubnetNamed =
|
||||||
|
{ location, typeName }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (subnetTypes ? typeName)
|
||||||
|
"metatron-addressing: unknown subnet type '${typeName}'";
|
||||||
|
type = subnetTypes.${typeName};
|
||||||
|
in
|
||||||
|
mkSubnet { inherit location type; };
|
||||||
|
|
||||||
|
mkVlan =
|
||||||
|
{ location, type }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (location >= 0 && location <= 255)
|
||||||
|
"metatron-addressing: location must be in 0..255, got ${toString location}";
|
||||||
|
__ = assertMsg (type >= 0 && type <= 7)
|
||||||
|
"metatron-addressing: type must be in 0..7, got ${toString type}";
|
||||||
|
in
|
||||||
|
(location * 8) + type + 2;
|
||||||
|
|
||||||
|
mkVlanNamed =
|
||||||
|
{ location, typeName }:
|
||||||
|
let
|
||||||
|
_ = assertMsg (subnetTypes ? typeName)
|
||||||
|
"metatron-addressing: unknown subnet type '${typeName}'";
|
||||||
|
type = subnetTypes.${typeName};
|
||||||
|
in
|
||||||
|
mkVlan { inherit location type; };
|
||||||
|
|
||||||
|
# locationName → numeric id (0, 1, 2, …)
|
||||||
|
locationIdForSpec =
|
||||||
|
spec:
|
||||||
|
let
|
||||||
|
locations =
|
||||||
|
spec.locations or(throw "metatron-addressing: spec.locations is required");
|
||||||
|
locationNames = attrNames locations;
|
||||||
|
in
|
||||||
|
name:
|
||||||
|
let
|
||||||
|
idx = elemIndex name locationNames;
|
||||||
|
in
|
||||||
|
if idx == null then
|
||||||
|
throw "metatron-addressing: unknown location '${name}'"
|
||||||
|
else
|
||||||
|
idx;
|
||||||
|
|
||||||
|
# Just the host map: { deimos = { ip-address = "..."; fqdn = "..."; ... }; ... }
|
||||||
|
mkHostsFromSpec =
|
||||||
|
spec:
|
||||||
|
let
|
||||||
|
locations =
|
||||||
|
spec.locations or (throw "metatron-addressing: spec.locations is required");
|
||||||
|
locationId = locationIdForSpec spec;
|
||||||
|
domain =
|
||||||
|
spec.domain or (throw "metatron-addressing: spec.domain is required for FQDN generation");
|
||||||
|
in
|
||||||
|
concatMapAttrs
|
||||||
|
(locationName: locCfg:
|
||||||
|
let
|
||||||
|
loc = locationId locationName;
|
||||||
|
locCode = mkLocationCode locationName;
|
||||||
|
|
||||||
|
# Strip meta-level hints; what’s left are subnets (main, dmz, etc.)
|
||||||
|
subnets =
|
||||||
|
builtins.removeAttrs locCfg [ "owner" "admins" "users" ];
|
||||||
|
in
|
||||||
|
concatMapAttrs
|
||||||
|
(typeName: subnetCfg:
|
||||||
|
let
|
||||||
|
# New shape: subnetCfg.hosts = { hostName = { role = "..."; ... }; ... }
|
||||||
|
hostsForSubnet = subnetCfg.hosts or { };
|
||||||
|
|
||||||
|
# Only treat non-underscore-prefixed keys as hosts
|
||||||
|
hostNames =
|
||||||
|
filter (hn: builtins.substring 0 1 hn != "_") (attrNames hostsForSubnet);
|
||||||
|
in
|
||||||
|
listToAttrs (imap1
|
||||||
|
(idx: hostName:
|
||||||
|
let
|
||||||
|
hostCfg = hostsForSubnet.${hostName};
|
||||||
|
roleName = hostCfg.role;
|
||||||
|
|
||||||
|
# Count how many hosts of this role exist up to *and including* this one
|
||||||
|
roleIndex =
|
||||||
|
let
|
||||||
|
prefix = lib.lists.sublist 0 idx hostNames;
|
||||||
|
in
|
||||||
|
length (filter
|
||||||
|
(hn: (hostsForSubnet.${hn}.role or null) == roleName)
|
||||||
|
prefix);
|
||||||
|
|
||||||
|
hostId = hostCfg.hostId or roleIndex;
|
||||||
|
|
||||||
|
ip = mkIpNamed {
|
||||||
|
location = loc;
|
||||||
|
inherit typeName;
|
||||||
|
roleName = hostCfg.role;
|
||||||
|
host = hostId;
|
||||||
|
};
|
||||||
|
|
||||||
|
subnetSlug =
|
||||||
|
if builtins.hasAttr typeName subnetSlugs
|
||||||
|
then subnetSlugs.${typeName}
|
||||||
|
else typeName;
|
||||||
|
|
||||||
|
roleSlug =
|
||||||
|
if builtins.hasAttr roleName roleSlugs
|
||||||
|
then roleSlugs.${roleName}
|
||||||
|
else roleName;
|
||||||
|
|
||||||
|
hostnameBase = "${roleSlug}-${builtins.toString hostId}";
|
||||||
|
hostname = hostCfg.hostname or hostnameBase;
|
||||||
|
|
||||||
|
fqdn = "${hostname}.${subnetSlug}.${locCode}.${domain}";
|
||||||
|
in
|
||||||
|
nameValuePair hostName (
|
||||||
|
{
|
||||||
|
ip-address = ip;
|
||||||
|
inherit hostname fqdn;
|
||||||
|
}
|
||||||
|
// optionalAttrs (hostCfg ? hw-address) {
|
||||||
|
inherit (hostCfg) hw-address;
|
||||||
|
}
|
||||||
|
// optionalAttrs (hostCfg ? dns) {
|
||||||
|
inherit (hostCfg) dns;
|
||||||
|
}
|
||||||
|
// optionalAttrs (hostCfg ? aliases) {
|
||||||
|
inherit (hostCfg) aliases;
|
||||||
|
}
|
||||||
|
))
|
||||||
|
hostNames))
|
||||||
|
subnets)
|
||||||
|
locations;
|
||||||
|
|
||||||
|
# Subnet map: { "home-dmz" = { cidr = "..."; vlan = ...; zone = "..."; ... }; ... }
|
||||||
|
mkSubnetsFromSpec =
|
||||||
|
spec:
|
||||||
|
let
|
||||||
|
locations =
|
||||||
|
spec.locations or (throw "metatron-addressing: spec.locations is required");
|
||||||
|
locationId = locationIdForSpec spec;
|
||||||
|
domain =
|
||||||
|
spec.domain or (throw "metatron-addressing: spec.domain is required");
|
||||||
|
in
|
||||||
|
concatMapAttrs
|
||||||
|
(locationName: locCfg:
|
||||||
|
let
|
||||||
|
loc = locationId locationName;
|
||||||
|
locCode = mkLocationCode locationName;
|
||||||
|
|
||||||
|
# Strip meta-level hints; remaining attrs are subnets
|
||||||
|
subnets =
|
||||||
|
builtins.removeAttrs locCfg [ "owner" "admins" "users" ];
|
||||||
|
in
|
||||||
|
mapAttrs'
|
||||||
|
(typeName: subnetCfg:
|
||||||
|
let
|
||||||
|
hostsForSubnet = subnetCfg.hosts or { };
|
||||||
|
|
||||||
|
cidr = mkSubnetNamed { location = loc; inherit typeName; };
|
||||||
|
|
||||||
|
subnetSlug =
|
||||||
|
if builtins.hasAttr typeName subnetSlugs
|
||||||
|
then subnetSlugs.${typeName}
|
||||||
|
else typeName;
|
||||||
|
|
||||||
|
zone = "${subnetSlug}.${locCode}.${domain}";
|
||||||
|
|
||||||
|
vlan =
|
||||||
|
# Priority: explicit vlan on subnet > old-style _vlan > computed
|
||||||
|
subnetCfg.vlan or
|
||||||
|
hostsForSubnet._vlan or
|
||||||
|
(mkVlanNamed { location = loc; inherit typeName; });
|
||||||
|
in
|
||||||
|
nameValuePair
|
||||||
|
"${locationName}-${typeName}"
|
||||||
|
{
|
||||||
|
inherit cidr locationName typeName zone vlan;
|
||||||
|
})
|
||||||
|
subnets)
|
||||||
|
locations;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Combined view, if you want both
|
||||||
|
mkNetworkFromSpec =
|
||||||
|
spec:
|
||||||
|
let
|
||||||
|
domain =
|
||||||
|
spec.domain or (throw "metatron-addressing: spec.domain is required");
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit domain;
|
||||||
|
hosts = mkHostsFromSpec spec;
|
||||||
|
subnets = mkSubnetsFromSpec spec;
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit
|
||||||
|
subnetTypes
|
||||||
|
roles
|
||||||
|
thirdOctet
|
||||||
|
decodeThirdOctet
|
||||||
|
mkIp
|
||||||
|
mkIpNamed
|
||||||
|
mkSubnet
|
||||||
|
mkSubnetNamed
|
||||||
|
mkHostsFromSpec
|
||||||
|
mkSubnetsFromSpec
|
||||||
|
mkNetworkFromSpec
|
||||||
|
mkRoleRange
|
||||||
|
mkRoleRangeNamed;
|
||||||
|
|
||||||
|
# Shorthand; you were calling mkHosts before
|
||||||
|
mkHosts = mkNetworkFromSpec;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue