Skip to content

Commit 862324e

Browse files
committed
feature: cli support --add-host
Signed-off-by: Lang Chi <[email protected]>
1 parent 7ff4bc0 commit 862324e

File tree

6 files changed

+139
-0
lines changed

6 files changed

+139
-0
lines changed

apis/server/container_bridge.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/alibaba/pouch/apis/metrics"
1414
"github.com/alibaba/pouch/apis/types"
15+
daemon_config "github.com/alibaba/pouch/daemon/config"
1516
"github.com/alibaba/pouch/daemon/mgr"
1617
"github.com/alibaba/pouch/pkg/httputils"
1718
"github.com/alibaba/pouch/pkg/streams"
@@ -50,6 +51,11 @@ func (s *Server) createContainer(ctx context.Context, rw http.ResponseWriter, re
5051
return httputils.NewHTTPError(err, http.StatusBadRequest)
5152
}
5253

54+
// validate network settings
55+
if err := daemon_config.ValidateNetMode(config); err != nil {
56+
return httputils.NewHTTPError(err, http.StatusBadRequest)
57+
}
58+
5359
name := req.FormValue("name")
5460
//consider set specific id by url params
5561
specificID := req.FormValue("specificId")

cli/common_flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func addCommonFlags(flagSet *pflag.FlagSet) *container {
7272
flagSet.StringVar(&c.ip, "ip", "", "Set IPv4 address of container endpoint")
7373
flagSet.StringVar(&c.ipv6, "ip6", "", "Set IPv6 address of container endpoint")
7474
flagSet.Int64Var(&c.netPriority, "net-priority", 0, "net priority")
75+
flagSet.StringArrayVar(&c.extraHosts, "add-host", nil, "Add a custom host-to-IP mapping (host:ip)")
7576
// dns
7677
flagSet.StringArrayVar(&c.dns, "dns", nil, "Set DNS servers")
7778
flagSet.StringSliceVar(&c.dnsOptions, "dns-option", nil, "Set DNS options")

cli/container.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type container struct {
7171
ipv6 string
7272
macAddress string
7373
netPriority int64
74+
extraHosts []string
7475
dns []string
7576
dnsOptions []string
7677
dnsSearch []string
@@ -266,6 +267,7 @@ func (c *container) config() (*types.ContainerCreateConfig, error) {
266267
Ulimits: c.ulimit.Value(),
267268
PidsLimit: c.pidsLimit,
268269
},
270+
ExtraHosts: c.extraHosts,
269271
DNS: c.dns,
270272
DNSOptions: c.dnsOptions,
271273
DNSSearch: c.dnsSearch,

daemon/config/config.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,41 @@ const (
3030
DefaultCgroupDriver = CgroupfsDriver
3131
)
3232

33+
var (
34+
// ErrConflictContainerNetworkAndLinks conflict between --net=container and links
35+
ErrConflictContainerNetworkAndLinks = fmt.Errorf("Conflicting options: container type network can't be used with links. This would result in undefined behavior")
36+
// ErrConflictUserDefinedNetworkAndLinks conflict between --net=<NETWORK> and links
37+
ErrConflictUserDefinedNetworkAndLinks = fmt.Errorf("Conflicting options: networking can't be used with links. This would result in undefined behavior")
38+
// ErrConflictSharedNetwork conflict between private and other networks
39+
ErrConflictSharedNetwork = fmt.Errorf("Container sharing network namespace with another container or host cannot be connected to any other network")
40+
// ErrConflictHostNetwork conflict from being disconnected from host network or connected to host network.
41+
ErrConflictHostNetwork = fmt.Errorf("Container cannot be disconnected from host network or connected to host network")
42+
// ErrConflictNoNetwork conflict between private and other networks
43+
ErrConflictNoNetwork = fmt.Errorf("Container cannot be connected to multiple networks with one of the networks in private (none) mode")
44+
// ErrConflictNetworkAndDNS conflict between --dns and the network mode
45+
ErrConflictNetworkAndDNS = fmt.Errorf("Conflicting options: dns and the network mode")
46+
// ErrConflictNetworkHostname conflict between the hostname and the network mode
47+
ErrConflictNetworkHostname = fmt.Errorf("Conflicting options: hostname and the network mode")
48+
// ErrConflictHostNetworkAndLinks conflict between --net=host and links
49+
ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: host type networking can't be used with links. This would result in undefined behavior")
50+
// ErrConflictContainerNetworkAndMac conflict between the mac address and the network mode
51+
ErrConflictContainerNetworkAndMac = fmt.Errorf("Conflicting options: mac-address and the network mode")
52+
// ErrConflictNetworkHosts conflict between add-host and the network mode
53+
ErrConflictNetworkHosts = fmt.Errorf("Conflicting options: custom host-to-IP mapping and the network mode")
54+
// ErrConflictNetworkPublishPorts conflict between the publish options and the network mode
55+
ErrConflictNetworkPublishPorts = fmt.Errorf("Conflicting options: port publishing and the container type network mode")
56+
// ErrConflictNetworkExposePorts conflict between the expose option and the network mode
57+
ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: port exposing and the container type network mode")
58+
// ErrUnsupportedNetworkAndIP conflict between network mode and requested ip address
59+
ErrUnsupportedNetworkAndIP = fmt.Errorf("User specified IP address is supported on user defined networks only")
60+
// ErrUnsupportedNetworkNoSubnetAndIP conflict between network with no configured subnet and requested ip address
61+
ErrUnsupportedNetworkNoSubnetAndIP = fmt.Errorf("User specified IP address is supported only when connecting to networks with user configured subnets")
62+
// ErrUnsupportedNetworkAndAlias conflict between network mode and alias
63+
ErrUnsupportedNetworkAndAlias = fmt.Errorf("Network-scoped alias is supported only for containers in user defined networks")
64+
// ErrConflictUTSHostname conflict between the hostname and the UTS mode
65+
ErrConflictUTSHostname = fmt.Errorf("Conflicting options: hostname and the UTS mode")
66+
)
67+
3368
// Config refers to daemon's whole configurations.
3469
type Config struct {
3570
sync.Mutex `json:"-"`
@@ -308,3 +343,62 @@ func validateCgroupDriver(driver string) error {
308343

309344
return fmt.Errorf("invalid cgroup driver: %s, valid driver is cgroupfs or systemd", driver)
310345
}
346+
347+
// ValidateNetMode ensures that the various combinations of requested
348+
// network settings are valid.
349+
func ValidateNetMode(config *types.ContainerCreateConfig) error {
350+
c := config.ContainerConfig
351+
hc := config.HostConfig
352+
if hc == nil {
353+
return nil
354+
}
355+
parts := strings.Split(string(hc.NetworkMode), ":")
356+
if parts[0] == "container" {
357+
if len(parts) < 2 || parts[1] == "" {
358+
return fmt.Errorf("--net: invalid net mode: invalid container format container:<name|id>")
359+
}
360+
361+
if c.Hostname != "" {
362+
return ErrConflictNetworkHostname
363+
}
364+
365+
if len(hc.Links) > 0 {
366+
return ErrConflictContainerNetworkAndLinks
367+
}
368+
369+
if len(hc.DNS) > 0 {
370+
return ErrConflictNetworkAndDNS
371+
}
372+
373+
if len(hc.ExtraHosts) > 0 {
374+
return ErrConflictNetworkHosts
375+
}
376+
377+
if c.MacAddress != "" {
378+
return ErrConflictContainerNetworkAndMac
379+
}
380+
381+
if len(hc.PortBindings) > 0 || hc.PublishAllPorts == true {
382+
return ErrConflictNetworkPublishPorts
383+
}
384+
385+
if len(c.ExposedPorts) > 0 {
386+
return ErrConflictNetworkExposePorts
387+
}
388+
}
389+
390+
if hc.UTSMode == "host" && c.Hostname != "" {
391+
return ErrConflictUTSHostname
392+
}
393+
394+
if hc.NetworkMode == "host" {
395+
if len(hc.Links) > 0 {
396+
return ErrConflictHostNetworkAndLinks
397+
}
398+
399+
if c.MacAddress != "" {
400+
return ErrConflictContainerNetworkAndMac
401+
}
402+
}
403+
return nil
404+
}

daemon/mgr/network.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,13 @@ func buildSandboxOptions(config network.Config, endpoint *types.Endpoint) ([]lib
695695

696696
// TODO: secondary ip address
697697
// TODO: parse extra hosts
698+
for _, extraHost := range endpoint.ExtraHosts {
699+
// allow IPv6 addresses in extra hosts; only split on first ":"
700+
parts := strings.SplitN(extraHost, ":", 2)
701+
fmt.Printf("\nparts[0]: %s, \n parts[1]: %s\n", parts[0], parts[1])
702+
sandboxOptions = append(sandboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
703+
}
704+
698705
var bindings = make(nat.PortMap)
699706
if endpoint.PortBindings != nil {
700707
for p, b := range endpoint.PortBindings {

test/cli_run_network_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,32 @@ func (suite *PouchRunNetworkSuite) TestRunWithIP(c *check.C) {
122122

123123
c.Assert(found, check.Equals, true)
124124
}
125+
126+
// TestRunAddHost is to verify run container with add-host flag
127+
func (suite *PouchRunNetworkSuite) TestRunAddHost(c *check.C) {
128+
res := command.PouchRun("run", "--add-host=extra:86.75.30.9", "busybox", "grep", "extra", "/etc/hosts")
129+
res.Assert(c, icmd.Success)
130+
131+
stdout := res.Stdout()
132+
actual := strings.Trim(stdout, "\r\n")
133+
if !strings.Contains(actual, "86.75.30.9\textra") {
134+
c.Fatalf("expected '86.75.30.9\textra', but says: %q", actual)
135+
}
136+
}
137+
138+
func (suite *PouchRunNetworkSuite) TestRunAddHostInHostMode(c *check.C) {
139+
expectedOutput := "1.2.3.4\textra"
140+
res := command.PouchRun("run", "--add-host=extra:1.2.3.4", "--net=host", "busybox", "cat", "/etc/hosts")
141+
res.Assert(c, icmd.Success)
142+
if !strings.Contains(res.Stdout(), expectedOutput) {
143+
check.Commentf("Expected '%s', but got %q", expectedOutput, res.Stdout())
144+
}
145+
}
146+
147+
func (suite *PouchRunNetworkSuite) TestConflictNetworkModeAndOptions(c *check.C) {
148+
conflictOutput := "Conflicting options: custom host-to-IP mapping and the network mode"
149+
res := command.PouchRun("run", "--net=container:other", "--add-host=name:8.8.8.8", "busybox", "ps")
150+
if !strings.Contains(res.Stdout(), conflictOutput) {
151+
check.Commentf("Expected '%s', but got %q", conflictOutput, res.Stdout())
152+
}
153+
}

0 commit comments

Comments
 (0)