diff options
-rw-r--r-- | cmd/podman/create.go | 81 | ||||
-rw-r--r-- | libpod/options.go | 132 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 8 | ||||
-rw-r--r-- | pkg/spec/parse.go | 6 | ||||
-rw-r--r-- | test/e2e/pod_infra_container_test.go | 24 | ||||
-rw-r--r-- | test/e2e/pod_pod_namespaces.go | 89 | ||||
-rw-r--r-- | test/e2e/run_test.go | 8 |
7 files changed, 170 insertions, 178 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 7a3b26c85..bc010d047 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -16,7 +16,7 @@ import ( ann "github.com/containers/libpod/pkg/annotations" "github.com/containers/libpod/pkg/apparmor" "github.com/containers/libpod/pkg/inspect" - "github.com/containers/libpod/pkg/namespaces" + ns "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" @@ -357,6 +357,33 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string { return entrypoint } +func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string) (map[string]string, error) { + pod, err := runtime.LookupPod(c.String("pod")) + if err != nil { + return namespaces, err + } + podInfraID, err := pod.InfraContainerID() + if err != nil { + return namespaces, err + } + if (namespaces["pid"] == cc.Pod) || (!c.IsSet("pid") && pod.SharesPID()) { + namespaces["pid"] = fmt.Sprintf("container:%s", podInfraID) + } + if (namespaces["net"] == cc.Pod) || (!c.IsSet("net") && pod.SharesNet()) { + namespaces["net"] = fmt.Sprintf("container:%s", podInfraID) + } + if (namespaces["user"] == cc.Pod) || (!c.IsSet("user") && pod.SharesUser()) { + namespaces["user"] = fmt.Sprintf("container:%s", podInfraID) + } + if (namespaces["ipc"] == cc.Pod) || (!c.IsSet("ipc") && pod.SharesIPC()) { + namespaces["ipc"] = fmt.Sprintf("container:%s", podInfraID) + } + if (namespaces["uts"] == cc.Pod) || (!c.IsSet("uts") && pod.SharesUTS()) { + namespaces["uts"] = fmt.Sprintf("container:%s", podInfraID) + } + return namespaces, nil +} + // Parses CLI options related to container creation into a config which can be // parsed into an OCI runtime spec func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) { @@ -444,56 +471,48 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim } // Kernel Namespaces - var pod *libpod.Pod + // TODO Fix handling of namespace from pod + // Instead of integrating here, should be done in libpod + // However, that also involves setting up security opts + // when the pod's namespace is integrated + namespaces := map[string]string{ + "pid": c.String("pid"), + "net": c.String("net"), + "ipc": c.String("ipc"), + "user": c.String("userns"), + "uts": c.String("uts"), + } + if c.IsSet("pod") { - pod, err = runtime.LookupPod(c.String("pod")) + namespaces, err = configurePod(c, runtime, namespaces) if err != nil { return nil, err } } - pidModeStr := c.String("pid") - if !c.IsSet("pid") && pod != nil && pod.SharesPID() { - pidModeStr = cc.POD - } - pidMode := namespaces.PidMode(pidModeStr) + pidMode := ns.PidMode(namespaces["pid"]) if !cc.Valid(string(pidMode), pidMode) { return nil, errors.Errorf("--pid %q is not valid", c.String("pid")) } - usernsModeStr := c.String("userns") - if !c.IsSet("userns") && pod != nil && pod.SharesUser() { - usernsModeStr = cc.POD - } - usernsMode := namespaces.UsernsMode(usernsModeStr) + usernsMode := ns.UsernsMode(namespaces["user"]) if !cc.Valid(string(usernsMode), usernsMode) { - return nil, errors.Errorf("--userns %q is not valid", c.String("userns")) + return nil, errors.Errorf("--userns %q is not valid", namespaces["user"]) } - utsModeStr := c.String("uts") - if !c.IsSet("uts") && pod != nil && pod.SharesUTS() { - utsModeStr = cc.POD - } - utsMode := namespaces.UTSMode(utsModeStr) + utsMode := ns.UTSMode(namespaces["uts"]) if !cc.Valid(string(utsMode), utsMode) { - return nil, errors.Errorf("--uts %q is not valid", c.String("uts")) + return nil, errors.Errorf("--uts %q is not valid", namespaces["uts"]) } - ipcModeStr := c.String("ipc") - if !c.IsSet("ipc") && pod != nil && pod.SharesIPC() { - ipcModeStr = cc.POD - } - ipcMode := namespaces.IpcMode(ipcModeStr) + ipcMode := ns.IpcMode(namespaces["ipc"]) if !cc.Valid(string(ipcMode), ipcMode) { return nil, errors.Errorf("--ipc %q is not valid", ipcMode) } - netModeStr := c.String("network") - if !c.IsSet("network") && pod != nil && pod.SharesNet() { - netModeStr = cc.POD - } + // Make sure if network is set to container namespace, port binding is not also being asked for - netMode := namespaces.NetworkMode(netModeStr) - if netMode.IsContainer() || cc.IsPod(netModeStr) { + netMode := ns.NetworkMode(namespaces["net"]) + if netMode.IsContainer() { if len(c.StringSlice("publish")) > 0 || c.Bool("publish-all") { return nil, errors.Errorf("cannot set port bindings on an existing container network namespace") } diff --git a/libpod/options.go b/libpod/options.go index ae6b19055..e6751d68d 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -549,94 +549,6 @@ func WithExitCommand(exitCommand []string) CtrCreateOption { } } -// WithIPCNSFromPod indicates the the container should join the IPC namespace of -// its pod -func WithIPCNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.IPCNsCtr = infraContainer - - return nil - } -} - -// WithMountNSFromPod indicates the the container should join the Mount namespace of -// its pod -func WithMountNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.MountNsCtr = infraContainer - - return nil - } -} - -// WithNetNSFromPod indicates the the container should join the network namespace of -// its pod -func WithNetNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.NetNsCtr = infraContainer - - return nil - } -} - -// WithPIDNSFromPod indicates the the container should join the PID namespace of -// its pod -func WithPIDNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.PIDNsCtr = infraContainer - - return nil - } -} - // WithUTSNSFromPod indicates the the container should join the UTS namespace of // its pod func WithUTSNSFromPod(p *Pod) CtrCreateOption { @@ -659,50 +571,6 @@ func WithUTSNSFromPod(p *Pod) CtrCreateOption { } } -// WithUserNSFromPod indicates the the container should join the User namespace of -// its pod -func WithUserNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.UserNsCtr = infraContainer - - return nil - } -} - -// WithCgroupNSFromPod indicates the the container should join the Cgroup namespace of -// its pod -func WithCgroupNSFromPod(p *Pod) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if err := validPodNSOption(p, ctr.config.Pod); err != nil { - return err - } - - infraContainer, err := p.InfraContainerID() - if err != nil { - return err - } - ctr.config.CgroupNsCtr = infraContainer - - return nil - } -} - // WithIPCNSFrom indicates the the container should join the IPC namespace of // the given container. // If the container has joined a pod, it can only join the namespaces of diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 0b7ee993d..3cca345b4 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -385,8 +385,6 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib return nil, errors.Wrapf(err, "container %q not found", c.NetMode.ConnectedContainer()) } options = append(options, libpod.WithNetNSFrom(connectedCtr)) - } else if IsPod(string(c.NetMode)) { - options = append(options, libpod.WithNetNSFromPod(pod)) } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { isRootless := rootless.IsRootless() postConfigureNetNS := isRootless || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() @@ -404,9 +402,6 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib options = append(options, libpod.WithPIDNSFrom(connectedCtr)) } - if IsPod(string(c.PidMode)) { - options = append(options, libpod.WithPIDNSFromPod(pod)) - } if c.IpcMode.IsContainer() { connectedCtr, err := c.Runtime.LookupContainer(c.IpcMode.Container()) @@ -416,9 +411,6 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib options = append(options, libpod.WithIPCNSFrom(connectedCtr)) } - if IsPod(string(c.IpcMode)) { - options = append(options, libpod.WithIPCNSFromPod(pod)) - } if IsPod(string(c.UtsMode)) { options = append(options, libpod.WithUTSNSFromPod(pod)) diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go index dc4f50a3e..9b2dd1347 100644 --- a/pkg/spec/parse.go +++ b/pkg/spec/parse.go @@ -8,9 +8,9 @@ import ( "github.com/docker/go-units" ) -// POD signifies a kernel namespace is being shared +// Pod signifies a kernel namespace is being shared // by a container with the pod it is associated with -const POD = "pod" +const Pod = "pod" // weightDevice is a structure that holds device:weight pair type weightDevice struct { @@ -36,7 +36,7 @@ func IsNS(s string) bool { // IsPod returns if the specified string is pod func IsPod(s string) bool { - return s == POD + return s == Pod } // Valid checks the validity of a linux namespace diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go index 2dcce6525..8fb0c388c 100644 --- a/test/e2e/pod_infra_container_test.go +++ b/test/e2e/pod_infra_container_test.go @@ -113,6 +113,30 @@ var _ = Describe("Podman pod create", func() { Expect(session.ExitCode()).To(Not(Equal(0))) }) + It("podman pod correctly sets up IPCNS", func() { + session := podmanTest.Podman([]string{"pod", "create", "--share", "ipc"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + session = podmanTest.Podman([]string{"pod", "start", podID}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + podmanTest.RestoreArtifact(fedoraMinimal) + session = podmanTest.Podman([]string{"run", "--pod", podID, fedoraMinimal, "/bin/sh", "-c", "'touch /dev/shm/hi'"}) + session.WaitWithDefaultTimeout() + if session.ExitCode() != 0 { + Skip("ShmDir not initialized, skipping...") + } + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "--pod", podID, fedoraMinimal, "/bin/sh", "-c", "'ls /dev/shm'"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal("hi")) + }) + It("podman pod correctly sets up PIDNS", func() { session := podmanTest.Podman([]string{"pod", "create", "--share", "pid", "--name", "test-pod"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/pod_pod_namespaces.go b/test/e2e/pod_pod_namespaces.go new file mode 100644 index 000000000..3e84005c3 --- /dev/null +++ b/test/e2e/pod_pod_namespaces.go @@ -0,0 +1,89 @@ +package integration + +import ( + "fmt" + "os" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman pod create", func() { + var ( + tempdir string + err error + podmanTest PodmanTest + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanCreate(tempdir) + podmanTest.RestoreAllArtifacts() + podmanTest.RestoreArtifact(infra) + }) + + AfterEach(func() { + podmanTest.CleanupPod() + f := CurrentGinkgoTestDescription() + timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds()) + GinkgoWriter.Write([]byte(timedResult)) + }) + + It("podman pod container share Namespaces", func() { + session := podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + session = podmanTest.Podman([]string{"pod", "start", podID}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "--pod", podID, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"ps", "-a", "--ns", "--format", "{{.IPC}} {{.UTS}} {{.NET}}"}) + check.WaitWithDefaultTimeout() + Expect(check.ExitCode()).To(Equal(0)) + outputArray := check.OutputToStringArray() + Expect(len(outputArray)).To(Equal(2)) + + NAMESPACE1 := outputArray[0] + fmt.Println("NAMESPACE1:", NAMESPACE1) + NAMESPACE2 := outputArray[1] + fmt.Println("NAMESPACE2:", NAMESPACE2) + Expect(NAMESPACE1).To(Equal(NAMESPACE2)) + }) + + It("podman pod container dontshare PIDNS", func() { + session := podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + podID := session.OutputToString() + + session = podmanTest.Podman([]string{"pod", "start", podID}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"run", "--pod", podID, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"ps", "-a", "--ns", "--format", "{{.PIDNS}}"}) + check.WaitWithDefaultTimeout() + Expect(check.ExitCode()).To(Equal(0)) + outputArray := check.OutputToStringArray() + Expect(len(outputArray)).To(Equal(2)) + + NAMESPACE1 := outputArray[0] + fmt.Println("NAMESPACE1:", NAMESPACE1) + NAMESPACE2 := outputArray[1] + fmt.Println("NAMESPACE2:", NAMESPACE2) + Expect(NAMESPACE1).To(Not(Equal(NAMESPACE2))) + }) + +}) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 3ea639a11..3d487db66 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -235,10 +235,10 @@ var _ = Describe("Podman run", func() { }) It("podman run with cidfile", func() { - session := podmanTest.Podman([]string{"run", "--cidfile", "/tmp/cidfile", ALPINE, "ls"}) + session := podmanTest.Podman([]string{"run", "--cidfile", tempdir + "cidfile", ALPINE, "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - err := os.Remove("/tmp/cidfile") + err := os.Remove(tempdir + "cidfile") Expect(err).To(BeNil()) }) @@ -317,7 +317,7 @@ var _ = Describe("Podman run", func() { It("podman test hooks", func() { hcheck := "/run/hookscheck" - hooksDir := "/tmp/hooks" + hooksDir := tempdir + "/hooks" os.Mkdir(hooksDir, 0755) fileutils.CopyFile("hooks/hooks.json", hooksDir) os.Setenv("HOOK_OPTION", fmt.Sprintf("--hooks-dir-path=%s", hooksDir)) @@ -347,7 +347,7 @@ var _ = Describe("Podman run", func() { err = ioutil.WriteFile(secretsFile, []byte(secretsString), 0755) Expect(err).To(BeNil()) - targetDir := "/tmp/symlink/target" + targetDir := tempdir + "/symlink/target" err = os.MkdirAll(targetDir, 0755) Expect(err).To(BeNil()) keyFile := filepath.Join(targetDir, "key.pem") |