diff --git a/libpod/container.go b/libpod/container.go index a4bbb5dd00..8bbe02b585 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 208e089b51..71e815a5a9 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 f82b2a3c6a..b897de6427 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -426,6 +426,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 0c30c498a1..312fa915a9 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -509,6 +509,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 8007e5d8e4..eba173a81f 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 8f640eacfa..63d7bcf587 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1664,6 +1664,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") @@ -1689,10 +1733,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() diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats index 76ce12b818..62a6e6a422 100644 --- a/test/system/035-logs.bats +++ b/test/system/035-logs.bats @@ -30,6 +30,17 @@ load helpers run_podman rm $cid } +function _additional_events_backend() { + local driver=$1 + # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend. + if [[ $driver = "journald" ]]; then + run_podman info --format '{{.Host.EventLogger}}' >/dev/null + if [[ $output != "journald" ]]; then + echo "--events-backend journald" + fi + fi +} + function _log_test_multi() { local driver=$1 @@ -42,10 +53,12 @@ function _log_test_multi() { etc='.*' fi + local events_backend=$(_additional_events_backend $driver) + # Simple helper to make the container starts, below, easier to read local -a cid doit() { - run_podman run --log-driver=$driver --rm -d --name "$1" $IMAGE sh -c "$2"; + run_podman ${events_backend} run --log-driver=$driver --rm -d --name "$1" $IMAGE sh -c "$2"; cid+=($(echo "${output:0:12}")) } @@ -57,7 +70,7 @@ function _log_test_multi() { doit c1 "echo a;sleep 10;echo d;sleep 3" doit c2 "sleep 1;echo b;sleep 2;echo c;sleep 3" - run_podman logs -f c1 c2 + run_podman ${events_backend} logs -f c1 c2 is "$output" \ "${cid[0]} a$etc ${cid[1]} b$etc @@ -187,15 +200,20 @@ function _log_test_follow() { contentA=$(random_string) contentB=$(random_string) contentC=$(random_string) + local events_backend=$(_additional_events_backend $driver) + + if [[ -n "${events_backend}" ]]; then + skip_if_remote "remote does not support --events-backend" + fi # Note: it seems we need at least three log lines to hit #11461. - run_podman run --log-driver=$driver --name $cname $IMAGE sh -c "echo $contentA; echo $contentB; echo $contentC" - run_podman logs -f $cname + run_podman ${events_backend} run --log-driver=$driver --name $cname $IMAGE sh -c "echo $contentA; echo $contentB; echo $contentC" + run_podman ${events_backend} logs -f $cname is "$output" "$contentA $contentB $contentC" "logs -f on exitted container works" - run_podman rm -f $cname + run_podman ${events_backend} rm -f $cname } @test "podman logs - --follow k8s-file" { diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats index d85f0a6a99..1ff3a7b619 100644 --- a/test/system/130-kill.bats +++ b/test/system/130-kill.bats @@ -6,9 +6,22 @@ load helpers @test "podman kill - test signal handling in containers" { + + # Prepare for 'logs -f' + run_podman info --format '{{.Host.LogDriver}}' + log_driver=$output + run_podman info --format '{{.Host.EventLogger}}' + event_logger=$output + opt_log_driver= + if [ $log_driver = "journald" ] && [ $event_logger != "journald" ]; then + # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend. + # Set '--log driver' temporally because remote doesn't support '--events-backend'. + opt_log_driver="--log-driver k8s-file" + fi + # Start a container that will handle all signals by emitting 'got: N' local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64) - run_podman run -d $IMAGE sh -c \ + run_podman run -d ${opt_log_driver} $IMAGE sh -c \ "for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done; echo READY; while ! test -e /stop; do sleep 0.05; done;