aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DISTRO_PACKAGE.md101
-rw-r--r--Makefile16
-rw-r--r--RELEASE_PROCESS.md34
-rwxr-xr-xcontrib/cirrus/runner.sh15
-rwxr-xr-xcontrib/cirrus/setup_environment.sh13
-rw-r--r--go.mod4
-rw-r--r--go.sum7
-rw-r--r--libpod/runtime_pod_linux.go71
-rw-r--r--pkg/domain/infra/abi/play.go11
-rw-r--r--pkg/machine/qemu/machine.go5
-rw-r--r--test/apiv2/12-imagesMore.at5
-rw-r--r--test/apiv2/python/conftest.py8
-rw-r--r--test/apiv2/python/requirements.txt5
-rwxr-xr-xtest/apiv2/test-apiv219
-rw-r--r--test/e2e/containers_conf_test.go5
-rw-r--r--test/e2e/play_kube_test.go20
-rw-r--r--test/system/070-build.bats24
-rw-r--r--troubleshooting.md12
-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
29 files changed, 521 insertions, 149 deletions
diff --git a/DISTRO_PACKAGE.md b/DISTRO_PACKAGE.md
new file mode 100644
index 000000000..133c62d23
--- /dev/null
+++ b/DISTRO_PACKAGE.md
@@ -0,0 +1,101 @@
+# Podman Packaging
+
+This document is currently written with Fedora as a reference, intended for use
+by packagers of other distros as well as package users.
+
+## Fedora Users
+Podman v4 is available as an official Fedora package on Fedora 36 and rawhide.
+This version of Podman brings with it a new container stack called
+Netavark which serves as a replacement for CNI plugins
+(containernetworking-plugins on Fedora), as well as Aardvark-dns, the
+authoritative DNS server for container records.
+
+Both Netavark and Aardvark-dns are available as official Fedora packages on
+Fedora 35 and newer versions and form the default network stack for new
+installations of Podman 4.0.
+
+On Fedora 36 and newer, fresh installations of Podman v4 will
+automatically install Aardvark-dns along with Netavark.
+
+To install Podman v4:
+
+```console
+$ sudo dnf install podman
+```
+
+To update Podman from an older version to v4:
+
+```console
+$ sudo dnf update podman
+```
+
+**NOTE:** Fedora 35 users will not be able to install Podman v4 using the default yum
+repositories and are recommended to use the COPR repo below:
+
+```console
+$ sudo dnf copr enable rhcontainerbot/podman4
+
+# install or update per your needs
+$ sudo dnf install podman
+```
+
+After installation, if you would like to migrate all your containers to use
+Netavark, you will need to set `network_backend = "netavark"` under
+the `[network]` section in your containers.conf, typically located at:
+`/usr/share/containers/containers.conf`
+
+### Testing the latest development version`
+
+If you would like to test the latest unreleased upstream code, try the
+podman-next COPR
+
+```console
+$ sudo dnf copr enable rhcontainerbot/podman-next
+
+$ sudo dnf install podman
+```
+
+**CAUTION:** The podman-next COPR provides the latest unreleased sources of Podman,
+Netavark and Aardvark-dns as rpms which would override the versions provided by
+the official packages.
+
+## Distro Packagers
+
+The Fedora packaging sources for Podman are available at the [Podman
+dist-git](https://src.fedoraproject.org/rpms/podman).
+
+The main `podman` package no longer explicitly depends on
+containernetworking-plugins. The network stack dependencies are now handled in
+the [containers-common](https://src.fedoraproject.org/rpms/containers-common)
+package which allows for a single point of dependency maintenance for Podman
+and Buildah.
+
+- containers-common
+```
+Requires: container-network-stack
+Recommends: netavark
+```
+
+- netavark
+```
+Provides: container-network-stack = 2
+```
+
+- containernetworking-plugins
+```
+Provides: container-network-stack = 1
+```
+
+This configuration ensures:
+- New installations of Podman will always install netavark by default.
+- The containernetworking-plugins package will not conflict with netavark and
+users can install them together.
+
+## Listing bundled dependencies
+If you need to list the bundled dependencies in your packaging sources, you can
+process the `go.mod` file in the upstream source.
+For example, Fedora's packaging source uses:
+
+```
+$ awk '{print "Provides: bundled(golang("$1")) = "$2}' go.mod | sort | uniq | sed -e 's/-/_/g' -e '/bundled(golang())/d' -e '/bundled(golang(go\|module\|replace\|require))/d'
+```
diff --git a/Makefile b/Makefile
index e45a3ba12..2924eb32b 100644
--- a/Makefile
+++ b/Makefile
@@ -542,7 +542,7 @@ validate.completions:
run-docker-py-tests:
touch test/__init__.py
env CONTAINERS_CONF=$(CURDIR)/test/apiv2/containers.conf pytest --disable-warnings test/python/docker/
- -rm test/__init__.py
+ rm -f test/__init__.py
.PHONY: localunit
localunit: test/goecho/goecho test/version/version
@@ -623,9 +623,15 @@ remotesystem:
.PHONY: localapiv2
localapiv2:
- env PODMAN=./bin/podman ./test/apiv2/test-apiv2
- env CONTAINERS_CONF=$(CURDIR)/test/apiv2/containers.conf PODMAN=./bin/podman ${PYTHON} -m unittest discover -v ./test/apiv2/python
- env CONTAINERS_CONF=$(CURDIR)/test/apiv2/containers.conf PODMAN=./bin/podman ${PYTHON} -m unittest discover -v ./test/python/docker
+ # Order is important running python tests first causes the bash tests to fail, see 12-imagesMore
+ # FIXME order of tests should not matter
+ env PODMAN=./bin/podman stdbuf -o0 -e0 ./test/apiv2/test-apiv2
+ env CONTAINERS_CONF=$(CURDIR)/test/apiv2/containers.conf PODMAN=./bin/podman \
+ pytest --disable-warnings ./test/apiv2/python
+ touch test/__init__.py
+ env CONTAINERS_CONF=$(CURDIR)/test/apiv2/containers.conf PODMAN=./bin/podman \
+ pytest --disable-warnings ./test/python/docker
+ rm -f test/__init__.py
.PHONY: remoteapiv2
remoteapiv2:
@@ -949,5 +955,5 @@ clean: clean-binaries ## Clean all make artifacts
libpod/pod_easyjson.go \
.install.goimports \
docs/build \
- venv
+ .venv
make -C docs clean
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
index e893d9e2e..3f63e5466 100644
--- a/RELEASE_PROCESS.md
+++ b/RELEASE_PROCESS.md
@@ -236,18 +236,22 @@ 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 +267,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/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index 3aa69183e..d1d87ad04 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -55,11 +55,8 @@ function _run_unit() {
}
function _run_apiv2() {
- local m="Testing of API was performed using the **PODMAN*** client"
- warn "$m"
- if ! make localapiv2 |& logformatter; then
- die "$m"
- fi
+ source .venv/requests/bin/activate
+ make localapiv2 |& logformatter
}
function _run_compose() {
@@ -100,12 +97,8 @@ function _run_bindings() {
}
function _run_docker-py() {
- m="Testing of API was performed using the **DOCKER** client"
- warn "$m"
- source venv/bin/activate
- if ! make run-docker-py-tests; then
- die "$m"
- fi
+ source .venv/docker-py/bin/activate
+ make run-docker-py-tests
}
function _run_endpoint() {
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 93f085983..696560166 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -265,14 +265,21 @@ case "$TEST_FLAVOR" in
msg "Installing previously downloaded/cached packages"
dnf install -y $PACKAGE_DOWNLOAD_DIR/python3*.rpm
- virtualenv venv
- source venv/bin/activate
+ virtualenv .venv/docker-py
+ source .venv/docker-py/bin/activate
pip install --upgrade pip
pip install --requirement $GOSRC/test/python/requirements.txt
;;
build) make clean ;;
unit) ;;
- apiv2) ;& # use next item
+ apiv2)
+ msg "Installing previously downloaded/cached packages"
+ dnf install -y $PACKAGE_DOWNLOAD_DIR/python3*.rpm
+ virtualenv .venv/requests
+ source .venv/requests/bin/activate
+ pip install --upgrade pip
+ pip install --requirement $GOSRC/test/apiv2/python/requirements.txt
+ ;& # continue with next item
compose)
rpm -ivh $PACKAGE_DOWNLOAD_DIR/podman-docker*
;& # continue with next item
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/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 155ad5c2d..230491c1a 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package libpod
@@ -59,50 +60,52 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option
pod.valid = true
// Check Cgroup parent sanity, and set it if it was not set
- switch r.config.Engine.CgroupManager {
- case config.CgroupfsCgroupsManager:
- canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
- if canUseCgroup {
+ if r.config.Cgroups() != "disabled" {
+ switch r.config.Engine.CgroupManager {
+ case config.CgroupfsCgroupsManager:
+ canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
+ if canUseCgroup {
+ if pod.config.CgroupParent == "" {
+ pod.config.CgroupParent = CgroupfsDefaultCgroupParent
+ } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
+ return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs")
+ }
+ // If we are set to use pod cgroups, set the cgroup parent that
+ // all containers in the pod will share
+ // No need to create it with cgroupfs - the first container to
+ // launch should do it for us
+ if pod.config.UsePodCgroup {
+ pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
+ if p.InfraContainerSpec != nil {
+ p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
+ }
+ }
+ }
+ case config.SystemdCgroupsManager:
if pod.config.CgroupParent == "" {
- pod.config.CgroupParent = CgroupfsDefaultCgroupParent
- } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
- return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs")
+ if rootless.IsRootless() {
+ pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
+ } else {
+ pod.config.CgroupParent = SystemdDefaultCgroupParent
+ }
+ } else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
+ return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups")
}
// If we are set to use pod cgroups, set the cgroup parent that
// all containers in the pod will share
- // No need to create it with cgroupfs - the first container to
- // launch should do it for us
if pod.config.UsePodCgroup {
- pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
+ cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()))
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
+ }
+ pod.state.CgroupPath = cgroupPath
if p.InfraContainerSpec != nil {
p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
}
}
+ default:
+ return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
}
- case config.SystemdCgroupsManager:
- if pod.config.CgroupParent == "" {
- if rootless.IsRootless() {
- pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
- } else {
- pod.config.CgroupParent = SystemdDefaultCgroupParent
- }
- } else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
- return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups")
- }
- // If we are set to use pod cgroups, set the cgroup parent that
- // all containers in the pod will share
- if pod.config.UsePodCgroup {
- cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()))
- if err != nil {
- return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
- }
- pod.state.CgroupPath = cgroupPath
- if p.InfraContainerSpec != nil {
- p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
- }
- }
- default:
- return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
}
if pod.config.UsePodCgroup {
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 8cbf5da9a..4d8112c47 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -359,7 +359,13 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
+ ctrNames := make(map[string]string)
for _, initCtr := range podYAML.Spec.InitContainers {
+ // Error out if same name is used for more than one container
+ if _, ok := ctrNames[initCtr.Name]; ok {
+ return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, initCtr.Name)
+ }
+ ctrNames[initCtr.Name] = ""
// Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set
if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil {
return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set")
@@ -408,6 +414,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
for _, container := range podYAML.Spec.Containers {
if !strings.Contains("infra", container.Name) {
+ // Error out if the same name is used for more than one container
+ if _, ok := ctrNames[container.Name]; ok {
+ return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, container.Name)
+ }
+ ctrNames[container.Name] = ""
pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options)
if err != nil {
return nil, err
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 9beec2173..8b567fb26 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -667,6 +667,11 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
if !opts.SaveImage {
files = append(files, v.ImagePath)
}
+ socketPath, err := v.getForwardSocketPath()
+ if err != nil {
+ logrus.Error(err)
+ }
+ files = append(files, socketPath)
files = append(files, v.archRemovalFiles()...)
if err := machine.RemoveConnection(v.Name); err != nil {
diff --git a/test/apiv2/12-imagesMore.at b/test/apiv2/12-imagesMore.at
index 96eba1db5..67b4f1c79 100644
--- a/test/apiv2/12-imagesMore.at
+++ b/test/apiv2/12-imagesMore.at
@@ -26,7 +26,8 @@ t GET libpod/images/$IMAGE/json 200 \
.RepoTags[1]=localhost:5000/myrepo:mytag
# Run registry container
-podman run -d --name registry -p 5000:5000 quay.io/libpod/registry:2.6 /entrypoint.sh /etc/docker/registry/config.yml
+# FIXME this fails if python tests have been run first...
+podman run -d --name registry -p 5000:5000 quay.io/libpod/registry:2.7 /entrypoint.sh /etc/docker/registry/config.yml
wait_for_port localhost 5000
# Push to local registry and check output
@@ -58,7 +59,7 @@ t DELETE libpod/containers/registry?force=true 200
# Remove images
t DELETE libpod/images/$IMAGE 200 \
.ExitCode=0
-t DELETE libpod/images/quay.io/libpod/registry:2.6 200 \
+t DELETE libpod/images/quay.io/libpod/registry:2.7 200 \
.ExitCode=0
if [ -z "${GOT_DIGEST}" ] ; then
diff --git a/test/apiv2/python/conftest.py b/test/apiv2/python/conftest.py
new file mode 100644
index 000000000..54a267049
--- /dev/null
+++ b/test/apiv2/python/conftest.py
@@ -0,0 +1,8 @@
+"""
+Configure pytest
+"""
+
+
+def pytest_report_header(config):
+ """Add header to report."""
+ return "python client -- requests library"
diff --git a/test/apiv2/python/requirements.txt b/test/apiv2/python/requirements.txt
new file mode 100644
index 000000000..d9cfc687a
--- /dev/null
+++ b/test/apiv2/python/requirements.txt
@@ -0,0 +1,5 @@
+requests-mock~=1.9.3
+requests~=2.20.0
+setuptools~=50.3.2
+python-dateutil~=2.8.1
+PyYAML~=5.4.1
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index bd728e130..ff328cfc8 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -368,7 +368,7 @@ function start_service() {
die "Cannot start service on non-localhost ($HOST)"
fi
- echo $WORKDIR
+ echo "rootdir: "$WORKDIR
# Some tests use shortnames; force registry override to work around
# docker.io throttling.
# FIXME esm revisit pulling expected images re: shortnames caused tests to fail
@@ -376,7 +376,7 @@ function start_service() {
$PODMAN_BIN \
--root $WORKDIR/server_root --syslog=true \
system service \
- --time 15 \
+ --time 0 \
tcp:127.0.0.1:$PORT \
&> $WORKDIR/server.log &
service_pid=$!
@@ -443,7 +443,7 @@ function start_registry() {
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
${REGISTRY_IMAGE}
- wait_for_port localhost $REGISTRY_PORT
+ wait_for_port localhost $REGISTRY_PORT 10
}
function stop_registry() {
@@ -492,13 +492,16 @@ function wait_for_port() {
local port=$2 # Numeric port
local _timeout=${3:-5} # Optional; default to 5 seconds
+ local path=/dev/tcp/$host/$port
+
# Wait
- while [ $_timeout -gt 0 ]; do
+ local i=$_timeout
+ while [ $i -gt 0 ]; do
{ exec 3<> /dev/tcp/$host/$port; } &>/dev/null && return
sleep 1
- _timeout=$(( $_timeout - 1 ))
+ i=$(( $i - 1 ))
done
- die "Timed out waiting for service"
+ die "Timed out (${_timeout}s) waiting for service ($path)"
}
############
@@ -543,6 +546,9 @@ done
###############################################################################
# BEGIN entry handler (subtest invoker)
+echo '============================= test session starts =============================='
+echo "podman client -- $(curl --version)"
+
# Identify the tests to run. If called with args, use those as globs.
tests_to_run=()
if [ -n "$*" ]; then
@@ -558,6 +564,7 @@ if [ -n "$*" ]; then
else
tests_to_run=($TESTS_DIR/*.at)
fi
+echo -e "collected ${#tests_to_run[@]} items\n"
start_service
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index bfed01854..09cd68042 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -562,6 +562,11 @@ var _ = Describe("Verify podman containers.conf usage", func() {
inspect = podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()})
inspect.WaitWithDefaultTimeout()
Expect(inspect.OutputToString()).To(Equal("disabled"))
+
+ // Check we can also create a pod when cgroups=disabled
+ result = podmanTest.Podman([]string{"pod", "create"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
})
It("podman containers.conf runtime", func() {
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 9b1e0c74b..6a4083565 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -1888,6 +1888,26 @@ var _ = Describe("Podman play kube", func() {
Expect(kube).Should(Exit(0))
})
+ It("podman play kube test duplicate container name", func() {
+ p := getPod(withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "hello"}))), withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "world"}))))
+
+ err := generateKubeYaml("pod", p, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).To(ExitWithError())
+
+ p = getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("initctr"))), withCtr(getCtr(withImage(ALPINE), withName("initctr"), withCmd([]string{"top"}))))
+
+ err = generateKubeYaml("pod", p, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube = podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).To(ExitWithError())
+ })
+
It("podman play kube test hostname", func() {
pod := getPod()
err := generateKubeYaml("pod", pod, kubeYaml)
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/troubleshooting.md b/troubleshooting.md
index 8bce8e50f..93f716e00 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -42,7 +42,7 @@ $ podman run -v ~/mycontent:/content:Z fedora touch /content/file
Make sure the content is private for the container. Do not relabel system directories and content.
Relabeling system content might cause other confined services on your machine to fail. For these
-types of containers we recommend that disable SELinux separation. The option `--security-opt label=disable`
+types of containers we recommend having SELinux separation disabled. The option `--security-opt label=disable`
will disable SELinux separation for the container.
$ podman run --security-opt label=disable -v ~:/home/user fedora touch /home/user/file
@@ -157,7 +157,7 @@ When rootless Podman attempts to execute a container on a non exec home director
#### Symptom
If you are running Podman or Buildah on a home directory that is mounted noexec,
-then they will fail. With a message like:
+then they will fail with a message like:
```
podman run centos:7
@@ -166,7 +166,7 @@ standard_init_linux.go:203: exec user process caused "permission denied"
#### Solution
-Since the administrator of the system setup your home directory to be noexec, you will not be allowed to execute containers from storage in your home directory. It is possible to work around this by manually specifying a container storage path that is not on a noexec mount. Simply copy the file /etc/containers/storage.conf to ~/.config/containers/ (creating the directory if necessary). Specify a graphroot directory which is not on a noexec mount point and to which you have read/write privileges. You will need to modify other fields to writable directories as well.
+Since the administrator of the system set up your home directory to be noexec, you will not be allowed to execute containers from storage in your home directory. It is possible to work around this by manually specifying a container storage path that is not on a noexec mount. Simply copy the file /etc/containers/storage.conf to ~/.config/containers/ (creating the directory if necessary). Specify a graphroot directory which is not on a noexec mount point and to which you have read/write privileges. You will need to modify other fields to writable directories as well.
For example
@@ -229,7 +229,7 @@ Rootless Podman requires the user running it to have a range of UIDs listed in /
#### Symptom
-An user, either via --user or through the default configured for the image, is not mapped inside the namespace.
+A user, either via --user or through the default configured for the image, is not mapped inside the namespace.
```
podman run --rm -ti --user 1000000 alpine echo hi
@@ -279,7 +279,7 @@ grep johndoe /etc/subuid /etc/subgid
### 11) Changing the location of the Graphroot leads to permission denied
When I change the graphroot storage location in storage.conf, the next time I
-run Podman I get an error like:
+run Podman, I get an error like:
```
# podman run -p 5000:5000 -it centos bash
@@ -323,7 +323,7 @@ Pulling an anonymous image that doesn't require authentication can result in an
#### Symptom
If you pull an anonymous image, one that should not require credentials, you can receive
-and `invalid username/password` error if you have credentials established in the
+an `invalid username/password` error if you have credentials established in the
authentication file for the target container registry that are no longer valid.
```
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