瀏覽代碼

Test coverage on bridge

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
Arnaud Porterie 10 年之前
父節點
當前提交
3845ec20c4

+ 53 - 0
libnetwork/drivers/bridge/bridge_test.go

@@ -0,0 +1,53 @@
+package bridge
+
+import (
+	"net"
+	"testing"
+
+	"github.com/docker/libnetwork"
+)
+
+func TestCreate(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	config := &Configuration{BridgeName: DefaultBridgeName}
+	netw, err := Create(config)
+	if err != nil {
+		t.Fatalf("Failed to create bridge: %v", err)
+	}
+
+	if expected := NetworkType; netw.Type() != NetworkType {
+		t.Fatalf("Expected networkType %q, got %q", expected, netw.Type())
+	}
+}
+
+func TestCreateFail(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	config := &Configuration{BridgeName: "dummy0"}
+	if _, err := Create(config); err == nil {
+		t.Fatal("Bridge creation was expected to fail")
+	}
+}
+
+func TestCreateFullOptions(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	config := &Configuration{
+		BridgeName:         DefaultBridgeName,
+		EnableIPv6:         true,
+		FixedCIDR:          bridgeNetworks[0],
+		EnableIPTables:     true,
+		EnableIPForwarding: true,
+	}
+	_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
+
+	netw, err := Create(config)
+	if err != nil {
+		t.Fatalf("Failed to create bridge: %v", err)
+	}
+
+	if expected := NetworkType; netw.Type() != NetworkType {
+		t.Fatalf("Expected networkType %q, got %q", expected, netw.Type())
+	}
+}

+ 3 - 0
libnetwork/drivers/bridge/interface.go

@@ -44,5 +44,8 @@ func (i *Interface) Addresses() (netlink.Addr, []netlink.Addr, error) {
 		return netlink.Addr{}, nil, err
 	}
 
+	if len(v4addr) == 0 {
+		return netlink.Addr{}, v6addr, nil
+	}
 	return v4addr[0], v6addr, nil
 }

+ 32 - 0
libnetwork/drivers/bridge/interface_test.go

@@ -0,0 +1,32 @@
+package bridge
+
+import (
+	"testing"
+
+	"github.com/docker/libnetwork"
+	"github.com/vishvananda/netlink"
+)
+
+func TestInterfaceDefaultName(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	if inf := NewInterface(&Configuration{}); inf.Config.BridgeName != DefaultBridgeName {
+		t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, inf.Config.BridgeName)
+	}
+}
+
+func TestAddressesEmptyInterface(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	inf := NewInterface(&Configuration{})
+	addrv4, addrsv6, err := inf.Addresses()
+	if err != nil {
+		t.Fatalf("Failed to get addresses of default interface: %v", err)
+	}
+	if expected := (netlink.Addr{}); addrv4 != expected {
+		t.Fatalf("Default interface has unexpected IPv4: %s", addrv4)
+	}
+	if len(addrsv6) != 0 {
+		t.Fatalf("Default interface has unexpected IPv6: %v", addrsv6)
+	}
+}

+ 53 - 0
libnetwork/drivers/bridge/resolvconf_test.go

@@ -0,0 +1,53 @@
+package bridge
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestResolveConfRead(t *testing.T) {
+	b, err := readResolvConf()
+	if err != nil {
+		t.Fatalf("Failed to read resolv.conf: %v", err)
+	}
+
+	if b == nil {
+		t.Fatal("Reading resolv.conf returned no content")
+	}
+}
+
+func TestResolveConfReadLines(t *testing.T) {
+	commentChar := []byte("#")
+
+	b, _ := readResolvConf()
+	lines := getLines(b, commentChar)
+	if lines == nil {
+		t.Fatal("Failed to read resolv.conf lines")
+	}
+
+	for _, line := range lines {
+		if bytes.Index(line, commentChar) != -1 {
+			t.Fatal("Returned comment content from resolv.conf")
+		}
+	}
+}
+
+func TestResolvConfNameserversAsCIDR(t *testing.T) {
+	resolvConf := `# Commented line
+nameserver 1.2.3.4
+
+nameserver 5.6.7.8 # Test
+`
+
+	cidrs := getNameserversAsCIDR([]byte(resolvConf))
+	if expected := 2; len(cidrs) != expected {
+		t.Fatalf("Expected %d nameservers, got %d", expected, len(cidrs))
+	}
+
+	expected := []string{"1.2.3.4/32", "5.6.7.8/32"}
+	for i, exp := range expected {
+		if cidrs[i] != exp {
+			t.Fatalf("Expected nameservers %s, got %s", exp, cidrs[i])
+		}
+	}
+}

+ 7 - 1
libnetwork/drivers/bridge/setup_fixedcidrv4.go

@@ -1,6 +1,8 @@
 package bridge
 
 import (
+	"fmt"
+
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/networkdriver/ipallocator"
 )
@@ -12,5 +14,9 @@ func SetupFixedCIDRv4(i *Interface) error {
 	}
 
 	log.Debugf("Using IPv4 subnet: %v", i.Config.FixedCIDR)
-	return ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR)
+	if err := ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR); err != nil {
+		return fmt.Errorf("Setup FixedCIDRv4 failed for subnet %s in %s: %v", i.Config.FixedCIDR, addrv4.IPNet, err)
+	}
+
+	return nil
 }

+ 59 - 0
libnetwork/drivers/bridge/setup_fixedcidrv4_test.go

@@ -0,0 +1,59 @@
+package bridge
+
+import (
+	"net"
+	"testing"
+
+	"github.com/docker/docker/daemon/networkdriver/ipallocator"
+	"github.com/docker/libnetwork"
+)
+
+func TestSetupFixedCIDRv4(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	br := &Interface{
+		Config: &Configuration{
+			BridgeName:  DefaultBridgeName,
+			AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(16, 32)},
+			FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
+		},
+	}
+	if err := SetupDevice(br); err != nil {
+		t.Fatalf("Bridge creation failed: %v", err)
+	}
+	if err := SetupBridgeIPv4(br); err != nil {
+		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
+	}
+
+	if err := SetupFixedCIDRv4(br); err != nil {
+		t.Fatalf("Failed to setup bridge FixedCIDRv4: %v", err)
+	}
+
+	if ip, err := ipallocator.RequestIP(br.Config.FixedCIDR, nil); err != nil {
+		t.Fatalf("Failed to request IP to allocator: %v", err)
+	} else if expected := "192.168.2.1"; ip.String() != expected {
+		t.Fatalf("Expected allocated IP %s, got %s", expected, ip)
+	}
+}
+
+func TestSetupBadFixedCIDRv4(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	br := &Interface{
+		Config: &Configuration{
+			BridgeName:  DefaultBridgeName,
+			AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(24, 32)},
+			FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
+		},
+	}
+	if err := SetupDevice(br); err != nil {
+		t.Fatalf("Bridge creation failed: %v", err)
+	}
+	if err := SetupBridgeIPv4(br); err != nil {
+		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
+	}
+
+	if err := SetupFixedCIDRv4(br); err == nil {
+		t.Fatal("Setup bridge FixedCIDRv4 should have failed")
+	}
+}

+ 5 - 7
libnetwork/drivers/bridge/setup_ipv4.go

@@ -105,13 +105,11 @@ func checkRouteOverlaps(toCheck *net.IPNet) error {
 }
 
 func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
-	if len(netX.IP) == len(netY.IP) {
-		if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
-			return true
-		}
-		if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
-			return true
-		}
+	if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
+		return true
+	}
+	if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
+		return true
 	}
 	return false
 }

+ 22 - 6
libnetwork/drivers/bridge/setup_verify.go

@@ -1,6 +1,10 @@
 package bridge
 
-import "fmt"
+import (
+	"fmt"
+
+	"github.com/vishvananda/netlink"
+)
 
 func SetupVerifyConfiguredAddresses(i *Interface) error {
 	// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
@@ -9,6 +13,11 @@ func SetupVerifyConfiguredAddresses(i *Interface) error {
 		return err
 	}
 
+	// Verify that the bridge does have an IPv4 address.
+	if addrv4.IPNet == nil {
+		return fmt.Errorf("Bridge has no IPv4 address configured")
+	}
+
 	// Verify that the bridge IPv4 address matches the requested configuration.
 	if i.Config.AddressIPv4 != nil && !addrv4.IP.Equal(i.Config.AddressIPv4.IP) {
 		return fmt.Errorf("Bridge IPv4 (%s) does not match requested configuration %s", addrv4.IP, i.Config.AddressIPv4.IP)
@@ -16,11 +25,18 @@ func SetupVerifyConfiguredAddresses(i *Interface) error {
 
 	// Verify that one of the bridge IPv6 addresses matches the requested
 	// configuration.
-	for _, addrv6 := range addrsv6 {
-		if addrv6.String() == BridgeIPv6.String() {
-			return nil
-		}
+	if i.Config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: BridgeIPv6}, addrsv6) {
+		return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6)
 	}
 
-	return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6)
+	return nil
+}
+
+func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
+	for _, addrv6 := range addresses {
+		if addrv6.String() == addr.String() {
+			return true
+		}
+	}
+	return false
 }

+ 105 - 0
libnetwork/drivers/bridge/setup_verify_test.go

@@ -0,0 +1,105 @@
+package bridge
+
+import (
+	"net"
+	"testing"
+
+	"github.com/docker/libnetwork"
+	"github.com/vishvananda/netlink"
+)
+
+func setupVerifyTest(t *testing.T) *Interface {
+	inf := &Interface{Config: &Configuration{}}
+
+	br := netlink.Bridge{}
+	br.LinkAttrs.Name = "default0"
+	if err := netlink.LinkAdd(&br); err == nil {
+		inf.Link = &br
+	} else {
+		t.Fatalf("Failed to create bridge interface: %v", err)
+	}
+
+	return inf
+}
+
+func TestSetupVerify(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	addrv4 := net.IPv4(192, 168, 1, 1)
+	inf := setupVerifyTest(t)
+	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	}
+
+	if err := SetupVerifyConfiguredAddresses(inf); err != nil {
+		t.Fatalf("Address verification failed: %v", err)
+	}
+}
+
+func TestSetupVerifyBad(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	addrv4 := net.IPv4(192, 168, 1, 1)
+	inf := setupVerifyTest(t)
+	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+
+	ipnet := &net.IPNet{IP: net.IPv4(192, 168, 1, 2), Mask: addrv4.DefaultMask()}
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: ipnet}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", ipnet, err)
+	}
+
+	if err := SetupVerifyConfiguredAddresses(inf); err == nil {
+		t.Fatal("Address verification was expected to fail")
+	}
+}
+
+func TestSetupVerifyMissing(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	addrv4 := net.IPv4(192, 168, 1, 1)
+	inf := setupVerifyTest(t)
+	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+
+	if err := SetupVerifyConfiguredAddresses(inf); err == nil {
+		t.Fatal("Address verification was expected to fail")
+	}
+}
+
+func TestSetupVerifyIPv6(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	addrv4 := net.IPv4(192, 168, 1, 1)
+	inf := setupVerifyTest(t)
+	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	inf.Config.EnableIPv6 = true
+
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: BridgeIPv6}); err != nil {
+		t.Fatalf("Failed to assign IPv6 %s to interface: %v", BridgeIPv6, err)
+	}
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	}
+
+	if err := SetupVerifyConfiguredAddresses(inf); err != nil {
+		t.Fatalf("Address verification failed: %v", err)
+	}
+}
+
+func TestSetupVerifyIPv6Missing(t *testing.T) {
+	defer libnetwork.SetupTestNetNS(t)()
+
+	addrv4 := net.IPv4(192, 168, 1, 1)
+	inf := setupVerifyTest(t)
+	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	inf.Config.EnableIPv6 = true
+
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	}
+
+	if err := SetupVerifyConfiguredAddresses(inf); err == nil {
+		t.Fatal("Address verification was expected to fail")
+	}
+}

+ 1 - 1
libnetwork/network.go

@@ -17,7 +17,7 @@
 //    // For each new container: allocate IP and interfaces. The returned network
 //    // settings will be used for container infos (inspect and such), as well as
 //    // iptables rules for port publishing.
-//    interfaces, err := network.CreateInterfaces(containerID)
+//    interfaces, err := network.Link(containerID)
 //    if err != nil {
 //    	return err
 //    }