|
@@ -4,8 +4,11 @@ import (
|
|
"testing"
|
|
"testing"
|
|
|
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
|
containertypes "github.com/docker/docker/api/types/container"
|
|
|
|
+ "github.com/docker/docker/client"
|
|
"github.com/docker/docker/integration/internal/container"
|
|
"github.com/docker/docker/integration/internal/container"
|
|
"github.com/docker/docker/integration/internal/network"
|
|
"github.com/docker/docker/integration/internal/network"
|
|
|
|
+ "github.com/docker/docker/libnetwork/drivers/bridge"
|
|
|
|
+ "github.com/docker/docker/testutil"
|
|
"github.com/docker/docker/testutil/daemon"
|
|
"github.com/docker/docker/testutil/daemon"
|
|
"gotest.tools/v3/assert"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
@@ -35,7 +38,7 @@ func TestMACAddrOnRestart(t *testing.T) {
|
|
const netName = "testmacaddrs"
|
|
const netName = "testmacaddrs"
|
|
network.CreateNoError(ctx, t, c, netName,
|
|
network.CreateNoError(ctx, t, c, netName,
|
|
network.WithDriver("bridge"),
|
|
network.WithDriver("bridge"),
|
|
- network.WithOption("com.docker.network.bridge.name", netName))
|
|
|
|
|
|
+ network.WithOption(bridge.BridgeName, netName))
|
|
defer network.RemoveNoError(ctx, t, c, netName)
|
|
defer network.RemoveNoError(ctx, t, c, netName)
|
|
|
|
|
|
const ctr1Name = "ctr1"
|
|
const ctr1Name = "ctr1"
|
|
@@ -77,3 +80,154 @@ func TestMACAddrOnRestart(t *testing.T) {
|
|
assert.Check(t, ctr1MAC != ctr2MAC,
|
|
assert.Check(t, ctr1MAC != ctr2MAC,
|
|
"expected containers to have different MAC addresses; got %q for both", ctr1MAC)
|
|
"expected containers to have different MAC addresses; got %q for both", ctr1MAC)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+// Check that a configured MAC address is restored after a container restart,
|
|
|
|
+// and after a daemon restart.
|
|
|
|
+func TestCfgdMACAddrOnRestart(t *testing.T) {
|
|
|
|
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
|
|
|
+
|
|
|
|
+ ctx := setupTest(t)
|
|
|
|
+
|
|
|
|
+ d := daemon.New(t)
|
|
|
|
+ d.StartWithBusybox(ctx, t)
|
|
|
|
+ defer d.Stop(t)
|
|
|
|
+
|
|
|
|
+ c := d.NewClientT(t)
|
|
|
|
+ defer c.Close()
|
|
|
|
+
|
|
|
|
+ const netName = "testcfgmacaddr"
|
|
|
|
+ network.CreateNoError(ctx, t, c, netName,
|
|
|
|
+ network.WithDriver("bridge"),
|
|
|
|
+ network.WithOption(bridge.BridgeName, netName))
|
|
|
|
+ defer network.RemoveNoError(ctx, t, c, netName)
|
|
|
|
+
|
|
|
|
+ const wantMAC = "02:42:ac:11:00:42"
|
|
|
|
+ const ctr1Name = "ctr1"
|
|
|
|
+ id1 := container.Run(ctx, t, c,
|
|
|
|
+ container.WithName(ctr1Name),
|
|
|
|
+ container.WithImage("busybox:latest"),
|
|
|
|
+ container.WithCmd("top"),
|
|
|
|
+ container.WithNetworkMode(netName),
|
|
|
|
+ container.WithMacAddress(netName, wantMAC))
|
|
|
|
+ defer c.ContainerRemove(ctx, id1, containertypes.RemoveOptions{
|
|
|
|
+ Force: true,
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ inspect := container.Inspect(ctx, t, c, ctr1Name)
|
|
|
|
+ gotMAC := inspect.NetworkSettings.Networks[netName].MacAddress
|
|
|
|
+ assert.Check(t, is.Equal(wantMAC, gotMAC))
|
|
|
|
+
|
|
|
|
+ startAndCheck := func() {
|
|
|
|
+ t.Helper()
|
|
|
|
+ err := c.ContainerStart(ctx, ctr1Name, containertypes.StartOptions{})
|
|
|
|
+ assert.Assert(t, is.Nil(err))
|
|
|
|
+ inspect = container.Inspect(ctx, t, c, ctr1Name)
|
|
|
|
+ gotMAC = inspect.NetworkSettings.Networks[netName].MacAddress
|
|
|
|
+ assert.Check(t, is.Equal(wantMAC, gotMAC))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Restart the container, check that the MAC address is restored.
|
|
|
|
+ err := c.ContainerStop(ctx, ctr1Name, containertypes.StopOptions{})
|
|
|
|
+ assert.Assert(t, is.Nil(err))
|
|
|
|
+ startAndCheck()
|
|
|
|
+
|
|
|
|
+ // Restart the daemon, check that the MAC address is restored.
|
|
|
|
+ err = c.ContainerStop(ctx, ctr1Name, containertypes.StopOptions{})
|
|
|
|
+ assert.Assert(t, is.Nil(err))
|
|
|
|
+ d.Restart(t)
|
|
|
|
+ startAndCheck()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Regression test for https://github.com/moby/moby/issues/47228 - check that a
|
|
|
|
+// generated MAC address is not included in the Config section of 'inspect'
|
|
|
|
+// output, but a configured address is.
|
|
|
|
+func TestInspectCfgdMAC(t *testing.T) {
|
|
|
|
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
|
|
|
+
|
|
|
|
+ ctx := setupTest(t)
|
|
|
|
+
|
|
|
|
+ d := daemon.New(t)
|
|
|
|
+ d.StartWithBusybox(ctx, t)
|
|
|
|
+ defer d.Stop(t)
|
|
|
|
+
|
|
|
|
+ testcases := []struct {
|
|
|
|
+ name string
|
|
|
|
+ desiredMAC string
|
|
|
|
+ netName string
|
|
|
|
+ ctrWide bool
|
|
|
|
+ }{
|
|
|
|
+ {
|
|
|
|
+ name: "generated address default bridge",
|
|
|
|
+ netName: "bridge",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "configured address default bridge",
|
|
|
|
+ desiredMAC: "02:42:ac:11:00:42",
|
|
|
|
+ netName: "bridge",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "generated address custom bridge",
|
|
|
|
+ netName: "testnet",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "configured address custom bridge",
|
|
|
|
+ desiredMAC: "02:42:ac:11:00:42",
|
|
|
|
+ netName: "testnet",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ name: "ctr-wide address default bridge",
|
|
|
|
+ desiredMAC: "02:42:ac:11:00:42",
|
|
|
|
+ netName: "bridge",
|
|
|
|
+ ctrWide: true,
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _, tc := range testcases {
|
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
|
+ ctx := testutil.StartSpan(ctx, t)
|
|
|
|
+
|
|
|
|
+ var copts []client.Opt
|
|
|
|
+ if tc.ctrWide {
|
|
|
|
+ copts = append(copts, client.WithVersion("1.43"))
|
|
|
|
+ }
|
|
|
|
+ c := d.NewClientT(t, copts...)
|
|
|
|
+ defer c.Close()
|
|
|
|
+
|
|
|
|
+ if tc.netName != "bridge" {
|
|
|
|
+ const netName = "inspectcfgmac"
|
|
|
|
+ network.CreateNoError(ctx, t, c, netName,
|
|
|
|
+ network.WithDriver("bridge"),
|
|
|
|
+ network.WithOption(bridge.BridgeName, netName))
|
|
|
|
+ defer network.RemoveNoError(ctx, t, c, netName)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const ctrName = "ctr"
|
|
|
|
+ opts := []func(*container.TestContainerConfig){
|
|
|
|
+ container.WithName(ctrName),
|
|
|
|
+ container.WithCmd("top"),
|
|
|
|
+ container.WithImage("busybox:latest"),
|
|
|
|
+ }
|
|
|
|
+ // Don't specify the network name for the bridge network, because that
|
|
|
|
+ // exercises a different code path (the network name isn't set until the
|
|
|
|
+ // container starts, until then it's "default").
|
|
|
|
+ if tc.netName != "bridge" {
|
|
|
|
+ opts = append(opts, container.WithNetworkMode(tc.netName))
|
|
|
|
+ }
|
|
|
|
+ if tc.desiredMAC != "" {
|
|
|
|
+ if tc.ctrWide {
|
|
|
|
+ opts = append(opts, container.WithContainerWideMacAddress(tc.desiredMAC))
|
|
|
|
+ } else {
|
|
|
|
+ opts = append(opts, container.WithMacAddress(tc.netName, tc.desiredMAC))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ id := container.Create(ctx, t, c, opts...)
|
|
|
|
+ defer c.ContainerRemove(ctx, id, containertypes.RemoveOptions{
|
|
|
|
+ Force: true,
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ inspect := container.Inspect(ctx, t, c, ctrName)
|
|
|
|
+ configMAC := inspect.Config.MacAddress //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
|
|
|
|
+ assert.Check(t, is.DeepEqual(configMAC, tc.desiredMAC))
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|