From 56c3adda07541eb39eb853eae3119be1bcf38b4d Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Thu, 16 Apr 2015 05:01:29 +0000 Subject: [PATCH] - Added more testcases for libnetwork API testing - Added new error types for all of libnetwork errors Signed-off-by: Jana Radhakrishnan --- libnetwork/error.go | 63 +++++++++ libnetwork/libnetwork_test.go | 234 ++++++++++++++++++++++++++++++++-- libnetwork/network.go | 35 +++-- 3 files changed, 310 insertions(+), 22 deletions(-) create mode 100644 libnetwork/error.go diff --git a/libnetwork/error.go b/libnetwork/error.go new file mode 100644 index 0000000000..da2d3f18f8 --- /dev/null +++ b/libnetwork/error.go @@ -0,0 +1,63 @@ +package libnetwork + +import ( + "errors" + "fmt" +) + +var ( + // ErrNilNetworkDriver is returned if a nil network driver + // is passed to NewNetwork api. + ErrNilNetworkDriver = errors.New("nil NetworkDriver instance") + // ErrInvalidNetworkDriver is returned if an invalid driver + // instance is passed. + ErrInvalidNetworkDriver = errors.New("invalid driver bound to network") +) + +// NetworkTypeError type is returned when the network type string is not +// known to libnetwork. +type NetworkTypeError string + +func (nt NetworkTypeError) Error() string { + return fmt.Sprintf("unknown driver %q", string(nt)) +} + +// NetworkNameError is returned when a network with the same name already exists. +type NetworkNameError string + +func (name NetworkNameError) Error() string { + return fmt.Sprintf("network with name %s already exists", string(name)) +} + +// UnknownNetworkError is returned when libnetwork could not find in it's database +// a network with the same name and id. +type UnknownNetworkError struct { + name string + id string +} + +func (une *UnknownNetworkError) Error() string { + return fmt.Sprintf("unknown network %s id %s", une.name, une.id) +} + +// ActiveEndpointsError is returned when a network is deleted which has active +// endpoints in it. +type ActiveEndpointsError struct { + name string + id string +} + +func (aee *ActiveEndpointsError) Error() string { + return fmt.Sprintf("network with name %s id %s has active endpoints", aee.name, aee.id) +} + +// UnknownEndpointError is returned when libnetwork could not find in it's database +// an endpoint with the same name and id. +type UnknownEndpointError struct { + name string + id string +} + +func (uee *UnknownEndpointError) Error() string { + return fmt.Sprintf("unknown endpoint %s id %s", uee.name, uee.id) +} diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index f122ef229c..2f6a1006e5 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -8,15 +8,27 @@ import ( "github.com/docker/libnetwork" _ "github.com/docker/libnetwork/drivers/bridge" "github.com/docker/libnetwork/pkg/options" - "github.com/vishvananda/netlink" ) var bridgeName = "dockertest0" -func TestSimplebridge(t *testing.T) { - bridge := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}} - netlink.LinkDel(bridge) +func createTestNetwork(networkType, networkName string, option options.Generic) (libnetwork.Network, error) { + controller := libnetwork.New() + driver, err := controller.NewNetworkDriver(networkType, option) + if err != nil { + return nil, err + } + + network, err := controller.NewNetwork(driver, networkName, "") + if err != nil { + return nil, err + } + + return network, nil +} + +func TestSimplebridge(t *testing.T) { ip, subnet, err := net.ParseCIDR("192.168.100.1/24") if err != nil { t.Fatal(err) @@ -36,7 +48,7 @@ func TestSimplebridge(t *testing.T) { cidrv6.IP = ip log.Debug("Adding a simple bridge") - options := options.Generic{ + option := options.Generic{ "BridgeName": bridgeName, "AddressIPv4": subnet, "FixedCIDR": cidr, @@ -48,14 +60,7 @@ func TestSimplebridge(t *testing.T) { "EnableIPForwarding": true, "AllowNonDefaultBridge": true} - controller := libnetwork.New() - - driver, err := controller.NewNetworkDriver("simplebridge", options) - if err != nil { - t.Fatal(err) - } - - network, err := controller.NewNetwork(driver, "testnetwork", "") + network, err := createTestNetwork("simplebridge", "testnetwork", option) if err != nil { t.Fatal(err) } @@ -73,3 +78,206 @@ func TestSimplebridge(t *testing.T) { t.Fatal(err) } } + +func TestUnknownDriver(t *testing.T) { + _, err := createTestNetwork("unknowndriver", "testnetwork", options.Generic{}) + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if _, ok := err.(libnetwork.NetworkTypeError); !ok { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } +} + +func TestNilDriver(t *testing.T) { + controller := libnetwork.New() + + option := options.Generic{} + _, err := controller.NewNetwork(nil, "dummy", option) + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if err != libnetwork.ErrNilNetworkDriver { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } +} + +func TestNoInitDriver(t *testing.T) { + controller := libnetwork.New() + + option := options.Generic{} + _, err := controller.NewNetwork(&libnetwork.NetworkDriver{}, "dummy", option) + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if err != libnetwork.ErrInvalidNetworkDriver { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } +} + +func TestDuplicateNetwork(t *testing.T) { + controller := libnetwork.New() + + option := options.Generic{} + driver, err := controller.NewNetworkDriver("simplebridge", option) + if err != nil { + t.Fatal(err) + } + + _, err = controller.NewNetwork(driver, "testnetwork", "") + if err != nil { + t.Fatal(err) + } + + _, err = controller.NewNetwork(driver, "testnetwork", "") + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if _, ok := err.(libnetwork.NetworkNameError); !ok { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } +} + +func TestNetworkName(t *testing.T) { + networkName := "testnetwork" + + n, err := createTestNetwork("simplebridge", networkName, options.Generic{}) + if err != nil { + t.Fatal(err) + } + + if n.Name() != networkName { + t.Fatalf("Expected network name %s, got %s", networkName, n.Name()) + } +} + +func TestNetworkType(t *testing.T) { + networkType := "simplebridge" + + n, err := createTestNetwork(networkType, "testnetwork", options.Generic{}) + if err != nil { + t.Fatal(err) + } + + if n.Type() != networkType { + t.Fatalf("Expected network type %s, got %s", networkType, n.Type()) + } +} + +func TestNetworkID(t *testing.T) { + networkType := "simplebridge" + + n, err := createTestNetwork(networkType, "testnetwork", options.Generic{}) + if err != nil { + t.Fatal(err) + } + + if n.ID() == "" { + t.Fatal("Expected non-empty network id") + } +} + +func TestDeleteNetworkWithActiveEndpoints(t *testing.T) { + option := options.Generic{ + "BridgeName": bridgeName, + "AllowNonDefaultBridge": true} + + network, err := createTestNetwork("simplebridge", "testnetwork", option) + if err != nil { + t.Fatal(err) + } + + ep, _, err := network.CreateEndpoint("testep", "", "") + if err != nil { + t.Fatal(err) + } + + err = network.Delete() + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if _, ok := err.(*libnetwork.ActiveEndpointsError); !ok { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } + + // Done testing. Now cleanup. + if err := ep.Delete(); err != nil { + t.Fatal(err) + } + + if err := network.Delete(); err != nil { + t.Fatal(err) + } +} + +func TestUnknownNetwork(t *testing.T) { + option := options.Generic{ + "BridgeName": bridgeName, + "AllowNonDefaultBridge": true} + + network, err := createTestNetwork("simplebridge", "testnetwork", option) + if err != nil { + t.Fatal(err) + } + + err = network.Delete() + if err != nil { + t.Fatal(err) + } + + err = network.Delete() + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if _, ok := err.(*libnetwork.UnknownNetworkError); !ok { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } +} + +func TestUnknownEndpoint(t *testing.T) { + ip, subnet, err := net.ParseCIDR("192.168.100.1/24") + if err != nil { + t.Fatal(err) + } + subnet.IP = ip + + option := options.Generic{ + "BridgeName": bridgeName, + "AddressIPv4": subnet, + "AllowNonDefaultBridge": true} + + network, err := createTestNetwork("simplebridge", "testnetwork", option) + if err != nil { + t.Fatal(err) + } + + ep, _, err := network.CreateEndpoint("testep", "", "") + if err != nil { + t.Fatal(err) + } + + err = ep.Delete() + if err != nil { + t.Fatal(err) + } + + err = ep.Delete() + if err == nil { + t.Fatal("Expected to fail. But instead succeeded") + } + + if _, ok := err.(*libnetwork.UnknownEndpointError); !ok { + t.Fatalf("Did not fail with expected error. Actual error: %v", err) + } + + // Done testing. Now cleanup + if err := network.Delete(); err != nil { + t.Fatal(err) + } +} diff --git a/libnetwork/network.go b/libnetwork/network.go index ff0a4dead3..ee6836c3ee 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -39,7 +39,6 @@ create network namespaces and allocate interfaces for containers to use. package libnetwork import ( - "fmt" "sync" "github.com/docker/docker/pkg/common" @@ -84,6 +83,7 @@ type Endpoint interface { // NetworkDriver provides a reference to driver and way to push driver specific config type NetworkDriver struct { + networkType string internalDriver driverapi.Driver } @@ -121,19 +121,32 @@ func New() NetworkController { func (c *controller) NewNetworkDriver(networkType string, options interface{}) (*NetworkDriver, error) { d, ok := c.drivers[networkType] if !ok { - return nil, fmt.Errorf("unknown driver %q", networkType) + return nil, NetworkTypeError(networkType) } if err := d.Config(options); err != nil { return nil, err } - return &NetworkDriver{internalDriver: d}, nil + return &NetworkDriver{networkType: networkType, internalDriver: d}, nil } -// NewNetwork creates a new network of the specified networkType. The options +// NewNetwork creates a new network of the specified NetworkDriver. The options // are driver specific and modeled in a generic way. func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interface{}) (Network, error) { + if nd == nil { + return nil, ErrNilNetworkDriver + } + + c.Lock() + for _, n := range c.networks { + if n.name == name { + c.Unlock() + return nil, NetworkNameError(name) + } + } + c.Unlock() + network := &network{ name: name, id: driverapi.UUID(common.GenerateRandomID()), @@ -143,7 +156,7 @@ func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interfac d := network.driver.internalDriver if d == nil { - return nil, fmt.Errorf("invalid driver bound to network") + return nil, ErrInvalidNetworkDriver } if err := d.CreateNetwork(network.id, options); err != nil { @@ -166,7 +179,11 @@ func (n *network) ID() string { } func (n *network) Type() string { - return n.networkType + if n.driver == nil { + return "" + } + + return n.driver.networkType } func (n *network) Delete() error { @@ -176,7 +193,7 @@ func (n *network) Delete() error { _, ok := n.ctrlr.networks[n.id] if !ok { n.ctrlr.Unlock() - return fmt.Errorf("unknown network %s id %s", n.name, n.id) + return &UnknownNetworkError{name: n.name, id: string(n.id)} } n.Lock() @@ -184,7 +201,7 @@ func (n *network) Delete() error { n.Unlock() if numEps != 0 { n.ctrlr.Unlock() - return fmt.Errorf("network %s has active endpoints", n.id) + return &ActiveEndpointsError{name: n.name, id: string(n.id)} } delete(n.ctrlr.networks, n.id) @@ -228,7 +245,7 @@ func (ep *endpoint) Delete() error { _, ok := n.endpoints[ep.id] if !ok { n.Unlock() - return fmt.Errorf("unknown endpoint %s id %s", ep.name, ep.id) + return &UnknownEndpointError{name: ep.name, id: string(ep.id)} } delete(n.endpoints, ep.id)