Files
nixpkgs/nixos/tests/netplan.nix
Mario Vitale ab20775a17 nixos/netplan: init module
nixos/netplan: init nixosTests.netplan
netplan: 0.106.1 -> 1.2.2

Notable changes across the two netplan versions:
- Build settings are now handled by Meson, rather than Make
- netplan now depends on systemd generators for the transient units
- netplan now installs `netplan-configure.service`
2026-07-27 20:53:43 +02:00

145 lines
5.2 KiB
Nix

{ pkgs, lib, ... }:
let
# Test by creating a "group" of interfaces: a VRF, plus a dummy interface under it, to which we'll assign an IPv6 ULA address
# This must be done for both configs under /etc ("static") and configs under /run ("dynamic"). So each test group gets an address
test-groups = {
"static" = "fd00::feed:cafe/32";
"dynamic" = "fd00::dead:beef/32";
};
# Generate link information, interface getter commands, and configuration files, to be used on all test VMs
# The variable respects the globs:
# - fixtures.{static,dynamic}.links.{vrf,dummy}.{name,getter-cmd,address} (NB: address is unavailable in 'vrf')
# - fixtures.{static,dynamic}.cfgs.{networkd,NetworkManager}.{filename,src}
fixtures = lib.mapAttrs (
group: address:
let
vrf-name = "np${group}";
in
{
links.vrf.name = "${vrf-name}";
links.vrf.getter-cmd = "ip -o link show dev ${vrf-name} type vrf";
links.dummy.name = "${vrf-name}-lo";
links.dummy.getter-cmd = "ip -o link show dev ${vrf-name}-lo type dummy master ${vrf-name}";
links.dummy.address = address;
cfgs = lib.genAttrs [ "networkd" "NetworkManager" ] (renderer: get-config-file group renderer);
}
) test-groups;
# Utility to generate netplan configuration objects
get-config-file = (
group: renderer:
let
links = fixtures.${group}.links;
content = ''
---
network:
version: 2
renderer: ${renderer}
dummy-devices:
${links.dummy.name}:
addresses: ["${links.dummy.address}"]
vrfs:
${links.vrf.name}:
table: 130
interfaces: [${links.dummy.name}]
'';
in
{
filename = "10-test-${group}-${renderer}.yaml";
src = pkgs.writeText "netplan-test-${group}-${renderer}" content;
}
);
in
{
name = "netplan";
meta.maintainers = with lib.maintainers; [
mkg20001
];
nodes = {
networkd = {
networking.useNetworkd = true;
systemd.network.enable = true;
networking.useDHCP = false;
networking.netplan.enable = true;
networking.netplan.configFiles = {
${fixtures.static.cfgs.networkd.filename} = builtins.readFile fixtures.static.cfgs.networkd.src;
};
systemd.tmpfiles.settings."netplan"."/run/netplan".d = {
user = "root";
group = "root";
mode = "0700";
};
};
networkmanager = {
networking.networkmanager.enable = true;
networking.netplan.enable = true;
networking.netplan.configFiles = {
${fixtures.static.cfgs.NetworkManager.filename} =
builtins.readFile fixtures.static.cfgs.NetworkManager.src;
};
systemd.tmpfiles.settings."netplan"."/run/netplan".d = {
user = "root";
group = "root";
mode = "0700";
};
};
};
testScript = ''
import json
fixtures = json.loads('${builtins.toJSON fixtures}')
start_all()
# Test both networkd and networkmanager backends
for machine in [networkd, networkmanager]:
# Prepare variables for testing
renderer = "networkd" if machine is networkd else "NetworkManager"
configfiles = dict()
links = dict()
for group in ['static', 'dynamic']:
links[group] = list(fixtures[group]['links'].items())
configfiles[group] = fixtures[group]['cfgs'][renderer]
# Wait for tests to be runnable
machine.wait_for_unit("network.target")
# Basic tests
with subtest("Check that netplan package has been installed and is able to run"):
machine.succeed("which netplan")
machine.succeed("netplan --help")
# Module tests
with subtest("Check that the nixos module wrote the configuration file"):
machine.succeed(f"ls /etc/netplan/{configfiles['static']['filename']}")
# Run the interface checks twice: once before applying the dynamic config, and once after
for dynamic_config in [False, True]:
# If testing the synamic, write out the fixture YAML file, and apply it
if dynamic_config:
with subtest("Run netplan apply to configure dynamic interfaces"):
destination_filename = f"/run/netplan/{configfiles['dynamic']['filename']}"
machine.copy_from_host_via_shell(configfiles['dynamic']['src'], destination_filename)
machine.succeed(f"chown root:root {destination_filename}")
machine.succeed(f"chmod 0700 {destination_filename}")
machine.succeed("netplan apply")
# Check that the interfaces exist and are of the right type
# Commands below rely on '-o pipefail' being set in the shell
links_to_test = links['static'] + (links['dynamic'] if dynamic_config else [])
with subtest(f"Check that netplan correctly configured the network interfaces ({'/run populated' if dynamic_config else 'right after boot'})"):
for link_type, link in links_to_test:
link_name = link['name']
machine.wait_until_succeeds(f"{link['getter-cmd']} | grep {link_name}")
# For the dummy interface, check the IP address as well
if link_type == 'dummy':
machine.wait_until_succeeds(f"ip -o addr show {link_name} to {link['address']} | grep {link_name}")
'';
}