git.iko.soy/typeable/nixpkgs
on master help sign in
Merge pull request #156718 from B4dM4n/bird-pre-check-config
commit5940ac847fdb230da796107531eaa9dbe3bf3f7d authorFranz Pletz <fpletz@fnordicwalking.de> dateTue 25 Jan 2022, 16:43 (5 years ago) parente8704f1520383d
4 files changed+229−3
nixos/modules/services/networking/bird.nix+20−2 nixos/tests/all-tests.nix+1 nixos/tests/bird.nix+205 pkgs/servers/bird/default.nix+3−1
nixos/modules/services/networking/bird.nix+20−2
@@ -31,7 +31,23 @@ let
3131 default = true;
3232 description = ''
3333 Whether the config should be checked at build time.
34− Disabling this might become necessary if the config includes files not present during build time.
34+ When the config can't be checked during build time, for example when it includes
35+ other files, either disable this option or use <code>preCheckConfig</code> to create
36+ the included files before checking.
37+ '';
38+ };
39+ preCheckConfig = mkOption {
40+ type = types.lines;
41+ default = "";
42+ example = ''
43+ echo "cost 100;" > include.conf
44+ '';
45+ description = ''
46+ Commands to execute before the config file check. The file to be checked will be
47+ available as <code>${variant}.conf</code> in the current directory.
48+
49+ Files created with this option will not be available at service runtime, only during
50+ build time checking.
3551 '';
3652 };
3753 };
@@ -45,7 +61,9 @@ let
4561 name = "${variant}.conf";
4662 text = cfg.config;
4763 checkPhase = optionalString cfg.checkConfig ''
48− ${pkg}/bin/${birdBin} -d -p -c $out
64+ ln -s $out ${variant}.conf
65+ ${cfg.preCheckConfig}
66+ ${pkg}/bin/${birdBin} -d -p -c ${variant}.conf
4967 '';
5068 };
5169
nixos/tests/all-tests.nix+1
@@ -46,6 +46,7 @@ in
4646 beanstalkd = handleTest ./beanstalkd.nix {};
4747 bees = handleTest ./bees.nix {};
4848 bind = handleTest ./bind.nix {};
49+ bird = handleTest ./bird.nix {};
4950 bitcoind = handleTest ./bitcoind.nix {};
5051 bittorrent = handleTest ./bittorrent.nix {};
5152 blockbook-frontend = handleTest ./blockbook-frontend.nix {};
nixos/tests/bird.nixnew file+205
@@ -0,0 +1,205 @@
1+# This test does a basic functionality check for all bird variants and demonstrates a use
2+# of the preCheckConfig option.
3+
4+{ system ? builtins.currentSystem
5+, pkgs ? import ../.. { inherit system; config = { }; }
6+}:
7+
8+let
9+ inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
10+ inherit (pkgs.lib) optionalString;
11+
12+ hostShared = hostId: { pkgs, ... }: {
13+ virtualisation.vlans = [ 1 ];
14+
15+ environment.systemPackages = with pkgs; [ jq ];
16+
17+ networking = {
18+ useNetworkd = true;
19+ useDHCP = false;
20+ firewall.enable = false;
21+ };
22+
23+ systemd.network.networks."01-eth1" = {
24+ name = "eth1";
25+ networkConfig.Address = "10.0.0.${hostId}/24";
26+ };
27+ };
28+
29+ birdTest = v4:
30+ let variant = "bird${optionalString (!v4) "6"}"; in
31+ makeTest {
32+ name = variant;
33+
34+ nodes.host1 = makeBirdHost variant "1";
35+ nodes.host2 = makeBirdHost variant "2";
36+
37+ testScript = makeTestScript variant v4 (!v4);
38+ };
39+
40+ bird2Test = makeTest {
41+ name = "bird2";
42+
43+ nodes.host1 = makeBird2Host "1";
44+ nodes.host2 = makeBird2Host "2";
45+
46+ testScript = makeTestScript "bird2" true true;
47+ };
48+
49+ makeTestScript = variant: v4: v6: ''
50+ start_all()
51+
52+ host1.wait_for_unit("${variant}.service")
53+ host2.wait_for_unit("${variant}.service")
54+
55+ ${optionalString v4 ''
56+ with subtest("Waiting for advertised IPv4 routes"):
57+ host1.wait_until_succeeds("ip --json r | jq -e 'map(select(.dst == \"10.10.0.2\")) | any'")
58+ host2.wait_until_succeeds("ip --json r | jq -e 'map(select(.dst == \"10.10.0.1\")) | any'")
59+ ''}
60+ ${optionalString v6 ''
61+ with subtest("Waiting for advertised IPv6 routes"):
62+ host1.wait_until_succeeds("ip --json -6 r | jq -e 'map(select(.dst == \"fdff::2\")) | any'")
63+ host2.wait_until_succeeds("ip --json -6 r | jq -e 'map(select(.dst == \"fdff::1\")) | any'")
64+ ''}
65+
66+ with subtest("Check fake routes in preCheckConfig do not exists"):
67+ ${optionalString v4 ''host1.fail("ip --json r | jq -e 'map(select(.dst == \"1.2.3.4\")) | any'")''}
68+ ${optionalString v4 ''host2.fail("ip --json r | jq -e 'map(select(.dst == \"1.2.3.4\")) | any'")''}
69+
70+ ${optionalString v6 ''host1.fail("ip --json -6 r | jq -e 'map(select(.dst == \"fd00::\")) | any'")''}
71+ ${optionalString v6 ''host2.fail("ip --json -6 r | jq -e 'map(select(.dst == \"fd00::\")) | any'")''}
72+ '';
73+
74+ makeBirdHost = variant: hostId: { pkgs, ... }: {
75+ imports = [ (hostShared hostId) ];
76+
77+ services.${variant} = {
78+ enable = true;
79+
80+ config = ''
81+ log syslog all;
82+
83+ debug protocols all;
84+
85+ router id 10.0.0.${hostId};
86+
87+ protocol device {
88+ }
89+
90+ protocol kernel {
91+ import none;
92+ export all;
93+ }
94+
95+ protocol static {
96+ include "static.conf";
97+ }
98+
99+ protocol ospf {
100+ export all;
101+ area 0 {
102+ interface "eth1" {
103+ hello 5;
104+ wait 5;
105+ };
106+ };
107+ }
108+ '';
109+
110+ preCheckConfig =
111+ let
112+ route = { bird = "1.2.3.4/32"; bird6 = "fd00::/128"; }.${variant};
113+ in
114+ ''echo "route ${route} blackhole;" > static.conf'';
115+ };
116+
117+ systemd.tmpfiles.rules =
118+ let
119+ route = { bird = "10.10.0.${hostId}/32"; bird6 = "fdff::${hostId}/128"; }.${variant};
120+ in
121+ [ "f /etc/bird/static.conf - - - - route ${route} blackhole;" ];
122+ };
123+
124+ makeBird2Host = hostId: { pkgs, ... }: {
125+ imports = [ (hostShared hostId) ];
126+
127+ services.bird2 = {
128+ enable = true;
129+
130+ config = ''
131+ log syslog all;
132+
133+ debug protocols all;
134+
135+ router id 10.0.0.${hostId};
136+
137+ protocol device {
138+ }
139+
140+ protocol kernel kernel4 {
141+ ipv4 {
142+ import none;
143+ export all;
144+ };
145+ }
146+
147+ protocol static static4 {
148+ ipv4;
149+ include "static4.conf";
150+ }
151+
152+ protocol ospf v2 ospf4 {
153+ ipv4 {
154+ export all;
155+ };
156+ area 0 {
157+ interface "eth1" {
158+ hello 5;
159+ wait 5;
160+ };
161+ };
162+ }
163+
164+ protocol kernel kernel6 {
165+ ipv6 {
166+ import none;
167+ export all;
168+ };
169+ }
170+
171+ protocol static static6 {
172+ ipv6;
173+ include "static6.conf";
174+ }
175+
176+ protocol ospf v3 ospf6 {
177+ ipv6 {
178+ export all;
179+ };
180+ area 0 {
181+ interface "eth1" {
182+ hello 5;
183+ wait 5;
184+ };
185+ };
186+ }
187+ '';
188+
189+ preCheckConfig = ''
190+ echo "route 1.2.3.4/32 blackhole;" > static4.conf
191+ echo "route fd00::/128 blackhole;" > static6.conf
192+ '';
193+ };
194+
195+ systemd.tmpfiles.rules = [
196+ "f /etc/bird/static4.conf - - - - route 10.10.0.${hostId}/32 blackhole;"
197+ "f /etc/bird/static6.conf - - - - route fdff::${hostId}/128 blackhole;"
198+ ];
199+ };
200+in
201+{
202+ bird = birdTest true;
203+ bird6 = birdTest false;
204+ bird2 = bird2Test;
205+}
pkgs/servers/bird/default.nix+3−1
@@ -1,4 +1,4 @@
1−{ lib, stdenv, fetchurl, fetchpatch, flex, bison, readline, libssh }:
1+{ lib, stdenv, fetchurl, fetchpatch, flex, bison, readline, libssh, nixosTests }:
22
33with lib;
44
@@ -34,6 +34,8 @@ let
3434 "--localstatedir=/var"
3535 ] ++ optional enableIPv6 "--enable-ipv6";
3636
37+ passthru.tests = nixosTests.bird;
38+
3739 meta = {
3840 description = "BIRD Internet Routing Daemon";
3941 homepage = "http://bird.network.cz";