diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index 21b444d6f5..fdbead8017 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -74,14 +74,6 @@ func TestBridge(t *testing.T) { t.Fatal(err) } - epList := network.Endpoints() - if len(epList) != 1 { - t.Fatal(err) - } - if ep != epList[0] { - t.Fatal(err) - } - if err := ep.Delete(); err != nil { t.Fatal(err) } @@ -299,3 +291,83 @@ func TestUnknownEndpoint(t *testing.T) { t.Fatal(err) } } + +func TestNetworkEndpointsWalkers(t *testing.T) { + defer netutils.SetupTestNetNS(t)() + controller := libnetwork.New() + netType := "bridge" + + option := options.Generic{} + err := controller.ConfigureNetworkDriver(netType, option) + if err != nil { + t.Fatal(err) + } + + // Create network 1 and add 2 endpoint: ep11, ep12 + net1, err := controller.NewNetwork(netType, "network1", "") + if err != nil { + t.Fatal(err) + } + ep11, err := net1.CreateEndpoint("ep11", "sbox1", nil) + if err != nil { + t.Fatal(err) + } + ep12, err := net1.CreateEndpoint("ep12", "sbox2", nil) + if err != nil { + t.Fatal(err) + } + + // Test list methods on net1 + epList1 := net1.Endpoints() + if len(epList1) != 2 { + t.Fatalf("Endpoints() returned wrong number of elements: %d instead of 2", len(epList1)) + } + // endpoint order is not guaranteed + for _, e := range epList1 { + if e != ep11 && e != ep12 { + t.Fatal("Endpoints() did not return all the expected elements") + } + } + + // Test Endpoint Walk method + var epName string + var epWanted libnetwork.Endpoint + wlk := func(ep libnetwork.Endpoint) bool { + if ep.Name() == epName { + epWanted = ep + return true + } + return false + } + + // Look for ep1 on network1 + epName = "ep11" + net1.WalkEndpoints(wlk) + if epWanted == nil { + t.Fatal(err) + } + if ep11 != epWanted { + t.Fatal(err) + } + + // Test Network Walk method + var netName string + var netWanted libnetwork.Network + nwWlk := func(nw libnetwork.Network) bool { + if nw.Name() == netName { + netWanted = nw + return true + } + return false + } + + // Look for network named "network1" + netName = "network1" + controller.WalkNetworks(nwWlk) + if netWanted == nil { + t.Fatal(err) + } + if net1 != netWanted { + t.Fatal(err) + } +} diff --git a/libnetwork/network.go b/libnetwork/network.go index 37197885a6..4e2472cbb5 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -52,9 +52,16 @@ import ( type NetworkController interface { // ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type ConfigureNetworkDriver(networkType string, options interface{}) error + // Create a new network. The options parameter carries network specific options. // Labels support will be added in the near future. NewNetwork(networkType, name string, options interface{}) (Network, error) + + // Networks returns the list of Network(s) managed by this controller. + Networks() []Network + + // WalkNetworks uses the provided function to walk the Network(s) managed by this controller. + WalkNetworks(walker NetworkWalker) } // A Network represents a logical connectivity zone that containers may @@ -74,13 +81,20 @@ type Network interface { // Labels support will be added in the near future. CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, error) - // Endpoints returns the list of Endpoint in this network. + // Endpoints returns the list of Endpoint(s) in this network. Endpoints() []Endpoint + // WalkEndpoints uses the provided function to walk the Endpoints + WalkEndpoints(walker EndpointWalker) + // Delete the network. Delete() error } +// NetworkWalker is a client provided function which will be used to walk the Networks. +// When the function returns true, the walk will stop. +type NetworkWalker func(nw Network) bool + // Endpoint represents a logical connection between a network and a sandbox. type Endpoint interface { // A system generated id for this endpoint. @@ -99,12 +113,9 @@ type Endpoint interface { Delete() error } -type endpoint struct { - name string - id types.UUID - network *network - sandboxInfo *sandbox.Info -} +// EndpointWalker is a client provided function which will be used to walk the Endpoints. +// When the function returns true, the walk will stop. +type EndpointWalker func(ep Endpoint) bool type network struct { ctrlr *controller @@ -116,6 +127,13 @@ type network struct { sync.Mutex } +type endpoint struct { + name string + id types.UUID + network *network + sandboxInfo *sandbox.Info +} + type networkTable map[types.UUID]*network type endpointTable map[types.UUID]*endpoint @@ -179,6 +197,26 @@ func (c *controller) NewNetwork(networkType, name string, options interface{}) ( return network, nil } +func (c *controller) Networks() []Network { + c.Lock() + defer c.Unlock() + + list := make([]Network, 0, len(c.networks)) + for _, n := range c.networks { + list = append(list, n) + } + + return list +} + +func (c *controller) WalkNetworks(walker NetworkWalker) { + for _, n := range c.Networks() { + if walker(n) { + return + } + } +} + func (n *network) Name() string { return n.name } @@ -248,18 +286,22 @@ func (n *network) CreateEndpoint(name string, sboxKey string, options interface{ func (n *network) Endpoints() []Endpoint { n.Lock() defer n.Unlock() - - list := make([]Endpoint, len(n.endpoints)) - - idx := 0 + list := make([]Endpoint, 0, len(n.endpoints)) for _, e := range n.endpoints { - list[idx] = e - idx++ + list = append(list, e) } return list } +func (n *network) WalkEndpoints(walker EndpointWalker) { + for _, e := range n.Endpoints() { + if walker(e) { + return + } + } +} + func (ep *endpoint) ID() string { return string(ep.id) }