mirror of
https://github.com/moby/moby.git
synced 2026-07-13 19:12:11 +00:00
On a freshly rebooted Linux host that's configured to use nftables
with the iptables front-end, "make test-unit" fails "TestUserChains"
on the first run - it's ok in subsequent runs.
The unit tests run in moby's dev container.
The first test in TestUserChain runs with ip6tables disabled, so the
bridge driver doesn't try to load the ip6_tables module. Then, because
the module isn't loaded (it wasn't needed by the daemon running on the
nftables host when it started), the test fails because it can't check
what's in the ip6tables filter chain.
The next test in TestUserChain does the same thing, but with ip6tables
enabled. So the module gets loaded by the bridge driver, and everything
works normally after that.
The dev container used to try to load the module on startup, but that
was removed in commit 2af19b6b ("Don't try to modprobe ip6_tables in
the moby dev container"), as part of a change to give the daemon a way
to load modules itself.
Rather that put back the dev container's code to load ip6_tables on
startup (which would mean the daemon's module-loading code not getting
to run on nftables/firewalld hosts) ...
Run the tests in TestUserChains in a different order, with iptables
enabled in the first test will make it happen to work. At least for
now.
It's not ideal, but we'll be switching to nftables soon, so the issue
will go away.
Signed-off-by: Rob Murray <rob.murray@docker.com>
112 lines
3.3 KiB
Go
112 lines
3.3 KiB
Go
package libnetwork
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/internal/testutils/netnsutils"
|
|
"github.com/docker/docker/libnetwork/config"
|
|
"github.com/docker/docker/libnetwork/iptables"
|
|
"github.com/docker/docker/libnetwork/netlabel"
|
|
"github.com/docker/docker/libnetwork/options"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
"gotest.tools/v3/golden"
|
|
)
|
|
|
|
const (
|
|
fwdChainName = "FORWARD"
|
|
usrChainName = userChain
|
|
)
|
|
|
|
func TestUserChain(t *testing.T) {
|
|
iptable4 := iptables.GetIptable(iptables.IPv4)
|
|
iptable6 := iptables.GetIptable(iptables.IPv6)
|
|
|
|
tests := []struct {
|
|
iptables bool
|
|
append bool // append other rules to FORWARD
|
|
}{
|
|
{
|
|
iptables: true,
|
|
append: false,
|
|
},
|
|
{
|
|
iptables: true,
|
|
append: true,
|
|
},
|
|
{
|
|
iptables: false,
|
|
append: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(fmt.Sprintf("iptables=%v,append=%v", tc.iptables, tc.append), func(t *testing.T) {
|
|
defer netnsutils.SetupTestOSContext(t)()
|
|
defer resetIptables(t)
|
|
|
|
c, err := New(
|
|
config.OptionDataDir(t.TempDir()),
|
|
config.OptionDriverConfig("bridge", map[string]any{
|
|
netlabel.GenericData: options.Generic{
|
|
"EnableIPTables": tc.iptables,
|
|
"EnableIP6Tables": tc.iptables,
|
|
},
|
|
}))
|
|
assert.NilError(t, err)
|
|
defer c.Stop()
|
|
|
|
// init. condition
|
|
golden.Assert(t, getRules(t, iptable4, fwdChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_fwdinit4", tc.iptables, tc.append))
|
|
golden.Assert(t, getRules(t, iptable6, fwdChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_fwdinit6", tc.iptables, tc.append))
|
|
|
|
if tc.append {
|
|
_, err := iptable4.Raw("-A", fwdChainName, "-j", "DROP")
|
|
assert.Check(t, err)
|
|
_, err = iptable6.Raw("-A", fwdChainName, "-j", "DROP")
|
|
assert.Check(t, err)
|
|
}
|
|
c.setupUserChains()
|
|
|
|
golden.Assert(t, getRules(t, iptable4, fwdChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_fwdafter4", tc.iptables, tc.append))
|
|
golden.Assert(t, getRules(t, iptable6, fwdChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_fwdafter6", tc.iptables, tc.append))
|
|
|
|
if tc.iptables {
|
|
golden.Assert(t, getRules(t, iptable4, usrChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_usrafter4", tc.iptables, tc.append))
|
|
golden.Assert(t, getRules(t, iptable6, usrChainName),
|
|
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_usrafter6", tc.iptables, tc.append))
|
|
} else {
|
|
_, err := iptable4.Raw("-S", usrChainName)
|
|
assert.Check(t, is.ErrorContains(err, "No chain/target/match by that name"), "ipv4 chain %v: created unexpectedly", usrChainName)
|
|
_, err = iptable6.Raw("-S", usrChainName)
|
|
assert.Check(t, is.ErrorContains(err, "No chain/target/match by that name"), "ipv6 chain %v: created unexpectedly", usrChainName)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func getRules(t *testing.T, iptable *iptables.IPTable, chain string) string {
|
|
t.Helper()
|
|
output, err := iptable.Raw("-S", chain)
|
|
assert.NilError(t, err, "chain %s: failed to get rules", chain)
|
|
return string(output)
|
|
}
|
|
|
|
func resetIptables(t *testing.T) {
|
|
t.Helper()
|
|
|
|
for _, ipVer := range []iptables.IPVersion{iptables.IPv4, iptables.IPv6} {
|
|
iptable := iptables.GetIptable(ipVer)
|
|
|
|
_, err := iptable.Raw("-F", fwdChainName)
|
|
assert.Check(t, err)
|
|
_ = iptable.RemoveExistingChain(usrChainName, iptables.Filter)
|
|
}
|
|
}
|