Esempio n. 1
2
func ports(c *config.ServiceConfig) (map[nat.Port]struct{}, nat.PortMap, error) {
	ports, binding, err := nat.ParsePortSpecs(c.Ports)
	if err != nil {
		return nil, nil, err
	}

	exPorts, _, err := nat.ParsePortSpecs(c.Expose)
	if err != nil {
		return nil, nil, err
	}

	for k, v := range exPorts {
		ports[k] = v
	}

	exposedPorts := map[nat.Port]struct{}{}
	for k, v := range ports {
		exposedPorts[nat.Port(k)] = v
	}

	portBindings := nat.PortMap{}
	for k, bv := range binding {
		dcbs := make([]nat.PortBinding, len(bv))
		for k, v := range bv {
			dcbs[k] = nat.PortBinding{HostIP: v.HostIP, HostPort: v.HostPort}
		}
		portBindings[nat.Port(k)] = dcbs
	}
	return exposedPorts, portBindings, nil
}
Esempio n. 2
1
func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) {
	if flags.Changed(flagPublishAdd) {
		values := flags.Lookup(flagPublishAdd).Value.(*opts.ListOpts).GetAll()
		ports, portBindings, _ := nat.ParsePortSpecs(values)

		for port := range ports {
			*portConfig = append(*portConfig, convertPortToPortConfig(port, portBindings)...)
		}
	}

	if !flags.Changed(flagPublishRemove) {
		return
	}
	toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.ListOpts).GetAll()
	newPorts := []swarm.PortConfig{}
portLoop:
	for _, port := range *portConfig {
		for _, rawTargetPort := range toRemove {
			targetPort := nat.Port(rawTargetPort)
			if equalPort(targetPort, port) {
				continue portLoop
			}
		}
		newPorts = append(newPorts, port)
	}
	*portConfig = newPorts
}
Esempio n. 3
1
func makeBinding(ip, port string) nat.PortMap {
	binding := nat.PortBinding{
		HostIP:   ip,
		HostPort: port,
	}
	bindingMap := map[nat.Port][]nat.PortBinding{nat.Port(fmt.Sprintf("%s/tcp", port)): {binding}}
	return nat.PortMap(bindingMap)
}
Esempio n. 4
1
func tranformPorts(in map[docker.Port]struct{}) map[nat.Port]struct{} {
	result := make(map[nat.Port]struct{})

	for k, v := range in {
		result[nat.Port(k)] = v
	}

	return result
}
Esempio n. 5
0
func TestPortFilterForHostMode(t *testing.T) {
	var (
		p     = PortFilter{}
		nodes = []*node.Node{
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
			},
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
			{
				ID:   "node-3-id",
				Name: "node-3-name",
				Addr: "node-3",
			},
		}
		result []*node.Node
		err    error
	)

	// Add a container taking away port 80 in the host mode to nodes[0].
	container := &cluster.Container{
		Container: types.Container{ID: "c1"},
		Info: types.ContainerJSON{
			Config: &containertypes.Config{
				ExposedPorts: map[nat.Port]struct{}{nat.Port("80"): {}},
			},
			ContainerJSONBase: &types.ContainerJSONBase{
				HostConfig: &containertypes.HostConfig{
					NetworkMode: containertypes.NetworkMode("host"),
				},
			},
		}}

	assert.NoError(t, nodes[0].AddContainer(container))

	// Request port 80 in the host mode
	config := &cluster.ContainerConfig{Config: containertypes.Config{
		ExposedPorts: map[nat.Port]struct{}{nat.Port("80"): {}},
	}, HostConfig: containertypes.HostConfig{
		NetworkMode: containertypes.NetworkMode("host"),
	}, NetworkingConfig: networktypes.NetworkingConfig{}}

	// nodes[0] should be excluded since port 80 is taken away
	result, err = p.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, 2, len(result))
	assert.NotContains(t, result, nodes[0])
}
Esempio n. 6
0
// Port returns the host port the specified port is mapped on.
func (c *Container) Port(ctx context.Context, port string) (string, error) {
	if bindings, ok := c.container.NetworkSettings.Ports[nat.Port(port)]; ok {
		result := []string{}
		for _, binding := range bindings {
			result = append(result, binding.HostIP+":"+binding.HostPort)
		}

		return strings.Join(result, "\n"), nil
	}
	return "", nil
}
Esempio n. 7
0
// Port returns the host port the specified port is mapped on.
func (c *Container) Port(port string) (string, error) {
	info, err := c.findInfo()
	if err != nil {
		return "", err
	}

	if bindings, ok := info.NetworkSettings.Ports[nat.Port(port)]; ok {
		result := []string{}
		for _, binding := range bindings {
			result = append(result, binding.HostIP+":"+binding.HostPort)
		}

		return strings.Join(result, "\n"), nil
	}
	return "", nil
}
Esempio n. 8
0
func (c *containerConfig) exposedPorts() map[nat.Port]struct{} {
	exposedPorts := make(map[nat.Port]struct{})
	if c.task.Endpoint == nil {
		return exposedPorts
	}

	for _, portConfig := range c.task.Endpoint.Ports {
		if portConfig.PublishMode != api.PublishModeHost {
			continue
		}

		port := nat.Port(fmt.Sprintf("%d/%s", portConfig.TargetPort, strings.ToLower(portConfig.Protocol.String())))
		exposedPorts[port] = struct{}{}
	}

	return exposedPorts
}
Esempio n. 9
0
func makePortsAndBindings(pm []*runtimeApi.PortMapping) (map[dockernat.Port]struct{}, map[dockernat.Port][]dockernat.PortBinding) {
	exposedPorts := map[dockernat.Port]struct{}{}
	portBindings := map[dockernat.Port][]dockernat.PortBinding{}
	for _, port := range pm {
		exteriorPort := port.GetHostPort()
		if exteriorPort == 0 {
			// No need to do port binding when HostPort is not specified
			continue
		}
		interiorPort := port.GetContainerPort()
		// Some of this port stuff is under-documented voodoo.
		// See http://stackoverflow.com/questions/20428302/binding-a-port-to-a-host-interface-using-the-rest-api
		var protocol string
		switch strings.ToUpper(string(port.GetProtocol())) {
		case "UDP":
			protocol = "/udp"
		case "TCP":
			protocol = "/tcp"
		default:
			glog.Warningf("Unknown protocol %q: defaulting to TCP", port.Protocol)
			protocol = "/tcp"
		}

		dockerPort := dockernat.Port(strconv.Itoa(int(interiorPort)) + protocol)
		exposedPorts[dockerPort] = struct{}{}

		hostBinding := dockernat.PortBinding{
			HostPort: strconv.Itoa(int(exteriorPort)),
			HostIP:   port.GetHostIp(),
		}

		// Allow multiple host ports bind to same docker port
		if existedBindings, ok := portBindings[dockerPort]; ok {
			// If a docker port already map to a host port, just append the host ports
			portBindings[dockerPort] = append(existedBindings, hostBinding)
		} else {
			// Otherwise, it's fresh new port binding
			portBindings[dockerPort] = []dockernat.PortBinding{
				hostBinding,
			}
		}
	}
	return exposedPorts, portBindings
}
Esempio n. 10
0
func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error {
	// The key of the map is `port/protocol`, e.g., `80/tcp`
	portSet := map[string]swarm.PortConfig{}
	// Check to see if there are any conflict in flags.
	if flags.Changed(flagPublishAdd) {
		values := flags.Lookup(flagPublishAdd).Value.(*opts.ListOpts).GetAll()
		ports, portBindings, _ := nat.ParsePortSpecs(values)

		for port := range ports {
			newConfigs := convertPortToPortConfig(port, portBindings)
			for _, entry := range newConfigs {
				if v, ok := portSet[portConfigToString(&entry)]; ok && v != entry {
					return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", entry.PublishedPort, entry.TargetPort, entry.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
				}
				portSet[portConfigToString(&entry)] = entry
			}
		}
	}

	// Override previous PortConfig in service if there is any duplicate
	for _, entry := range *portConfig {
		if _, ok := portSet[portConfigToString(&entry)]; !ok {
			portSet[portConfigToString(&entry)] = entry
		}
	}

	toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.ListOpts).GetAll()
	newPorts := []swarm.PortConfig{}
portLoop:
	for _, port := range portSet {
		for _, rawTargetPort := range toRemove {
			targetPort := nat.Port(rawTargetPort)
			if equalPort(targetPort, port) {
				continue portLoop
			}
		}
		newPorts = append(newPorts, port)
	}
	// Sort the PortConfig to avoid unnecessary updates
	sort.Sort(byPortConfig(newPorts))
	*portConfig = newPorts
	return nil
}
Esempio n. 11
0
func (c *containerConfig) portBindings() nat.PortMap {
	portBindings := nat.PortMap{}
	if c.task.Endpoint == nil {
		return portBindings
	}

	for _, portConfig := range c.task.Endpoint.Ports {
		if portConfig.PublishMode != api.PublishModeHost {
			continue
		}

		port := nat.Port(fmt.Sprintf("%d/%s", portConfig.TargetPort, strings.ToLower(portConfig.Protocol.String())))
		binding := []nat.PortBinding{
			{},
		}

		if portConfig.PublishedPort != 0 {
			binding[0].HostPort = strconv.Itoa(int(portConfig.PublishedPort))
		}
		portBindings[port] = binding
	}

	return portBindings
}
Esempio n. 12
0
// Addr returns the host and port from the node in the format HOST:PORT.
func (l *LocalCluster) Addr(ctx context.Context, i int, port string) string {
	return l.Nodes[i].Addr(ctx, nat.Port(port+"/tcp")).String()
}
Esempio n. 13
0
func TestPortFilterRandomAssignment(t *testing.T) {
	var (
		p     = PortFilter{}
		nodes = []*node.Node{
			{
				ID:   "node-0-id",
				Name: "node-0-name",
				Addr: "node-0",
			},
			{
				ID:   "node-1-id",
				Name: "node-1-name",
				Addr: "node-1",
			},
			{
				ID:   "node-2-id",
				Name: "node-2-name",
				Addr: "node-2",
			},
		}
		result []*node.Node
		err    error
	)

	// Simulate a container that requested to map 80 to a random port.
	// In this case, HostConfig.PortBindings should contain a binding with no
	// HostPort defined and NetworkSettings.Ports should contain the actual
	// mapped port.
	container := &cluster.Container{
		Container: types.Container{ID: "c1"},
		Info: types.ContainerJSON{
			ContainerJSONBase: &types.ContainerJSONBase{
				HostConfig: &containertypes.HostConfig{
					PortBindings: nat.PortMap(
						map[nat.Port][]nat.PortBinding{
							nat.Port("80/tcp"): {
								{
									HostIP:   "",
									HostPort: "",
								},
							},
						},
					),
				}}}}

	container.Info.NetworkSettings = &types.NetworkSettings{
		NetworkSettingsBase: types.NetworkSettingsBase{
			Ports: nat.PortMap(
				map[nat.Port][]nat.PortBinding{
					nat.Port("80/tcp"): {
						{
							HostIP:   "127.0.0.1",
							HostPort: "1234",
						},
					},
				},
			),
		}}

	assert.NoError(t, nodes[0].AddContainer(container))

	// Request port 80.
	config := &cluster.ContainerConfig{Config: containertypes.Config{}, HostConfig: containertypes.HostConfig{
		PortBindings: makeBinding("", "80"),
	}, NetworkingConfig: networktypes.NetworkingConfig{}}

	// Since port "80" has been mapped to "1234", we should be able to request "80".
	result, err = p.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.Equal(t, result, nodes)

	// However, we should not be able to request "1234" since it has been used for a random assignment.
	config = &cluster.ContainerConfig{Config: containertypes.Config{}, HostConfig: containertypes.HostConfig{
		PortBindings: makeBinding("", "1234"),
	}, NetworkingConfig: networktypes.NetworkingConfig{}}
	result, err = p.Filter(config, nodes, true)
	assert.NoError(t, err)
	assert.NotContains(t, result, nodes[0])
}
Esempio n. 14
0
// Addr returns the host and port from the node in the format HOST:PORT.
func (l *LocalCluster) Addr(i int, port string) string {
	return l.Nodes[i].Addr(nat.Port(port + "/tcp")).String()
}
Esempio n. 15
0
func portSpec(port uint32, protocol api.PortConfig_Protocol) nat.Port {
	return nat.Port(fmt.Sprintf("%d/%s", port, strings.ToLower(protocol.String())))
}