diff --git a/libnetwork/driverapi/driverapi.go b/libnetwork/driverapi/driverapi.go index fc91f1d78c..b0c64a9280 100644 --- a/libnetwork/driverapi/driverapi.go +++ b/libnetwork/driverapi/driverapi.go @@ -40,6 +40,12 @@ type Driver interface { // passing the network id and endpoint id. DeleteEndpoint(nid, eid types.UUID) error + // Join method is invoked when a Sandbox is attached to an endpoint. + Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error + + // Leave method is invoked when a Sandbox detaches from an endpoint. + Leave(nid, eid types.UUID, options map[string]interface{}) error + // Type returns the the type of this driver, the network type this driver manages Type() string } diff --git a/libnetwork/drivers/bridge/bridge.go b/libnetwork/drivers/bridge/bridge.go index 099e176d6e..955ac6801a 100644 --- a/libnetwork/drivers/bridge/bridge.go +++ b/libnetwork/drivers/bridge/bridge.go @@ -49,6 +49,11 @@ type EndpointConfiguration struct { MacAddress net.HardwareAddr } +// ContainerConfiguration represents the user specified configuration for a container +type ContainerConfiguration struct { + // TODO : Add container specific configuration when Join processing is handled +} + type bridgeEndpoint struct { id types.UUID port *sandbox.Interface @@ -175,7 +180,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err d.Lock() if d.config == nil { d.Unlock() - return ErrInvalidConfig + return ErrInvalidNetworkConfig } config := d.config @@ -554,6 +559,16 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error { return nil } +// Join method is invoked when a Sandbox is attached to an endpoint. +func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error { + return nil +} + +// Leave method is invoked when a Sandbox detaches from an endpoint. +func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error { + return nil +} + func (d *driver) Type() string { return networkType } @@ -580,6 +595,24 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfigurat } } +func parseContainerOptions(cOptions interface{}) (*ContainerConfiguration, error) { + if cOptions == nil { + return nil, nil + } + switch opt := cOptions.(type) { + case options.Generic: + opaqueConfig, err := options.GenerateFromModel(opt, &ContainerConfiguration{}) + if err != nil { + return nil, err + } + return opaqueConfig.(*ContainerConfiguration), nil + case *ContainerConfiguration: + return opt, nil + default: + return nil, ErrInvalidContainerConfig + } +} + // Generates a name to be used for a virtual ethernet // interface. The name is constructed by 'veth' appended // by a randomly generated hex value. (example: veth0f60e2c) diff --git a/libnetwork/drivers/bridge/error.go b/libnetwork/drivers/bridge/error.go index a16f3dc3a1..fe635959e4 100644 --- a/libnetwork/drivers/bridge/error.go +++ b/libnetwork/drivers/bridge/error.go @@ -13,8 +13,11 @@ var ( // ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config ErrInvalidDriverConfig = errors.New("Invalid configuration passed to Bridge Driver") - // ErrInvalidConfig error is returned when a network is created on a driver without valid config. - ErrInvalidConfig = errors.New("trying to create a network on a driver without valid config") + // ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config. + ErrInvalidNetworkConfig = errors.New("trying to create a network on a driver without valid config") + + // ErrInvalidContainerConfig error is returned when a endpoint create is attempted with an invalid configuration. + ErrInvalidContainerConfig = errors.New("Error in joining a container due to invalid configuration") // ErrInvalidEndpointConfig error is returned when a endpoint create is attempted with an invalid endpoint configuration. ErrInvalidEndpointConfig = errors.New("trying to create an endpoint with an invalid endpoint configuration") diff --git a/libnetwork/drivers/null/null.go b/libnetwork/drivers/null/null.go index c3dd6a3b50..c95dc820ea 100644 --- a/libnetwork/drivers/null/null.go +++ b/libnetwork/drivers/null/null.go @@ -35,6 +35,16 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error { return nil } +// Join method is invoked when a Sandbox is attached to an endpoint. +func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error { + return nil +} + +// Leave method is invoked when a Sandbox detaches from an endpoint. +func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error { + return nil +} + func (d *driver) Type() string { return networkType } diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 9fa2c8586e..0261689eb5 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -5,7 +5,6 @@ import ( "path/filepath" "github.com/docker/docker/pkg/etchosts" - "github.com/docker/libnetwork/pkg/options" "github.com/docker/libnetwork/sandbox" "github.com/docker/libnetwork/types" ) @@ -28,7 +27,7 @@ type Endpoint interface { // Leave removes the sandbox associated with container ID and detaches // the network resources populated in the sandbox - Leave(containerID string) error + Leave(containerID string, options ...LeaveOption) error // SandboxInfo returns the sandbox information for this endpoint. SandboxInfo() *sandbox.Info @@ -48,9 +47,15 @@ type ContainerData struct { // provided by libnetwork, they look like JoinOption[...](...) type JoinOption func(ep *endpoint) +// LeaveOption is a option setter function type used to pass varios options to +// endpoint Leave method. The various setter functions of type LeaveOption are +// provided by libnetwork, they look like LeaveOptionXXXX(...) +type LeaveOption func(ep *endpoint) + type containerConfig struct { Hostname string Domainname string + generic map[string]interface{} } type containerInfo struct { @@ -66,7 +71,8 @@ type endpoint struct { sandboxInfo *sandbox.Info sandBox sandbox.Sandbox container *containerInfo - generic options.Generic + generic map[string]interface{} + context map[string]interface{} } const prefix = "/var/lib/docker/network/files" @@ -179,6 +185,12 @@ func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerD } }() + n := ep.network + err = n.driver.Join(n.id, ep.id, sboxKey, ep.container.Config.generic) + if err != nil { + return nil, err + } + sinfo := ep.SandboxInfo() if sinfo != nil { for _, i := range sinfo.Interfaces { @@ -206,14 +218,23 @@ func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerD return &cData, nil } -func (ep *endpoint) Leave(containerID string) error { +func (ep *endpoint) Leave(containerID string, options ...LeaveOption) error { if ep.container == nil || ep.container.ID == "" || containerID == "" || ep.container.ID != containerID { return InvalidContainerIDError(containerID) } - ep.network.ctrlr.sandboxRm(sandbox.GenerateKey(containerID)) + n := ep.network + ep.processLeaveOptions(options...) + + err := n.driver.Leave(n.id, ep.id, ep.context) + if err != nil { + return err + } + + ep.network.ctrlr.sandboxRm(ep.container.Data.SandboxKey) ep.container = nil + ep.context = nil return nil } @@ -276,6 +297,15 @@ func JoinOptionDomainname(name string) JoinOption { } } +// JoinOptionGeneric function returns an option setter for Generic configuration +// that is not managed by libNetwork but can be used by the Drivers during the call to +// endpoint join method. Container Labels are a good example. +func JoinOptionGeneric(generic map[string]interface{}) JoinOption { + return func(ep *endpoint) { + ep.container.Config.generic = generic + } +} + func (ep *endpoint) processJoinOptions(options ...JoinOption) { for _, opt := range options { if opt != nil { @@ -283,3 +313,20 @@ func (ep *endpoint) processJoinOptions(options ...JoinOption) { } } } + +// LeaveOptionGeneric function returns an option setter for Generic configuration +// that is not managed by libNetwork but can be used by the Drivers during the call to +// endpoint leave method. Container Labels are a good example. +func LeaveOptionGeneric(context map[string]interface{}) JoinOption { + return func(ep *endpoint) { + ep.context = context + } +} + +func (ep *endpoint) processLeaveOptions(options ...LeaveOption) { + for _, opt := range options { + if opt != nil { + opt(ep) + } + } +} diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index e4676fe247..1a601ebb4f 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -173,12 +173,12 @@ func TestDuplicateNetwork(t *testing.T) { err := controller.ConfigureNetworkDriver(netType, genericOption) if err != nil { - t.Fatal(err.Error()) + t.Fatal(err) } _, err = controller.NewNetwork(netType, "testnetwork", nil) if err != nil { - t.Fatal("Expected to fail. But instead succeeded") + t.Fatal(err) } _, err = controller.NewNetwork(netType, "testnetwork")