Skip to content

Commit

Permalink
Merge pull request containers#2747 from mheon/dns_none
Browse files Browse the repository at this point in the history
Add --dns=none
  • Loading branch information
openshift-merge-robot authored Mar 27, 2019
2 parents 1ff03ee + 0cd92ea commit 340eeec
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 40 deletions.
4 changes: 4 additions & 0 deletions cmd/podman/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"network", getDefaultNetwork(),
"Connect a container to a network",
)
createFlags.Bool(
"no-hosts", false,
"Do not create /etc/hosts within the container, instead use the version from the image",
)
createFlags.Bool(
"oom-kill-disable", false,
"Disable OOM Killer",
Expand Down
5 changes: 5 additions & 0 deletions cmd/podman/shared/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
}

if c.Bool("no-hosts") && c.Flag("add-host").Changed {
return nil, errors.Errorf("--no-hosts and --add-host cannot be set together")
}

// EXPOSED PORTS
var portBindings map[nat.Port][]nat.PortBinding
if data != nil {
Expand Down Expand Up @@ -646,6 +650,7 @@ func ParseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
GroupAdd: c.StringSlice("group-add"),
Hostname: c.String("hostname"),
HostAdd: c.StringSlice("add-host"),
NoHosts: c.Bool("no-hosts"),
IDMappings: idmappings,
Image: imageName,
ImageID: imageID,
Expand Down
1 change: 1 addition & 0 deletions completions/bash/podman
Original file line number Diff line number Diff line change
Expand Up @@ -1727,6 +1727,7 @@ _podman_container_run() {
--memory-reservation
--name
--network
--no-hosts
--oom-score-adj
--pid
--pids-limit
Expand Down
10 changes: 10 additions & 0 deletions docs/podman-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
is the case the **--dns** flags is necessary for every run.

The special value **none** can be specified to disable creation of **/etc/resolv.conf** in the container by Podman.
The **/etc/resolv.conf** file in the image will be used without changes.

**--dns-option**=[]

Set custom DNS options
Expand Down Expand Up @@ -457,6 +460,13 @@ Set the Network mode for the container

Not implemented

**--no-hosts**=*true*|*false*

Do not create /etc/hosts for the container.
By default, Podman will manage /etc/hosts, adding the container's own IP address and any hosts from **--add-host**.
**--no-hosts** disables this, and the image's **/etc/host** will be preserved unmodified.
This option conflicts with **--add-host**.

**--oom-kill-disable**=*true*|*false*

Whether to disable OOM Killer for the container or not.
Expand Down
10 changes: 10 additions & 0 deletions docs/podman-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
is the case the **--dns** flags is necessary for every run.

The special value **none** can be specified to disable creation of **/etc/resolv.conf** in the container by Podman.
The **/etc/resolv.conf** file in the image will be used without changes.

**--dns-option**=[]

Set custom DNS options
Expand Down Expand Up @@ -441,6 +444,13 @@ Set the Network mode for the container:

Not implemented

**--no-hosts**=*true*|*false*

Do not create /etc/hosts for the container.
By default, Podman will manage /etc/hosts, adding the container's own IP address and any hosts from **--add-host**.
**--no-hosts** disables this, and the image's **/etc/host** will be preserved unmodified.
This option conflicts with **--add-host**.

**--oom-kill-disable**=*true*|*false*

Whether to disable OOM Killer for the container or not.
Expand Down
8 changes: 8 additions & 0 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ type ContainerConfig struct {
// namespace
// These are not used unless CreateNetNS is true
PortMappings []ocicni.PortMapping `json:"portMappings,omitempty"`
// UseImageResolvConf indicates that resolv.conf should not be
// bind-mounted inside the container.
// Conflicts with DNSServer, DNSSearch, DNSOption.
UseImageResolvConf bool
// DNS servers to use in container resolv.conf
// Will override servers in host resolv if set
DNSServer []net.IP `json:"dnsServer,omitempty"`
Expand All @@ -302,6 +306,10 @@ type ContainerConfig struct {
// DNS options to be set in container resolv.conf
// With override options in host resolv if set
DNSOption []string `json:"dnsOption,omitempty"`
// UseImageHosts indicates that /etc/hosts should not be
// bind-mounted inside the container.
// Conflicts with HostAdd.
UseImageHosts bool
// Hosts to add in container
// Will be appended to host's host file
HostAdd []string `json:"hostsAdd,omitempty"`
Expand Down
85 changes: 49 additions & 36 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,10 +703,11 @@ func (c *Container) makeBindMounts() error {
}
}

if c.config.NetNsCtr != "" {
// We share a net namespace
if c.config.NetNsCtr != "" && (!c.config.UseImageResolvConf || !c.config.UseImageHosts) {
// We share a net namespace.
// We want /etc/resolv.conf and /etc/hosts from the
// other container
// other container. Unless we're not creating both of
// them.
depCtr, err := c.runtime.state.Container(c.config.NetNsCtr)
if err != nil {
return errors.Wrapf(err, "error fetching dependency %s of container %s", c.config.NetNsCtr, c.ID())
Expand All @@ -718,53 +719,65 @@ func (c *Container) makeBindMounts() error {
return errors.Wrapf(err, "error fetching bind mounts from dependency %s of container %s", depCtr.ID(), c.ID())
}

// The other container may not have a resolv.conf or /etc/hosts
// If it doesn't, don't copy them
resolvPath, exists := bindMounts["/etc/resolv.conf"]
if exists {
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
if !c.config.UseImageResolvConf {
// The other container may not have a resolv.conf or /etc/hosts
// If it doesn't, don't copy them
resolvPath, exists := bindMounts["/etc/resolv.conf"]
if exists {
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
}
}

// check if dependency container has an /etc/hosts file
hostsPath, exists := bindMounts["/etc/hosts"]
if !exists {
return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
}
if !c.config.UseImageHosts {
// check if dependency container has an /etc/hosts file
hostsPath, exists := bindMounts["/etc/hosts"]
if !exists {
return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
}

depCtr.lock.Lock()
// generate a hosts file for the dependency container,
// based on either its old hosts file, or the default,
// and add the relevant information from the new container (hosts and IP)
hostsPath, err = depCtr.appendHosts(hostsPath, c)
depCtr.lock.Lock()
// generate a hosts file for the dependency container,
// based on either its old hosts file, or the default,
// and add the relevant information from the new container (hosts and IP)
hostsPath, err = depCtr.appendHosts(hostsPath, c)

if err != nil {
if err != nil {
depCtr.lock.Unlock()
return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
}
depCtr.lock.Unlock()
return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
}
depCtr.lock.Unlock()

// finally, save it in the new container
c.state.BindMounts["/etc/hosts"] = hostsPath
// finally, save it in the new container
c.state.BindMounts["/etc/hosts"] = hostsPath
}
} else {
newResolv, err := c.generateResolvConf()
if err != nil {
return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
if !c.config.UseImageResolvConf {
newResolv, err := c.generateResolvConf()
if err != nil {
return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
}
c.state.BindMounts["/etc/resolv.conf"] = newResolv
}
c.state.BindMounts["/etc/resolv.conf"] = newResolv

newHosts, err := c.generateHosts("/etc/hosts")
if err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
if !c.config.UseImageHosts {
newHosts, err := c.generateHosts("/etc/hosts")
if err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
}
c.state.BindMounts["/etc/hosts"] = newHosts
}
c.state.BindMounts["/etc/hosts"] = newHosts
}

if err := label.Relabel(c.state.BindMounts["/etc/hosts"], c.config.MountLabel, true); err != nil {
return err
if c.state.BindMounts["/etc/hosts"] != "" {
if err := label.Relabel(c.state.BindMounts["/etc/hosts"], c.config.MountLabel, true); err != nil {
return err
}
}

if err := label.Relabel(c.state.BindMounts["/etc/resolv.conf"], c.config.MountLabel, true); err != nil {
return err
if c.state.BindMounts["/etc/resolv.conf"] != "" {
if err := label.Relabel(c.state.BindMounts["/etc/resolv.conf"], c.config.MountLabel, true); err != nil {
return err
}
}
}

Expand Down
52 changes: 52 additions & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,9 @@ func WithDNSSearch(searchDomains []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
if ctr.config.UseImageResolvConf {
return errors.Wrapf(ErrInvalidArg, "cannot add DNS search domains if container will not create /etc/resolv.conf")
}
ctr.config.DNSSearch = searchDomains
return nil
}
Expand All @@ -1008,6 +1011,9 @@ func WithDNS(dnsServers []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
if ctr.config.UseImageResolvConf {
return errors.Wrapf(ErrInvalidArg, "cannot add DNS servers if container will not create /etc/resolv.conf")
}
var dns []net.IP
for _, i := range dnsServers {
result := net.ParseIP(i)
Expand All @@ -1027,6 +1033,9 @@ func WithDNSOption(dnsOptions []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}
if ctr.config.UseImageResolvConf {
return errors.Wrapf(ErrInvalidArg, "cannot add DNS options if container will not create /etc/resolv.conf")
}
ctr.config.DNSOption = dnsOptions
return nil
}
Expand All @@ -1038,6 +1047,11 @@ func WithHosts(hosts []string) CtrCreateOption {
if ctr.valid {
return ErrCtrFinalized
}

if ctr.config.UseImageHosts {
return errors.Wrapf(ErrInvalidArg, "cannot add hosts if container will not create /etc/hosts")
}

ctr.config.HostAdd = hosts
return nil
}
Expand Down Expand Up @@ -1184,6 +1198,44 @@ func WithCtrNamespace(ns string) CtrCreateOption {
}
}

// WithUseImageResolvConf tells the container not to bind-mount resolv.conf in.
// This conflicts with other DNS-related options.
func WithUseImageResolvConf() CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
}

if len(ctr.config.DNSServer) != 0 ||
len(ctr.config.DNSSearch) != 0 ||
len(ctr.config.DNSOption) != 0 {
return errors.Wrapf(ErrInvalidArg, "not creating resolv.conf conflicts with DNS options")
}

ctr.config.UseImageResolvConf = true

return nil
}
}

// WithUseImageHosts tells the container not to bind-mount /etc/hosts in.
// This conflicts with WithHosts().
func WithUseImageHosts() CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
}

if len(ctr.config.HostAdd) != 0 {
return errors.Wrapf(ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
}

ctr.config.UseImageHosts = true

return nil
}
}

// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden
// and expected to be the first container in the pod.
func withIsInfra() CtrCreateOption {
Expand Down
12 changes: 10 additions & 2 deletions pkg/spec/createconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type CreateConfig struct {
ExposedPorts map[nat.Port]struct{}
GroupAdd []string // group-add
HealthCheck *manifest.Schema2HealthConfig
NoHosts bool
HostAdd []string //add-host
Hostname string //hostname
Image string
Expand Down Expand Up @@ -505,12 +506,19 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l
options = append(options, libpod.WithDNSSearch(c.DNSSearch))
}
if len(c.DNSServers) > 0 {
options = append(options, libpod.WithDNS(c.DNSServers))
if len(c.DNSServers) == 1 && strings.ToLower(c.DNSServers[0]) == "none" {
options = append(options, libpod.WithUseImageResolvConf())
} else {
options = append(options, libpod.WithDNS(c.DNSServers))
}
}
if len(c.DNSOpt) > 0 {
options = append(options, libpod.WithDNSOption(c.DNSOpt))
}
if len(c.HostAdd) > 0 {
if c.NoHosts {
options = append(options, libpod.WithUseImageHosts())
}
if len(c.HostAdd) > 0 && !c.NoHosts {
options = append(options, libpod.WithHosts(c.HostAdd))
}
logPath := getLoggingPath(c.LogDriverOpt)
Expand Down
10 changes: 8 additions & 2 deletions test/e2e/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,13 +749,19 @@ USER mail`

It("podman run with bad healthcheck timeout", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-timeout", "0s", ALPINE, "top"})
session.Wait()
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).ToNot(Equal(0))
})

It("podman run with bad healthcheck start-period", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--healthcheck-cmd", "foo", "--healthcheck-start-period", "-1s", ALPINE, "top"})
session.Wait()
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).ToNot(Equal(0))
})

It("podman run with --add-host and --no-hosts fails", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).ToNot(Equal(0))
})
})

0 comments on commit 340eeec

Please sign in to comment.