From 1e4e9161c570eb80718b86a2f6ece58d77aaf121 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 9 Aug 2023 19:42:01 +0200 Subject: [PATCH 1/5] libnetwork: move TestDNSOptions to a non-windows file It was only testing stub implementations on Windows that are not used in production code. Signed-off-by: Sebastiaan van Stijn --- libnetwork/sandbox_dns_unix_test.go | 87 +++++++++++++++++++++++++++++ libnetwork/sandbox_dns_windows.go | 10 ---- libnetwork/service_common_test.go | 76 ------------------------- 3 files changed, 87 insertions(+), 86 deletions(-) create mode 100644 libnetwork/sandbox_dns_unix_test.go diff --git a/libnetwork/sandbox_dns_unix_test.go b/libnetwork/sandbox_dns_unix_test.go new file mode 100644 index 0000000000..5a01a13d52 --- /dev/null +++ b/libnetwork/sandbox_dns_unix_test.go @@ -0,0 +1,87 @@ +//go:build !windows + +package libnetwork + +import ( + "runtime" + "testing" + + "github.com/docker/docker/libnetwork/resolvconf" + "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" + "gotest.tools/v3/skip" +) + +func TestDNSOptions(t *testing.T) { + skip.If(t, runtime.GOOS == "windows", "test only works on linux") + + c, err := New() + assert.NilError(t, err) + + sb, err := c.NewSandbox("cnt1", nil) + assert.NilError(t, err) + + cleanup := func(s *Sandbox) { + if err := s.Delete(); err != nil { + t.Error(err) + } + } + + defer cleanup(sb) + sb.startResolver(false) + + err = sb.setupDNS() + assert.NilError(t, err) + err = sb.rebuildDNS() + assert.NilError(t, err) + currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) + assert.NilError(t, err) + dnsOptionsList := resolvconf.GetOptions(currRC.Content) + assert.Check(t, is.Len(dnsOptionsList, 1)) + assert.Check(t, is.Equal("ndots:0", dnsOptionsList[0])) + + sb.config.dnsOptionsList = []string{"ndots:5"} + err = sb.setupDNS() + assert.NilError(t, err) + currRC, err = resolvconf.GetSpecific(sb.config.resolvConfPath) + assert.NilError(t, err) + dnsOptionsList = resolvconf.GetOptions(currRC.Content) + assert.Check(t, is.Len(dnsOptionsList, 1)) + assert.Check(t, is.Equal("ndots:5", dnsOptionsList[0])) + + err = sb.rebuildDNS() + assert.NilError(t, err) + currRC, err = resolvconf.GetSpecific(sb.config.resolvConfPath) + assert.NilError(t, err) + dnsOptionsList = resolvconf.GetOptions(currRC.Content) + assert.Check(t, is.Len(dnsOptionsList, 1)) + assert.Check(t, is.Equal("ndots:5", dnsOptionsList[0])) + + sb2, err := c.NewSandbox("cnt2", nil) + assert.NilError(t, err) + defer cleanup(sb2) + sb2.startResolver(false) + + sb2.config.dnsOptionsList = []string{"ndots:0"} + err = sb2.setupDNS() + assert.NilError(t, err) + err = sb2.rebuildDNS() + assert.NilError(t, err) + currRC, err = resolvconf.GetSpecific(sb2.config.resolvConfPath) + assert.NilError(t, err) + dnsOptionsList = resolvconf.GetOptions(currRC.Content) + assert.Check(t, is.Len(dnsOptionsList, 1)) + assert.Check(t, is.Equal("ndots:0", dnsOptionsList[0])) + + sb2.config.dnsOptionsList = []string{"ndots:foobar"} + err = sb2.setupDNS() + assert.NilError(t, err) + err = sb2.rebuildDNS() + assert.Error(t, err, "invalid number for ndots option: foobar") + + sb2.config.dnsOptionsList = []string{"ndots:-1"} + err = sb2.setupDNS() + assert.NilError(t, err) + err = sb2.rebuildDNS() + assert.Error(t, err, "invalid number for ndots option: -1") +} diff --git a/libnetwork/sandbox_dns_windows.go b/libnetwork/sandbox_dns_windows.go index 35e0a49de4..876dca0944 100644 --- a/libnetwork/sandbox_dns_windows.go +++ b/libnetwork/sandbox_dns_windows.go @@ -20,18 +20,8 @@ func (sb *Sandbox) updateHostsFile(ifaceIP []string) error { return nil } -func (sb *Sandbox) addHostsEntries(recs []etchosts.Record) {} - func (sb *Sandbox) deleteHostsEntries(recs []etchosts.Record) {} func (sb *Sandbox) updateDNS(ipv6Enabled bool) error { return nil } - -func (sb *Sandbox) setupDNS() error { - return nil -} - -func (sb *Sandbox) rebuildDNS() error { - return nil -} diff --git a/libnetwork/service_common_test.go b/libnetwork/service_common_test.go index 1c386c05bb..99f0fcec8f 100644 --- a/libnetwork/service_common_test.go +++ b/libnetwork/service_common_test.go @@ -6,9 +6,7 @@ import ( "testing" "github.com/docker/docker/internal/testutils/netnsutils" - "github.com/docker/docker/libnetwork/resolvconf" "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/skip" ) @@ -56,77 +54,3 @@ func TestCleanupServiceDiscovery(t *testing.T) { t.Fatalf("Service record not cleaned correctly:%v", c.svcRecords) } } - -func TestDNSOptions(t *testing.T) { - skip.If(t, runtime.GOOS == "windows", "test only works on linux") - - c, err := New() - assert.NilError(t, err) - - sb, err := c.NewSandbox("cnt1", nil) - assert.NilError(t, err) - - cleanup := func(s *Sandbox) { - if err := s.Delete(); err != nil { - t.Error(err) - } - } - - defer cleanup(sb) - sb.startResolver(false) - - err = sb.setupDNS() - assert.NilError(t, err) - err = sb.rebuildDNS() - assert.NilError(t, err) - currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) - assert.NilError(t, err) - dnsOptionsList := resolvconf.GetOptions(currRC.Content) - assert.Check(t, is.Len(dnsOptionsList, 1)) - assert.Check(t, is.Equal("ndots:0", dnsOptionsList[0])) - - sb.config.dnsOptionsList = []string{"ndots:5"} - err = sb.setupDNS() - assert.NilError(t, err) - currRC, err = resolvconf.GetSpecific(sb.config.resolvConfPath) - assert.NilError(t, err) - dnsOptionsList = resolvconf.GetOptions(currRC.Content) - assert.Check(t, is.Len(dnsOptionsList, 1)) - assert.Check(t, is.Equal("ndots:5", dnsOptionsList[0])) - - err = sb.rebuildDNS() - assert.NilError(t, err) - currRC, err = resolvconf.GetSpecific(sb.config.resolvConfPath) - assert.NilError(t, err) - dnsOptionsList = resolvconf.GetOptions(currRC.Content) - assert.Check(t, is.Len(dnsOptionsList, 1)) - assert.Check(t, is.Equal("ndots:5", dnsOptionsList[0])) - - sb2, err := c.NewSandbox("cnt2", nil) - assert.NilError(t, err) - defer cleanup(sb2) - sb2.startResolver(false) - - sb2.config.dnsOptionsList = []string{"ndots:0"} - err = sb2.setupDNS() - assert.NilError(t, err) - err = sb2.rebuildDNS() - assert.NilError(t, err) - currRC, err = resolvconf.GetSpecific(sb2.config.resolvConfPath) - assert.NilError(t, err) - dnsOptionsList = resolvconf.GetOptions(currRC.Content) - assert.Check(t, is.Len(dnsOptionsList, 1)) - assert.Check(t, is.Equal("ndots:0", dnsOptionsList[0])) - - sb2.config.dnsOptionsList = []string{"ndots:foobar"} - err = sb2.setupDNS() - assert.NilError(t, err) - err = sb2.rebuildDNS() - assert.Error(t, err, "invalid number for ndots option: foobar") - - sb2.config.dnsOptionsList = []string{"ndots:-1"} - err = sb2.setupDNS() - assert.NilError(t, err) - err = sb2.rebuildDNS() - assert.Error(t, err, "invalid number for ndots option: -1") -} From de4ba1340097c5a93a1575ea65168db31c56b55b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 10 Aug 2023 12:35:52 +0200 Subject: [PATCH 2/5] libnetwork: move resolver tests that were skipped on Windows Signed-off-by: Sebastiaan van Stijn --- libnetwork/resolver_test.go | 171 ----------------------------- libnetwork/resolver_unix_test.go | 178 +++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 171 deletions(-) create mode 100644 libnetwork/resolver_unix_test.go diff --git a/libnetwork/resolver_test.go b/libnetwork/resolver_test.go index 507826af5e..f5deef9972 100644 --- a/libnetwork/resolver_test.go +++ b/libnetwork/resolver_test.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "errors" "net" - "runtime" "syscall" "testing" "time" @@ -16,7 +15,6 @@ import ( "github.com/sirupsen/logrus" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/skip" ) // a simple/null address type that will be used to fake a local address for unit testing @@ -95,102 +93,6 @@ func checkDNSRRType(t *testing.T, actual, expected uint16) { } } -func TestDNSIPQuery(t *testing.T) { - skip.If(t, runtime.GOOS == "windows", "test only works on linux") - - defer netnsutils.SetupTestOSContext(t)() - c, err := New() - if err != nil { - t.Fatal(err) - } - defer c.Stop() - - n, err := c.NewNetwork("bridge", "dtnet1", "", nil) - if err != nil { - t.Fatal(err) - } - defer func() { - if err := n.Delete(); err != nil { - t.Fatal(err) - } - }() - - ep, err := n.CreateEndpoint("testep") - if err != nil { - t.Fatal(err) - } - - sb, err := c.NewSandbox("c1") - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := sb.Delete(); err != nil { - t.Fatal(err) - } - }() - - // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name - // it is not set as a target for name resolution and does not serve any other purpose - err = ep.Join(sb) - if err != nil { - t.Fatal(err) - } - - // add service records which are used to resolve names. These are the real targets for the DNS querries - n.addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test") - - w := new(tstwriter) - // the unit tests right now will focus on non-proxyed DNS requests - r := NewResolver(resolverIPSandbox, false, sb) - - // test name1's IP is resolved correctly with the default A type query - // Also make sure DNS lookups are case insensitive - names := []string{"name1", "NaMe1"} - for _, name := range names { - q := new(dns.Msg) - q.SetQuestion(name, dns.TypeA) - r.serveDNS(w, q) - resp := w.GetResponse() - checkNonNullResponse(t, resp) - t.Log("Response: ", resp.String()) - checkDNSResponseCode(t, resp, dns.RcodeSuccess) - checkDNSAnswersCount(t, resp, 1) - checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA) - if answer, ok := resp.Answer[0].(*dns.A); ok { - if !answer.A.Equal(net.ParseIP("192.168.0.1")) { - t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A) - } - } else { - t.Fatal("Answer of type A not found") - } - w.ClearResponse() - } - - // test MX query with name1 results in Success response with 0 answer records - q := new(dns.Msg) - q.SetQuestion("name1", dns.TypeMX) - r.serveDNS(w, q) - resp := w.GetResponse() - checkNonNullResponse(t, resp) - t.Log("Response: ", resp.String()) - checkDNSResponseCode(t, resp, dns.RcodeSuccess) - checkDNSAnswersCount(t, resp, 0) - w.ClearResponse() - - // test MX query with non existent name results in ServFail response with 0 answer records - // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN - q = new(dns.Msg) - q.SetQuestion("nonexistent", dns.TypeMX) - r.serveDNS(w, q) - resp = w.GetResponse() - checkNonNullResponse(t, resp) - t.Log("Response: ", resp.String()) - checkDNSResponseCode(t, resp, dns.RcodeServerFailure) - w.ClearResponse() -} - func newDNSHandlerServFailOnce(requests *int) func(w dns.ResponseWriter, r *dns.Msg) { return func(w dns.ResponseWriter, r *dns.Msg) { m := new(dns.Msg) @@ -234,79 +136,6 @@ func waitForLocalDNSServer(t *testing.T) { } } -func TestDNSProxyServFail(t *testing.T) { - skip.If(t, runtime.GOOS == "windows", "test only works on linux") - - osctx := netnsutils.SetupTestOSContextEx(t) - defer osctx.Cleanup(t) - - c, err := New() - if err != nil { - t.Fatal(err) - } - defer c.Stop() - - n, err := c.NewNetwork("bridge", "dtnet2", "", nil) - if err != nil { - t.Fatal(err) - } - defer func() { - if err := n.Delete(); err != nil { - t.Fatal(err) - } - }() - - sb, err := c.NewSandbox("c1") - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := sb.Delete(); err != nil { - t.Fatal(err) - } - }() - - var nRequests int - // initialize a local DNS server and configure it to fail the first query - dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests)) - // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP - server := &dns.Server{Addr: "127.0.0.1:53", Net: "tcp"} - srvErrCh := make(chan error, 1) - osctx.Go(t, func() { - srvErrCh <- server.ListenAndServe() - }) - defer func() { - server.Shutdown() //nolint:errcheck - if err := <-srvErrCh; err != nil { - t.Error(err) - } - }() - - waitForLocalDNSServer(t) - t.Log("DNS Server can be reached") - - w := new(tstwriter) - r := NewResolver(resolverIPSandbox, true, sb) - q := new(dns.Msg) - q.SetQuestion("name1.", dns.TypeA) - - var localDNSEntries []extDNSEntry - extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true} - - // configure two external DNS entries and point both to local DNS server thread - localDNSEntries = append(localDNSEntries, extTestDNSEntry) - localDNSEntries = append(localDNSEntries, extTestDNSEntry) - - // this should generate two requests: the first will fail leading to a retry - r.SetExtServers(localDNSEntries) - r.serveDNS(w, q) - if nRequests != 2 { - t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests) - } - t.Logf("Expected number of DNS requests generated") -} - // Packet 24 extracted from // https://gist.github.com/vojtad/3bac63b8c91b1ec50e8d8b36047317fa/raw/7d75eb3d3448381bf252ae55ea5123a132c46658/host.pcap // (https://github.com/moby/moby/issues/44575) diff --git a/libnetwork/resolver_unix_test.go b/libnetwork/resolver_unix_test.go new file mode 100644 index 0000000000..5493c16cca --- /dev/null +++ b/libnetwork/resolver_unix_test.go @@ -0,0 +1,178 @@ +//go:build !windows + +package libnetwork + +import ( + "net" + "testing" + + "github.com/docker/docker/internal/testutils/netnsutils" + "github.com/miekg/dns" +) + +// test only works on linux +func TestDNSIPQuery(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + c, err := New() + if err != nil { + t.Fatal(err) + } + defer c.Stop() + + n, err := c.NewNetwork("bridge", "dtnet1", "", nil) + if err != nil { + t.Fatal(err) + } + defer func() { + if err := n.Delete(); err != nil { + t.Fatal(err) + } + }() + + ep, err := n.CreateEndpoint("testep") + if err != nil { + t.Fatal(err) + } + + sb, err := c.NewSandbox("c1") + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := sb.Delete(); err != nil { + t.Fatal(err) + } + }() + + // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name + // it is not set as a target for name resolution and does not serve any other purpose + err = ep.Join(sb) + if err != nil { + t.Fatal(err) + } + + // add service records which are used to resolve names. These are the real targets for the DNS querries + n.addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test") + + w := new(tstwriter) + // the unit tests right now will focus on non-proxyed DNS requests + r := NewResolver(resolverIPSandbox, false, sb) + + // test name1's IP is resolved correctly with the default A type query + // Also make sure DNS lookups are case insensitive + names := []string{"name1", "NaMe1"} + for _, name := range names { + q := new(dns.Msg) + q.SetQuestion(name, dns.TypeA) + r.serveDNS(w, q) + resp := w.GetResponse() + checkNonNullResponse(t, resp) + t.Log("Response: ", resp.String()) + checkDNSResponseCode(t, resp, dns.RcodeSuccess) + checkDNSAnswersCount(t, resp, 1) + checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA) + if answer, ok := resp.Answer[0].(*dns.A); ok { + if !answer.A.Equal(net.ParseIP("192.168.0.1")) { + t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A) + } + } else { + t.Fatal("Answer of type A not found") + } + w.ClearResponse() + } + + // test MX query with name1 results in Success response with 0 answer records + q := new(dns.Msg) + q.SetQuestion("name1", dns.TypeMX) + r.serveDNS(w, q) + resp := w.GetResponse() + checkNonNullResponse(t, resp) + t.Log("Response: ", resp.String()) + checkDNSResponseCode(t, resp, dns.RcodeSuccess) + checkDNSAnswersCount(t, resp, 0) + w.ClearResponse() + + // test MX query with non existent name results in ServFail response with 0 answer records + // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN + q = new(dns.Msg) + q.SetQuestion("nonexistent", dns.TypeMX) + r.serveDNS(w, q) + resp = w.GetResponse() + checkNonNullResponse(t, resp) + t.Log("Response: ", resp.String()) + checkDNSResponseCode(t, resp, dns.RcodeServerFailure) + w.ClearResponse() +} + +// test only works on linux +func TestDNSProxyServFail(t *testing.T) { + osctx := netnsutils.SetupTestOSContextEx(t) + defer osctx.Cleanup(t) + + c, err := New() + if err != nil { + t.Fatal(err) + } + defer c.Stop() + + n, err := c.NewNetwork("bridge", "dtnet2", "", nil) + if err != nil { + t.Fatal(err) + } + defer func() { + if err := n.Delete(); err != nil { + t.Fatal(err) + } + }() + + sb, err := c.NewSandbox("c1") + if err != nil { + t.Fatal(err) + } + + defer func() { + if err := sb.Delete(); err != nil { + t.Fatal(err) + } + }() + + var nRequests int + // initialize a local DNS server and configure it to fail the first query + dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests)) + // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP + server := &dns.Server{Addr: "127.0.0.1:53", Net: "tcp"} + srvErrCh := make(chan error, 1) + osctx.Go(t, func() { + srvErrCh <- server.ListenAndServe() + }) + defer func() { + server.Shutdown() //nolint:errcheck + if err := <-srvErrCh; err != nil { + t.Error(err) + } + }() + + waitForLocalDNSServer(t) + t.Log("DNS Server can be reached") + + w := new(tstwriter) + r := NewResolver(resolverIPSandbox, true, sb) + q := new(dns.Msg) + q.SetQuestion("name1.", dns.TypeA) + + var localDNSEntries []extDNSEntry + extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true} + + // configure two external DNS entries and point both to local DNS server thread + localDNSEntries = append(localDNSEntries, extTestDNSEntry) + localDNSEntries = append(localDNSEntries, extTestDNSEntry) + + // this should generate two requests: the first will fail leading to a retry + r.SetExtServers(localDNSEntries) + r.serveDNS(w, q) + if nRequests != 2 { + t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests) + } + t.Logf("Expected number of DNS requests generated") +} From f661bd8ee5ab2174ef7640fc91d3d0f0b970ee67 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 9 Aug 2023 20:08:08 +0200 Subject: [PATCH 3/5] libnetwork: Resolved.SetupFunc() minor cleanup Remove intermediate variables in favor of struct-literals. Signed-off-by: Sebastiaan van Stijn --- libnetwork/resolver.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libnetwork/resolver.go b/libnetwork/resolver.go index 9786ccefcf..9d95e990f5 100644 --- a/libnetwork/resolver.go +++ b/libnetwork/resolver.go @@ -105,24 +105,20 @@ func (r *Resolver) SetupFunc(port int) func() { var err error // DNS operates primarily on UDP - addr := &net.UDPAddr{ + r.conn, err = net.ListenUDP("udp", &net.UDPAddr{ IP: net.ParseIP(r.listenAddress), Port: port, - } - - r.conn, err = net.ListenUDP("udp", addr) + }) if err != nil { r.err = fmt.Errorf("error in opening name server socket %v", err) return } // Listen on a TCP as well - tcpaddr := &net.TCPAddr{ + r.tcpListen, err = net.ListenTCP("tcp", &net.TCPAddr{ IP: net.ParseIP(r.listenAddress), Port: port, - } - - r.tcpListen, err = net.ListenTCP("tcp", tcpaddr) + }) if err != nil { r.err = fmt.Errorf("error in opening name TCP server socket %v", err) return From d4e1c072e24938ed3e8641b019c9ae0f7146d6ea Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 9 Aug 2023 20:07:19 +0200 Subject: [PATCH 4/5] libnetwork: move resolverIPSandbox closer to where it's used It's only used on non-Windows platforms, so let's move it there. Signed-off-by: Sebastiaan van Stijn --- libnetwork/sandbox.go | 4 ---- libnetwork/sandbox_dns_unix.go | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index 6da04993b8..73c4fc100a 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -99,10 +99,6 @@ type containerConfig struct { exposedPorts []types.TransportPort } -const ( - resolverIPSandbox = "127.0.0.11" -) - // ID returns the ID of the sandbox. func (sb *Sandbox) ID() string { return sb.id diff --git a/libnetwork/sandbox_dns_unix.go b/libnetwork/sandbox_dns_unix.go index 990cad144a..c1e4d6feb6 100644 --- a/libnetwork/sandbox_dns_unix.go +++ b/libnetwork/sandbox_dns_unix.go @@ -23,6 +23,8 @@ const ( defaultPrefix = "/var/lib/docker/network/files" dirPerm = 0o755 filePerm = 0o644 + + resolverIPSandbox = "127.0.0.11" ) func (sb *Sandbox) startResolver(restore bool) { From 05deecaa45d45673a548d18ca72c14b17d762b6e Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 10 Aug 2023 12:36:33 +0200 Subject: [PATCH 5/5] internal/testutils/netnsutils: move utils that were not used on Windows Signed-off-by: Sebastiaan van Stijn --- internal/testutils/netnsutils/context.go | 36 ------------------- internal/testutils/netnsutils/context_unix.go | 31 ++++++++++++++++ .../testutils/netnsutils/context_windows.go | 19 +++------- 3 files changed, 35 insertions(+), 51 deletions(-) delete mode 100644 internal/testutils/netnsutils/context.go diff --git a/internal/testutils/netnsutils/context.go b/internal/testutils/netnsutils/context.go deleted file mode 100644 index a493da0e82..0000000000 --- a/internal/testutils/netnsutils/context.go +++ /dev/null @@ -1,36 +0,0 @@ -package netnsutils - -import ( - "testing" -) - -// SetupTestOSContext joins the current goroutine to a new network namespace, -// and returns its associated teardown function. -// -// Example usage: -// -// defer SetupTestOSContext(t)() -func SetupTestOSContext(t *testing.T) func() { - c := SetupTestOSContextEx(t) - return func() { c.Cleanup(t) } -} - -// Go starts running fn in a new goroutine inside the test OS context. -func (c *OSContext) Go(t *testing.T, fn func()) { - t.Helper() - errCh := make(chan error, 1) - go func() { - teardown, err := c.Set() - if err != nil { - errCh <- err - return - } - defer teardown(t) - close(errCh) - fn() - }() - - if err := <-errCh; err != nil { - t.Fatalf("%+v", err) - } -} diff --git a/internal/testutils/netnsutils/context_unix.go b/internal/testutils/netnsutils/context_unix.go index 9c527f026e..8e8543203f 100644 --- a/internal/testutils/netnsutils/context_unix.go +++ b/internal/testutils/netnsutils/context_unix.go @@ -23,6 +23,17 @@ type OSContext struct { caller string // The file:line where SetupTestOSContextEx was called, for interpolating into error messages. } +// SetupTestOSContext joins the current goroutine to a new network namespace, +// and returns its associated teardown function. +// +// Example usage: +// +// defer SetupTestOSContext(t)() +func SetupTestOSContext(t *testing.T) func() { + c := SetupTestOSContextEx(t) + return func() { c.Cleanup(t) } +} + // SetupTestOSContextEx joins the current goroutine to a new network namespace. // // Compared to [SetupTestOSContext], this function allows goroutines to be @@ -167,3 +178,23 @@ func (c *OSContext) Set() (func(testutils.Logger), error) { } }, nil } + +// Go starts running fn in a new goroutine inside the test OS context. +func (c *OSContext) Go(t *testing.T, fn func()) { + t.Helper() + errCh := make(chan error, 1) + go func() { + teardown, err := c.Set() + if err != nil { + errCh <- err + return + } + defer teardown(t) + close(errCh) + fn() + }() + + if err := <-errCh; err != nil { + t.Fatalf("%+v", err) + } +} diff --git a/internal/testutils/netnsutils/context_windows.go b/internal/testutils/netnsutils/context_windows.go index eef0689c44..ca6e3b9b1f 100644 --- a/internal/testutils/netnsutils/context_windows.go +++ b/internal/testutils/netnsutils/context_windows.go @@ -1,19 +1,8 @@ package netnsutils -import ( - "testing" +import "testing" - "github.com/docker/docker/internal/testutils" -) - -type OSContext struct{} - -func SetupTestOSContextEx(*testing.T) *OSContext { - return nil -} - -func (*OSContext) Cleanup(t *testing.T) {} - -func (*OSContext) Set() (func(testutils.Logger), error) { - return func(testutils.Logger) {}, nil +// SetupTestOSContext is a no-op on Windows. +func SetupTestOSContext(*testing.T) func() { + return func() {} }