Skip to content

Commit 5fa86c7

Browse files
committed
refactor: bash+jq instead of python closure
1 parent 635d1ba commit 5fa86c7

File tree

3 files changed

+124
-120
lines changed

3 files changed

+124
-120
lines changed

nix/kexec-installer/module.nix

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{ config, lib, modulesPath, pkgs, ... }:
22
let
3-
restore-network = pkgs.writers.writePython3 "restore-network" { flakeIgnore = [ "E501" ]; }
4-
./restore_routes.py;
3+
4+
restore-network = pkgs.writers.writeBash "restore-network" ./restore_routes.sh;
55

66
# does not link with iptables enabled
77
iprouteStatic = pkgs.pkgsStatic.iproute2.override { iptables = null; };
@@ -56,6 +56,7 @@ in
5656
environment.etc.is_kexec.text = "true";
5757

5858
systemd.services.restore-network = {
59+
path = [pkgs.jq];
5960
before = [ "network-pre.target" ];
6061
wants = [ "network-pre.target" ];
6162
wantedBy = [ "multi-user.target" ];

nix/kexec-installer/restore_routes.py

Lines changed: 0 additions & 118 deletions
This file was deleted.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env bash
2+
3+
# filter_interfaces function
4+
filter_interfaces() {
5+
# This function takes a list of network interfaces as input and filters
6+
# out loopback interfaces, interfaces without a MAC address, and addresses
7+
# with a "link" scope or marked as dynamic (from DHCP or router
8+
# advertisements). The filtered interfaces are returned as an array.
9+
local network=("$@")
10+
11+
for net in "${network[@]}"; do
12+
local link_type="$(jq -r '.link_type' <<< "$net")"
13+
local address="$(jq -r '.address // ""' <<< "$net")"
14+
local addr_info="$(jq -r '.addr_info | map(select(.scope != "link" and (.dynamic | not)))' <<< "$net")"
15+
local has_dynamic_address=$(jq -r '.addr_info | any(.dynamic)' <<< "$net")
16+
17+
# echo "Link Type: $link_type -- Address: $address -- Has Dynamic Address: $has_dynamic_address -- Addr Info: $addr_info"
18+
19+
if [[ "$link_type" != "loopback" && -n "$address" && ("$addr_info" != "[]" || "$has_dynamic_address" == "true") ]]; then
20+
net=$(jq -c --argjson addr_info "$addr_info" '.addr_info = $addr_info' <<< "$net")
21+
echo "$net" # "return"
22+
fi
23+
done
24+
}
25+
26+
# filter_routes function
27+
filter_routes() {
28+
# This function takes a list of routes as input and filters out routes
29+
# with protocols "dhcp", "kernel", or "ra". The filtered routes are
30+
# returned as an array.
31+
local routes=("$@")
32+
33+
for route in "${routes[@]}"; do
34+
local protocol=$(jq -r '.protocol' <<< "$route")
35+
if [[ $protocol != "dhcp" && $protocol != "kernel" && $protocol != "ra" ]]; then
36+
echo "$route" # "return"
37+
fi
38+
done
39+
}
40+
41+
# generate_networkd_units function
42+
generate_networkd_units() {
43+
# This function takes the filtered interfaces and routes, along with a
44+
# directory path. It generates systemd-networkd unit files for each interface,
45+
# including the configured addresses and routes. The unit files are written
46+
# to the specified directory with the naming convention 00-<ifname>.network.
47+
local -n interfaces=$1
48+
local -n routes=$2
49+
local directory="$3"
50+
51+
mkdir -p "$directory"
52+
53+
for interface in "${interfaces[@]}"; do
54+
local ifname=$(jq -r '.ifname' <<< "$interface")
55+
local address=$(jq -r '.address' <<< "$interface")
56+
local addresses=$(jq -r '.addr_info | map("Address = \(.local)/\(.prefixlen)") | join("\n")' <<< "$interface")
57+
local route_sections=()
58+
59+
for route in "${routes[@]}"; do
60+
local dev=$(jq -r '.dev' <<< "$route")
61+
if [[ $dev == $ifname ]]; then
62+
local route_section="[Route]"
63+
local dst=$(jq -r '.dst' <<< "$route")
64+
if [[ $dst != "default" ]]; then
65+
route_section+="\nDestination = $dst"
66+
fi
67+
local gateway=$(jq -r '.gateway // ""' <<< "$route")
68+
if [[ -n $gateway ]]; then
69+
route_section+="\nGateway = $gateway"
70+
fi
71+
route_sections+=("$route_section")
72+
fi
73+
done
74+
75+
local unit=$(cat <<-EOF
76+
[Match]
77+
MACAddress = $address
78+
79+
[Network]
80+
DHCP = yes
81+
LLDP = yes
82+
IPv6AcceptRA = yes
83+
MulticastDNS = yes
84+
85+
$addresses
86+
$(printf '%s\n' "${route_sections[@]}")
87+
EOF
88+
)
89+
echo -e "$unit" > "$directory/00-$ifname.network"
90+
done
91+
}
92+
93+
# main function
94+
main() {
95+
if [[ $# -lt 4 ]]; then
96+
echo "USAGE: $0 addresses routes-v4 routes-v6 networkd-directory" >&2
97+
# exit 1
98+
return 1
99+
fi
100+
101+
local addresses
102+
readarray -t addresses < <(jq -c '.[]' "$1") # Read JSON data into array
103+
104+
local v4_routes
105+
readarray -t v4_routes < <(jq -c '.[]' "$2")
106+
107+
local v6_routes
108+
readarray -t v6_routes < <(jq -c '.[]' "$3")
109+
110+
local networkd_directory="$4"
111+
112+
local relevant_interfaces
113+
readarray -t relevant_interfaces < <(filter_interfaces "${addresses[@]}")
114+
115+
local relevant_routes
116+
readarray -t relevant_routes < <(filter_routes "${v4_routes[@]}" "${v6_routes[@]}")
117+
118+
generate_networkd_units relevant_interfaces relevant_routes "$networkd_directory"
119+
}
120+
121+
main "$@"

0 commit comments

Comments
 (0)