Kaynağa Gözat

Merge pull request #119 from aboch/fmzhen-test-dev

Separate ExpsoedPorts from PortBindings
Madhu Venugopal 10 yıl önce
ebeveyn
işleme
5b576f4dcc

+ 13 - 4
libnetwork/drivers/bridge/bridge.go

@@ -50,6 +50,7 @@ type Configuration struct {
 type EndpointConfiguration struct {
 type EndpointConfiguration struct {
 	MacAddress   net.HardwareAddr
 	MacAddress   net.HardwareAddr
 	PortBindings []netutils.PortBinding
 	PortBindings []netutils.PortBinding
+	ExposedPorts []netutils.TransportPort
 }
 }
 
 
 // ContainerConfiguration represents the user specified configuration for a container
 // ContainerConfiguration represents the user specified configuration for a container
@@ -663,7 +664,7 @@ func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enabl
 		return nil
 		return nil
 	}
 	}
 
 
-	if endpoint.config != nil && endpoint.config.PortBindings != nil {
+	if endpoint.config != nil && endpoint.config.ExposedPorts != nil {
 		for _, p := range cc.ParentEndpoints {
 		for _, p := range cc.ParentEndpoints {
 			var parentEndpoint *bridgeEndpoint
 			var parentEndpoint *bridgeEndpoint
 			parentEndpoint, err = network.getEndpoint(types.UUID(p))
 			parentEndpoint, err = network.getEndpoint(types.UUID(p))
@@ -677,7 +678,7 @@ func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enabl
 
 
 			l := newLink(parentEndpoint.intf.Address.IP.String(),
 			l := newLink(parentEndpoint.intf.Address.IP.String(),
 				endpoint.intf.Address.IP.String(),
 				endpoint.intf.Address.IP.String(),
-				endpoint.config.PortBindings, d.config.BridgeName)
+				endpoint.config.ExposedPorts, d.config.BridgeName)
 			if enable {
 			if enable {
 				err = l.Enable()
 				err = l.Enable()
 				if err != nil {
 				if err != nil {
@@ -704,12 +705,12 @@ func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enabl
 			err = InvalidEndpointIDError(c)
 			err = InvalidEndpointIDError(c)
 			return err
 			return err
 		}
 		}
-		if childEndpoint.config == nil || childEndpoint.config.PortBindings == nil {
+		if childEndpoint.config == nil || childEndpoint.config.ExposedPorts == nil {
 			continue
 			continue
 		}
 		}
 		l := newLink(endpoint.intf.Address.IP.String(),
 		l := newLink(endpoint.intf.Address.IP.String(),
 			childEndpoint.intf.Address.IP.String(),
 			childEndpoint.intf.Address.IP.String(),
-			childEndpoint.config.PortBindings, d.config.BridgeName)
+			childEndpoint.config.ExposedPorts, d.config.BridgeName)
 		if enable {
 		if enable {
 			err = l.Enable()
 			err = l.Enable()
 			if err != nil {
 			if err != nil {
@@ -754,6 +755,14 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfigurat
 		}
 		}
 	}
 	}
 
 
+	if opt, ok := epOptions[options.ExposedPorts]; ok {
+		if ports, ok := opt.([]netutils.TransportPort); ok {
+			ec.ExposedPorts = ports
+		} else {
+			return nil, ErrInvalidEndpointConfig
+		}
+	}
+
 	return ec, nil
 	return ec, nil
 }
 }
 
 

+ 21 - 14
libnetwork/drivers/bridge/bridge_test.go

@@ -171,6 +171,14 @@ func TestCreateLinkWithOptions(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func getExposedPorts() []netutils.TransportPort {
+	return []netutils.TransportPort{
+		netutils.TransportPort{Proto: netutils.TCP, Port: uint16(5000)},
+		netutils.TransportPort{Proto: netutils.UDP, Port: uint16(400)},
+		netutils.TransportPort{Proto: netutils.TCP, Port: uint16(600)},
+	}
+}
+
 func getPortMapping() []netutils.PortBinding {
 func getPortMapping() []netutils.PortBinding {
 	return []netutils.PortBinding{
 	return []netutils.PortBinding{
 		netutils.PortBinding{Proto: netutils.TCP, Port: uint16(230), HostPort: uint16(23000)},
 		netutils.PortBinding{Proto: netutils.TCP, Port: uint16(230), HostPort: uint16(23000)},
@@ -201,9 +209,9 @@ func TestLinkContainers(t *testing.T) {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
-	portMappings := getPortMapping()
+	exposedPorts := getExposedPorts()
 	epOptions := make(map[string]interface{})
 	epOptions := make(map[string]interface{})
-	epOptions[options.PortMap] = portMappings
+	epOptions[options.ExposedPorts] = exposedPorts
 
 
 	sinfo, err := d.CreateEndpoint("net1", "ep1", epOptions)
 	sinfo, err := d.CreateEndpoint("net1", "ep1", epOptions)
 	if err != nil {
 	if err != nil {
@@ -235,13 +243,12 @@ func TestLinkContainers(t *testing.T) {
 		t.Fatalf("Failed to link ep1 and ep2")
 		t.Fatalf("Failed to link ep1 and ep2")
 	}
 	}
 
 
-	out, err := iptables.Raw("-L", "DOCKER")
-	for _, pm := range portMappings {
+	out, err := iptables.Raw("-L", DockerChain)
+	for _, pm := range exposedPorts {
 		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 		re := regexp.MustCompile(regex)
 		re := regexp.MustCompile(regex)
 		matches := re.FindAllString(string(out[:]), -1)
 		matches := re.FindAllString(string(out[:]), -1)
-		// There will be 2 matches : Port-Mapping and Linking table rules
-		if len(matches) < 2 {
+		if len(matches) != 1 {
 			t.Fatalf("IP Tables programming failed %s", string(out[:]))
 			t.Fatalf("IP Tables programming failed %s", string(out[:]))
 		}
 		}
 
 
@@ -257,13 +264,12 @@ func TestLinkContainers(t *testing.T) {
 		t.Fatalf("Failed to unlink ep1 and ep2")
 		t.Fatalf("Failed to unlink ep1 and ep2")
 	}
 	}
 
 
-	out, err = iptables.Raw("-L", "DOCKER")
-	for _, pm := range portMappings {
+	out, err = iptables.Raw("-L", DockerChain)
+	for _, pm := range exposedPorts {
 		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 		regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 		re := regexp.MustCompile(regex)
 		re := regexp.MustCompile(regex)
 		matches := re.FindAllString(string(out[:]), -1)
 		matches := re.FindAllString(string(out[:]), -1)
-		// There will be 1 match : Port-Mapping
-		if len(matches) > 1 {
+		if len(matches) != 0 {
 			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
 			t.Fatalf("Leave should have deleted relevant IPTables rules  %s", string(out[:]))
 		}
 		}
 
 
@@ -282,13 +288,12 @@ func TestLinkContainers(t *testing.T) {
 
 
 	_, err = d.Join("net1", "ep2", "", genericOption)
 	_, err = d.Join("net1", "ep2", "", genericOption)
 	if err != nil {
 	if err != nil {
-		out, err = iptables.Raw("-L", "DOCKER")
-		for _, pm := range portMappings {
+		out, err = iptables.Raw("-L", DockerChain)
+		for _, pm := range exposedPorts {
 			regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 			regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
 			re := regexp.MustCompile(regex)
 			re := regexp.MustCompile(regex)
 			matches := re.FindAllString(string(out[:]), -1)
 			matches := re.FindAllString(string(out[:]), -1)
-			// There must be 1 match : Port-Mapping
-			if len(matches) > 1 {
+			if len(matches) != 0 {
 				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
 				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
 			}
 			}
 
 
@@ -298,6 +303,8 @@ func TestLinkContainers(t *testing.T) {
 				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
 				t.Fatalf("Error handling should rollback relevant IPTables rules  %s", string(out[:]))
 			}
 			}
 		}
 		}
+	} else {
+		t.Fatalf("Expected Join to fail given link conditions are not satisfied")
 	}
 	}
 }
 }
 
 

+ 3 - 3
libnetwork/drivers/bridge/link.go

@@ -12,7 +12,7 @@ import (
 type link struct {
 type link struct {
 	parentIP string
 	parentIP string
 	childIP  string
 	childIP  string
-	ports    []netutils.PortBinding
+	ports    []netutils.TransportPort
 	bridge   string
 	bridge   string
 }
 }
 
 
@@ -20,7 +20,7 @@ func (l *link) String() string {
 	return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
 	return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
 }
 }
 
 
-func newLink(parentIP, childIP string, ports []netutils.PortBinding, bridge string) *link {
+func newLink(parentIP, childIP string, ports []netutils.TransportPort, bridge string) *link {
 	return &link{
 	return &link{
 		childIP:  childIP,
 		childIP:  childIP,
 		parentIP: parentIP,
 		parentIP: parentIP,
@@ -45,7 +45,7 @@ func (l *link) Disable() {
 	// that returns typed errors
 	// that returns typed errors
 }
 }
 
 
-func linkContainers(action, parentIP, childIP string, ports []netutils.PortBinding, bridge string,
+func linkContainers(action, parentIP, childIP string, ports []netutils.TransportPort, bridge string,
 	ignoreErrors bool) error {
 	ignoreErrors bool) error {
 	var nfAction iptables.Action
 	var nfAction iptables.Action
 
 

+ 16 - 11
libnetwork/endpoint.go

@@ -482,22 +482,27 @@ func JoinOptionUseDefaultSandbox() EndpointOption {
 	}
 	}
 }
 }
 
 
-// CreateOptionPortMapping function returns an option setter for the container exposed
+// CreateOptionExposedPorts function returns an option setter for the container exposed
+// ports option to be passed to network.CreateEndpoint() method.
+func CreateOptionExposedPorts(exposedPorts []netutils.TransportPort) EndpointOption {
+	return func(ep *endpoint) {
+		// Defensive copy
+		eps := make([]netutils.TransportPort, len(exposedPorts))
+		copy(eps, exposedPorts)
+		// Store endpoint label and in generic because driver needs it
+		ep.exposedPorts = eps
+		ep.generic[options.ExposedPorts] = eps
+	}
+}
+
+// CreateOptionPortMapping function returns an option setter for the mapping
 // ports option to be passed to network.CreateEndpoint() method.
 // ports option to be passed to network.CreateEndpoint() method.
 func CreateOptionPortMapping(portBindings []netutils.PortBinding) EndpointOption {
 func CreateOptionPortMapping(portBindings []netutils.PortBinding) EndpointOption {
 	return func(ep *endpoint) {
 	return func(ep *endpoint) {
-		// Extract and store exposed ports as this is the only concern of libnetwork endpoint
 		// Store a copy of the bindings as generic data to pass to the driver
 		// Store a copy of the bindings as generic data to pass to the driver
-		pbs := make([]netutils.PortBinding, 0, len(portBindings))
-		exp := make([]netutils.TransportPort, 0, len(portBindings))
-
-		for _, b := range portBindings {
-			pbs = append(pbs, b.GetCopy())
-			exp = append(exp, netutils.TransportPort{Proto: b.Proto, Port: b.Port})
-		}
-
+		pbs := make([]netutils.PortBinding, len(portBindings))
+		copy(pbs, portBindings)
 		ep.generic[options.PortMap] = pbs
 		ep.generic[options.PortMap] = pbs
-		ep.exposedPorts = exp
 	}
 	}
 }
 }
 
 

+ 1 - 1
libnetwork/libnetwork_test.go

@@ -179,7 +179,7 @@ func TestBridge(t *testing.T) {
 		t.Fatalf("Unexpected format for port mapping in endpoint operational data")
 		t.Fatalf("Unexpected format for port mapping in endpoint operational data")
 	}
 	}
 	if len(pm) != 3 {
 	if len(pm) != 3 {
-		t.Fatalf("Incomplete data for port mapping in endpoint operational data")
+		t.Fatalf("Incomplete data for port mapping in endpoint operational data: %d", len(pm))
 	}
 	}
 
 
 	if err := ep.Delete(); err != nil {
 	if err := ep.Delete(); err != nil {

+ 5 - 0
libnetwork/netutils/utils.go

@@ -39,6 +39,11 @@ type TransportPort struct {
 	Port  uint16
 	Port  uint16
 }
 }
 
 
+// GetCopy returns a copy of this TransportPort structure instance
+func (t *TransportPort) GetCopy() TransportPort {
+	return TransportPort{Proto: t.Proto, Port: t.Port}
+}
+
 // PortBinding represent a port binding between the container an the host
 // PortBinding represent a port binding between the container an the host
 type PortBinding struct {
 type PortBinding struct {
 	Proto    Protocol
 	Proto    Protocol

+ 2 - 0
libnetwork/pkg/options/options.go

@@ -14,6 +14,8 @@ const (
 	PortMap = "io.docker.network.endpoint.portmap"
 	PortMap = "io.docker.network.endpoint.portmap"
 	// MacAddress constant represents Mac Address config of a Container
 	// MacAddress constant represents Mac Address config of a Container
 	MacAddress = "io.docker.network.endpoint.macaddress"
 	MacAddress = "io.docker.network.endpoint.macaddress"
+	// ExposedPorts constant represents exposedports of a Container
+	ExposedPorts = "io.docker.network.endpoint.exposedports"
 )
 )
 
 
 // NoSuchFieldError is the error returned when the generic parameters hold a
 // NoSuchFieldError is the error returned when the generic parameters hold a