etchosts_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package networking
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. containertypes "github.com/docker/docker/api/types/container"
  7. "github.com/docker/docker/integration/internal/container"
  8. "github.com/docker/docker/testutil"
  9. "github.com/docker/docker/testutil/daemon"
  10. "gotest.tools/v3/assert"
  11. is "gotest.tools/v3/assert/cmp"
  12. "gotest.tools/v3/skip"
  13. )
  14. // Check that the '/etc/hosts' file in a container is created according to
  15. // whether the container supports IPv6.
  16. // Regression test for https://github.com/moby/moby/issues/35954
  17. func TestEtcHostsIpv6(t *testing.T) {
  18. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  19. ctx := setupTest(t)
  20. d := daemon.New(t)
  21. d.StartWithBusybox(ctx, t,
  22. "--ipv6",
  23. "--ip6tables",
  24. "--experimental",
  25. "--fixed-cidr-v6=fdc8:ffe2:d8d7:1234::/64")
  26. defer d.Stop(t)
  27. c := d.NewClientT(t)
  28. defer c.Close()
  29. testcases := []struct {
  30. name string
  31. sysctls map[string]string
  32. expIPv6Enabled bool
  33. expEtcHosts string
  34. }{
  35. {
  36. // Create a container with no overrides, on the IPv6-enabled default bridge.
  37. // Expect the container to have a working '::1' address, on the assumption
  38. // the test host's kernel supports IPv6 - and for its '/etc/hosts' file to
  39. // include IPv6 addresses.
  40. name: "IPv6 enabled",
  41. expIPv6Enabled: true,
  42. expEtcHosts: `127.0.0.1 localhost
  43. ::1 localhost ip6-localhost ip6-loopback
  44. fe00::0 ip6-localnet
  45. ff00::0 ip6-mcastprefix
  46. ff02::1 ip6-allnodes
  47. ff02::2 ip6-allrouters
  48. `,
  49. },
  50. {
  51. // Create a container in the same network, with IPv6 disabled. Expect '::1'
  52. // not to be pingable, and no IPv6 addresses in its '/etc/hosts'.
  53. name: "IPv6 disabled",
  54. sysctls: map[string]string{"net.ipv6.conf.all.disable_ipv6": "1"},
  55. expIPv6Enabled: false,
  56. expEtcHosts: "127.0.0.1\tlocalhost\n",
  57. },
  58. }
  59. for _, tc := range testcases {
  60. t.Run(tc.name, func(t *testing.T) {
  61. ctx := testutil.StartSpan(ctx, t)
  62. ctrId := container.Run(ctx, t, c,
  63. container.WithName("etchosts_"+sanitizeCtrName(t.Name())),
  64. container.WithImage("busybox:latest"),
  65. container.WithCmd("top"),
  66. container.WithSysctls(tc.sysctls),
  67. )
  68. defer func() {
  69. c.ContainerRemove(ctx, ctrId, containertypes.RemoveOptions{Force: true})
  70. }()
  71. runCmd := func(ctrId string, cmd []string, expExitCode int) string {
  72. t.Helper()
  73. execCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
  74. defer cancel()
  75. res, err := container.Exec(execCtx, c, ctrId, cmd)
  76. assert.Check(t, is.Nil(err))
  77. assert.Check(t, is.Equal(res.ExitCode, expExitCode))
  78. return res.Stdout()
  79. }
  80. // Check that IPv6 is/isn't enabled, as expected.
  81. var expPingExitStatus int
  82. if !tc.expIPv6Enabled {
  83. expPingExitStatus = 1
  84. }
  85. runCmd(ctrId, []string{"ping", "-6", "-c1", "-W3", "::1"}, expPingExitStatus)
  86. // Check the contents of /etc/hosts.
  87. stdout := runCmd(ctrId, []string{"cat", "/etc/hosts"}, 0)
  88. // Append the container's own addresses/name to the expected hosts file content.
  89. inspect := container.Inspect(ctx, t, c, ctrId)
  90. exp := tc.expEtcHosts + inspect.NetworkSettings.IPAddress + "\t" + inspect.Config.Hostname + "\n"
  91. if tc.expIPv6Enabled {
  92. exp += inspect.NetworkSettings.GlobalIPv6Address + "\t" + inspect.Config.Hostname + "\n"
  93. }
  94. assert.Check(t, is.Equal(stdout, exp))
  95. })
  96. }
  97. }