summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE_PROCESS.md30
-rw-r--r--go.mod4
-rw-r--r--go.sum7
-rw-r--r--libpod/container_internal_linux.go56
-rw-r--r--test/e2e/build/workdir-symlink/Dockerfile5
-rw-r--r--test/e2e/build_test.go13
-rw-r--r--test/e2e/play_kube_test.go35
-rw-r--r--test/system/070-build.bats24
-rw-r--r--vendor/github.com/containers/image/v5/oci/layout/oci_dest.go2
-rw-r--r--vendor/github.com/containers/image/v5/storage/storage_image.go20
-rw-r--r--vendor/github.com/containers/image/v5/version/version.go4
-rw-r--r--vendor/github.com/containers/storage/containers.go53
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go2
-rw-r--r--vendor/github.com/containers/storage/errors.go5
-rw-r--r--vendor/github.com/containers/storage/images.go57
-rw-r--r--vendor/github.com/containers/storage/layers.go53
-rw-r--r--vendor/github.com/containers/storage/store.go63
-rw-r--r--vendor/github.com/containers/storage/utils.go32
-rw-r--r--vendor/modules.txt4
19 files changed, 387 insertions, 82 deletions
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
index e893d9e2e..bc2e4c01f 100644
--- a/RELEASE_PROCESS.md
+++ b/RELEASE_PROCESS.md
@@ -236,18 +236,18 @@ spelled with complete minutiae.
1. Return to the Cirrus-CI Build page for the new release tag, confirm
(or wait for) it to complete, re-running any failed tasks as appropriate.
- 1. For anything other than an RC, download the new release artifacts from CI
- (the binaries which were actually tested). The items are
- located under the *checks* tab in github for:
-
- * `Cirrus CI / Alt Arch. Cross` - tarball for each architecture
- * `Cirrus CI / OSX Cross` - two zip files (amd64 and arm64)
- * `Cirrus CI / Windows Cross` - an `msi` file
-
- Under the "Artifacts" section of each task, click the "gosrc" link,
- find and download the release archive (`zip`, `tar.gz` or `.msi`).
- Save the the archive with a meaningful name, for example
- `podman-v3.0.0.msi`.
+ 1. For anything other than an RC, the release artifacts need to be published along
+ with the release. These can be built locally using:
+
+ ```shell
+ $ git checkout vX.Y.Z
+ $ make podman-remote-release-darwin_amd64.zip podman-remote-release-darwin_arm64.zip podman-remote-release-windows_amd64.zip podman.msi podman-remote-static
+ $ mv podman-* bin/
+ $ cd bin/
+ $ tar -cvzf podman-remote-static.tar.gz podman-remote-static
+ $ sha256sum *.zip *.msi *.tar.gz > shasums
+ ```
+
1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in
possession of a developer signing key.
1. In the directory where you downloaded the archives, run
@@ -263,8 +263,10 @@ spelled with complete minutiae.
that to upload the artifacts you previously downloaded, including
the `shasums` file.
- * podman-remote-release-darwin.zip
- * podman-remote-release-windows.zip
+ * podman-remote-release-darwin_amd64.zip
+ * podman-remote-release-darwin_arm64.zip
+ * podman-remote-release-windows_amd64.zip
* podman-vX.Y.Z.msi
+ * podman-remote-static.tar.gz
* shasums
1. Save the release.
diff --git a/go.mod b/go.mod
index e529225e0..bb4942500 100644
--- a/go.mod
+++ b/go.mod
@@ -14,10 +14,10 @@ require (
github.com/containers/buildah v1.24.2
github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde
github.com/containers/conmon v2.0.20+incompatible
- github.com/containers/image/v5 v5.19.2-0.20220224100137-1045fb70b094
+ github.com/containers/image/v5 v5.19.2-0.20220302121925-9a9cd9322006
github.com/containers/ocicrypt v1.1.2
github.com/containers/psgo v1.7.2
- github.com/containers/storage v1.38.3-0.20220228132533-ebc90aba7d29
+ github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3
diff --git a/go.sum b/go.sum
index 7120c89d9..37a3eb977 100644
--- a/go.sum
+++ b/go.sum
@@ -358,8 +358,9 @@ github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde/go.mod h1:pks
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.19.1/go.mod h1:ewoo3u+TpJvGmsz64XgzbyTHwHtM94q7mgK/pX+v2SE=
-github.com/containers/image/v5 v5.19.2-0.20220224100137-1045fb70b094 h1:27NmJhSA35ldAiq0pV2cXjj6YERVrQU8ectvWqblFxE=
github.com/containers/image/v5 v5.19.2-0.20220224100137-1045fb70b094/go.mod h1:XoYK6kE0dpazFNcuS+a8lra+QfbC6s8tzv+cUuCrZpE=
+github.com/containers/image/v5 v5.19.2-0.20220302121925-9a9cd9322006 h1:84BWsbDrrkzKG2nj3bA+/RyBcjJbb3vEwT2rwqsEWsw=
+github.com/containers/image/v5 v5.19.2-0.20220302121925-9a9cd9322006/go.mod h1:S3gHB0QSB4IdADVtDbFbvFDdDq5v4ENMyXIo+Qi4cm8=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a h1:spAGlqziZjCJL25C6F1zsQY05tfCKE9F5YwtEWWe6hU=
github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
@@ -373,8 +374,8 @@ github.com/containers/psgo v1.7.2/go.mod h1:SLpqxsPOHtTqRygjutCPXmeU2PoEFzV3gzJp
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc=
github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ=
-github.com/containers/storage v1.38.3-0.20220228132533-ebc90aba7d29 h1:jKxTQc8+kAoYi/oQoMOptWi7CXsicJ/i6DR5GZCyISw=
-github.com/containers/storage v1.38.3-0.20220228132533-ebc90aba7d29/go.mod h1:LkkL34WRi4dI4jt9Cp+ImdZi/P5i36glSHimT5CP5zM=
+github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa h1:rdJIWaQ7PwS2N0ZWgn6NXDp+8KtvfSmPTJ3S5i6fJr4=
+github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa/go.mod h1:LkkL34WRi4dI4jt9Cp+ImdZi/P5i36glSHimT5CP5zM=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index cef9e2c04..1517a7df7 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -173,6 +173,57 @@ func (c *Container) prepare() error {
return nil
}
+// isWorkDirSymlink returns true if resolved workdir is symlink or a chain of symlinks,
+// and final resolved target is present either on volume, mount or inside of container
+// otherwise it returns false. Following function is meant for internal use only and
+// can change at any point of time.
+func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
+ // We cannot create workdir since explicit --workdir is
+ // set in config but workdir could also be a symlink.
+ // If its a symlink lets check if resolved link is present
+ // on the container or not.
+
+ // If we can resolve symlink and resolved link is present on the container
+ // then return nil cause its a valid use-case.
+
+ maxSymLinks := 0
+ for {
+ // Linux only supports a chain of 40 links.
+ // Reference: https://github.com/torvalds/linux/blob/master/include/linux/namei.h#L13
+ if maxSymLinks > 40 {
+ break
+ }
+ resolvedSymlink, err := os.Readlink(resolvedPath)
+ if err != nil {
+ // End sym-link resolution loop.
+ break
+ }
+ if resolvedSymlink != "" {
+ _, resolvedSymlinkWorkdir, err := c.resolvePath(c.state.Mountpoint, resolvedSymlink)
+ if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnBindMount(c, resolvedSymlinkWorkdir) {
+ // Resolved symlink exists on external volume or mount
+ return true
+ }
+ if err != nil {
+ // Could not resolve path so end sym-link resolution loop.
+ break
+ }
+ if resolvedSymlinkWorkdir != "" {
+ resolvedPath = resolvedSymlinkWorkdir
+ _, err := os.Stat(resolvedSymlinkWorkdir)
+ if err == nil {
+ // Symlink resolved successfully and resolved path exists on container,
+ // this is a valid use-case so return nil.
+ logrus.Debugf("Workdir is a symlink with target to %q and resolved symlink exists on container", resolvedSymlink)
+ return true
+ }
+ }
+ }
+ maxSymLinks++
+ }
+ return false
+}
+
// resolveWorkDir resolves the container's workdir and, depending on the
// configuration, will create it, or error out if it does not exist.
// Note that the container must be mounted before.
@@ -205,6 +256,11 @@ func (c *Container) resolveWorkDir() error {
// the path exists on the container.
if err != nil {
if os.IsNotExist(err) {
+ // If resolved Workdir path gets marked as a valid symlink,
+ // return nil cause this is valid use-case.
+ if c.isWorkDirSymlink(resolvedWorkdir) {
+ return nil
+ }
return errors.Errorf("workdir %q does not exist on container %s", workdir, c.ID())
}
// This might be a serious error (e.g., permission), so
diff --git a/test/e2e/build/workdir-symlink/Dockerfile b/test/e2e/build/workdir-symlink/Dockerfile
new file mode 100644
index 000000000..abc9b47ee
--- /dev/null
+++ b/test/e2e/build/workdir-symlink/Dockerfile
@@ -0,0 +1,5 @@
+FROM alpine
+RUN mkdir /tmp/destination
+RUN ln -s /tmp/destination /tmp/link
+WORKDIR /tmp/link
+CMD ["echo", "hello"]
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index a1c2f5e54..14fa12fa2 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -259,6 +259,19 @@ var _ = Describe("Podman build", func() {
Expect(session.OutputToString()).NotTo(ContainSubstring("io.podman.annotations.seccomp"))
})
+ It("podman build where workdir is a symlink and run without creating new workdir", func() {
+ session := podmanTest.Podman([]string{
+ "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--workdir", "/tmp/link", "test-symlink"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("hello"))
+ })
+
It("podman build --http_proxy flag", func() {
os.Setenv("http_proxy", "1.2.3.4")
if IsRemote() {
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index c0c71652e..9b1e0c74b 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -38,6 +38,21 @@ spec:
hostname: unknown
`
+var workdirSymlinkPodYaml = `
+apiVersion: v1
+kind: Pod
+metadata:
+ labels:
+ app: test-symlink
+ name: test-symlink
+spec:
+ containers:
+ - image: test-symlink
+ name: test-symlink
+ resources: {}
+ restartPolicy: Never
+`
+
var podnameEqualsContainerNameYaml = `
apiVersion: v1
kind: Pod
@@ -1332,6 +1347,26 @@ var _ = Describe("Podman play kube", func() {
Expect(sharednamespaces).To(ContainSubstring("pid"))
})
+ It("podman play kube should be able to run image where workdir is a symlink", func() {
+ session := podmanTest.Podman([]string{
+ "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ err := writeYaml(workdirSymlinkPodYaml, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-symlink-test-symlink", "test-symlink"})
+ logs.WaitWithDefaultTimeout()
+ Expect(logs).Should(Exit(0))
+ Expect(logs.OutputToString()).To(ContainSubstring("hello"))
+ })
+
It("podman play kube should not rename pod if container in pod has same name", func() {
err := writeYaml(podnameEqualsContainerNameYaml, kubeYaml)
Expect(err).To(BeNil())
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index c963d8325..e47d66542 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -210,6 +210,30 @@ EOF
run_podman rmi -f build_test
}
+@test "podman parallel build should not race" {
+ skip_if_remote "following test is not supported for remote clients"
+
+ # Run thirty parallel builds using the same Containerfile
+ cat >$PODMAN_TMPDIR/Containerfile <<EOF
+FROM $IMAGE
+RUN echo hi
+EOF
+
+ local count=30
+ for i in $(seq --format '%02g' 1 $count); do
+ timeout --foreground -v --kill=10 60 \
+ $PODMAN build -t i$i $PODMAN_TMPDIR &>/dev/null &
+ done
+
+ # Wait for all background builds to complete. Note that this succeeds
+ # even if some of the individual builds fail! Our actual test is below.
+ wait
+
+ # Now delete all built images. If any image wasn't built, rmi will fail
+ # and test will fail.
+ run_podman rmi $(seq --format 'i%02g' 1 $count)
+}
+
@test "podman build - URLs" {
tmpdir=$PODMAN_TMPDIR/build-test
mkdir -p $tmpdir
diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go b/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go
index d0ee72635..c8156cc3a 100644
--- a/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go
+++ b/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go
@@ -112,7 +112,7 @@ func (d *ociImageDestination) IgnoresEmbeddedDockerReference() bool {
// HasThreadSafePutBlob indicates whether PutBlob can be executed concurrently.
func (d *ociImageDestination) HasThreadSafePutBlob() bool {
- return false
+ return true
}
// PutBlob writes contents of stream and returns data representing the result.
diff --git a/vendor/github.com/containers/image/v5/storage/storage_image.go b/vendor/github.com/containers/image/v5/storage/storage_image.go
index bcb09c83c..08ae042ac 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_image.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_image.go
@@ -1197,21 +1197,13 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
}
logrus.Debugf("saved image metadata %q", string(metadata))
}
- // Set the reference's name on the image. We don't need to worry about avoiding duplicate
- // values because SetNames() will deduplicate the list that we pass to it.
- if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil {
- names := []string{}
- if name != nil {
- names = append(names, name.String())
+ // Adds the reference's name on the image. We don't need to worry about avoiding duplicate
+ // values because AddNames() will deduplicate the list that we pass to it.
+ if name := s.imageRef.DockerReference(); name != nil {
+ if err := s.imageRef.transport.store.AddNames(img.ID, []string{name.String()}); err != nil {
+ return errors.Wrapf(err, "adding names %v to image %q", name, img.ID)
}
- if len(oldNames) > 0 {
- names = append(names, oldNames...)
- }
- if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil {
- logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err)
- return errors.Wrapf(err, "setting names %v on image %q", names, img.ID)
- }
- logrus.Debugf("set names of image %q to %v", img.ID, names)
+ logrus.Debugf("added name %q to image %q", name, img.ID)
}
commitSucceeded = true
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index a9163e059..05bb40fb4 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -6,9 +6,9 @@ const (
// VersionMajor is for an API incompatible changes
VersionMajor = 5
// VersionMinor is for functionality in a backwards-compatible manner
- VersionMinor = 19
+ VersionMinor = 20
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 2
+ VersionPatch = 1
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = "-dev"
diff --git a/vendor/github.com/containers/storage/containers.go b/vendor/github.com/containers/storage/containers.go
index 5425f0339..a8b20f03a 100644
--- a/vendor/github.com/containers/storage/containers.go
+++ b/vendor/github.com/containers/storage/containers.go
@@ -84,8 +84,17 @@ type ContainerStore interface {
// SetNames updates the list of names associated with the container
// with the specified ID.
+ // Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
SetNames(id string, names []string) error
+ // AddNames adds the supplied values to the list of names associated with the container with
+ // the specified id.
+ AddNames(id string, names []string) error
+
+ // RemoveNames removes the supplied values from the list of names associated with the container with
+ // the specified id.
+ RemoveNames(id string, names []string) error
+
// Get retrieves information about a container given an ID or name.
Get(id string) (*Container, error)
@@ -377,22 +386,40 @@ func (r *containerStore) removeName(container *Container, name string) {
container.Names = stringSliceWithoutValue(container.Names, name)
}
+// Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
func (r *containerStore) SetNames(id string, names []string) error {
- names = dedupeNames(names)
- if container, ok := r.lookup(id); ok {
- for _, name := range container.Names {
- delete(r.byname, name)
- }
- for _, name := range names {
- if otherContainer, ok := r.byname[name]; ok {
- r.removeName(otherContainer, name)
- }
- r.byname[name] = container
+ return r.updateNames(id, names, setNames)
+}
+
+func (r *containerStore) AddNames(id string, names []string) error {
+ return r.updateNames(id, names, addNames)
+}
+
+func (r *containerStore) RemoveNames(id string, names []string) error {
+ return r.updateNames(id, names, removeNames)
+}
+
+func (r *containerStore) updateNames(id string, names []string, op updateNameOperation) error {
+ container, ok := r.lookup(id)
+ if !ok {
+ return ErrContainerUnknown
+ }
+ oldNames := container.Names
+ names, err := applyNameOperation(oldNames, names, op)
+ if err != nil {
+ return err
+ }
+ for _, name := range oldNames {
+ delete(r.byname, name)
+ }
+ for _, name := range names {
+ if otherContainer, ok := r.byname[name]; ok {
+ r.removeName(otherContainer, name)
}
- container.Names = names
- return r.Save()
+ r.byname[name] = container
}
- return ErrContainerUnknown
+ container.Names = names
+ return r.Save()
}
func (r *containerStore) Delete(id string) error {
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index e9a06d8be..739828b35 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -1530,7 +1530,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
diffDir := path.Join(id, "diff")
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(relLowers, ":"), diffDir, workdir)
} else {
- opts = fmt.Sprintf("lowerdir=%s", strings.Join(absLowers, ":"))
+ opts = fmt.Sprintf("lowerdir=%s", strings.Join(relLowers, ":"))
}
if len(optsList) > 0 {
opts = fmt.Sprintf("%s,%s", opts, strings.Join(optsList, ","))
diff --git a/vendor/github.com/containers/storage/errors.go b/vendor/github.com/containers/storage/errors.go
index 0b55639e6..de6e37754 100644
--- a/vendor/github.com/containers/storage/errors.go
+++ b/vendor/github.com/containers/storage/errors.go
@@ -1,6 +1,8 @@
package storage
import (
+ "errors"
+
"github.com/containers/storage/types"
)
@@ -57,4 +59,7 @@ var (
ErrNotSupported = types.ErrNotSupported
// ErrInvalidMappings is returned when the specified mappings are invalid.
ErrInvalidMappings = types.ErrInvalidMappings
+ // ErrInvalidNameOperation is returned when updateName is called with invalid operation.
+ // Internal error
+ errInvalidUpdateNameOperation = errors.New("invalid update name operation")
)
diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go
index 882ba7894..a4c3ed22c 100644
--- a/vendor/github.com/containers/storage/images.go
+++ b/vendor/github.com/containers/storage/images.go
@@ -136,8 +136,19 @@ type ImageStore interface {
// SetNames replaces the list of names associated with an image with the
// supplied values. The values are expected to be valid normalized
// named image references.
+ // Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
SetNames(id string, names []string) error
+ // AddNames adds the supplied values to the list of names associated with the image with
+ // the specified id. The values are expected to be valid normalized
+ // named image references.
+ AddNames(id string, names []string) error
+
+ // RemoveNames removes the supplied values from the list of names associated with the image with
+ // the specified id. The values are expected to be valid normalized
+ // named image references.
+ RemoveNames(id string, names []string) error
+
// Delete removes the record of the image.
Delete(id string) error
@@ -505,26 +516,44 @@ func (i *Image) addNameToHistory(name string) {
i.NamesHistory = dedupeNames(append([]string{name}, i.NamesHistory...))
}
+// Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
func (r *imageStore) SetNames(id string, names []string) error {
+ return r.updateNames(id, names, setNames)
+}
+
+func (r *imageStore) AddNames(id string, names []string) error {
+ return r.updateNames(id, names, addNames)
+}
+
+func (r *imageStore) RemoveNames(id string, names []string) error {
+ return r.updateNames(id, names, removeNames)
+}
+
+func (r *imageStore) updateNames(id string, names []string, op updateNameOperation) error {
if !r.IsReadWrite() {
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change image name assignments at %q", r.imagespath())
}
- names = dedupeNames(names)
- if image, ok := r.lookup(id); ok {
- for _, name := range image.Names {
- delete(r.byname, name)
- }
- for _, name := range names {
- if otherImage, ok := r.byname[name]; ok {
- r.removeName(otherImage, name)
- }
- r.byname[name] = image
- image.addNameToHistory(name)
+ image, ok := r.lookup(id)
+ if !ok {
+ return errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id)
+ }
+ oldNames := image.Names
+ names, err := applyNameOperation(oldNames, names, op)
+ if err != nil {
+ return err
+ }
+ for _, name := range oldNames {
+ delete(r.byname, name)
+ }
+ for _, name := range names {
+ if otherImage, ok := r.byname[name]; ok {
+ r.removeName(otherImage, name)
}
- image.Names = names
- return r.Save()
+ r.byname[name] = image
+ image.addNameToHistory(name)
}
- return errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id)
+ image.Names = names
+ return r.Save()
}
func (r *imageStore) Delete(id string) error {
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 985d5f644..8a5616dfc 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -221,8 +221,17 @@ type LayerStore interface {
// SetNames replaces the list of names associated with a layer with the
// supplied values.
+ // Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
SetNames(id string, names []string) error
+ // AddNames adds the supplied values to the list of names associated with the layer with the
+ // specified id.
+ AddNames(id string, names []string) error
+
+ // RemoveNames remove the supplied values from the list of names associated with the layer with the
+ // specified id.
+ RemoveNames(id string, names []string) error
+
// Delete deletes a layer with the specified name or ID.
Delete(id string) error
@@ -1040,25 +1049,43 @@ func (r *layerStore) removeName(layer *Layer, name string) {
layer.Names = stringSliceWithoutValue(layer.Names, name)
}
+// Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
func (r *layerStore) SetNames(id string, names []string) error {
+ return r.updateNames(id, names, setNames)
+}
+
+func (r *layerStore) AddNames(id string, names []string) error {
+ return r.updateNames(id, names, addNames)
+}
+
+func (r *layerStore) RemoveNames(id string, names []string) error {
+ return r.updateNames(id, names, removeNames)
+}
+
+func (r *layerStore) updateNames(id string, names []string, op updateNameOperation) error {
if !r.IsReadWrite() {
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to change layer name assignments at %q", r.layerspath())
}
- names = dedupeNames(names)
- if layer, ok := r.lookup(id); ok {
- for _, name := range layer.Names {
- delete(r.byname, name)
- }
- for _, name := range names {
- if otherLayer, ok := r.byname[name]; ok {
- r.removeName(otherLayer, name)
- }
- r.byname[name] = layer
+ layer, ok := r.lookup(id)
+ if !ok {
+ return ErrLayerUnknown
+ }
+ oldNames := layer.Names
+ names, err := applyNameOperation(oldNames, names, op)
+ if err != nil {
+ return err
+ }
+ for _, name := range oldNames {
+ delete(r.byname, name)
+ }
+ for _, name := range names {
+ if otherLayer, ok := r.byname[name]; ok {
+ r.removeName(otherLayer, name)
}
- layer.Names = names
- return r.Save()
+ r.byname[name] = layer
}
- return ErrLayerUnknown
+ layer.Names = names
+ return r.Save()
}
func (r *layerStore) datadir(id string) string {
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index f49266c2c..6b40b68ca 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -31,6 +31,14 @@ import (
"github.com/pkg/errors"
)
+type updateNameOperation int
+
+const (
+ setNames updateNameOperation = iota
+ addNames
+ removeNames
+)
+
var (
stores []*store
storesLock sync.Mutex
@@ -368,8 +376,17 @@ type Store interface {
// SetNames changes the list of names for a layer, image, or container.
// Duplicate names are removed from the list automatically.
+ // Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
SetNames(id string, names []string) error
+ // AddNames adds the list of names for a layer, image, or container.
+ // Duplicate names are removed from the list automatically.
+ AddNames(id string, names []string) error
+
+ // RemoveNames removes the list of names for a layer, image, or container.
+ // Duplicate names are removed from the list automatically.
+ RemoveNames(id string, names []string) error
+
// ListImageBigData retrieves a list of the (possibly large) chunks of
// named data associated with an image.
ListImageBigData(id string) ([]string, error)
@@ -2050,7 +2067,20 @@ func dedupeNames(names []string) []string {
return deduped
}
+// Deprecated: Prone to race conditions, suggested alternatives are `AddNames` and `RemoveNames`.
func (s *store) SetNames(id string, names []string) error {
+ return s.updateNames(id, names, setNames)
+}
+
+func (s *store) AddNames(id string, names []string) error {
+ return s.updateNames(id, names, addNames)
+}
+
+func (s *store) RemoveNames(id string, names []string) error {
+ return s.updateNames(id, names, removeNames)
+}
+
+func (s *store) updateNames(id string, names []string, op updateNameOperation) error {
deduped := dedupeNames(names)
rlstore, err := s.LayerStore()
@@ -2063,7 +2093,16 @@ func (s *store) SetNames(id string, names []string) error {
return err
}
if rlstore.Exists(id) {
- return rlstore.SetNames(id, deduped)
+ switch op {
+ case setNames:
+ return rlstore.SetNames(id, deduped)
+ case removeNames:
+ return rlstore.RemoveNames(id, deduped)
+ case addNames:
+ return rlstore.AddNames(id, deduped)
+ default:
+ return errInvalidUpdateNameOperation
+ }
}
ristore, err := s.ImageStore()
@@ -2076,7 +2115,16 @@ func (s *store) SetNames(id string, names []string) error {
return err
}
if ristore.Exists(id) {
- return ristore.SetNames(id, deduped)
+ switch op {
+ case setNames:
+ return ristore.SetNames(id, deduped)
+ case removeNames:
+ return ristore.RemoveNames(id, deduped)
+ case addNames:
+ return ristore.AddNames(id, deduped)
+ default:
+ return errInvalidUpdateNameOperation
+ }
}
// Check is id refers to a RO Store
@@ -2114,7 +2162,16 @@ func (s *store) SetNames(id string, names []string) error {
return err
}
if rcstore.Exists(id) {
- return rcstore.SetNames(id, deduped)
+ switch op {
+ case setNames:
+ return rcstore.SetNames(id, deduped)
+ case removeNames:
+ return rcstore.RemoveNames(id, deduped)
+ case addNames:
+ return rcstore.AddNames(id, deduped)
+ default:
+ return errInvalidUpdateNameOperation
+ }
}
return ErrLayerUnknown
}
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index 80d56041b..cec377f26 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -40,3 +40,35 @@ func validateMountOptions(mountOptions []string) error {
}
return nil
}
+
+func applyNameOperation(oldNames []string, opParameters []string, op updateNameOperation) ([]string, error) {
+ result := make([]string, 0)
+ switch op {
+ case setNames:
+ // ignore all old names and just return new names
+ return dedupeNames(opParameters), nil
+ case removeNames:
+ // remove given names from old names
+ for _, name := range oldNames {
+ // only keep names in final result which do not intersect with input names
+ // basically `result = oldNames - opParameters`
+ nameShouldBeRemoved := false
+ for _, opName := range opParameters {
+ if name == opName {
+ nameShouldBeRemoved = true
+ }
+ }
+ if !nameShouldBeRemoved {
+ result = append(result, name)
+ }
+ }
+ return dedupeNames(result), nil
+ case addNames:
+ result = append(result, opParameters...)
+ result = append(result, oldNames...)
+ return dedupeNames(result), nil
+ default:
+ return result, errInvalidUpdateNameOperation
+ }
+ return dedupeNames(result), nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ef38b67b0..319a3592f 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -153,7 +153,7 @@ github.com/containers/common/version
# github.com/containers/conmon v2.0.20+incompatible
## explicit
github.com/containers/conmon/runner/config
-# github.com/containers/image/v5 v5.19.2-0.20220224100137-1045fb70b094
+# github.com/containers/image/v5 v5.19.2-0.20220302121925-9a9cd9322006
## explicit
github.com/containers/image/v5/copy
github.com/containers/image/v5/directory
@@ -232,7 +232,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.38.3-0.20220228132533-ebc90aba7d29
+# github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa
## explicit
github.com/containers/storage
github.com/containers/storage/drivers