Skip to content

Commit 9d7a24e

Browse files
Merge pull request #26945 from Luap99/vol-opts
do not pass volume options as bind mounts options to runtime
2 parents fcdb6b5 + 46d7575 commit 9d7a24e

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

libpod/container_internal_common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
420420
// Podman decided for --no-dereference as many
421421
// bin-utils tools (e..g, touch, chown, cp) do.
422422
options = append(options, "copy-symlink")
423+
case "copy", "nocopy":
424+
// no real OCI runtime bind mount options, these should already be handled by the named volume mount above
423425
default:
424426
options = append(options, o)
425427
}

libpod/runtime_ctr.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
504504
_, err := r.state.Volume(vol.Name)
505505
if err == nil {
506506
// The volume exists, we're good
507+
// Make sure to drop all volume-opt options as they only apply to
508+
// the volume create which we don't do again.
509+
var volOpts []string
510+
for _, opts := range vol.Options {
511+
if !strings.HasPrefix(opts, "volume-opt") {
512+
volOpts = append(volOpts, opts)
513+
}
514+
}
515+
vol.Options = volOpts
507516
continue
508517
} else if !errors.Is(err, define.ErrNoSuchVolume) {
509518
return nil, fmt.Errorf("retrieving named volume %s for new container: %w", vol.Name, err)
@@ -530,6 +539,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
530539
if len(vol.Options) > 0 {
531540
isDriverOpts := false
532541
driverOpts := make(map[string]string)
542+
var volOpts []string
533543
for _, opts := range vol.Options {
534544
if strings.HasPrefix(opts, "volume-opt") {
535545
isDriverOpts = true
@@ -538,8 +548,11 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
538548
return nil, err
539549
}
540550
driverOpts[driverOptKey] = driverOptValue
551+
} else {
552+
volOpts = append(volOpts, opts)
541553
}
542554
}
555+
vol.Options = volOpts
543556
if isDriverOpts {
544557
parsedOptions := []VolumeCreateOption{WithVolumeOptions(driverOpts)}
545558
volOptions = append(volOptions, parsedOptions...)

test/e2e/run_volume_test.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33
package integration
44

55
import (
6+
"encoding/json"
67
"fmt"
78
"os"
89
"os/exec"
910
"os/user"
1011
"path/filepath"
12+
"strconv"
1113
"strings"
1214

1315
. "github.com/containers/podman/v5/test/utils"
1416
. "github.com/onsi/ginkgo/v2"
1517
. "github.com/onsi/gomega"
1618
. "github.com/onsi/gomega/gexec"
19+
"github.com/opencontainers/runtime-spec/specs-go"
1720
)
1821

1922
// in-container mount point: using a path that is definitely not present
@@ -447,9 +450,27 @@ var _ = Describe("Podman run with volumes", func() {
447450
Expect(separateVolumeSession).Should(ExitCleanly())
448451
Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
449452

450-
copySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
451-
copySession.WaitWithDefaultTimeout()
452-
Expect(copySession).Should(ExitCleanly())
453+
podmanTest.PodmanExitCleanly("run", "--name", "testctr", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch")
454+
455+
inspect := podmanTest.PodmanExitCleanly("container", "inspect", "testctr", "--format", "{{.OCIConfigPath}}")
456+
457+
// Make extra check that the OCI config does not contain the copy opt, runc 1.3.0 fails on that while crun does not.
458+
// We only test crun upstream so make sure the spec is sane: https://github.com/containers/podman/issues/26938
459+
f, err := os.Open(inspect.OutputToString())
460+
Expect(err).ToNot(HaveOccurred())
461+
defer f.Close()
462+
var spec specs.Spec
463+
err = json.NewDecoder(f).Decode(&spec)
464+
Expect(err).ToNot(HaveOccurred())
465+
466+
found := false
467+
for _, m := range spec.Mounts {
468+
if m.Destination == "/etc/apk" {
469+
found = true
470+
Expect(m.Options).To(Equal([]string{"rprivate", "nosuid", "nodev", "rbind"}))
471+
}
472+
}
473+
Expect(found).To(BeTrue(), "OCI spec contains /etc/apk mount")
453474

454475
noCopySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol4:/etc/apk:nocopy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
455476
noCopySession.WaitWithDefaultTimeout()
@@ -859,14 +880,17 @@ VOLUME /test/`, ALPINE)
859880
It("podman run with --mount and named volume with driver-opts", func() {
860881
// anonymous volume mount with driver opts
861882
vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev"
862-
session := podmanTest.Podman([]string{"run", "--rm", "--mount", vol, ALPINE, "echo", "hello"})
863-
session.WaitWithDefaultTimeout()
864-
Expect(session).Should(ExitCleanly())
883+
// Loop twice to cover both the initial code path that creates the volume and the ones which reuses it.
884+
for i := range 2 {
885+
name := "testctr" + strconv.Itoa(i)
886+
podmanTest.PodmanExitCleanly("run", "--name", name, "--mount", vol, ALPINE, "echo", "hello")
865887

866-
inspectVol := podmanTest.Podman([]string{"volume", "inspect", "test_vol"})
867-
inspectVol.WaitWithDefaultTimeout()
868-
Expect(inspectVol).Should(ExitCleanly())
869-
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
888+
inspectVol := podmanTest.PodmanExitCleanly("volume", "inspect", "test_vol")
889+
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
890+
891+
inspect := podmanTest.PodmanExitCleanly("container", "inspect", name, "--format", "{{range .Mounts}}{{.Options}}{{end}}")
892+
Expect(inspect.OutputToString()).To(ContainSubstring("[nosuid nodev rbind]"))
893+
}
870894
})
871895

872896
It("volume permissions after run", func() {

0 commit comments

Comments
 (0)