mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Move exposed ports from Endpoint to Sandbox
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
b532754b19
commit
1638fbdf27
21 changed files with 552 additions and 236 deletions
|
@ -251,6 +251,12 @@ func (sc *sandboxCreate) parseOptions() []libnetwork.SandboxOption {
|
|||
setFctList = append(setFctList, libnetwork.OptionExtraHost(e.Name, e.Address))
|
||||
}
|
||||
}
|
||||
if sc.ExposedPorts != nil {
|
||||
setFctList = append(setFctList, libnetwork.OptionExposedPorts(sc.ExposedPorts))
|
||||
}
|
||||
if sc.PortMapping != nil {
|
||||
setFctList = append(setFctList, libnetwork.OptionPortMapping(sc.PortMapping))
|
||||
}
|
||||
return setFctList
|
||||
}
|
||||
|
||||
|
@ -384,13 +390,6 @@ func procCreateEndpoint(c libnetwork.NetworkController, vars map[string]string,
|
|||
}
|
||||
|
||||
var setFctList []libnetwork.EndpointOption
|
||||
if ec.ExposedPorts != nil {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionExposedPorts(ec.ExposedPorts))
|
||||
}
|
||||
if ec.PortMapping != nil {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(ec.PortMapping))
|
||||
}
|
||||
|
||||
for _, str := range ec.MyAliases {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str))
|
||||
}
|
||||
|
@ -633,13 +632,6 @@ func procPublishService(c libnetwork.NetworkController, vars map[string]string,
|
|||
}
|
||||
|
||||
var setFctList []libnetwork.EndpointOption
|
||||
if sp.ExposedPorts != nil {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionExposedPorts(sp.ExposedPorts))
|
||||
}
|
||||
if sp.PortMapping != nil {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(sp.PortMapping))
|
||||
}
|
||||
|
||||
for _, str := range sp.MyAliases {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str))
|
||||
}
|
||||
|
|
|
@ -294,8 +294,6 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
|
|||
|
||||
ec1 := endpointCreate{
|
||||
Name: "ep1",
|
||||
ExposedPorts: getExposedPorts(),
|
||||
PortMapping: getPortMapping(),
|
||||
}
|
||||
b1, err := json.Marshal(ec1)
|
||||
if err != nil {
|
||||
|
@ -825,8 +823,6 @@ func TestProcPublishUnpublishService(t *testing.T) {
|
|||
sp := servicePublish{
|
||||
Name: "web",
|
||||
Network: "network",
|
||||
ExposedPorts: getExposedPorts(),
|
||||
PortMapping: getPortMapping(),
|
||||
}
|
||||
b, err = json.Marshal(sp)
|
||||
if err != nil {
|
||||
|
@ -2087,7 +2083,10 @@ func TestEndToEnd(t *testing.T) {
|
|||
cpid1 := string(chars[0 : len(chars)/2])
|
||||
|
||||
// Create sandboxes
|
||||
sb1, err := json.Marshal(sandboxCreate{ContainerID: cid1})
|
||||
sb1, err := json.Marshal(sandboxCreate{
|
||||
ContainerID: cid1,
|
||||
PortMapping: getPortMapping(),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -2111,7 +2110,10 @@ func TestEndToEnd(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sb2, err := json.Marshal(sandboxCreate{ContainerID: cid2})
|
||||
sb2, err := json.Marshal(sandboxCreate{
|
||||
ContainerID: cid2,
|
||||
ExposedPorts: getExposedPorts(),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -44,8 +44,6 @@ type networkCreate struct {
|
|||
type endpointCreate struct {
|
||||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
||||
// sandboxCreate is the expected body of the "create sandbox" http request message
|
||||
|
@ -59,6 +57,8 @@ type sandboxCreate struct {
|
|||
ExtraHosts []extraHost `json:"extra_hosts"`
|
||||
UseDefaultSandbox bool `json:"use_default_sandbox"`
|
||||
UseExternalKey bool `json:"use_external_key"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
||||
// endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages
|
||||
|
@ -72,8 +72,6 @@ type servicePublish struct {
|
|||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
Network string `json:"network_name"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
||||
// serviceDelete represents the body of the "unpublish service" http request message
|
||||
|
|
|
@ -45,8 +45,6 @@ type serviceCreate struct {
|
|||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
Network string `json:"network_name"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
||||
// serviceDelete represents the body of the "unpublish service" http request message
|
||||
|
@ -71,6 +69,8 @@ type SandboxCreate struct {
|
|||
DNS []string `json:"dns"`
|
||||
ExtraHosts []extraHost `json:"extra_hosts"`
|
||||
UseDefaultSandbox bool `json:"use_default_sandbox"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
||||
// extraHost represents the extra host object
|
||||
|
|
|
@ -3,7 +3,6 @@ package libnetwork
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
|
@ -28,15 +27,15 @@ var procGwNetwork = make(chan (bool), 1)
|
|||
- its deleted when an endpoint with GW joins the container
|
||||
*/
|
||||
|
||||
func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
||||
var createOptions []EndpointOption
|
||||
c := srcEp.getNetwork().getController()
|
||||
func (sb *sandbox) setupDefaultGW() error {
|
||||
|
||||
// check if the conitainer already has a GW endpoint
|
||||
if ep := sb.getEndpointInGWNetwork(); ep != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := sb.controller
|
||||
|
||||
// Look for default gw network. In case of error (includes not found),
|
||||
// retry and create it if needed in a serialized execution.
|
||||
n, err := c.NetworkByName(libnGWNetwork)
|
||||
|
@ -46,19 +45,7 @@ func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
|||
}
|
||||
}
|
||||
|
||||
if opt, ok := srcEp.generic[netlabel.PortMap]; ok {
|
||||
if pb, ok := opt.([]types.PortBinding); ok {
|
||||
createOptions = append(createOptions, CreateOptionPortMapping(pb))
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := srcEp.generic[netlabel.ExposedPorts]; ok {
|
||||
if exp, ok := opt.([]types.TransportPort); ok {
|
||||
createOptions = append(createOptions, CreateOptionExposedPorts(exp))
|
||||
}
|
||||
}
|
||||
|
||||
createOptions = append(createOptions, CreateOptionAnonymous())
|
||||
createOptions := []EndpointOption{CreateOptionAnonymous()}
|
||||
|
||||
eplen := gwEPlen
|
||||
if len(sb.containerID) < gwEPlen {
|
||||
|
@ -74,9 +61,13 @@ func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
|||
if err := epLocal.sbJoin(sb); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// If present, removes the endpoint connecting the sandbox to the default gw network.
|
||||
// Unless it is the endpoint designated to provide the external connectivity.
|
||||
// If the sandbox is being deleted, removes the endpoint unconditionally.
|
||||
func (sb *sandbox) clearDefaultGW() error {
|
||||
var ep *endpoint
|
||||
|
||||
|
@ -84,6 +75,10 @@ func (sb *sandbox) clearDefaultGW() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if ep == sb.getGatewayEndpoint() && !sb.inDelete {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ep.sbLeave(sb, false); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
@ -98,7 +93,7 @@ func (sb *sandbox) needDefaultGW() bool {
|
|||
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.endpointInGWNetwork() {
|
||||
continue
|
||||
return false
|
||||
}
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
|
@ -165,3 +160,16 @@ func (c *controller) defaultGwNetwork() (Network, error) {
|
|||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Returns the endpoint which is providing external connectivity to the sandbox
|
||||
func (sb *sandbox) getGatewayEndpoint() *endpoint {
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
}
|
||||
if len(ep.Gateway()) != 0 {
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -42,6 +42,14 @@ type Driver interface {
|
|||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
Leave(nid, eid string) error
|
||||
|
||||
// ProgramExternalConnectivity invokes the driver method which does the necessary
|
||||
// programming to allow the external connectivity dictated by the passed options
|
||||
ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error
|
||||
|
||||
// RevokeExternalConnectivity aks the driver to remove any external connectivity
|
||||
// programming that was done so far
|
||||
RevokeExternalConnectivity(nid, eid string) error
|
||||
|
||||
// Type returns the the type of this driver, the network type this driver manages
|
||||
Type() string
|
||||
}
|
||||
|
|
|
@ -75,8 +75,6 @@ type networkConfiguration struct {
|
|||
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type endpointConfiguration struct {
|
||||
MacAddress net.HardwareAddr
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
// containerConfiguration represents the user specified configuration for a container
|
||||
|
@ -85,6 +83,12 @@ type containerConfiguration struct {
|
|||
ChildEndpoints []string
|
||||
}
|
||||
|
||||
// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity
|
||||
type connectivityConfiguration struct {
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
type bridgeEndpoint struct {
|
||||
id string
|
||||
srcName string
|
||||
|
@ -93,6 +97,7 @@ type bridgeEndpoint struct {
|
|||
macAddress net.HardwareAddr
|
||||
config *endpointConfiguration // User specified parameters
|
||||
containerConfig *containerConfiguration
|
||||
extConnConfig *connectivityConfiguration
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
}
|
||||
|
||||
|
@ -1004,12 +1009,6 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
}
|
||||
|
||||
// Program any required port mapping and store them in the endpoint
|
||||
endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1064,9 +1063,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|||
}
|
||||
}()
|
||||
|
||||
// Remove port mappings. Do not stop endpoint delete on unmap failure
|
||||
n.releasePorts(ep)
|
||||
|
||||
// Try removal of link. Discard error: it is a best effort.
|
||||
// Also make sure defer does not see this error either.
|
||||
if link, err := netlink.LinkByName(ep.srcName); err == nil {
|
||||
|
@ -1107,10 +1103,10 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
|||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
if ep.config.ExposedPorts != nil {
|
||||
if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil {
|
||||
// Return a copy of the config data
|
||||
epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
|
||||
for _, tp := range ep.config.ExposedPorts {
|
||||
epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts))
|
||||
for _, tp := range ep.extConnConfig.ExposedPorts {
|
||||
epc = append(epc, tp.GetCopy())
|
||||
}
|
||||
m[netlabel.ExposedPorts] = epc
|
||||
|
@ -1150,6 +1146,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
endpoint.containerConfig, err = parseContainerOptions(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iNames := jinfo.InterfaceName()
|
||||
err = iNames.SetNames(endpoint.srcName, containerVethPrefix)
|
||||
if err != nil {
|
||||
|
@ -1166,10 +1167,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, options, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1192,32 +1189,87 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, nil, false)
|
||||
if err = d.link(network, endpoint, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options map[string]interface{}, enable bool) error {
|
||||
var (
|
||||
cc *containerConfiguration
|
||||
err error
|
||||
)
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
if enable {
|
||||
cc, err = parseContainerOptions(options)
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cc = endpoint.containerConfig
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint == nil {
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
endpoint.extConnConfig, err = parseConnectivityOptions(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Program any required port mapping and store them in the endpoint
|
||||
endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint == nil {
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
err = network.releasePorts(endpoint)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error {
|
||||
var err error
|
||||
|
||||
cc := endpoint.containerConfig
|
||||
if cc == nil {
|
||||
return nil
|
||||
}
|
||||
ec := endpoint.extConnConfig
|
||||
if ec == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if endpoint.config != nil && endpoint.config.ExposedPorts != nil {
|
||||
if ec.ExposedPorts != nil {
|
||||
for _, p := range cc.ParentEndpoints {
|
||||
var parentEndpoint *bridgeEndpoint
|
||||
parentEndpoint, err = network.getEndpoint(p)
|
||||
|
@ -1231,7 +1283,7 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
|
||||
l := newLink(parentEndpoint.addr.IP.String(),
|
||||
endpoint.addr.IP.String(),
|
||||
endpoint.config.ExposedPorts, network.config.BridgeName)
|
||||
ec.ExposedPorts, network.config.BridgeName)
|
||||
if enable {
|
||||
err = l.Enable()
|
||||
if err != nil {
|
||||
|
@ -1258,13 +1310,13 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
err = InvalidEndpointIDError(c)
|
||||
return err
|
||||
}
|
||||
if childEndpoint.config == nil || childEndpoint.config.ExposedPorts == nil {
|
||||
if childEndpoint.extConnConfig == nil || childEndpoint.extConnConfig.ExposedPorts == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
l := newLink(endpoint.addr.IP.String(),
|
||||
childEndpoint.addr.IP.String(),
|
||||
childEndpoint.config.ExposedPorts, network.config.BridgeName)
|
||||
childEndpoint.extConnConfig.ExposedPorts, network.config.BridgeName)
|
||||
if enable {
|
||||
err = l.Enable()
|
||||
if err != nil {
|
||||
|
@ -1280,10 +1332,6 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
}
|
||||
}
|
||||
|
||||
if enable {
|
||||
endpoint.containerConfig = cc
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1316,22 +1364,6 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
|
|||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
ec.PortBindings = bs
|
||||
} else {
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
ec.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
|
@ -1339,22 +1371,52 @@ func parseContainerOptions(cOptions map[string]interface{}) (*containerConfigura
|
|||
if cOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
genericData := cOptions[netlabel.GenericData]
|
||||
if genericData == nil {
|
||||
|
||||
cc := &containerConfiguration{}
|
||||
|
||||
if opt, ok := cOptions[ParentEndpoints]; ok {
|
||||
if pe, ok := opt.([]string); ok {
|
||||
cc.ParentEndpoints = pe
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid parent endpoints data in sandbox configuration: %v", opt)
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := cOptions[ChildEndpoints]; ok {
|
||||
if ce, ok := opt.([]string); ok {
|
||||
cc.ChildEndpoints = ce
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid child endpoints data in sandbox configuration: %v", opt)
|
||||
}
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) {
|
||||
if cOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
switch opt := genericData.(type) {
|
||||
case options.Generic:
|
||||
opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
cc := &connectivityConfiguration{}
|
||||
|
||||
if opt, ok := cOptions[netlabel.PortMap]; ok {
|
||||
if pb, ok := opt.([]types.PortBinding); ok {
|
||||
cc.PortBindings = pb
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt)
|
||||
}
|
||||
return opaqueConfig.(*containerConfiguration), nil
|
||||
case *containerConfiguration:
|
||||
return opt, nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if opt, ok := cOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
cc.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt)
|
||||
}
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr {
|
||||
|
|
|
@ -463,16 +463,25 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
portMappings := getPortMapping()
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portMappings
|
||||
sbOptions := make(map[string]interface{})
|
||||
sbOptions[netlabel.PortMap] = getPortMapping()
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep1", te.Interface(), epOptions)
|
||||
err = d.CreateEndpoint("net1", "ep1", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.Join("net1", "ep1", "sbox", te, sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
err = d.ProgramExternalConnectivity("net1", "ep1", sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to program external connectivity: %v", err)
|
||||
}
|
||||
|
||||
network, ok := d.networks["net1"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find network %s inside driver", "net1")
|
||||
|
@ -499,10 +508,15 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// Cleanup as host ports are there
|
||||
err = network.releasePorts(ep)
|
||||
err = d.RevokeExternalConnectivity("net1", "ep1")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to release mapped ports: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// release host mapped ports
|
||||
err = d.Leave("net1", "ep1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,16 +608,26 @@ func TestLinkContainers(t *testing.T) {
|
|||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
exposedPorts := getExposedPorts()
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.ExposedPorts] = exposedPorts
|
||||
|
||||
te1 := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep1", te1.Interface(), epOptions)
|
||||
err = d.CreateEndpoint("net1", "ep1", te1.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
exposedPorts := getExposedPorts()
|
||||
sbOptions := make(map[string]interface{})
|
||||
sbOptions[netlabel.ExposedPorts] = exposedPorts
|
||||
|
||||
err = d.Join("net1", "ep1", "sbox", te1, sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
err = d.ProgramExternalConnectivity("net1", "ep1", sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to program external connectivity: %v", err)
|
||||
}
|
||||
|
||||
addr1 := te1.iface.addr
|
||||
if addr1.IP.To4() == nil {
|
||||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep1")
|
||||
|
@ -620,16 +644,19 @@ func TestLinkContainers(t *testing.T) {
|
|||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep2")
|
||||
}
|
||||
|
||||
ce := []string{"ep1"}
|
||||
cConfig := &containerConfiguration{ChildEndpoints: ce}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
sbOptions = make(map[string]interface{})
|
||||
sbOptions[ChildEndpoints] = []string{"ep1"}
|
||||
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
err = d.Join("net1", "ep2", "", te2, sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to link ep1 and ep2")
|
||||
}
|
||||
|
||||
err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to program external connectivity: %v", err)
|
||||
}
|
||||
|
||||
out, err := iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
|
||||
|
@ -646,6 +673,11 @@ func TestLinkContainers(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
err = d.RevokeExternalConnectivity("net1", "ep2")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to revoke external connectivity: %v", err)
|
||||
}
|
||||
|
||||
err = d.Leave("net1", "ep2")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unlink ep1 and ep2")
|
||||
|
@ -668,12 +700,14 @@ func TestLinkContainers(t *testing.T) {
|
|||
}
|
||||
|
||||
// Error condition test with an invalid endpoint-id "ep4"
|
||||
ce = []string{"ep1", "ep4"}
|
||||
cConfig = &containerConfiguration{ChildEndpoints: ce}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
sbOptions = make(map[string]interface{})
|
||||
sbOptions[ChildEndpoints] = []string{"ep1", "ep4"}
|
||||
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
err = d.Join("net1", "ep2", "", te2, sbOptions)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions)
|
||||
if err != nil {
|
||||
out, err = iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
|
|
|
@ -15,4 +15,10 @@ const (
|
|||
|
||||
// DefaultBridge label
|
||||
DefaultBridge = "com.docker.network.bridge.default_bridge"
|
||||
|
||||
// ChildEndpoints for links
|
||||
ChildEndpoints = "com.docker.network.bridge.child_endpoints"
|
||||
|
||||
// ParentEndpoints for links
|
||||
ParentEndpoints = "com.docker.network.bridge.parent_endpoints"
|
||||
)
|
||||
|
|
|
@ -14,8 +14,8 @@ var (
|
|||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if epConfig == nil || epConfig.PortBindings == nil {
|
||||
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, ep *bridg
|
|||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
return n.allocatePortsInternal(epConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
return n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
|
|
|
@ -35,8 +35,8 @@ func TestPortMappingConfig(t *testing.T) {
|
|||
binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
||||
portBindings := []types.PortBinding{binding1, binding2}
|
||||
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portBindings
|
||||
sbOptions := make(map[string]interface{})
|
||||
sbOptions[netlabel.PortMap] = portBindings
|
||||
|
||||
netConfig := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
|
@ -51,11 +51,19 @@ func TestPortMappingConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
if err = d.Join("dummy", "ep1", "sbox", te, sbOptions); err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
if err = d.ProgramExternalConnectivity("dummy", "ep1", sbOptions); err != nil {
|
||||
t.Fatalf("Failed to program external connectivity: %v", err)
|
||||
}
|
||||
|
||||
network, ok := d.networks["dummy"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find network %s inside driver", "dummy")
|
||||
|
@ -73,8 +81,14 @@ func TestPortMappingConfig(t *testing.T) {
|
|||
t.Fatalf("operational port mapping data not found on bridgeEndpoint")
|
||||
}
|
||||
|
||||
err = network.releasePorts(ep)
|
||||
// release host mapped ports
|
||||
err = d.Leave("dummy", "ep1")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to release mapped ports: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = d.RevokeExternalConnectivity("dummy", "ep1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
|
|
@ -114,6 +114,14 @@ func (d *driver) DeleteNetwork(nid string) error {
|
|||
return n.releaseVxlanID()
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) incEndpointCount() {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
|
|
@ -153,6 +153,29 @@ type LeaveResponse struct {
|
|||
Response
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityRequest describes the API for programming the external connectivity for the given endpoint.
|
||||
type ProgramExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityResponse is the answer to ProgramExternalConnectivityRequest.
|
||||
type ProgramExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityRequest describes the API for revoking the external connectivity for the given endpoint.
|
||||
type RevokeExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityResponse is the answer to RevokeExternalConnectivityRequest.
|
||||
type RevokeExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// DiscoveryNotification represents a discovery notification
|
||||
type DiscoveryNotification struct {
|
||||
DiscoveryType discoverapi.DiscoveryType
|
||||
|
|
|
@ -3,6 +3,7 @@ package remote
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
|
@ -13,6 +14,10 @@ import (
|
|||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
missingMethod = "404 page not found"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
endpoint *plugins.Client
|
||||
networkType string
|
||||
|
@ -247,6 +252,35 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return d.call("Leave", leave, &api.LeaveResponse{})
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivity is invoked to program the rules to allow external connectivity for the endpoint.
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
data := &api.ProgramExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
Options: options,
|
||||
}
|
||||
err := d.call("ProgramExternalConnectivity", data, &api.ProgramExternalConnectivityResponse{})
|
||||
if err != nil && strings.Contains(err.Error(), missingMethod) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivity method is invoked to remove any external connectivity programming related to the endpoint.
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
data := &api.RevokeExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
err := d.call("RevokeExternalConnectivity", data, &api.RevokeExternalConnectivityResponse{})
|
||||
if err != nil && strings.Contains(err.Error(), missingMethod) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.networkType
|
||||
}
|
||||
|
|
|
@ -509,6 +509,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.name
|
||||
}
|
||||
|
|
|
@ -359,22 +359,16 @@ func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
|
|||
sb.joinLeaveStart()
|
||||
defer sb.joinLeaveEnd()
|
||||
|
||||
return ep.sbJoin(sbox, options...)
|
||||
return ep.sbJoin(sb, options...)
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
||||
var err error
|
||||
sb, ok := sbox.(*sandbox)
|
||||
if !ok {
|
||||
return types.BadRequestErrorf("not a valid Sandbox interface")
|
||||
}
|
||||
|
||||
network, err := ep.getNetworkFromStore()
|
||||
func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network from store during join: %v", err)
|
||||
}
|
||||
|
||||
ep, err = network.getEndpointFromStore(ep.ID())
|
||||
ep, err = n.getEndpointFromStore(ep.ID())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get endpoint from store during join: %v", err)
|
||||
}
|
||||
|
@ -384,11 +378,8 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
ep.Unlock()
|
||||
return types.ForbiddenErrorf("another container is attached to the same network endpoint")
|
||||
}
|
||||
ep.Unlock()
|
||||
|
||||
ep.Lock()
|
||||
ep.network = network
|
||||
ep.sandboxID = sbox.ID()
|
||||
ep.network = n
|
||||
ep.sandboxID = sb.ID()
|
||||
ep.joinInfo = &endpointJoinInfo{}
|
||||
epid := ep.id
|
||||
ep.Unlock()
|
||||
|
@ -400,32 +391,29 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
}
|
||||
}()
|
||||
|
||||
network.Lock()
|
||||
nid := network.id
|
||||
network.Unlock()
|
||||
nid := n.ID()
|
||||
|
||||
ep.processOptions(options...)
|
||||
|
||||
driver, err := network.driver(true)
|
||||
d, err := n.driver(true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to join endpoint: %v", err)
|
||||
}
|
||||
|
||||
err = driver.Join(nid, epid, sbox.Key(), ep, sbox.Labels())
|
||||
err = d.Join(nid, epid, sb.Key(), ep, sb.Labels())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// Do not alter global err variable, it's needed by the previous defer
|
||||
if err := driver.Leave(nid, epid); err != nil {
|
||||
if err := d.Leave(nid, epid); err != nil {
|
||||
log.Warnf("driver leave failed while rolling back join: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Watch for service records
|
||||
network.getController().watchSvcRecord(ep)
|
||||
n.getController().watchSvcRecord(ep)
|
||||
|
||||
address := ""
|
||||
if ip := ep.getFirstInterfaceAddress(); ip != nil {
|
||||
|
@ -434,27 +422,23 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
if err = sb.updateHostsFile(address); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = sb.updateDNS(network.enableIPv6); err != nil {
|
||||
if err = sb.updateDNS(n.enableIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = network.getController().updateToStore(ep); err != nil {
|
||||
if err = n.getController().updateToStore(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Current endpoint providing external connectivity for the sandbox
|
||||
extEp := sb.getGatewayEndpoint()
|
||||
|
||||
sb.Lock()
|
||||
heap.Push(&sb.endpoints, ep)
|
||||
sb.Unlock()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
for i, e := range sb.getConnectedEndpoints() {
|
||||
if e == ep {
|
||||
sb.Lock()
|
||||
heap.Remove(&sb.endpoints, i)
|
||||
sb.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
sb.removeEndpoint(ep)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -463,9 +447,29 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
}
|
||||
|
||||
if sb.needDefaultGW() {
|
||||
return sb.setupDefaultGW(ep)
|
||||
return sb.setupDefaultGW()
|
||||
}
|
||||
return nil
|
||||
|
||||
moveExtConn := sb.getGatewayEndpoint() != extEp
|
||||
|
||||
if moveExtConn {
|
||||
if extEp != nil {
|
||||
log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
||||
if err := d.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
|
||||
log.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
|
||||
extEp.Name(), extEp.ID(), err)
|
||||
}
|
||||
}
|
||||
if !n.internal {
|
||||
log.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
||||
if err := d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
|
||||
log.Warnf("driver failed programming external connectivity on endpoint %s (%s): %v",
|
||||
extEp.Name(), extEp.ID(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.clearDefaultGW()
|
||||
}
|
||||
|
||||
func (ep *endpoint) rename(name string) error {
|
||||
|
@ -533,15 +537,10 @@ func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
|
|||
sb.joinLeaveStart()
|
||||
defer sb.joinLeaveEnd()
|
||||
|
||||
return ep.sbLeave(sbox, false, options...)
|
||||
return ep.sbLeave(sb, false, options...)
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption) error {
|
||||
sb, ok := sbox.(*sandbox)
|
||||
if !ok {
|
||||
return types.BadRequestErrorf("not a valid Sandbox interface")
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) error {
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network from store during leave: %v", err)
|
||||
|
@ -559,8 +558,8 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
if sid == "" {
|
||||
return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
|
||||
}
|
||||
if sid != sbox.ID() {
|
||||
return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sbox.ID())
|
||||
if sid != sb.ID() {
|
||||
return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID())
|
||||
}
|
||||
|
||||
ep.processOptions(options...)
|
||||
|
@ -575,7 +574,19 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
ep.network = n
|
||||
ep.Unlock()
|
||||
|
||||
// Current endpoint providing external connectivity to the sandbox
|
||||
extEp := sb.getGatewayEndpoint()
|
||||
moveExtConn := extEp != nil && (extEp.ID() == ep.ID())
|
||||
|
||||
if d != nil {
|
||||
if moveExtConn {
|
||||
log.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
||||
if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
|
||||
log.Warnf("driver failed removing external connectivity on endpoint %s (%s): %v",
|
||||
ep.Name(), ep.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.Leave(n.id, ep.id); err != nil {
|
||||
if _, ok := err.(types.MaskableError); !ok {
|
||||
log.Warnf("driver error disconnecting container %s : %v", ep.name, err)
|
||||
|
@ -597,7 +608,24 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
}
|
||||
|
||||
sb.deleteHostsEntries(n.getSvcRecords(ep))
|
||||
return nil
|
||||
if !sb.inDelete && sb.needDefaultGW() {
|
||||
if sb.getEPwithoutGateway() == nil {
|
||||
return fmt.Errorf("endpoint without GW expected, but not found")
|
||||
}
|
||||
return sb.setupDefaultGW()
|
||||
}
|
||||
|
||||
// New endpoint providing external connectivity for the sandbox
|
||||
extEp = sb.getGatewayEndpoint()
|
||||
if moveExtConn && extEp != nil {
|
||||
log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
||||
if err := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
|
||||
log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
|
||||
extEp.Name(), extEp.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return sb.clearDefaultGW()
|
||||
}
|
||||
|
||||
func (n *network) validateForceDelete(locator string) error {
|
||||
|
@ -643,7 +671,7 @@ func (ep *endpoint) Delete(force bool) error {
|
|||
}
|
||||
|
||||
if sb != nil {
|
||||
if e := ep.sbLeave(sb, force); e != nil {
|
||||
if e := ep.sbLeave(sb.(*sandbox), force); e != nil {
|
||||
log.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -455,3 +455,9 @@ func (b *badDriver) DiscoverDelete(dType discoverapi.DiscoveryType, data interfa
|
|||
func (b *badDriver) Type() string {
|
||||
return badDriverName
|
||||
}
|
||||
func (b *badDriver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
func (b *badDriver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -283,8 +283,28 @@ func TestBridge(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := network.Delete(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
ep, err := network.CreateEndpoint("testep", libnetwork.CreateOptionPortMapping(getPortMapping()))
|
||||
ep, err := network.CreateEndpoint("testep")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sb, err := controller.NewSandbox(containerID, libnetwork.OptionPortMapping(getPortMapping()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := sb.Delete(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
err = ep.Join(sb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -304,14 +324,6 @@ func TestBridge(t *testing.T) {
|
|||
if len(pm) != 5 {
|
||||
t.Fatalf("Incomplete data for port mapping in endpoint operational data: %d", len(pm))
|
||||
}
|
||||
|
||||
if err := ep.Delete(false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := network.Delete(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Testing IPV6 from MAC address
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -118,6 +119,7 @@ type containerConfig struct {
|
|||
useDefaultSandBox bool
|
||||
useExternalKey bool
|
||||
prio int // higher the value, more the priority
|
||||
exposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
func (sb *sandbox) ID() string {
|
||||
|
@ -136,7 +138,13 @@ func (sb *sandbox) Key() string {
|
|||
}
|
||||
|
||||
func (sb *sandbox) Labels() map[string]interface{} {
|
||||
return sb.config.generic
|
||||
sb.Lock()
|
||||
sb.Unlock()
|
||||
opts := make(map[string]interface{}, len(sb.config.generic))
|
||||
for k, v := range sb.config.generic {
|
||||
opts[k] = v
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (sb *sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) {
|
||||
|
@ -329,6 +337,18 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint {
|
|||
return eps
|
||||
}
|
||||
|
||||
func (sb *sandbox) removeEndpoint(ep *endpoint) {
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
|
||||
for i, e := range sb.endpoints {
|
||||
if e == ep {
|
||||
heap.Remove(&sb.endpoints, i)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sb *sandbox) getEndpoint(id string) *endpoint {
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
|
@ -624,16 +644,11 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
|||
}
|
||||
}
|
||||
|
||||
for _, gwep := range sb.getConnectedEndpoints() {
|
||||
if len(gwep.Gateway()) > 0 {
|
||||
if gwep != ep {
|
||||
break
|
||||
}
|
||||
if err := sb.updateGateway(gwep); err != nil {
|
||||
if ep == sb.getGatewayEndpoint() {
|
||||
if err := sb.updateGateway(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only update the store if we did not come here as part of
|
||||
// sandbox delete. If we came here as part of delete then do
|
||||
|
@ -742,6 +757,13 @@ func (sb *sandbox) joinLeaveEnd() {
|
|||
}
|
||||
}
|
||||
|
||||
func (sb *sandbox) hasPortConfigs() bool {
|
||||
opts := sb.Labels()
|
||||
_, hasExpPorts := opts[netlabel.ExposedPorts]
|
||||
_, hasPortMaps := opts[netlabel.PortMap]
|
||||
return hasExpPorts || hasPortMaps
|
||||
}
|
||||
|
||||
// OptionHostname function returns an option setter for hostname option to
|
||||
// be passed to NewSandbox method.
|
||||
func OptionHostname(name string) SandboxOption {
|
||||
|
@ -851,7 +873,42 @@ func OptionUseExternalKey() SandboxOption {
|
|||
// net container creation method. Container Labels are a good example.
|
||||
func OptionGeneric(generic map[string]interface{}) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
sb.config.generic = generic
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{}, len(generic))
|
||||
}
|
||||
for k, v := range generic {
|
||||
sb.config.generic[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OptionExposedPorts function returns an option setter for the container exposed
|
||||
// ports option to be passed to container Create method.
|
||||
func OptionExposedPorts(exposedPorts []types.TransportPort) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{})
|
||||
}
|
||||
// Defensive copy
|
||||
eps := make([]types.TransportPort, len(exposedPorts))
|
||||
copy(eps, exposedPorts)
|
||||
// Store endpoint label and in generic because driver needs it
|
||||
sb.config.exposedPorts = eps
|
||||
sb.config.generic[netlabel.ExposedPorts] = eps
|
||||
}
|
||||
}
|
||||
|
||||
// OptionPortMapping function returns an option setter for the mapping
|
||||
// ports option to be passed to container Create method.
|
||||
func OptionPortMapping(portBindings []types.PortBinding) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{})
|
||||
}
|
||||
// Store a copy of the bindings as generic data to pass to the driver
|
||||
pbs := make([]types.PortBinding, len(portBindings))
|
||||
copy(pbs, portBindings)
|
||||
sb.config.generic[netlabel.PortMap] = pbs
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue