func TestIPDataMarshalling(t *testing.T) { i := &IPAMData{ AddressSpace: "giallo", Pool: &net.IPNet{IP: net.IP{10, 10, 10, 8}, Mask: net.IPMask{255, 255, 255, 0}}, Gateway: &net.IPNet{IP: net.IP{10, 10, 10, 254}, Mask: net.IPMask{255, 255, 255, 0}}, AuxAddresses: map[string]*net.IPNet{ "ip1": &net.IPNet{IP: net.IP{10, 10, 10, 1}, Mask: net.IPMask{255, 255, 255, 0}}, "ip2": &net.IPNet{IP: net.IP{10, 10, 10, 2}, Mask: net.IPMask{255, 255, 255, 0}}, }, } b, err := json.Marshal(i) if err != nil { t.Fatal(err) } ii := &IPAMData{} err = json.Unmarshal(b, &ii) if err != nil { t.Fatal(err) } if i.AddressSpace != ii.AddressSpace || !types.CompareIPNet(i.Pool, ii.Pool) || !types.CompareIPNet(i.Gateway, ii.Gateway) || !compareAddresses(i.AuxAddresses, ii.AuxAddresses) { t.Fatalf("JSON marsh/unmarsh failed.\nOriginal:\n%s\nDecoded:\n%s", i, ii) } }
// Install/Removes the iptables rules needed to isolate this network // from each of the other networks func (n *bridgeNetwork) isolateNetwork(others []*bridgeNetwork, enable bool) error { n.Lock() thisV4 := n.bridge.bridgeIPv4 thisV6 := getV6Network(n.config, n.bridge) n.Unlock() // Install the rules to isolate this networks against each of the other networks for _, o := range others { o.Lock() otherV4 := o.bridge.bridgeIPv4 otherV6 := getV6Network(o.config, o.bridge) o.Unlock() if !types.CompareIPNet(thisV4, otherV4) { // It's ok to pass a.b.c.d/x, iptables will ignore the host subnet bits if err := setINC(thisV4.String(), otherV4.String(), enable); err != nil { return err } } if thisV6 != nil && otherV6 != nil && !types.CompareIPNet(thisV6, otherV6) { if err := setINC(thisV6.String(), otherV6.String(), enable); err != nil { return err } } } return nil }
func compareEndpointInterface(a, b *endpointInterface) bool { if a == b { return true } if a == nil || b == nil { return false } return a.srcName == b.srcName && a.dstPrefix == b.dstPrefix && a.v4PoolID == b.v4PoolID && a.v6PoolID == b.v6PoolID && types.CompareIPNet(a.addr, b.addr) && types.CompareIPNet(a.addrv6, b.addrv6) }
func TestNetworkRequest(t *testing.T) { defer testutils.SetupTestOSContext(t)() ipamutils.InitNetworks() nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) if err != nil { t.Fatal(err) } var found bool for _, exp := range ipamutils.PredefinedBroadNetworks { if types.CompareIPNet(exp, nw) { found = true break } } if !found { t.Fatalf("Found unexpected broad network %s", nw) } nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks) if err != nil { t.Fatal(err) } found = false for _, exp := range ipamutils.PredefinedGranularNetworks { if types.CompareIPNet(exp, nw) { found = true break } } if !found { t.Fatalf("Found unexpected granular network %s", nw) } // Add iface and ssert returned address on request createInterface(t, "test", "172.17.42.1/16") _, exp, err := net.ParseCIDR("172.18.0.0/16") if err != nil { t.Fatal(err) } nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) if err != nil { t.Fatal(err) } if !types.CompareIPNet(exp, nw) { t.Fatalf("exected %s. got %s", exp, nw) } }
func TestPredefinedPool(t *testing.T) { a, err := getAllocator() if err != nil { t.Fatal(err) } if _, err := a.getPredefinedPool("blue", false); err == nil { t.Fatalf("Expected failure for non default addr space") } exp, err := ipamutils.FindAvailableNetwork(a.predefined[localAddressSpace]) if err != nil { t.Fatal(err) } nw, err := a.getPredefinedPool(localAddressSpace, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(nw, exp) { t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp) } pid, nw, _, err := a.RequestPool(localAddressSpace, exp.String(), "", nil, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(nw, exp) { t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp) } nw2, err := a.getPredefinedPool(localAddressSpace, false) if err != nil { t.Fatal(err) } if types.CompareIPNet(nw, nw2) { t.Fatalf("Unexpected default network returned: %s = %s", nw2, nw) } if err := a.ReleasePool(pid); err != nil { t.Fatal(err) } nw, err = a.getPredefinedPool(localAddressSpace, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(nw, exp) { t.Fatalf("Unexpected default network returned: %s. Expected %s", nw, exp) } }
func TestPoolDataMarshal(t *testing.T) { _, nw, err := net.ParseCIDR("172.28.30.1/24") if err != nil { t.Fatal(err) } p := &PoolData{ ParentKey: SubnetKey{AddressSpace: "Blue", Subnet: "172.28.0.0/16"}, Pool: nw, Range: &AddressRange{Sub: &net.IPNet{IP: net.IP{172, 28, 20, 0}, Mask: net.IPMask{255, 255, 255, 0}}, Start: 0, End: 255}, RefCount: 4, } ba, err := json.Marshal(p) if err != nil { t.Fatal(err) } var q PoolData err = json.Unmarshal(ba, &q) if err != nil { t.Fatal(err) } if p.ParentKey != q.ParentKey || !types.CompareIPNet(p.Range.Sub, q.Range.Sub) || p.Range.Start != q.Range.Start || p.Range.End != q.Range.End || p.RefCount != q.RefCount || !types.CompareIPNet(p.Pool, q.Pool) { t.Fatalf("\n%#v\n%#v", p, &q) } p = &PoolData{ ParentKey: SubnetKey{AddressSpace: "Blue", Subnet: "172.28.0.0/16"}, Pool: nw, RefCount: 4, } ba, err = json.Marshal(p) if err != nil { t.Fatal(err) } err = json.Unmarshal(ba, &q) if err != nil { t.Fatal(err) } if q.Range != nil { t.Fatalf("Unexpected Range") } }
func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error { // Fetch a single IPv4 and a slice of IPv6 addresses from the bridge. addrv4, addrsv6, err := i.addresses() if err != nil { return fmt.Errorf("Failed to verify ip addresses: %v", err) } // Verify that the bridge does have an IPv4 address. if addrv4.IPNet == nil { return &ErrNoIPAddr{} } // Verify that the bridge IPv4 address matches the requested configuration. if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) { return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP} } // Verify that one of the bridge IPv6 addresses matches the requested // configuration. if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) { return (*IPv6AddrNoMatchError)(bridgeIPv6) } // Release any residual IPv6 address that might be there because of older daemon instances for _, addrv6 := range addrsv6 { if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) { if err := i.nlh.AddrDel(i.Link, &addrv6); err != nil { log.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err) } } } return nil }
func TestPoolRequest(t *testing.T) { a := allocator{} pid, pool, _, err := a.RequestPool(defaultAS, "", "", nil, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(defaultPool, pool) { t.Fatalf("Unexpected pool returned. Expected %v. Got: %v", defaultPool, pool) } if pid != defaultPoolID { t.Fatalf("Unexpected pool id returned. Expected: %s. Got: %s", defaultPoolID, pid) } _, _, _, err = a.RequestPool("default", "", "", nil, false) if err == nil { t.Fatalf("Unexpected success") } _, _, _, err = a.RequestPool(defaultAS, "192.168.0.0/16", "", nil, false) if err == nil { t.Fatalf("Unexpected success") } _, _, _, err = a.RequestPool(defaultAS, "", "192.168.0.0/24", nil, false) if err == nil { t.Fatalf("Unexpected success") } _, _, _, err = a.RequestPool(defaultAS, "", "", nil, true) if err == nil { t.Fatalf("Unexpected success") } }
func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error { addrv4List, _, err := i.addresses() if err != nil { return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err) } addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4) if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) { if addrv4.IPNet != nil { if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil { return fmt.Errorf("failed to remove current ip address from bridge: %v", err) } } log.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4) if err := i.nlh.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil { return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err} } } // Store bridge network and default gateway i.bridgeIPv4 = config.AddressIPv4 i.gatewayIPv4 = config.AddressIPv4.IP return nil }
func TestPredefinedPool(t *testing.T) { a, err := getAllocator() if err != nil { t.Fatal(err) } if _, err := a.getPredefinedPool("blue", false); err == nil { t.Fatalf("Expected failure for non default addr space") } pid, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false) if err != nil { t.Fatal(err) } nw2, err := a.getPredefinedPool(localAddressSpace, false) if err != nil { t.Fatal(err) } if types.CompareIPNet(nw, nw2) { t.Fatalf("Unexpected default network returned: %s = %s", nw2, nw) } if err := a.ReleasePool(pid); err != nil { t.Fatal(err) } }
func TestIpamReleaseOnNetDriverFailures(t *testing.T) { if !testutils.IsRunningInContainer() { defer testutils.SetupTestOSContext(t)() } cfgOptions, err := OptionBoltdbWithRandomDBFile() c, err := New(cfgOptions...) if err != nil { t.Fatal(err) } defer c.Stop() cc := c.(*controller) bd := badDriver{failNetworkCreation: true} cc.drivers[badDriverName] = &driverData{driver: &bd, capability: driverapi.Capability{DataScope: datastore.LocalScope}} // Test whether ipam state release is invoked on network create failure from net driver // by checking whether subsequent network creation requesting same gateway IP succeeds ipamOpt := NetworkOptionIpam(ipamapi.DefaultIPAM, "", []*IpamConf{&IpamConf{PreferredPool: "10.34.0.0/16", Gateway: "10.34.255.254"}}, nil) if _, err := c.NewNetwork(badDriverName, "badnet1", ipamOpt); err == nil { t.Fatalf("bad network driver should have failed network creation") } gnw, err := c.NewNetwork("bridge", "goodnet1", ipamOpt) if err != nil { t.Fatal(err) } gnw.Delete() // Now check whether ipam release works on endpoint creation failure bd.failNetworkCreation = false bnw, err := c.NewNetwork(badDriverName, "badnet2", ipamOpt) if err != nil { t.Fatal(err) } defer bnw.Delete() if _, err := bnw.CreateEndpoint("ep0"); err == nil { t.Fatalf("bad network driver should have failed endpoint creation") } // Now create good bridge network with different gateway ipamOpt2 := NetworkOptionIpam(ipamapi.DefaultIPAM, "", []*IpamConf{&IpamConf{PreferredPool: "10.34.0.0/16", Gateway: "10.34.255.253"}}, nil) gnw, err = c.NewNetwork("bridge", "goodnet2", ipamOpt2) if err != nil { t.Fatal(err) } defer gnw.Delete() ep, err := gnw.CreateEndpoint("ep1") if err != nil { t.Fatal(err) } defer ep.Delete() expectedIP, _ := types.ParseCIDR("10.34.0.1/16") if !types.CompareIPNet(ep.Info().Iface().Address(), expectedIP) { t.Fatalf("Ipam release must have failed, endpoint has unexpected address: %v", ep.Info().Iface().Address()) } }
func TestSubnetsMarshal(t *testing.T) { a, err := getAllocator() if err != nil { t.Fatal(err) } pid0, _, _, err := a.RequestPool(localAddressSpace, "192.168.0.0/16", "", nil, false) if err != nil { t.Fatal(err) } pid1, _, _, err := a.RequestPool(localAddressSpace, "192.169.0.0/16", "", nil, false) if err != nil { t.Fatal(err) } _, _, err = a.RequestAddress(pid0, nil, nil) if err != nil { t.Fatal(err) } cfg, err := a.getAddrSpace(localAddressSpace) if err != nil { t.Fatal(err) } ba := cfg.Value() if err := cfg.SetValue(ba); err != nil { t.Fatal(err) } expIP := &net.IPNet{IP: net.IP{192, 168, 0, 2}, Mask: net.IPMask{255, 255, 0, 0}} ip, _, err := a.RequestAddress(pid0, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(expIP, ip) { t.Fatalf("Got unexpected ip after pool config restore: %s", ip) } expIP = &net.IPNet{IP: net.IP{192, 169, 0, 1}, Mask: net.IPMask{255, 255, 0, 0}} ip, _, err = a.RequestAddress(pid1, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(expIP, ip) { t.Fatalf("Got unexpected ip after pool config restore: %s", ip) } }
func compareIPNets(t *testing.T, kind string, shouldBe string, supplied net.IPNet) { _, net, _ := net.ParseCIDR(shouldBe) if net == nil { t.Fatalf(`Invalid IP network to test against: "%s"`, shouldBe) } if !types.CompareIPNet(net, &supplied) { t.Fatalf(`%s IP networks are not equal: expected "%s", got %v`, kind, shouldBe, supplied) } }
func compareIpamInfoList(listA, listB []*IpamInfo) bool { var a, b *IpamInfo if len(listA) != len(listB) { return false } for i := 0; i < len(listA); i++ { a = listA[i] b = listB[i] if a.PoolID != b.PoolID || !compareStringMaps(a.Meta, b.Meta) || !types.CompareIPNet(a.Gateway, b.Gateway) || a.AddressSpace != b.AddressSpace || !types.CompareIPNet(a.Pool, b.Pool) || !compareAddresses(a.AuxAddresses, b.AuxAddresses) { return false } } return true }
func TestNetworkRequest(t *testing.T) { defer testutils.SetupTestOSContext(t)() ipamutils.InitNetworks() _, exp, err := net.ParseCIDR("172.17.0.0/16") if err != nil { t.Fatal(err) } nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) if err != nil { t.Fatal(err) } if !types.CompareIPNet(exp, nw) { t.Fatalf("exected %s. got %s", exp, nw) } _, exp, err = net.ParseCIDR("10.0.0.0/24") if err != nil { t.Fatal(err) } nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks) if err != nil { t.Fatal(err) } if !types.CompareIPNet(exp, nw) { t.Fatalf("exected %s. got %s", exp, nw) } // Add iface and ssert returned address on request createInterface(t, "test", "172.17.42.1/16") _, exp, err = net.ParseCIDR("172.18.0.0/16") if err != nil { t.Fatal(err) } nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) if err != nil { t.Fatal(err) } if !types.CompareIPNet(exp, nw) { t.Fatalf("exected %s. got %s", exp, nw) } }
func compareNwLists(a, b []*net.IPNet) bool { if len(a) != len(b) { return false } for k := range a { if !types.CompareIPNet(a[k], b[k]) { return false } } return true }
func compareAddresses(a, b map[string]*net.IPNet) bool { if len(a) != len(b) { return false } if len(a) > 0 { for k := range a { if !types.CompareIPNet(a[k], b[k]) { return false } } } return true }
// Testing IPV6 from MAC address func TestBridgeIpv6FromMac(t *testing.T) { if !testutils.IsRunningInContainer() { defer testutils.SetupTestOSContext(t)() } netOption := options.Generic{ netlabel.GenericData: options.Generic{ "BridgeName": "testipv6mac", "EnableICC": true, "EnableIPMasquerade": true, }, } ipamV4ConfList := []*libnetwork.IpamConf{{PreferredPool: "192.168.100.0/24", Gateway: "192.168.100.1"}} ipamV6ConfList := []*libnetwork.IpamConf{{PreferredPool: "fe90::/64", Gateway: "fe90::22"}} network, err := controller.NewNetwork(bridgeNetType, "testipv6mac", "", libnetwork.NetworkOptionGeneric(netOption), libnetwork.NetworkOptionEnableIPv6(true), libnetwork.NetworkOptionIpam(ipamapi.DefaultIPAM, "", ipamV4ConfList, ipamV6ConfList, nil), libnetwork.NetworkOptionDeferIPv6Alloc(true)) if err != nil { t.Fatal(err) } mac := net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} epOption := options.Generic{netlabel.MacAddress: mac} ep, err := network.CreateEndpoint("testep", libnetwork.EndpointOptionGeneric(epOption)) if err != nil { t.Fatal(err) } iface := ep.Info().Iface() if !bytes.Equal(iface.MacAddress(), mac) { t.Fatalf("Unexpected mac address: %v", iface.MacAddress()) } ip, expIP, _ := net.ParseCIDR("fe90::aabb:ccdd:eeff/64") expIP.IP = ip if !types.CompareIPNet(expIP, iface.AddressIPv6()) { t.Fatalf("Expected %v. Got: %v", expIP, iface.AddressIPv6()) } if err := ep.Delete(false); err != nil { t.Fatal(err) } if err := network.Delete(); err != nil { t.Fatal(err) } }
// Equal checks if this instance of Interface is equal to the passed one func (i *Interface) Equal(o *Interface) bool { if i == o { return true } if o == nil { return false } if i.SrcName != o.SrcName || i.DstName != o.DstName { return false } if !types.CompareIPNet(i.Address, o.Address) { return false } if !types.CompareIPNet(i.AddressIPv6, o.AddressIPv6) { return false } return true }
func TestRequestReleaseAddressFromSubPool(t *testing.T) { a, err := getAllocator() if err != nil { t.Fatal(err) } a.addrSpace2Configs["rosso"] = a.addrSpace2Configs[localAddressSpace] poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false) if err != nil { t.Fatal(err) } var ip *net.IPNet expected := &net.IPNet{IP: net.IP{172, 28, 30, 255}, Mask: net.IPMask{255, 255, 0, 0}} for err == nil { var c *net.IPNet if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { ip = c } } if err != ipamapi.ErrNoAvailableIPs { t.Fatal(err) } if !types.CompareIPNet(expected, ip) { t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) } rp := &net.IPNet{IP: net.IP{172, 28, 30, 97}, Mask: net.IPMask{255, 255, 0, 0}} if err = a.ReleaseAddress(poolID, rp.IP); err != nil { t.Fatal(err) } if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { t.Fatal(err) } if !types.CompareIPNet(rp, ip) { t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) } _, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false) if err != nil { t.Fatal(err) } poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false) if err != nil { t.Fatal(err) } expected = &net.IPNet{IP: net.IP{10, 0, 0, 255}, Mask: net.IPMask{255, 255, 0, 0}} for err == nil { var c *net.IPNet if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { ip = c } } if err != ipamapi.ErrNoAvailableIPs { t.Fatal(err) } if !types.CompareIPNet(expected, ip) { t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) } rp = &net.IPNet{IP: net.IP{10, 0, 0, 79}, Mask: net.IPMask{255, 255, 0, 0}} if err = a.ReleaseAddress(poolID, rp.IP); err != nil { t.Fatal(err) } if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { t.Fatal(err) } if !types.CompareIPNet(rp, ip) { t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) } }
func TestRemoteDriver(t *testing.T) { var plugin = "test-net-driver" ep := &testEndpoint{ t: t, src: "vethsrc", dst: "vethdst", address: "192.168.5.7/16", addressIPv6: "2001:DB8::5:7/48", macAddress: "ab:cd:ef:ee:ee:ee", gateway: "192.168.0.1", gatewayIPv6: "2001:DB8::1", hostsPath: "/here/comes/the/host/path", resolvConfPath: "/there/goes/the/resolv/conf", destination: "10.0.0.0/8", nextHop: "10.0.0.1", routeType: 1, } mux := http.NewServeMux() defer setupPlugin(t, plugin, mux)() var networkID string handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} { return map[string]interface{}{ "Scope": "global", } }) handle(t, mux, "CreateNetwork", func(msg map[string]interface{}) interface{} { nid := msg["NetworkID"] var ok bool if networkID, ok = nid.(string); !ok { t.Fatal("RPC did not include network ID string") } return map[string]interface{}{} }) handle(t, mux, "DeleteNetwork", func(msg map[string]interface{}) interface{} { if nid, ok := msg["NetworkID"]; !ok || nid != networkID { t.Fatal("Network ID missing or does not match that created") } return map[string]interface{}{} }) handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} { iface := map[string]interface{}{ "MacAddress": ep.macAddress, "Address": ep.address, "AddressIPv6": ep.addressIPv6, } return map[string]interface{}{ "Interface": iface, } }) handle(t, mux, "Join", func(msg map[string]interface{}) interface{} { options := msg["Options"].(map[string]interface{}) foo, ok := options["foo"].(string) if !ok || foo != "fooValue" { t.Fatalf("Did not receive expected foo string in request options: %+v", msg) } return map[string]interface{}{ "Gateway": ep.gateway, "GatewayIPv6": ep.gatewayIPv6, "HostsPath": ep.hostsPath, "ResolvConfPath": ep.resolvConfPath, "InterfaceName": map[string]interface{}{ "SrcName": ep.src, "DstPrefix": ep.dst, }, "StaticRoutes": []map[string]interface{}{ { "Destination": ep.destination, "RouteType": ep.routeType, "NextHop": ep.nextHop, }, }, } }) handle(t, mux, "Leave", func(msg map[string]interface{}) interface{} { return map[string]string{} }) handle(t, mux, "DeleteEndpoint", func(msg map[string]interface{}) interface{} { return map[string]interface{}{} }) handle(t, mux, "EndpointOperInfo", func(msg map[string]interface{}) interface{} { return map[string]interface{}{ "Value": map[string]string{ "Arbitrary": "key", "Value": "pairs?", }, } }) handle(t, mux, "DiscoverNew", func(msg map[string]interface{}) interface{} { return map[string]string{} }) handle(t, mux, "DiscoverDelete", func(msg map[string]interface{}) interface{} { return map[string]interface{}{} }) p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType) if err != nil { t.Fatal(err) } d := newDriver(plugin, p.Client) if d.Type() != plugin { t.Fatal("Driver type does not match that given") } c, err := d.(*driver).getCapabilities() if err != nil { t.Fatal(err) } else if c.DataScope != datastore.GlobalScope { t.Fatalf("get capability '%s', expecting 'global'", c.DataScope) } netID := "dummy-network" err = d.CreateNetwork(netID, map[string]interface{}{}, nil, nil, nil) if err != nil { t.Fatal(err) } endID := "dummy-endpoint" ifInfo := &testEndpoint{} err = d.CreateEndpoint(netID, endID, ifInfo, map[string]interface{}{}) if err != nil { t.Fatal(err) } if !bytes.Equal(ep.MacAddress(), ifInfo.MacAddress()) || !types.CompareIPNet(ep.Address(), ifInfo.Address()) || !types.CompareIPNet(ep.AddressIPv6(), ifInfo.AddressIPv6()) { t.Fatalf("Unexpected InterfaceInfo data. Expected (%s, %s, %s). Got (%v, %v, %v)", ep.MacAddress(), ep.Address(), ep.AddressIPv6(), ifInfo.MacAddress(), ifInfo.Address(), ifInfo.AddressIPv6()) } joinOpts := map[string]interface{}{"foo": "fooValue"} err = d.Join(netID, endID, "sandbox-key", ep, joinOpts) if err != nil { t.Fatal(err) } if _, err = d.EndpointOperInfo(netID, endID); err != nil { t.Fatal(err) } if err = d.Leave(netID, endID); err != nil { t.Fatal(err) } if err = d.DeleteEndpoint(netID, endID); err != nil { t.Fatal(err) } if err = d.DeleteNetwork(netID); err != nil { t.Fatal(err) } data := discoverapi.NodeDiscoveryData{ Address: "192.168.1.1", } if err = d.DiscoverNew(discoverapi.NodeDiscovery, data); err != nil { t.Fatal(err) } if err = d.DiscoverDelete(discoverapi.NodeDiscovery, data); err != nil { t.Fatal(err) } }
func TestWindowsIPAM(t *testing.T) { a := &allocator{} requestPool, _ := types.ParseCIDR("192.168.0.0/16") requestAddress := net.ParseIP("192.168.1.1") pid, pool, _, err := a.RequestPool(localAddressSpace, "", "", nil, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(defaultPool, pool) || pid != pool.String() { t.Fatalf("Unexpected data returned. Expected %v : %s. Got: %v : %s", defaultPool, pid, pool, pool.String()) } pid, pool, _, err = a.RequestPool(localAddressSpace, requestPool.String(), "", nil, false) if err != nil { t.Fatal(err) } if !types.CompareIPNet(requestPool, pool) || pid != requestPool.String() { t.Fatalf("Unexpected data returned. Expected %v : %s. Got: %v : %s", requestPool, requestPool.String(), pool, pool.String()) } _, _, _, err = a.RequestPool(localAddressSpace, requestPool.String(), requestPool.String(), nil, false) if err == nil { t.Fatal("Unexpected success for subpool request") } _, _, _, err = a.RequestPool(localAddressSpace, requestPool.String(), "", nil, true) if err == nil { t.Fatal("Unexpected success for v6 request") } err = a.ReleasePool(requestPool.String()) if err != nil { t.Fatal(err) } ip, _, err := a.RequestAddress(requestPool.String(), nil, map[string]string{}) if err != nil { t.Fatal(err) } if !types.CompareIPNet(ip, requestPool) { t.Fatalf("Unexpected data returned. Expected %v . Got: %v ", requestPool, ip) } ip, _, err = a.RequestAddress(requestPool.String(), requestAddress, map[string]string{}) if err != nil { t.Fatal(err) } if !ip.IP.Equal(requestAddress) { t.Fatalf("Unexpected data returned. Expected %v . Got: %v ", requestAddress, ip.IP) } err = a.ReleaseAddress(requestPool.String(), requestAddress) if err != nil { t.Fatal(err) } }
func runParallelTests(t *testing.T, instance int) { var err error t.Parallel() pTest := flag.Lookup("test.parallel") if pTest == nil { t.Skip("Skipped because test.parallel flag not set;") } numParallel, err := strconv.Atoi(pTest.Value.String()) if err != nil { t.Fatal(err) } if numParallel < numInstances { t.Skip("Skipped because t.parallel was less than ", numInstances) } // The first instance creates the allocator, gives the start // and finally checks the pools each instance was assigned if instance == first { allocator, err = getAllocator() if err != nil { t.Fatal(err) } close(start) } if instance != first { select { case <-start: } instDone := make(chan struct{}) done <- instDone defer close(instDone) if instance == last { defer close(done) } } _, pools[instance], _, err = allocator.RequestPool(localAddressSpace, "", "", nil, false) if err != nil { t.Fatal(err) } if instance == first { for instDone := range done { select { case <-instDone: } } // Now check each instance got a different pool for i := 0; i < numInstances; i++ { for j := i + 1; j < numInstances; j++ { if types.CompareIPNet(pools[i], pools[j]) { t.Fatalf("Instance %d and %d were given the same predefined pool: %v", i, j, pools) } } } } }
func TestCreateFullOptionsLabels(t *testing.T) { defer testutils.SetupTestOSContext(t)() d := newDriver() config := &configuration{ EnableIPForwarding: true, } genericOption := make(map[string]interface{}) genericOption[netlabel.GenericData] = config if err := d.configure(genericOption); err != nil { t.Fatalf("Failed to setup driver config: %v", err) } bndIPs := "127.0.0.1" nwV6s := "2100:2400:2600:2700:2800::/80" gwV6s := "2100:2400:2600:2700:2800::25/80" nwV6, _ := types.ParseCIDR(nwV6s) gwV6, _ := types.ParseCIDR(gwV6s) labels := map[string]string{ BridgeName: DefaultBridgeName, DefaultBridge: "true", netlabel.EnableIPv6: "true", EnableICC: "true", EnableIPMasquerade: "true", DefaultBindingIP: bndIPs, } netOption := make(map[string]interface{}) netOption[netlabel.GenericData] = labels ipdList := getIPv4Data(t) ipd6List := []driverapi.IPAMData{ driverapi.IPAMData{ Pool: nwV6, AuxAddresses: map[string]*net.IPNet{ DefaultGatewayV6AuxKey: gwV6, }, }, } err := d.CreateNetwork("dummy", netOption, ipdList, ipd6List) if err != nil { t.Fatalf("Failed to create bridge: %v", err) } nw, ok := d.networks["dummy"] if !ok { t.Fatalf("Cannot find dummy network in bridge driver") } if nw.config.BridgeName != DefaultBridgeName { t.Fatalf("incongruent name in bridge network") } if !nw.config.EnableIPv6 { t.Fatalf("incongruent EnableIPv6 in bridge network") } if !nw.config.EnableICC { t.Fatalf("incongruent EnableICC in bridge network") } if !nw.config.EnableIPMasquerade { t.Fatalf("incongruent EnableIPMasquerade in bridge network") } bndIP := net.ParseIP(bndIPs) if !bndIP.Equal(nw.config.DefaultBindingIP) { t.Fatalf("Unexpected: %v", nw.config.DefaultBindingIP) } if !types.CompareIPNet(nw.config.AddressIPv6, nwV6) { t.Fatalf("Unexpected: %v", nw.config.AddressIPv6) } if !gwV6.IP.Equal(nw.config.DefaultGatewayIPv6) { t.Fatalf("Unexpected: %v", nw.config.DefaultGatewayIPv6) } // In short here we are testing --fixed-cidr-v6 daemon option // plus --mac-address run option mac, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff") epOptions := map[string]interface{}{netlabel.MacAddress: mac} te := newTestEndpoint(ipdList[0].Pool, 20) err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions) if err != nil { t.Fatal(err) } if !nwV6.Contains(te.Interface().AddressIPv6().IP) { t.Fatalf("endpoint got assigned address outside of container network(%s): %s", nwV6.String(), te.Interface().AddressIPv6()) } if te.Interface().AddressIPv6().IP.String() != "2100:2400:2600:2700:2800:aabb:ccdd:eeff" { t.Fatalf("Unexpected endpoint IPv6 address: %v", te.Interface().AddressIPv6().IP) } }
func TestRequestReleaseAddressFromSubPool(t *testing.T) { a, err := getAllocator() if err != nil { t.Fatal(err) } a.addrSpaces["rosso"] = &addrSpace{ id: dsConfigKey + "/" + "rosso", ds: a.addrSpaces[localAddressSpace].ds, alloc: a.addrSpaces[localAddressSpace].alloc, scope: a.addrSpaces[localAddressSpace].scope, subnets: map[SubnetKey]*PoolData{}, } poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false) if err != nil { t.Fatal(err) } var ip *net.IPNet expected := &net.IPNet{IP: net.IP{172, 28, 30, 255}, Mask: net.IPMask{255, 255, 0, 0}} for err == nil { var c *net.IPNet if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { ip = c } } if err != ipamapi.ErrNoAvailableIPs { t.Fatal(err) } if !types.CompareIPNet(expected, ip) { t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) } rp := &net.IPNet{IP: net.IP{172, 28, 30, 97}, Mask: net.IPMask{255, 255, 0, 0}} if err = a.ReleaseAddress(poolID, rp.IP); err != nil { t.Fatal(err) } if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { t.Fatal(err) } if !types.CompareIPNet(rp, ip) { t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) } _, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false) if err != nil { t.Fatal(err) } poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false) if err != nil { t.Fatal(err) } expected = &net.IPNet{IP: net.IP{10, 0, 0, 255}, Mask: net.IPMask{255, 255, 0, 0}} for err == nil { var c *net.IPNet if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { ip = c } } if err != ipamapi.ErrNoAvailableIPs { t.Fatal(err) } if !types.CompareIPNet(expected, ip) { t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) } rp = &net.IPNet{IP: net.IP{10, 0, 0, 79}, Mask: net.IPMask{255, 255, 0, 0}} if err = a.ReleaseAddress(poolID, rp.IP); err != nil { t.Fatal(err) } if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { t.Fatal(err) } if !types.CompareIPNet(rp, ip) { t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) } // Request any addresses from subpool after explicit address request unoExp, _ := types.ParseCIDR("10.2.2.0/16") dueExp, _ := types.ParseCIDR("10.2.2.2/16") treExp, _ := types.ParseCIDR("10.2.2.1/16") if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil { t.Fatal(err) } tre, _, err := a.RequestAddress(poolID, treExp.IP, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(tre, treExp) { t.Fatalf("Unexpected address: %v", tre) } uno, _, err := a.RequestAddress(poolID, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(uno, unoExp) { t.Fatalf("Unexpected address: %v", uno) } due, _, err := a.RequestAddress(poolID, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(due, dueExp) { t.Fatalf("Unexpected address: %v", due) } if err = a.ReleaseAddress(poolID, uno.IP); err != nil { t.Fatal(err) } uno, _, err = a.RequestAddress(poolID, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(uno, unoExp) { t.Fatalf("Unexpected address: %v", uno) } if err = a.ReleaseAddress(poolID, tre.IP); err != nil { t.Fatal(err) } tre, _, err = a.RequestAddress(poolID, nil, nil) if err != nil { t.Fatal(err) } if !types.CompareIPNet(tre, treExp) { t.Fatalf("Unexpected address: %v", tre) } }
func TestEndpointMarshalling(t *testing.T) { ip1, _ := types.ParseCIDR("172.22.0.9/16") ip2, _ := types.ParseCIDR("2001:db8::9") mac, _ := net.ParseMAC("ac:bd:24:57:66:77") e := &bridgeEndpoint{ id: "d2c015a1fe5930650cbcd50493efba0500bcebd8ee1f4401a16319f8a567de33", nid: "ee33fbb43c323f1920b6b35a0101552ac22ede960d0e5245e9738bccc68b2415", addr: ip1, addrv6: ip2, macAddress: mac, srcName: "veth123456", config: &endpointConfiguration{MacAddress: mac}, containerConfig: &containerConfiguration{ ParentEndpoints: []string{"one", "due", "three"}, ChildEndpoints: []string{"four", "five", "six"}, }, extConnConfig: &connectivityConfiguration{ ExposedPorts: []types.TransportPort{ { Proto: 6, Port: uint16(18), }, }, PortBindings: []types.PortBinding{ { Proto: 6, IP: net.ParseIP("17210.33.9.56"), Port: uint16(18), HostPort: uint16(3000), HostPortEnd: uint16(14000), }, }, }, portMapping: []types.PortBinding{ { Proto: 17, IP: net.ParseIP("172.33.9.56"), Port: uint16(99), HostIP: net.ParseIP("10.10.100.2"), HostPort: uint16(9900), HostPortEnd: uint16(10000), }, { Proto: 6, IP: net.ParseIP("171.33.9.56"), Port: uint16(55), HostIP: net.ParseIP("10.11.100.2"), HostPort: uint16(5500), HostPortEnd: uint16(55000), }, }, } b, err := json.Marshal(e) if err != nil { t.Fatal(err) } ee := &bridgeEndpoint{} err = json.Unmarshal(b, ee) if err != nil { t.Fatal(err) } if e.id != ee.id || e.nid != ee.nid || e.srcName != ee.srcName || !bytes.Equal(e.macAddress, ee.macAddress) || !types.CompareIPNet(e.addr, ee.addr) || !types.CompareIPNet(e.addrv6, ee.addrv6) || !compareEpConfig(e.config, ee.config) || !compareContainerConfig(e.containerConfig, ee.containerConfig) || !compareConnConfig(e.extConnConfig, ee.extConnConfig) || !compareBindings(e.portMapping, ee.portMapping) { t.Fatalf("JSON marsh/unmarsh failed.\nOriginal:\n%#v\nDecoded:\n%#v", e, ee) } }