From 18e9ae59ca0800789ea6cfef3a27516801a7e1a5 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 11 Nov 2021 15:35:11 +0100 Subject: Fix network mode in play kube We need to use the config network mode when no network mode was set. To do so we have to keep the nsmode empty, MakeContainer() will use the correct network mode from the config when needed. Fixes #12248 Signed-off-by: Paul Holzinger Signed-off-by: Matthew Heon --- test/e2e/config/containers-netns2.conf | 3 +++ test/e2e/play_kube_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/e2e/config/containers-netns2.conf (limited to 'test/e2e') diff --git a/test/e2e/config/containers-netns2.conf b/test/e2e/config/containers-netns2.conf new file mode 100644 index 000000000..1ffd100f5 --- /dev/null +++ b/test/e2e/config/containers-netns2.conf @@ -0,0 +1,3 @@ +[containers] + +netns = "bridge" diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index f38350413..c9899c0bc 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -2759,6 +2759,34 @@ invalid kube kind Expect(exists).To(Exit(0)) }) + It("podman play kube use network mode from config", func() { + confPath, err := filepath.Abs("config/containers-netns2.conf") + Expect(err).ToNot(HaveOccurred()) + os.Setenv("CONTAINERS_CONF", confPath) + defer os.Unsetenv("CONTAINERS_CONF") + if IsRemote() { + podmanTest.RestartRemoteService() + } + + pod := getPod() + err = generateKubeYaml("pod", pod, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + podInspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{.InfraContainerID}}"}) + podInspect.WaitWithDefaultTimeout() + Expect(podInspect).To(Exit(0)) + infraID := podInspect.OutputToString() + + inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.NetworkMode}}", infraID}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).To(Exit(0)) + Expect(inspect.OutputToString()).To(Equal("bridge")) + }) + Describe("verify environment variables", func() { var maxLength int BeforeEach(func() { -- cgit v1.2.3-54-g00ecf From db6b9131ef1a14cd19cdd52425fb60d90862f05e Mon Sep 17 00:00:00 2001 From: Aditya Rajan Date: Mon, 15 Nov 2021 14:39:26 +0530 Subject: secret: honor custom target for secrets with run Honor custom `target` if specified while running or creating containers with secret `type=mount`. Example: `podman run -it --secret token,type=mount,target=TOKEN ubi8/ubi:latest bash` Signed-off-by: Aditya Rajan --- libpod/container.go | 2 ++ libpod/container_internal_linux.go | 11 +++++++- pkg/specgen/generate/container_create.go | 1 + pkg/specgen/specgen.go | 1 + pkg/specgenutil/specgen.go | 5 ++-- test/e2e/run_test.go | 48 +++++++++++++++++++++++++++++--- 6 files changed, 60 insertions(+), 8 deletions(-) (limited to 'test/e2e') diff --git a/libpod/container.go b/libpod/container.go index a4bbb5dd0..8bbe02b58 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -253,6 +253,8 @@ type ContainerSecret struct { GID uint32 // Mode is the mode of the secret file Mode uint32 + // Secret target inside container + Target string } // ContainerNetworkDescriptions describes the relationship between the CNI diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 89869e2f5..1c85339c7 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1777,8 +1777,17 @@ rootless=%d return errors.Wrapf(err, "error creating secrets mount") } for _, secret := range c.Secrets() { + secretFileName := secret.Name + base := "/run/secrets" + if secret.Target != "" { + secretFileName = secret.Target + //If absolute path for target given remove base. + if filepath.IsAbs(secretFileName) { + base = "" + } + } src := filepath.Join(c.config.SecretsPath, secret.Name) - dest := filepath.Join("/run/secrets", secret.Name) + dest := filepath.Join(base, secretFileName) c.state.BindMounts[dest] = src } } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index fc66145df..4003567e9 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -429,6 +429,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. UID: s.UID, GID: s.GID, Mode: s.Mode, + Target: s.Target, }) } options = append(options, libpod.WithSecrets(secrs)) diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 50ef3f197..70518c073 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -513,6 +513,7 @@ type SpecGenerator struct { type Secret struct { Source string + Target string UID uint32 GID uint32 Mode uint32 diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 8007e5d8e..eba173a81 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -861,6 +861,7 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) if len(split) == 1 { mountSecret := specgen.Secret{ Source: val, + Target: target, UID: uid, GID: gid, Mode: mode, @@ -926,11 +927,9 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) return nil, nil, errors.Wrapf(secretParseError, "no source found %s", val) } if secretType == "mount" { - if target != "" { - return nil, nil, errors.Wrapf(secretParseError, "target option is invalid for mounted secrets") - } mountSecret := specgen.Secret{ Source: source, + Target: target, UID: uid, GID: gid, Mode: mode, diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index a5a0aad8b..e21b1dcf3 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1670,6 +1670,50 @@ WORKDIR /madethis`, BB) }) + It("podman run --secret source=mysecret,type=mount with target", func() { + secretsString := "somesecretdata" + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte(secretsString), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "mysecret_target", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret_target,type=mount,target=hello", "--name", "secr_target", ALPINE, "cat", "/run/secrets/hello"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(secretsString)) + + session = podmanTest.Podman([]string{"inspect", "secr_target", "--format", " {{(index .Config.Secrets 0).Name}}"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("mysecret_target")) + + }) + + It("podman run --secret source=mysecret,type=mount with target at /tmp", func() { + secretsString := "somesecretdata" + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte(secretsString), 0755) + Expect(err).To(BeNil()) + + session := podmanTest.Podman([]string{"secret", "create", "mysecret_target2", secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret_target2,type=mount,target=/tmp/hello", "--name", "secr_target2", ALPINE, "cat", "/tmp/hello"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(secretsString)) + + session = podmanTest.Podman([]string{"inspect", "secr_target2", "--format", " {{(index .Config.Secrets 0).Name}}"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("mysecret_target2")) + + }) + It("podman run --secret source=mysecret,type=env", func() { secretsString := "somesecretdata" secretFilePath := filepath.Join(podmanTest.TempDir, "secret") @@ -1695,10 +1739,6 @@ WORKDIR /madethis`, BB) session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - // target with mount type should fail - session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=mount,target=anotherplace", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"}) - session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=env,target=anotherplace", "--name", "secr", ALPINE, "printenv", "anotherplace"}) session.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf From 905eabf0bef95d5202483464779680f01a3cc1a1 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 24 Nov 2021 10:35:07 +0100 Subject: libpod: improve heuristic to detect cgroup improve the heuristic to detect the scope that was created for the container. This is necessary with systemd running as PID 1, since it moves itself to a different sub-cgroup, thus stats would not account for other processes in the same container. Closes: https://github.com/containers/podman/issues/12400 Signed-off-by: Giuseppe Scrivano Signed-off-by: Matthew Heon --- libpod/container.go | 25 +++++++++++++++++++++++++ libpod/container_internal_linux.go | 2 +- test/e2e/systemd_test.go | 5 +++++ 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'test/e2e') diff --git a/libpod/container.go b/libpod/container.go index 8bbe02b58..b83420ee7 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -6,10 +6,12 @@ import ( "io/ioutil" "net" "os" + "strings" "time" "github.com/containernetworking/cni/pkg/types" cnitypes "github.com/containernetworking/cni/pkg/types/current" + "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/secrets" "github.com/containers/image/v5/manifest" "github.com/containers/podman/v3/libpod/define" @@ -1001,6 +1003,29 @@ func (c *Container) cGroupPath() (string, error) { return "", errors.Errorf("could not find any cgroup in %q", procPath) } + cgroupManager := c.CgroupManager() + switch { + case c.config.CgroupsMode == cgroupSplit: + name := fmt.Sprintf("/libpod-payload-%s/", c.ID()) + if index := strings.LastIndex(cgroupPath, name); index >= 0 { + return cgroupPath[:index+len(name)-1], nil + } + case cgroupManager == config.CgroupfsCgroupsManager: + name := fmt.Sprintf("/libpod-%s/", c.ID()) + if index := strings.LastIndex(cgroupPath, name); index >= 0 { + return cgroupPath[:index+len(name)-1], nil + } + case cgroupManager == config.SystemdCgroupsManager: + // When running under systemd, try to detect the scope that was requested + // to be created. It improves the heuristic since we report the first + // cgroup that was created instead of the cgroup where PID 1 might have + // moved to. + name := fmt.Sprintf("/libpod-%s.scope/", c.ID()) + if index := strings.LastIndex(cgroupPath, name); index >= 0 { + return cgroupPath[:index+len(name)-1], nil + } + } + return cgroupPath, nil } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 1c85339c7..8bd433427 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -2512,7 +2512,7 @@ func (c *Container) getOCICgroupPath() (string, error) { if err != nil { return "", err } - return filepath.Join(selfCgroup, "container"), nil + return filepath.Join(selfCgroup, fmt.Sprintf("libpod-payload-%s", c.ID())), nil case cgroupManager == config.SystemdCgroupsManager: // When the OCI runtime is set to use Systemd as a cgroup manager, it // expects cgroups to be passed as follows: diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 7212f8843..bb2cd11f2 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -109,6 +109,11 @@ WantedBy=default.target stats := podmanTest.Podman([]string{"stats", "--no-stream", ctrName}) stats.WaitWithDefaultTimeout() Expect(stats).Should(Exit(0)) + + cgroupPath := podmanTest.Podman([]string{"inspect", "--format='{{.State.CgroupPath}}'", ctrName}) + cgroupPath.WaitWithDefaultTimeout() + Expect(cgroupPath).Should(Exit(0)) + Expect(result.OutputToString()).To(Not(ContainSubstring("init.scope"))) }) It("podman create container with systemd entrypoint triggers systemd mode", func() { -- cgit v1.2.3-54-g00ecf From 39318f177965b3fa49cb4343c6a8c224836febd6 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Tue, 30 Nov 2021 17:39:05 +0100 Subject: top: parse ps(1) args correctly The arguments of ps(1) should be shlexed. Fixes: #12452 Signed-off-by: Valentin Rothberg --- libpod/container_top_linux.go | 18 +++++++++++++++++- test/e2e/top_test.go | 5 +++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'test/e2e') diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go index 0d4cba85e..d4f4ddfc1 100644 --- a/libpod/container_top_linux.go +++ b/libpod/container_top_linux.go @@ -4,6 +4,7 @@ package libpod import ( "bufio" + "fmt" "os" "strconv" "strings" @@ -11,6 +12,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/psgo" + "github.com/google/shlex" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -51,7 +53,21 @@ func (c *Container) Top(descriptors []string) ([]string, error) { return nil, psgoErr } - output, err = c.execPS(descriptors) + // Note that the descriptors to ps(1) must be shlexed (see #12452). + psDescriptors := []string{} + for _, d := range descriptors { + shSplit, err := shlex.Split(d) + if err != nil { + return nil, fmt.Errorf("parsing ps args: %v", err) + } + for _, s := range shSplit { + if s != "" { + psDescriptors = append(psDescriptors, s) + } + } + } + + output, err = c.execPS(psDescriptors) if err != nil { return nil, errors.Wrapf(err, "error executing ps(1) in the container") } diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go index 93c4f3f12..1a71ebf33 100644 --- a/test/e2e/top_test.go +++ b/test/e2e/top_test.go @@ -101,6 +101,11 @@ var _ = Describe("Podman top", func() { result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1)) + + result = podmanTest.Podman([]string{"top", session.OutputToString(), "ax -o args"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).To(Equal([]string{"COMMAND", "top -d 2"})) }) It("podman top with comma-separated options", func() { -- cgit v1.2.3-54-g00ecf