From 9e4277b970d96ddc1c2bbe4686757ae761baa18a Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 6 Jun 2022 23:46:39 +0200 Subject: [PATCH] nixos/testing/network.nix: Fix for specialisations and specialArgs.name Before this, it relied on being able to `imports` from the `name` module argument, which wasn't really necessary and required a potentially quite breaking change. We can revert that now. --- nixos/lib/testing/network.nix | 161 +++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 62 deletions(-) diff --git a/nixos/lib/testing/network.nix b/nixos/lib/testing/network.nix index dfdd9b8314a..c87abee30c9 100644 --- a/nixos/lib/testing/network.nix +++ b/nixos/lib/testing/network.nix @@ -1,75 +1,112 @@ { lib, nodes, ... }: -with lib; - - let - machines = attrNames nodes; + inherit (lib) + attrNames concatMap concatMapStrings flip forEach head + listToAttrs mkDefault mkOption nameValuePair optionalString + range types zipListsWith zipLists + ; - machinesNumbered = zipLists machines (range 1 254); + nodeNumbers = + listToAttrs + (zipListsWith + nameValuePair + (attrNames nodes) + (range 1 254) + ); - nodes_ = forEach machinesNumbered (m: nameValuePair m.fst - [ - ({ config, nodes, pkgs, ... }: - let - interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); - interfaces = forEach interfacesNumbered ({ fst, snd }: - nameValuePair "eth${toString snd}" { - ipv4.addresses = - [{ - address = "192.168.${toString fst}.${toString m.snd}"; - prefixLength = 24; - }]; - }); + networkModule = { config, nodes, pkgs, ... }: + let + interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); + interfaces = forEach interfacesNumbered ({ fst, snd }: + nameValuePair "eth${toString snd}" { + ipv4.addresses = + [{ + address = "192.168.${toString fst}.${toString config.virtualisation.test.nodeNumber}"; + prefixLength = 24; + }]; + }); - networkConfig = - { - networking.hostName = mkDefault m.fst; - - networking.interfaces = listToAttrs interfaces; - - networking.primaryIPAddress = - optionalString (interfaces != [ ]) (head (head interfaces).value.ipv4.addresses).address; - - # Put the IP addresses of all VMs in this machine's - # /etc/hosts file. If a machine has multiple - # interfaces, use the IP address corresponding to - # the first interface (i.e. the first network in its - # virtualisation.vlans option). - networking.extraHosts = flip concatMapStrings machines - (m': - let config = getAttr m' nodes; in - optionalString (config.networking.primaryIPAddress != "") - ("${config.networking.primaryIPAddress} " + - optionalString (config.networking.domain != null) - "${config.networking.hostName}.${config.networking.domain} " + - "${config.networking.hostName}\n")); - - virtualisation.qemu.options = - let qemu-common = import ../qemu-common.nix { inherit lib pkgs; }; - in - flip concatMap interfacesNumbered - ({ fst, snd }: qemu-common.qemuNICFlags snd fst m.snd); - }; - - in + networkConfig = { - key = "ip-address"; - config = networkConfig // { - # Expose the networkConfig items for tests like nixops - # that need to recreate the network config. - system.build.networkConfig = networkConfig; - }; - } - ) - ]); + networking.hostName = mkDefault config.virtualisation.test.nodeName; + + networking.interfaces = listToAttrs interfaces; + + networking.primaryIPAddress = + optionalString (interfaces != [ ]) (head (head interfaces).value.ipv4.addresses).address; + + # Put the IP addresses of all VMs in this machine's + # /etc/hosts file. If a machine has multiple + # interfaces, use the IP address corresponding to + # the first interface (i.e. the first network in its + # virtualisation.vlans option). + networking.extraHosts = flip concatMapStrings (attrNames nodes) + (m': + let config = nodes.${m'}; in + optionalString (config.networking.primaryIPAddress != "") + ("${config.networking.primaryIPAddress} " + + optionalString (config.networking.domain != null) + "${config.networking.hostName}.${config.networking.domain} " + + "${config.networking.hostName}\n")); + + virtualisation.qemu.options = + let qemu-common = import ../qemu-common.nix { inherit lib pkgs; }; + in + flip concatMap interfacesNumbered + ({ fst, snd }: qemu-common.qemuNICFlags snd fst config.virtualisation.test.nodeNumber); + }; + + in + { + key = "ip-address"; + config = networkConfig // { + # Expose the networkConfig items for tests like nixops + # that need to recreate the network config. + system.build.networkConfig = networkConfig; + }; + }; + + nodeNumberModule = (regular@{ config, name, ... }: { + options = { + virtualisation.test.nodeName = mkOption { + internal = true; + default = name; + # We need to force this in specilisations, otherwise it'd be + # readOnly = true; + description = '' + The `name` in `nodes.`; stable across `specialisations`. + ''; + }; + virtualisation.test.nodeNumber = mkOption { + internal = true; + type = types.int; + readOnly = true; + default = nodeNumbers.${config.virtualisation.test.nodeName}; + description = '' + A unique number assigned for each node in `nodes`. + ''; + }; + + # specialisations override the `name` module argument, + # so we push the real `virtualisation.test.nodeName`. + specialisation = mkOption { + type = types.attrsOf (types.submodule { + options.configuration = mkOption { + type = types.submodule ({ + config.virtualisation.test.nodeName = + # assert regular.config.virtualisation.test.nodeName != "configuration"; + regular.config.virtualisation.test.nodeName; + }); + }; + }); + }; + }; + }); - extraNodeConfigs = lib.listToAttrs nodes_; in { config = { - defaults = { config, name, ... }: { - imports = extraNodeConfigs.${name}; - }; + defaults = { imports = [ networkModule nodeNumberModule ]; }; }; }