summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE_NOTES.md6
-rw-r--r--changelog.txt92
-rw-r--r--cmd/podman/common/completion.go6
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--libpod/container_inspect.go4
-rw-r--r--libpod/container_internal.go75
-rw-r--r--libpod/container_internal_linux.go17
-rw-r--r--libpod/define/container_inspect.go4
-rw-r--r--libpod/volume.go11
-rw-r--r--pkg/domain/infra/abi/images.go17
-rw-r--r--test/e2e/inspect_test.go24
-rw-r--r--test/e2e/rmi_test.go30
-rw-r--r--test/e2e/run_volume_test.go18
-rw-r--r--version/version.go2
14 files changed, 255 insertions, 53 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index b4823e1d2..17d90aeca 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -112,6 +112,10 @@
- Fixed a bug where failures during the resizing of a container's TTY would print the wrong error.
- Fixed a bug where the `podman network disconnect` command could cause the `podman inspect` command to fail for a container until it was restarted ([#9234](https://github.com/containers/podman/issues/9234)).
- Fixed a bug where containers created from a read-only rootfs (using the `--rootfs` option to `podman create` and `podman run`) would fail ([#9230](https://github.com/containers/podman/issues/9230)).
+- Fixed a bug where specifying Go templates to the `--format` option to multiple Podman commands did not support the `join` function ([#8773](https://github.com/containers/podman/issues/8773)).
+- Fixed a bug where the `podman rmi` command could, when run in parallel on multiple images, return `layer not known` errors ([#6510](https://github.com/containers/podman/issues/6510)).
+- Fixed a bug where the `podman inspect` command on containers displayed unlimited ulimits incorrectly ([#9303](https://github.com/containers/podman/issues/9303)).
+- Fixed a bug where Podman would fail to start when a volume was mounted over a directory in a container that contained symlinks that terminated outside the directory and its subdirectories ([#6003](https://github.com/containers/podman/issues/6003)).
### API
- Libpod API version has been bumped to v3.0.0.
@@ -134,10 +138,12 @@
- Fixed a bug where the Compat Load API for Images did not properly clean up temporary files.
- Fixed a bug where the Compat Create API for Networks could panic when an empty IPAM configuration was specified.
- Fixed a bug where the Compat Inspect and List APIs for Networks did not include Scope.
+- Fixed a bug where the Compat Wait endpoint for Containers did not support the same wait conditions that Docker did.
### Misc
- Updated Buildah to v1.19.2
- Updated the containers/storage library to v1.24.5
+- Updated the containers/image library to v5.10.2
- Updated the containers/common library to v0.33.4
## v2.2.1
diff --git a/changelog.txt b/changelog.txt
index 71af154a6..7b5fb1848 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,95 @@
+- Changelog for v3.0.0 (2021-02-11):
+ * Update release notes for v3.0 final
+ * Rewrite copy-up to use buildah Copier
+ * Display correct value for unlimited ulimit
+ * make `podman rmi` more robust
+ * Allow path completion for podman create/run --rootfs
+ * vendor github.com/containers/image v5.10.2
+ * Add default template functions
+ * Fix per review request
+ * Increase timeouts in some tests
+ * Add test for Docker APIv2 wait
+ * Implement Docker wait conditions
+ * Improve ContainerEngine.ContainerWait()
+ * Improve container libpod.Wait*() functions
+ * [NO TESTS NEEDED] style: indendation
+ * [NO TESTS NEEDED] fixup: remove debug code
+ * [NO TESTS NEEDED] Generated files
+ * Cleanup bindings for image pull
+ * [NO TESTS NEEDED] Improve generator
+ * Fix invalid wait condition on kill
+ * Switch podman image push handlers to use abi
+ * podman-remote ps --external --pod --sort do not work.
+ * Fix --arch and --os flags to work correctly
+ * Switch podman stop/kill/wait handlers to use abi
+ * Fix handling of container remove
+ * Bump to v3.0.0-dev
+ * Bump to v3.0.0-RC3
+ * Further release notes for v3.0
+ * Bump remote API version to 3.0.0
+ * fix logic when not creating a workdir
+ * play kube selinux test case
+ * play kube selinux test case
+ * play kube selinux label test case
+ * play kube selinux label issue
+ * Fix podman network disconnect wrong NetworkStatus number
+ * Bump to v0.33.4
+ * Bump github.com/containernetworking/cni from 0.8.0 to 0.8.1
+ * Update release notes for v3.0.0-RC3
+ * generate kube: handle entrypoint
+ * Allow pods to use --net=none
+ * Report StatusConflict on Pod opt partial failures
+ * bindings: attach: warn correct error
+ * Make slirp MTU configurable (network_cmd_options)
+ * Fix podman generate systemd --new special char handling
+ * Fix --network parsing for podman pod create
+ * Endpoint that lists containers does not return correct Status value
+ * Docker ignores mount flags that begin with constency
+ * podman generate kube ignores --network=host
+ * Honor custom DNS in play|generate kube
+ * Don't fail if one of the cgroups is not setup
+ * Fix #9100 Change console mode message to debug
+ * Update release notes from master
+ * libpod: move slirp magic IPs to consts
+ * rootlessport: set source IP to slirp4netns device
+ * Bump rootless-containers/rootlesskit to v0.12.0
+ * Gating tests: diff test: workaround for RHEL8 failure
+ * Bump to containers/common v0.33.3
+ * add macvlan as a supported network driver
+ * podman build --pull: refine help message and docs
+ * Cirrus: Build static podman-remote
+ * Fix static build cache by using cachix
+ * Cirrus: Fix running Validate task on branches
+ * Bump to v3.0.0-dev
+ * Bump to v3.0.0-RC2
+ * Cirrus: add bindings checks
+ * make bindings generation explicit
+ * make bindings generation more robuts
+ * simplify bindings generation
+ * make: generate bindings: use vendor
+ * Make generate systemd --new robust against double curly braces
+ * Ensure shutdown handler access is syncronized
+ * workdir presence checks
+ * libpod: add (*Container).ResolvePath()
+ * Add default net info in container inspect
+ * Fix podman history --no-trunc for the CREATED BY field
+ * Ensure the Volumes field in Compat Create is honored
+ * remote exec: write conmon error on hijacked connection
+ * Add support for rootless network-aliases
+ * Allow static ip and mac with rootless cni network
+ * [CI:DOCS]Correct static API html path
+ * disable dnsname when --internal
+ * Use random network names in the e2e tests
+ * [v3.0] fix RHEL gating test: the /sys thing
+ * Bump golang.org/x/crypto v3.0
+ * Set log driver for compatability containers
+ * [CI:DOCS] Cirrus: Skip smoke task on branch-push
+ * [CI:DOCS]Do not run compose tests with CI:DOCS
+ * Add binding options for container|pod exists
+ * runner.sh : deal with bash 'set -e'
+ * [CI:DOCS]Add readthedoc link for 3.0 docs
+ * [CI:DOCS]Add static HTML for api docs for v3.0
+
- Changelog for v3.0.0-rc1 (2021-01-17):
* Create release notes for V3.0.0
* Rename AutocompletePortCommand func
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 09dd74e20..92163efde 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -426,6 +426,12 @@ func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string)
return nil, cobra.ShellCompDirectiveNoFileComp
}
if len(args) < 1 {
+ // check if the rootfs flag is set
+ // if it is set to true provide directory completion
+ rootfs, err := cmd.Flags().GetBool("rootfs")
+ if err == nil && rootfs {
+ return nil, cobra.ShellCompDirectiveFilterDirs
+ }
return getImages(cmd, toComplete)
}
// TODO: add path completion for files in the image
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index db79ebede..fce2afbeb 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -42,7 +42,7 @@ Epoch: 99
%else
Epoch: 0
%endif
-Version: 3.0.0
+Version: 3.0.1
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index ac7eae56b..cc8b75472 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -864,8 +864,8 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
for _, limit := range ctrSpec.Process.Rlimits {
newLimit := define.InspectUlimit{}
newLimit.Name = limit.Type
- newLimit.Soft = limit.Soft
- newLimit.Hard = limit.Hard
+ newLimit.Soft = int64(limit.Soft)
+ newLimit.Hard = int64(limit.Hard)
hostConfig.Ulimits = append(hostConfig.Ulimits, newLimit)
}
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 5a61f7fe6..15958471f 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -13,6 +13,7 @@ import (
"strings"
"time"
+ "github.com/containers/buildah/copier"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/pkg/cgroups"
@@ -1580,18 +1581,8 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
return nil, err
}
- // HACK HACK HACK - copy up into a volume driver is 100% broken
- // right now.
- if vol.UsesVolumeDriver() {
- logrus.Infof("Not copying up into volume %s as it uses a volume driver", vol.Name())
- return vol, nil
- }
-
// If the volume is not empty, we should not copy up.
- volMount, err := vol.MountPoint()
- if err != nil {
- return nil, err
- }
+ volMount := vol.mountPoint()
contents, err := ioutil.ReadDir(volMount)
if err != nil {
return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID())
@@ -1607,8 +1598,55 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
if err != nil {
return nil, errors.Wrapf(err, "error calculating destination path to copy up container %s volume %s", c.ID(), vol.Name())
}
- if err := c.copyWithTarFromImage(srcDir, volMount); err != nil && !os.IsNotExist(err) {
- return nil, errors.Wrapf(err, "error copying content from container %s into volume %s", c.ID(), vol.Name())
+ // Do a manual stat on the source directory to verify existence.
+ // Skip the rest if it exists.
+ // TODO: Should this be stat or lstat? I'm using lstat because I
+ // think copy-up doesn't happen when the source is a link.
+ srcStat, err := os.Lstat(srcDir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // Source does not exist, don't bother copying
+ // up.
+ return vol, nil
+ }
+ return nil, errors.Wrapf(err, "error identifying source directory for copy up into volume %s", vol.Name())
+ }
+ // If it's not a directory we're mounting over it.
+ if !srcStat.IsDir() {
+ return vol, nil
+ }
+
+ // Buildah Copier accepts a reader, so we'll need a pipe.
+ reader, writer := io.Pipe()
+ defer reader.Close()
+
+ errChan := make(chan error, 1)
+
+ logrus.Infof("About to copy up into volume %s", vol.Name())
+
+ // Copy, container side: get a tar archive of what needs to be
+ // streamed into the volume.
+ go func() {
+ defer writer.Close()
+ getOptions := copier.GetOptions{
+ KeepDirectoryNames: false,
+ }
+ errChan <- copier.Get(mountpoint, "", getOptions, []string{v.Dest + "/."}, writer)
+ }()
+
+ // Copy, volume side: stream what we've written to the pipe, into
+ // the volume.
+ copyOpts := copier.PutOptions{}
+ if err := copier.Put(volMount, "", copyOpts, reader); err != nil {
+ err2 := <-errChan
+ if err2 != nil {
+ logrus.Errorf("Error streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2)
+ }
+ return nil, errors.Wrapf(err, "error copying up to volume %s", vol.Name())
+ }
+
+ if err := <-errChan; err != nil {
+ return nil, errors.Wrapf(err, "error streaming container content for copy up into volume %s", vol.Name())
}
}
return vol, nil
@@ -2058,17 +2096,6 @@ func (c *Container) unmount(force bool) error {
return nil
}
-// this should be from chrootarchive.
-// Container MUST be mounted before calling.
-func (c *Container) copyWithTarFromImage(source, dest string) error {
- mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap)
- a := archive.NewArchiver(mappings)
- if err := c.copyOwnerAndPerms(source, dest); err != nil {
- return err
- }
- return a.CopyWithTar(source, dest)
-}
-
// checkReadyForRemoval checks whether the given container is ready to be
// removed.
// These checks are only used if force-remove is not specified.
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index ba85a1f47..952cc42d1 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -2261,23 +2261,6 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) {
return passwdPath, groupPath, nil
}
-func (c *Container) copyOwnerAndPerms(source, dest string) error {
- info, err := os.Stat(source)
- if err != nil {
- if os.IsNotExist(err) {
- return nil
- }
- return err
- }
- if err := os.Chmod(dest, info.Mode()); err != nil {
- return err
- }
- if err := os.Chown(dest, int(info.Sys().(*syscall.Stat_t).Uid), int(info.Sys().(*syscall.Stat_t).Gid)); err != nil {
- return err
- }
- return nil
-}
-
// Get cgroup path in a format suitable for the OCI spec
func (c *Container) getOCICgroupPath() (string, error) {
unified, err := cgroups.IsCgroup2UnifiedMode()
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index 9a93e2ffd..7d4b8a46f 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -120,9 +120,9 @@ type InspectUlimit struct {
// Name is the name (type) of the ulimit.
Name string `json:"Name"`
// Soft is the soft limit that will be applied.
- Soft uint64 `json:"Soft"`
+ Soft int64 `json:"Soft"`
// Hard is the hard limit that will be applied.
- Hard uint64 `json:"Hard"`
+ Hard int64 `json:"Hard"`
}
// InspectDevice is a single device that will be mounted into the container.
diff --git a/libpod/volume.go b/libpod/volume.go
index 4c137cb8e..5cc5e7e40 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -130,11 +130,18 @@ func (v *Volume) MountPoint() (string, error) {
if err := v.update(); err != nil {
return "", err
}
+ }
+
+ return v.mountPoint(), nil
+}
- return v.state.MountPoint, nil
+// Internal-only helper for volume mountpoint
+func (v *Volume) mountPoint() string {
+ if v.UsesVolumeDriver() {
+ return v.state.MountPoint
}
- return v.config.MountPoint, nil
+ return v.config.MountPoint
}
// Options return the volume's options
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 8ca93e770..f2d0f2c39 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -580,12 +580,21 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie
// without having to pass all local data around.
deleteImage := func(img *image.Image) error {
results, err := ir.Libpod.RemoveImage(ctx, img, opts.Force)
- if err != nil {
+ switch errors.Cause(err) {
+ case nil:
+ // Removal worked, so let's report it.
+ report.Deleted = append(report.Deleted, results.Deleted)
+ report.Untagged = append(report.Untagged, results.Untagged...)
+ return nil
+ case storage.ErrImageUnknown:
+ // The image must have been removed already (see #6510).
+ report.Deleted = append(report.Deleted, img.ID())
+ report.Untagged = append(report.Untagged, img.ID())
+ return nil
+ default:
+ // Fatal error.
return err
}
- report.Deleted = append(report.Deleted, results.Deleted)
- report.Untagged = append(report.Untagged, results.Untagged...)
- return nil
}
// Delete all images from the local storage.
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index 8fc9721f9..12bc886a8 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -466,4 +466,28 @@ var _ = Describe("Podman inspect", func() {
Expect(len(inspect)).To(Equal(1))
Expect(len(inspect[0].NetworkSettings.Networks)).To(Equal(1))
})
+
+ It("Container inspect with unlimited uilimits should be -1", func() {
+ ctrName := "testctr"
+ session := podmanTest.Podman([]string{"run", "-d", "--ulimit", "core=-1:-1", "--name", ctrName, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+
+ inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(BeZero())
+
+ data := inspect.InspectContainerToJSON()
+ ulimits := data[0].HostConfig.Ulimits
+ Expect(len(ulimits)).To(BeNumerically(">", 0))
+ found := false
+ for _, ulimit := range ulimits {
+ if ulimit.Name == "RLIMIT_CORE" {
+ found = true
+ Expect(ulimit.Soft).To(BeNumerically("==", -1))
+ Expect(ulimit.Hard).To(BeNumerically("==", -1))
+ }
+ }
+ Expect(found).To(BeTrue())
+ })
})
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 1f40e4928..c1fbe0440 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -1,7 +1,9 @@
package integration
import (
+ "fmt"
"os"
+ "sync"
. "github.com/containers/podman/v2/test/utils"
. "github.com/onsi/ginkgo"
@@ -276,4 +278,32 @@ RUN find $LOCAL
match, _ := session.ErrorGrepString("image name or ID must be specified")
Expect(match).To(BeTrue())
})
+
+ It("podman image rm - concurrent with shared layers", func() {
+ // #6510 has shown a fairly simple reproducer to force storage
+ // errors during parallel image removal. Since it's subject to
+ // a race, we may not hit the condition a 100 percent of times
+ // but ocal reproducers hit it all the time.
+
+ var wg sync.WaitGroup
+
+ buildAndRemove := func(i int) {
+ defer GinkgoRecover()
+ defer wg.Done()
+ imageName := fmt.Sprintf("rmtest:%d", i)
+ containerfile := `FROM quay.io/libpod/cirros:latest
+RUN ` + fmt.Sprintf("touch %s", imageName)
+
+ podmanTest.BuildImage(containerfile, imageName, "false")
+ session := podmanTest.Podman([]string{"rmi", "-f", imageName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ }
+
+ wg.Add(10)
+ for i := 0; i < 10; i++ {
+ go buildAndRemove(i)
+ }
+ wg.Wait()
+ })
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index bc89b59de..19d82c974 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -304,6 +304,24 @@ var _ = Describe("Podman run with volumes", func() {
Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
})
+ It("podman named volume copyup symlink", func() {
+ imgName := "testimg"
+ dockerfile := `FROM alpine
+RUN touch /testfile
+RUN sh -c "cd /etc/apk && ln -s ../../testfile"`
+ podmanTest.BuildImage(dockerfile, imgName, "false")
+
+ baselineSession := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", imgName, "ls", "/etc/apk/"})
+ baselineSession.WaitWithDefaultTimeout()
+ Expect(baselineSession.ExitCode()).To(Equal(0))
+ baselineOutput := baselineSession.OutputToString()
+
+ outputSession := podmanTest.Podman([]string{"run", "-t", "-i", "-v", "/etc/apk/", imgName, "ls", "/etc/apk/"})
+ outputSession.WaitWithDefaultTimeout()
+ Expect(outputSession.ExitCode()).To(Equal(0))
+ Expect(outputSession.OutputToString()).To(Equal(baselineOutput))
+ })
+
It("podman read-only tmpfs conflict with volume", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "-v", "tmp_volume:" + dest, ALPINE, "touch", dest + "/a"})
session.WaitWithDefaultTimeout()
diff --git a/version/version.go b/version/version.go
index 0bba0147b..8785dd9fd 100644
--- a/version/version.go
+++ b/version/version.go
@@ -8,7 +8,7 @@ import (
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-var Version = semver.MustParse("3.0.0-dev")
+var Version = semver.MustParse("3.0.1-dev")
// APIVersion is the version for the remote
// client API. It is used to determine compatibility