Skip to content

Commit 5919a01

Browse files
committed
Run CI tests with nftables
Signed-off-by: Rob Murray <[email protected]>
1 parent 8e18a1c commit 5919a01

File tree

8 files changed

+46
-38
lines changed

8 files changed

+46
-38
lines changed

.github/workflows/.test.yml

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ jobs:
145145
];
146146
if ("${{ inputs.storage }}" == "snapshotter") {
147147
includes.push({ os: 'ubuntu-24.04', mode: 'firewalld' });
148+
includes.push({ os: 'ubuntu-24.04', mode: 'nftables' });
148149
}
149150
await core.group(`Set matrix`, async () => {
150151
core.info(`matrix: ${JSON.stringify(includes)}`);
@@ -190,6 +191,10 @@ jobs:
190191
echo "FIREWALLD=true" >> $GITHUB_ENV
191192
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
192193
fi
194+
if [[ "${{ matrix.mode }}" == *"nftables"* ]]; then
195+
echo "DOCKER_FIREWALL_BACKEND=nftables" >> $GITHUB_ENV
196+
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}nftables"
197+
fi
193198
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
194199
-
195200
name: Set up Docker Buildx
@@ -328,7 +333,7 @@ jobs:
328333
// 'include' with other matrix variables that aren't part of the
329334
// include items.
330335
// Moreover, since the goal is to run only relevant tests with
331-
// firewalld enabled to minimize the number of CI jobs, we
336+
// firewalld/nftables enabled to minimize the number of CI jobs, we
332337
// statically define the list of test suites that we want to run.
333338
if ("${{ inputs.storage }}" == "snapshotter") {
334339
matrix.include.push({
@@ -343,6 +348,18 @@ jobs:
343348
'mode': 'firewalld',
344349
'test': 'DockerNetworkSuite'
345350
});
351+
matrix.include.push({
352+
'mode': 'nftables',
353+
'test': 'DockerCLINetworkSuite|DockerCLIPortSuite|DockerDaemonSuite'
354+
});
355+
matrix.include.push({
356+
'mode': 'nftables',
357+
'test': 'DockerSwarmSuite'
358+
});
359+
matrix.include.push({
360+
'mode': 'nftables',
361+
'test': 'DockerNetworkSuite'
362+
});
346363
}
347364
await core.group(`Set matrix`, async () => {
348365
core.info(`matrix: ${JSON.stringify(matrix)}`);
@@ -380,6 +397,10 @@ jobs:
380397
echo "FIREWALLD=true" >> $GITHUB_ENV
381398
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
382399
fi
400+
if [[ "${{ matrix.mode }}" == *"nftables"* ]]; then
401+
echo "DOCKER_FIREWALL_BACKEND=nftables" >> $GITHUB_ENV
402+
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}nftables"
403+
fi
383404
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
384405
-
385406
name: Set up Docker Buildx
@@ -437,7 +458,7 @@ jobs:
437458
if: always()
438459
uses: actions/upload-artifact@v4
439460
with:
440-
name: test-reports-integration-cli-${{ inputs.storage }}-${{ env.TESTREPORTS_NAME }}
461+
name: test-reports-integration-cli-${{ inputs.storage }}-${{ matrix.mode }}-${{ env.TESTREPORTS_NAME }}
441462
path: /tmp/reports/*
442463
retention-days: 1
443464

@@ -460,7 +481,7 @@ jobs:
460481
uses: actions/download-artifact@v4
461482
with:
462483
path: /tmp/reports
463-
pattern: test-reports-integration-cli-${{ inputs.storage }}-*
484+
pattern: test-reports-integration-cli-${{ inputs.storage }}-${{ matrix.mode }}-*
464485
merge-multiple: true
465486
-
466487
name: Install teststat

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ DOCKER_ENVS := \
3838
-e DOCKERCLI_INTEGRATION_REPOSITORY \
3939
-e DOCKER_DEBUG \
4040
-e DOCKER_EXPERIMENTAL \
41+
-e DOCKER_FIREWALL_BACKEND \
4142
-e DOCKER_GITCOMMIT \
4243
-e DOCKER_GRAPHDRIVER \
4344
-e DOCKER_LDFLAGS \

integration/networking/firewall_linux_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package networking
22

33
import (
4+
"os"
45
"testing"
56

67
"github.com/docker/docker/client"
@@ -10,12 +11,16 @@ import (
1011
is "gotest.tools/v3/assert/cmp"
1112
)
1213

14+
const defaultFirewallBackend = "iptables"
15+
1316
func TestInfoFirewallBackend(t *testing.T) {
1417
ctx := setupTest(t)
1518
c := testEnv.APIClient()
1619

17-
expDriver := "iptables"
18-
if !testEnv.IsRootless() && networking.FirewalldRunning() {
20+
expDriver := defaultFirewallBackend
21+
if val := os.Getenv("DOCKER_FIREWALL_BACKEND"); val != "" {
22+
expDriver = val
23+
} else if !testEnv.IsRootless() && networking.FirewalldRunning() {
1924
expDriver = "iptables+firewalld"
2025
}
2126
info, err := c.Info(ctx)

libnetwork/controller_linux.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ func (c *Controller) FirewallBackend() *system.FirewallInfo {
2020
if nftables.Enabled() {
2121
return &system.FirewallInfo{Driver: "nftables"}
2222
}
23-
usingFirewalld, err := iptables.UsingFirewalld()
24-
if err != nil {
25-
return nil
26-
}
27-
if usingFirewalld {
23+
if iptables.UsingFirewalld() {
2824
info := &system.FirewallInfo{Driver: "iptables+firewalld"}
2925
reloadedAt := iptables.FirewalldReloadedAt()
3026
if !reloadedAt.IsZero() {

libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,8 @@ import (
2121
"gotest.tools/v3/skip"
2222
)
2323

24-
func usingFirewalld() bool {
25-
// Check for existence of a dummy rule to make sure iptables is initialised - then can
26-
// check whether firewalld is running.
27-
_ = iptables.GetIptable(iptables.IPv4).Exists(iptables.Filter, "FORWARD", "-j", "DROP")
28-
fw, _ := iptables.UsingFirewalld()
29-
return fw
30-
}
31-
3224
func TestCleanupIptableRules(t *testing.T) {
33-
skip.If(t, usingFirewalld(), "firewalld is running in the host netns, it can't modify rules in the test's netns")
25+
skip.If(t, iptables.UsingFirewalld(), "firewalld is running in the host netns, it can't modify rules in the test's netns")
3426

3527
defer netnsutils.SetupTestOSContext(t)()
3628
bridgeChains := []struct {
@@ -84,7 +76,7 @@ func TestCleanupIptableRules(t *testing.T) {
8476

8577
// TestIptabler tests combinations of firewaller options against golden results.
8678
func TestIptabler(t *testing.T) {
87-
skip.If(t, usingFirewalld(), "firewalld is running in the host netns, it can't modify rules in the test's netns")
79+
skip.If(t, iptables.UsingFirewalld(), "firewalld is running in the host netns, it can't modify rules in the test's netns")
8880

8981
const (
9082
ipv4 int64 = iota

libnetwork/firewall_linux.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import (
1414
const userChain = "DOCKER-USER"
1515

1616
func (c *Controller) selectFirewallBackend() {
17+
// Don't try to enable nftables if firewalld is running.
18+
if iptables.UsingFirewalld() {
19+
return
20+
}
1721
// Only try to use nftables if explicitly enabled by env-var.
1822
// TODO(robmry) - command line options?
1923
if os.Getenv("DOCKER_FIREWALL_BACKEND") == "nftables" {

libnetwork/iptables/firewalld.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"time"
1212

1313
"github.com/containerd/log"
14-
"github.com/docker/docker/pkg/rootless"
1514
dbus "github.com/godbus/dbus/v5"
1615
"github.com/pkg/errors"
1716
)
@@ -35,8 +34,7 @@ type Conn struct {
3534
var (
3635
connection *Conn
3736

38-
firewalldInitCalled bool
39-
firewalldRunning bool // is Firewalld service running
37+
firewalldRunning bool // is Firewalld service running
4038
// Time of the last firewalld reload.
4139
firewalldReloadedAt atomic.Value
4240
// Mutex to serialise firewalld reload callbacks.
@@ -45,16 +43,10 @@ var (
4543
)
4644

4745
// UsingFirewalld returns true if iptables rules will be applied via firewalld's
48-
// passthrough interface. The error return is non-nil if the status cannot be
49-
// determined because the initialisation function has not been called.
50-
func UsingFirewalld() (bool, error) {
51-
// If called before startup has completed, the firewall backend is unknown.
52-
// But, if running rootless, the init function is not called because
53-
// firewalld will be running in the host's netns, not in rootlesskit's.
54-
if !firewalldInitCalled && !rootless.RunningWithRootlessKit() {
55-
return false, fmt.Errorf("iptables.firewalld is not initialised")
56-
}
57-
return firewalldRunning, nil
46+
// passthrough interface.
47+
func UsingFirewalld() bool {
48+
_ = initCheck()
49+
return firewalldRunning
5850
}
5951

6052
// FirewalldReloadedAt returns the time at which the daemon last completed a
@@ -72,7 +64,6 @@ func FirewalldReloadedAt() time.Time {
7264
func firewalldInit() error {
7365
var err error
7466

75-
firewalldInitCalled = true
7667
if connection, err = newConnection(); err != nil {
7768
return fmt.Errorf("Failed to connect to D-Bus system bus: %v", err)
7869
}

libnetwork/iptables/iptables_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/docker/docker/internal/testutils/netnsutils"
1414
"golang.org/x/sync/errgroup"
1515
"gotest.tools/v3/assert"
16+
"gotest.tools/v3/skip"
1617
)
1718

1819
const (
@@ -258,10 +259,7 @@ func TestExistsRaw(t *testing.T) {
258259
}
259260

260261
func TestRule(t *testing.T) {
261-
_ = firewalldInit()
262-
if res, _ := UsingFirewalld(); res {
263-
t.Skip("firewalld in host netns cannot create rules in the test's netns")
264-
}
262+
skip.If(t, UsingFirewalld(), "firewalld is running in the host netns, it can't modify rules in the test's netns")
265263
defer netnsutils.SetupTestOSContext(t)()
266264

267265
assert.NilError(t, exec.Command("iptables", "-N", "TESTCHAIN").Run())

0 commit comments

Comments
 (0)