From 13f3fd2555b1f02af4c183ef51d1707af1198eb9 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 6 Jan 2022 10:42:34 -0500 Subject: Set volume NeedsCopyUp to false iff data was copied up Currently Docker copies up the first volume on a mountpoint with data. Fixes: https://github.com/containers/podman/issues/12714 Also added NeedsCopyUP, NeedsChown and MountCount to the podman volume inspect code. Signed-off-by: Daniel J Walsh --- libpod/container_internal.go | 14 +++++++------- libpod/define/volume_inspect.go | 8 ++++++++ libpod/volume_inspect.go | 3 +++ test/system/160-volumes.bats | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 2d12a90d1..3361fb3b2 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1700,13 +1700,6 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) if vol.state.NeedsCopyUp { logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name()) - // Set NeedsCopyUp to false immediately, so we don't try this - // again when there are already files copied. - vol.state.NeedsCopyUp = false - if err := vol.save(); err != nil { - return nil, err - } - // If the volume is not empty, we should not copy up. volMount := vol.mountPoint() contents, err := ioutil.ReadDir(volMount) @@ -1753,6 +1746,13 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) return vol, nil } + // Set NeedsCopyUp to false since we are about to do first copy + // Do not copy second time. + vol.state.NeedsCopyUp = false + if err := vol.save(); err != nil { + return nil, err + } + // Buildah Copier accepts a reader, so we'll need a pipe. reader, writer := io.Pipe() defer reader.Close() diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go index 20602ea16..fac179176 100644 --- a/libpod/define/volume_inspect.go +++ b/libpod/define/volume_inspect.go @@ -48,4 +48,12 @@ type InspectVolumeData struct { // volume for a specific container, and will be be removed when any // container using it is removed. Anonymous bool `json:"Anonymous,omitempty"` + // MountCount is the number of times this volume has been mounted. + MountCount uint `json:"MountCount"` + // NeedsCopyUp indicates that the next time the volume is mounted into + NeedsCopyUp bool `json:"NeedsCopyUp,omitempty"` + // NeedsChown indicates that the next time the volume is mounted into + // a container, the container will chown the volume to the container process + // UID/GID. + NeedsChown bool `json:"NeedsChown,omitempty"` } diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index c3f51222d..70098df5a 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -60,6 +60,9 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { data.UID = v.uid() data.GID = v.gid() data.Anonymous = v.config.IsAnon + data.MountCount = v.state.MountCount + data.NeedsCopyUp = v.state.NeedsCopyUp + data.NeedsChown = v.state.NeedsChown return data, nil } diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats index 1271b7c0b..b6030ba3c 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -345,4 +345,44 @@ EOF is "$output" "tmpfs" "volume should be tmpfs" } +# Named volumes copyup +@test "podman volume create copyup" { + myvolume=myvol$(random_string) + mylabel=$(random_string) + + # Create a named volume + run_podman volume create $myvolume + is "$output" "$myvolume" "output from volume create" + + # Confirm that it shows up in 'volume ls', and confirm values + run_podman volume ls --format json + tests=" +Name | $myvolume +Driver | local +NeedsCopyUp | true +NeedsChown | true +" + parse_table "$tests" | while read field expect; do + actual=$(jq -r ".[0].$field" <<<"$output") + is "$actual" "$expect" "volume ls .$field" + done + + run_podman run --rm --volume $myvolume:/vol $IMAGE true + run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume + is "${output}" "true" "If content in dest '/vol' empty NeedsCopyUP should still be true" + run_podman volume inspect --format '{{ .NeedsChown }}' $myvolume + is "${output}" "false" "After first use within a container NeedsChown should still be false" + + run_podman run --rm --volume $myvolume:/etc $IMAGE ls /etc/passwd + run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume + is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happend and be false" + + run_podman volume inspect --format '{{.Mountpoint}}' $myvolume + mountpoint="$output" + test -e "$mountpoint/passwd" + + # Clean up + run_podman volume rm $myvolume +} + # vim: filetype=sh -- cgit v1.2.3-54-g00ecf