From b3b12f00593d96c6d0e93f9e333ee368278e871d Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 28 Jan 2014 16:28:32 -0800 Subject: [PATCH] Move port mapper tests out of core and into portmapper Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- network.go | 6 +- network_test.go | 72 ---------------- networkdriver/portmapper/mapper.go | 18 +--- networkdriver/portmapper/mapper_test.go | 107 ++++++++++++++++++++++++ proxy/stub_proxy.go | 22 +++++ 5 files changed, 136 insertions(+), 89 deletions(-) delete mode 100644 network_test.go create mode 100644 networkdriver/portmapper/mapper_test.go create mode 100644 proxy/stub_proxy.go diff --git a/network.go b/network.go index 05ff005ee6..c72ea12055 100644 --- a/network.go +++ b/network.go @@ -392,14 +392,16 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) { } // We can always try removing the iptables - if err := portmapper.RemoveIpTablesChain("DOCKER"); err != nil { + if err := iptables.RemoveExistingChain("DOCKER"); err != nil { return nil, err } if config.EnableIptables { - if err := portmapper.RegisterIpTablesChain("DOCKER", config.BridgeIface); err != nil { + chain, err := iptables.NewChain("DOCKER", config.BridgeIface) + if err != nil { return nil, err } + portmapper.SetIptablesChain(chain) } manager := &NetworkManager{ diff --git a/network_test.go b/network_test.go deleted file mode 100644 index 6cdf50ab6e..0000000000 --- a/network_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package docker - -import ( - "github.com/dotcloud/docker/pkg/iptables" - "github.com/dotcloud/docker/proxy" - "net" - "testing" -) - -type StubProxy struct { - frontendAddr *net.Addr - backendAddr *net.Addr -} - -func (proxy *StubProxy) Run() {} -func (proxy *StubProxy) Close() {} -func (proxy *StubProxy) FrontendAddr() net.Addr { return *proxy.frontendAddr } -func (proxy *StubProxy) BackendAddr() net.Addr { return *proxy.backendAddr } - -func NewStubProxy(frontendAddr, backendAddr net.Addr) (proxy.Proxy, error) { - return &StubProxy{ - frontendAddr: &frontendAddr, - backendAddr: &backendAddr, - }, nil -} - -func TestPortMapper(t *testing.T) { - // FIXME: is this iptables chain still used anywhere? - var chain *iptables.Chain - mapper := &PortMapper{ - tcpMapping: make(map[string]*net.TCPAddr), - tcpProxies: make(map[string]proxy.Proxy), - udpMapping: make(map[string]*net.UDPAddr), - udpProxies: make(map[string]proxy.Proxy), - iptables: chain, - defaultIp: net.IP("0.0.0.0"), - proxyFactoryFunc: NewStubProxy, - } - - dstIp1 := net.ParseIP("192.168.0.1") - dstIp2 := net.ParseIP("192.168.0.2") - srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} - srcAddr2 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")} - - if err := mapper.Map(dstIp1, 80, srcAddr1); err != nil { - t.Fatalf("Failed to allocate port: %s", err) - } - - if mapper.Map(dstIp1, 80, srcAddr1) == nil { - t.Fatalf("Port is in use - mapping should have failed") - } - - if mapper.Map(dstIp1, 80, srcAddr2) == nil { - t.Fatalf("Port is in use - mapping should have failed") - } - - if err := mapper.Map(dstIp2, 80, srcAddr2); err != nil { - t.Fatalf("Failed to allocate port: %s", err) - } - - if mapper.Unmap(dstIp1, 80, "tcp") != nil { - t.Fatalf("Failed to release port") - } - - if mapper.Unmap(dstIp2, 80, "tcp") != nil { - t.Fatalf("Failed to release port") - } - - if mapper.Unmap(dstIp2, 80, "tcp") == nil { - t.Fatalf("Port already released, but no error reported") - } -} diff --git a/networkdriver/portmapper/mapper.go b/networkdriver/portmapper/mapper.go index 74e2728ab6..f052c48143 100644 --- a/networkdriver/portmapper/mapper.go +++ b/networkdriver/portmapper/mapper.go @@ -22,6 +22,7 @@ var ( // udp:ip:port currentMappings = make(map[string]*mapping) + newProxy = proxy.NewProxy ) var ( @@ -30,21 +31,8 @@ var ( ErrPortNotMapped = errors.New("port is not mapped") ) -func RegisterIpTablesChain(name, bridge string) error { - c, err := iptables.NewChain(name, bridge) - if err != nil { - return fmt.Errorf("failed to create %s chain: %s", name, err) - } +func SetIptablesChain(c *iptables.Chain) { chain = c - return nil -} - -func RemoveIpTablesChain(name string) error { - if err := iptables.RemoveExistingChain(name); err != nil { - return err - } - chain = nil - return nil } func Map(container net.Addr, hostIP net.IP, hostPort int) error { @@ -79,7 +67,7 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) error { return err } - p, err := proxy.NewProxy(m.host, m.container) + p, err := newProxy(m.host, m.container) if err != nil { // need to undo the iptables rules before we reutrn forward(iptables.Delete, m.proto, hostIP, hostPort, containerIP.String(), containerPort) diff --git a/networkdriver/portmapper/mapper_test.go b/networkdriver/portmapper/mapper_test.go new file mode 100644 index 0000000000..05718063e3 --- /dev/null +++ b/networkdriver/portmapper/mapper_test.go @@ -0,0 +1,107 @@ +package portmapper + +import ( + "github.com/dotcloud/docker/pkg/iptables" + "github.com/dotcloud/docker/proxy" + "net" + "testing" +) + +func init() { + // override this func to mock out the proxy server + newProxy = proxy.NewStubProxy +} + +func reset() { + chain = nil + currentMappings = make(map[string]*mapping) +} + +func TestSetIptablesChain(t *testing.T) { + defer reset() + + c := &iptables.Chain{ + Name: "TEST", + Bridge: "192.168.1.1", + } + + if chain != nil { + t.Fatal("chain should be nil at init") + } + + SetIptablesChain(c) + if chain == nil { + t.Fatal("chain should not be nil after set") + } +} + +func TestMapPorts(t *testing.T) { + dstIp1 := net.ParseIP("192.168.0.1") + dstIp2 := net.ParseIP("192.168.0.2") + dstAddr1 := &net.TCPAddr{IP: dstIp1, Port: 80} + dstAddr2 := &net.TCPAddr{IP: dstIp2, Port: 80} + + srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")} + srcAddr2 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")} + + if err := Map(srcAddr1, dstIp1, 80); err != nil { + t.Fatalf("Failed to allocate port: %s", err) + } + + if Map(srcAddr1, dstIp1, 80) == nil { + t.Fatalf("Port is in use - mapping should have failed") + } + + if Map(srcAddr2, dstIp1, 80) == nil { + t.Fatalf("Port is in use - mapping should have failed") + } + + if err := Map(srcAddr2, dstIp2, 80); err != nil { + t.Fatalf("Failed to allocate port: %s", err) + } + + if Unmap(dstAddr1) != nil { + t.Fatalf("Failed to release port") + } + + if Unmap(dstAddr2) != nil { + t.Fatalf("Failed to release port") + } + + if Unmap(dstAddr2) == nil { + t.Fatalf("Port already released, but no error reported") + } +} + +func TestGetUDPKey(t *testing.T) { + addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53} + + key := getKey(addr) + + if expected := "192.168.1.5:53/udp"; key != expected { + t.Fatalf("expected key %s got %s", expected, key) + } +} + +func TestGetTCPKey(t *testing.T) { + addr := &net.TCPAddr{IP: net.ParseIP("192.168.1.5"), Port: 80} + + key := getKey(addr) + + if expected := "192.168.1.5:80/tcp"; key != expected { + t.Fatalf("expected key %s got %s", expected, key) + } +} + +func TestGetUDPIPAndPort(t *testing.T) { + addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53} + + ip, port := getIPAndPort(addr) + if expected := "192.168.1.5"; ip.String() != expected { + t.Fatalf("expected ip %s got %s", expected, ip) + } + + if ep := 53; port != ep { + t.Fatalf("expected port %d got %d", ep, port) + } +} diff --git a/proxy/stub_proxy.go b/proxy/stub_proxy.go new file mode 100644 index 0000000000..7684427058 --- /dev/null +++ b/proxy/stub_proxy.go @@ -0,0 +1,22 @@ +package proxy + +import ( + "net" +) + +type StubProxy struct { + frontendAddr net.Addr + backendAddr net.Addr +} + +func (p *StubProxy) Run() {} +func (p *StubProxy) Close() {} +func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr } +func (p *StubProxy) BackendAddr() net.Addr { return p.backendAddr } + +func NewStubProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { + return &StubProxy{ + frontendAddr: frontendAddr, + backendAddr: backendAddr, + }, nil +}