summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2019-02-17 21:55:30 -0500
committerDaniel J Walsh <dwalsh@redhat.com>2019-02-23 05:47:27 -0500
commitb87bdced1fa967846916b47cba5f093f72f3d11f (patch)
tree27342efd5d84839584260b9e2883e27ed8fbbd22
parentb223d4e1367463a32eeeb31a4b9d8a351641d83c (diff)
downloadpodman-b87bdced1fa967846916b47cba5f093f72f3d11f.tar.gz
podman-b87bdced1fa967846916b47cba5f093f72f3d11f.tar.bz2
podman-b87bdced1fa967846916b47cba5f093f72f3d11f.zip
Fix up handling of user defined network namespaces
If user specifies network namespace and the /etc/netns/XXX/resolv.conf exists, we should use this rather then /etc/resolv.conf Also fail cleaner if the user specifies an invalid Network Namespace. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
-rw-r--r--contrib/cirrus/packer/fedora_setup.sh1
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh1
-rw-r--r--docs/podman-run.1.md14
-rw-r--r--libpod/container_internal_linux.go18
-rw-r--r--libpod/options.go4
-rw-r--r--pkg/spec/createconfig.go10
-rw-r--r--test/e2e/run_networking_test.go39
7 files changed, 74 insertions, 13 deletions
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh
index 01c468901..de7ad4506 100644
--- a/contrib/cirrus/packer/fedora_setup.sh
+++ b/contrib/cirrus/packer/fedora_setup.sh
@@ -40,6 +40,7 @@ ooe.sh sudo dnf install -y \
golang-github-cpuguy83-go-md2man \
gpgme-devel \
iptables \
+ iproute \
libassuan-devel \
libcap-devel \
libnet \
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index 7d49c5dc7..5b7e1d714 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -48,6 +48,7 @@ ooe.sh sudo -E apt-get -qq install \
gettext \
go-md2man \
golang \
+ iproute \
iptables \
libaio-dev \
libapparmor-dev \
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index b928f61f5..bbf10a2ce 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -28,6 +28,8 @@ servers in the created `resolv.conf`). Additionally, an empty file is created in
each container to indicate to programs they are running in a container. This file
is located at `/run/.containerenv`.
+When running from a user defined network namespace, the /etc/netns/NSNAME/resolv.conf will be used if it exists, otherwise /etc/resolv.conf will be used.
+
## OPTIONS
**--add-host**=[]
@@ -694,21 +696,21 @@ Current supported mount TYPES are bind, and tmpfs.
Common Options:
- · src, source: mount source spec for bind and volume. Mandatory for bind.
+ · src, source: mount source spec for bind and volume. Mandatory for bind.
- · dst, destination, target: mount destination spec.
+ · dst, destination, target: mount destination spec.
- · ro, read-only: true or false (default).
+ · ro, read-only: true or false (default).
Options specific to bind:
- · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+ · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
Options specific to tmpfs:
- · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
+ · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux.
- · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux.
+ · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux.
**--userns**=""
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 86f94477e..2665dd81d 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -758,8 +758,24 @@ func (c *Container) makeBindMounts() error {
// generateResolvConf generates a containers resolv.conf
func (c *Container) generateResolvConf() (string, error) {
+ resolvConf := "/etc/resolv.conf"
+ for _, ns := range c.config.Spec.Linux.Namespaces {
+ if ns.Type == spec.NetworkNamespace {
+ if ns.Path != "" && !strings.HasPrefix(ns.Path, "/proc/") {
+ definedPath := filepath.Join("/etc/netns", filepath.Base(ns.Path), "resolv.conf")
+ _, err := os.Stat(definedPath)
+ if err == nil {
+ resolvConf = definedPath
+ } else if !os.IsNotExist(err) {
+ return "", errors.Wrapf(err, "failed to stat %s", definedPath)
+ }
+ }
+ break
+ }
+ }
+
// Determine the endpoint for resolv.conf in case it is a symlink
- resolvPath, err := filepath.EvalSymlinks("/etc/resolv.conf")
+ resolvPath, err := filepath.EvalSymlinks(resolvConf)
if err != nil {
return "", err
}
diff --git a/libpod/options.go b/libpod/options.go
index 9aa020b56..e22c81f91 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -904,10 +904,10 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo
}
ctr.config.PostConfigureNetNS = postConfigureNetNS
- ctr.config.CreateNetNS = true
+ ctr.config.NetMode = namespaces.NetworkMode(netmode)
+ ctr.config.CreateNetNS = !ctr.config.NetMode.IsUserDefined()
ctr.config.PortMappings = portMappings
ctr.config.Networks = networks
- ctr.config.NetMode = namespaces.NetworkMode(netmode)
return nil
}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 8da44a2f0..50e07ee74 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -446,7 +446,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l
}
if IsNS(string(c.NetMode)) {
- // pass
+ split := strings.SplitN(string(c.NetMode), ":", 2)
+ if len(split[0]) != 2 {
+ return nil, errors.Errorf("invalid user defined network namespace %q", c.NetMode.UserDefined())
+ }
+ _, err := os.Stat(split[1])
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, libpod.WithNetNS(portBindings, false, string(c.NetMode), networks))
} else if c.NetMode.IsContainer() {
connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.Container())
if err != nil {
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 1c09a4d0b..a07e4d047 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -36,19 +36,19 @@ var _ = Describe("Podman run networking", func() {
})
It("podman run network connection with default bridge", func() {
- session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
It("podman run network connection with host", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
It("podman run network connection with loopback", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
Expect(session.ExitCode()).To(Equal(0))
})
@@ -178,4 +178,37 @@ var _ = Describe("Podman run networking", func() {
Expect(exec4.ExitCode()).To(Equal(0))
Expect(exec4.OutputToString()).To(ContainSubstring("192.0.2.2 test1"))
})
+
+ It("podman run network in user created network namespace", func() {
+ if Containerized() {
+ Skip("Can not be run within a container.")
+ }
+ SystemExec("ip", []string{"netns", "add", "xxx"})
+ session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxx", ALPINE, "wget", "www.podman.io"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Equal(0))
+ SystemExec("ip", []string{"netns", "delete", "xxx"})
+ })
+
+ It("podman run n user created network namespace with resolv.conf", func() {
+ if Containerized() {
+ Skip("Can not be run within a container.")
+ }
+ SystemExec("ip", []string{"netns", "add", "xxx"})
+ SystemExec("mkdir", []string{"-p", "/etc/netns/xxx"})
+ SystemExec("bash", []string{"-c", "echo nameserver 11.11.11.11 > /etc/netns/xxx/resolv.conf"})
+ session := podmanTest.Podman([]string{"run", "--net", "ns:/run/netns/xxx", ALPINE, "cat", "/etc/resolv.conf"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("11.11.11.11"))
+ SystemExec("ip", []string{"netns", "delete", "xxx"})
+ SystemExec("rm", []string{"-rf", "/etc/netns/xxx"})
+ })
+
+ It("podman run network in bogus user created network namespace", func() {
+ session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxy", ALPINE, "wget", "www.podman.io"})
+ session.Wait(90)
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session.ErrorToString()).To(ContainSubstring("stat /run/netns/xxy: no such file or directory"))
+ })
})