Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add publish-all cli flag #2545

Merged
merged 1 commit into from
Dec 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/common_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func addCommonFlags(flagSet *pflag.FlagSet) *container {
flagSet.StringSliceVar(&c.networks, "net", nil, "Set networks to container")
flagSet.StringSliceVarP(&c.ports, "publish", "p", nil, "Set container ports mapping")
flagSet.StringSliceVar(&c.expose, "expose", nil, "Set expose container's ports")
flagSet.BoolVarP(&c.publishAll, "publish-all", "P", false, "Publish all exposed ports to random ports")

flagSet.StringVar(&c.pidMode, "pid", "", "PID namespace to use")
flagSet.BoolVar(&c.privileged, "privileged", false, "Give extended privileges to the container")
Expand Down
35 changes: 18 additions & 17 deletions cli/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,23 +239,24 @@ func (c *container) config() (*types.ContainerCreateConfig, error) {
Ulimits: c.ulimit.Value(),
PidsLimit: c.pidsLimit,
},
DNS: c.dns,
DNSOptions: c.dnsOptions,
DNSSearch: c.dnsSearch,
EnableLxcfs: c.enableLxcfs,
Privileged: c.privileged,
RestartPolicy: restartPolicy,
IpcMode: c.ipcMode,
PidMode: c.pidMode,
UTSMode: c.utsMode,
GroupAdd: c.groupAdd,
Sysctls: sysctls,
SecurityOpt: c.securityOpt,
NetworkMode: networkMode,
CapAdd: c.capAdd,
CapDrop: c.capDrop,
PortBindings: portBindings,
OomScoreAdj: c.oomScoreAdj,
DNS: c.dns,
DNSOptions: c.dnsOptions,
DNSSearch: c.dnsSearch,
EnableLxcfs: c.enableLxcfs,
Privileged: c.privileged,
RestartPolicy: restartPolicy,
IpcMode: c.ipcMode,
PidMode: c.pidMode,
UTSMode: c.utsMode,
GroupAdd: c.groupAdd,
Sysctls: sysctls,
SecurityOpt: c.securityOpt,
NetworkMode: networkMode,
PublishAllPorts: c.publishAll,
CapAdd: c.capAdd,
CapDrop: c.capDrop,
PortBindings: portBindings,
OomScoreAdj: c.oomScoreAdj,
LogConfig: &types.LogConfig{
LogDriver: c.logDriver,
LogOpts: logOpts,
Expand Down
11 changes: 10 additions & 1 deletion daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,15 @@ func (mgr *ContainerManager) prepareContainerNetwork(ctx context.Context, c *Con
}
}

sb, err := mgr.NetworkMgr.Controller().SandboxByID(c.NetworkSettings.SandboxID)
if err != nil {
// sandbox not found, maybe caused by disconnect network or no endpoint
logrus.Warnf("failed to get sandbox by id(%s), err(%v)", c.NetworkSettings.SandboxID, err)
c.NetworkSettings.Ports = types.PortMap{}
return nil
}

c.NetworkSettings.Ports = getSandboxPortMapInfo(sb)
return nil
}

Expand Down Expand Up @@ -1461,7 +1470,7 @@ func (mgr *ContainerManager) Disconnect(ctx context.Context, containerName, netw
c.Unlock()
endpoint.EndpointConfig = epConfig
if err := mgr.NetworkMgr.EndpointRemove(ctx, endpoint); err != nil {
// TODO(ziren): it is a trick, we should wrapper sanbox
// TODO(ziren): it is a trick, we should wrapper sandbox
ZYecho marked this conversation as resolved.
Show resolved Hide resolved
// not found as an error type
if !strings.Contains(err.Error(), "not found") {
logrus.Errorf("failed to remove endpoint: %v", err)
Expand Down
65 changes: 64 additions & 1 deletion daemon/mgr/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net"
"path"
"strconv"
"strings"

apitypes "github.com/alibaba/pouch/apis/types"
Expand Down Expand Up @@ -662,7 +663,6 @@ func buildSandboxOptions(config network.Config, endpoint *types.Endpoint) ([]lib

// TODO: secondary ip address
// TODO: parse extra hosts
// TODO: port mapping
var bindings = make(nat.PortMap)
if endpoint.PortBindings != nil {
for p, b := range endpoint.PortBindings {
Expand Down Expand Up @@ -744,3 +744,66 @@ func joinOptions(endpoint *types.Endpoint) ([]libnetwork.EndpointOption, error)
joinOptions = append(joinOptions, libnetwork.JoinOptionPriority(nil, endpoint.Priority))
return joinOptions, nil
}

// getSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox.
func getSandboxPortMapInfo(sb libnetwork.Sandbox) apitypes.PortMap {
pm := apitypes.PortMap{}
if sb == nil {
return pm
}

for _, ep := range sb.Endpoints() {
pm, _ = getEndpointPortMapInfo(ep)
if len(pm) > 0 {
break
}
}
return pm
}

func getEndpointPortMapInfo(ep libnetwork.Endpoint) (apitypes.PortMap, error) {
ZYecho marked this conversation as resolved.
Show resolved Hide resolved
pm := apitypes.PortMap{}
driverInfo, err := ep.DriverInfo()
if err != nil {
return pm, err
}

if driverInfo == nil {
return pm, nil
}

// get exposedPorts from driverInfo, which was open by --expose and so on
if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
if exposedPorts, ok := expData.([]networktypes.TransportPort); ok {
for _, tp := range exposedPorts {
natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
if err != nil {
return pm, fmt.Errorf("failed to parse Port value(%v):%v", tp.Port, err)
}
pm[string(natPort)] = nil
}
}
}

mapData, ok := driverInfo[netlabel.PortMap]
if !ok {
return pm, nil
}

// get the port-mapping from driverInfo, which was open by -p HostPort:port
portMapping, ok := mapData.([]networktypes.PortBinding)
if !ok {
return pm, nil
}

for _, pp := range portMapping {
natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
if err != nil {
return pm, err
}
natBndg := apitypes.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
pm[string(natPort)] = append(pm[string(natPort)], natBndg)
}

return pm, nil
}
2 changes: 1 addition & 1 deletion test/cli_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,5 @@ func (suite *PouchInspectSuite) TestContainerInspectPorts(c *check.C) {
c.Fatal("fail to format container json")
}
data, _ := json.Marshal(containers[0].NetworkSettings.Ports)
c.Assert(string(data), check.Equals, "{\"80/tcp\":[{\"HostPort\":\"8080\"}]}")
c.Assert(string(data), check.Equals, "{\"80/tcp\":[{\"HostIp\":\"0.0.0.0\",\"HostPort\":\"8080\"}]}")
}
41 changes: 41 additions & 0 deletions test/cli_run_network_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package main

import (
"encoding/json"

"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/test/command"
"github.com/alibaba/pouch/test/environment"

Expand Down Expand Up @@ -33,3 +36,41 @@ func (suite *PouchRunNetworkSuite) TestRunWithPing(c *check.C) {
defer DelContainerForceMultyTime(c, name)
res.Assert(c, icmd.Success)
}

// TestRunWithPublicAll is to verify run container with publish-all flag
func (suite *PouchRunNetworkSuite) TestRunWithPublishAll(c *check.C) {
ZYecho marked this conversation as resolved.
Show resolved Hide resolved
name := "TestRunWithPublishAll"

command.PouchRun("run", "--name", name, "--expose", "8080", "-P", busyboxImage).Assert(c, icmd.Success)
defer DelContainerForceMultyTime(c, name)

output := command.PouchRun("inspect", name).Stdout()
containers := make([]types.ContainerJSON, 1)
err := json.Unmarshal([]byte(output), &containers)
if err != nil || len(containers) == 0 {
c.Fatal("fail to format container json")
}
c.Assert(len(containers[0].NetworkSettings.Ports), check.Equals, 1)
checkPortMapExists(c, containers[0].NetworkSettings.Ports, "8080/tcp")

// multiple expose port case
ZYecho marked this conversation as resolved.
Show resolved Hide resolved
name1 := "TestRunMultipleWithPublishAll"
command.PouchRun("run", "--name", name1, "--expose", "8081", "--expose", "8082", "-P", busyboxImage).Assert(c, icmd.Success)
defer DelContainerForceMultyTime(c, name1)

output = command.PouchRun("inspect", name1).Stdout()
containers = make([]types.ContainerJSON, 1)
err = json.Unmarshal([]byte(output), &containers)
if err != nil || len(containers) == 0 {
c.Fatal("fail to format container json")
}
c.Assert(len(containers[0].NetworkSettings.Ports), check.Equals, 2)
checkPortMapExists(c, containers[0].NetworkSettings.Ports, "8081/tcp")
checkPortMapExists(c, containers[0].NetworkSettings.Ports, "8082/tcp")
}

func checkPortMapExists(c *check.C, portMap types.PortMap, port string) {
portBs, ok := portMap[port]
c.Assert(ok, check.Equals, true)
c.Assert(len(portBs), check.Equals, 1)
}