summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/completion.go6
-rw-r--r--cmd/podman/images/push.go4
-rw-r--r--docs/source/markdown/podman-push.1.md4
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/container_top_linux.go18
-rw-r--r--pkg/domain/entities/images.go2
-rw-r--r--pkg/domain/infra/abi/images.go9
-rw-r--r--pkg/specgen/generate/oci.go8
-rw-r--r--pkg/specgenutil/specgen.go17
-rw-r--r--test/e2e/push_test.go32
-rw-r--r--test/e2e/top_test.go5
-rw-r--r--test/system/180-blkio.bats69
12 files changed, 170 insertions, 9 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 4cb29383a..cb3efe592 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -1289,3 +1289,9 @@ func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toCom
types := []string{"gzip", "none", "zstd"}
return types, cobra.ShellCompDirectiveNoFileComp
}
+
+// AutocompleteCompressionFormat - Autocomplete compression-format type options.
+func AutocompleteCompressionFormat(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ types := []string{"gzip", "zstd", "zstd:chunked"}
+ return types, cobra.ShellCompDirectiveNoFileComp
+}
diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go
index cf787a71f..37ace3ffe 100644
--- a/cmd/podman/images/push.go
+++ b/cmd/podman/images/push.go
@@ -108,6 +108,10 @@ func pushFlags(cmd *cobra.Command) {
flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ compressionFormat := "compression-format"
+ flags.StringVar(&pushOptions.CompressionFormat, compressionFormat, "", "compression format to use")
+ _ = cmd.RegisterFlagCompletionFunc(compressionFormat, common.AutocompleteCompressionFormat)
+
if registry.IsRemote() {
_ = flags.MarkHidden("cert-dir")
_ = flags.MarkHidden("compress")
diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md
index 55f294158..19c64a7e3 100644
--- a/docs/source/markdown/podman-push.1.md
+++ b/docs/source/markdown/podman-push.1.md
@@ -71,6 +71,10 @@ Please refer to containers-certs.d(5) for details. (This option is not available
Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source)
Note: This flag can only be set when using the **dir** transport
+#### **--compression-format** *COMPRESSION*
+
+Specifies the compression format to use. Supported values are: `gzip`, `zstd` and `zstd:chunked`. The default is `gzip`.
+
#### **--digestfile** *Digestfile*
After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client)
diff --git a/libpod/container.go b/libpod/container.go
index 482af43f3..2b74a1943 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -939,6 +939,11 @@ func (c *Container) cGroupPath() (string, error) {
procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID)
lines, err := ioutil.ReadFile(procPath)
if err != nil {
+ // If the file doesn't exist, it means the container could have been terminated
+ // so report it.
+ if os.IsNotExist(err) {
+ return "", errors.Wrapf(define.ErrCtrStopped, "cannot get cgroup path unless container %s is running", c.ID())
+ }
return "", err
}
diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go
index 0d4cba85e..d4f4ddfc1 100644
--- a/libpod/container_top_linux.go
+++ b/libpod/container_top_linux.go
@@ -4,6 +4,7 @@ package libpod
import (
"bufio"
+ "fmt"
"os"
"strconv"
"strings"
@@ -11,6 +12,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/psgo"
+ "github.com/google/shlex"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -51,7 +53,21 @@ func (c *Container) Top(descriptors []string) ([]string, error) {
return nil, psgoErr
}
- output, err = c.execPS(descriptors)
+ // Note that the descriptors to ps(1) must be shlexed (see #12452).
+ psDescriptors := []string{}
+ for _, d := range descriptors {
+ shSplit, err := shlex.Split(d)
+ if err != nil {
+ return nil, fmt.Errorf("parsing ps args: %v", err)
+ }
+ for _, s := range shSplit {
+ if s != "" {
+ psDescriptors = append(psDescriptors, s)
+ }
+ }
+ }
+
+ output, err = c.execPS(psDescriptors)
if err != nil {
return nil, errors.Wrapf(err, "error executing ps(1) in the container")
}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 54f7b5d45..8b0fd2b85 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -208,6 +208,8 @@ type ImagePushOptions struct {
SkipTLSVerify types.OptionalBool
// Progress to get progress notifications
Progress chan types.ProgressProperties
+ // CompressionFormat is the format to use for the compression of the blobs
+ CompressionFormat string
}
// ImageSearchOptions are the arguments for searching images.
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 8b44b869a..7a3451a7d 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -18,6 +18,7 @@ import (
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/signature"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
@@ -305,6 +306,14 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.SignBy = options.SignBy
pushOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+ if options.CompressionFormat != "" {
+ algo, err := compression.AlgorithmByName(options.CompressionFormat)
+ if err != nil {
+ return err
+ }
+ pushOptions.CompressionFormat = &algo
+ }
+
if !options.Quiet {
pushOptions.Writer = os.Stderr
}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 1b022b912..df5788099 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -329,6 +329,14 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
}
+ for k, v := range s.WeightDevice {
+ statT := unix.Stat_t{}
+ if err := unix.Stat(k, &statT); err != nil {
+ return nil, errors.Wrapf(err, "failed to inspect '%s' in --blkio-weight-device", k)
+ }
+ g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight)
+ }
+
BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
g.ClearProcessEnv()
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index 7a572e730..637a6a8dd 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -85,7 +85,7 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (
}
if len(c.BlkIOWeightDevice) > 0 {
- if err := parseWeightDevices(s, c.BlkIOWeightDevice); err != nil {
+ if s.WeightDevice, err = parseWeightDevices(c.BlkIOWeightDevice); err != nil {
return nil, err
}
hasLimits = true
@@ -791,29 +791,30 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start
return &hc, nil
}
-func parseWeightDevices(s *specgen.SpecGenerator, weightDevs []string) error {
+func parseWeightDevices(weightDevs []string) (map[string]specs.LinuxWeightDevice, error) {
+ wd := make(map[string]specs.LinuxWeightDevice)
for _, val := range weightDevs {
split := strings.SplitN(val, ":", 2)
if len(split) != 2 {
- return fmt.Errorf("bad format: %s", val)
+ return nil, fmt.Errorf("bad format: %s", val)
}
if !strings.HasPrefix(split[0], "/dev/") {
- return fmt.Errorf("bad format for device path: %s", val)
+ return nil, fmt.Errorf("bad format for device path: %s", val)
}
weight, err := strconv.ParseUint(split[1], 10, 0)
if err != nil {
- return fmt.Errorf("invalid weight for device: %s", val)
+ return nil, fmt.Errorf("invalid weight for device: %s", val)
}
if weight > 0 && (weight < 10 || weight > 1000) {
- return fmt.Errorf("invalid weight for device: %s", val)
+ return nil, fmt.Errorf("invalid weight for device: %s", val)
}
w := uint16(weight)
- s.WeightDevice[split[0]] = specs.LinuxWeightDevice{
+ wd[split[0]] = specs.LinuxWeightDevice{
Weight: &w,
LeafWeight: nil,
}
}
- return nil
+ return wd, nil
}
func parseThrottleBPSDevices(bpsDevices []string) (map[string]specs.LinuxThrottleDevice, error) {
diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go
index 7038a09e8..a3b5e31bb 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -2,12 +2,14 @@ package integration
import (
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/containers/podman/v3/pkg/rootless"
. "github.com/containers/podman/v3/test/utils"
+ "github.com/containers/storage/pkg/archive"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@@ -63,6 +65,36 @@ var _ = Describe("Podman push", func() {
Expect(session).Should(Exit(0))
})
+ It("podman push to oci with compression-format", func() {
+ SkipIfRemote("Remote push does not support dir transport")
+ bbdir := filepath.Join(podmanTest.TempDir, "busybox-oci")
+ session := podmanTest.Podman([]string{"push", "--compression-format=zstd", "--remove-signatures", ALPINE,
+ fmt.Sprintf("oci:%s", bbdir)})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ foundZstdFile := false
+
+ blobsDir := filepath.Join(bbdir, "blobs/sha256")
+
+ blobs, err := ioutil.ReadDir(blobsDir)
+ Expect(err).To(BeNil())
+
+ for _, f := range blobs {
+ blobPath := filepath.Join(blobsDir, f.Name())
+
+ sourceFile, err := ioutil.ReadFile(blobPath)
+ Expect(err).To(BeNil())
+
+ compressionType := archive.DetectCompression(sourceFile)
+ if compressionType == archive.Zstd {
+ foundZstdFile = true
+ break
+ }
+ }
+ Expect(foundZstdFile).To(BeTrue())
+ })
+
It("podman push to local registry", func() {
SkipIfRemote("Remote does not support --digestfile or --remove-signatures")
if podmanTest.Host.Arch == "ppc64le" {
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index 93c4f3f12..1a71ebf33 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -101,6 +101,11 @@ var _ = Describe("Podman top", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
+
+ result = podmanTest.Podman([]string{"top", session.OutputToString(), "ax -o args"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.OutputToStringArray()).To(Equal([]string{"COMMAND", "top -d 2"}))
})
It("podman top with comma-separated options", func() {
diff --git a/test/system/180-blkio.bats b/test/system/180-blkio.bats
new file mode 100644
index 000000000..68449681a
--- /dev/null
+++ b/test/system/180-blkio.bats
@@ -0,0 +1,69 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# podman blkio-related tests
+#
+
+load helpers
+
+function teardown() {
+ lofile=${PODMAN_TMPDIR}/disk.img
+ if [ -f ${lofile} ]; then
+ run_podman '?' rm -t 0 --all --force
+
+ while read path dev; do
+ if [[ "$path" == "$lofile" ]]; then
+ losetup -d $dev
+ fi
+ done < <(losetup -l --noheadings --output BACK-FILE,NAME)
+
+ rm ${lofile}
+ fi
+ basic_teardown
+}
+
+@test "podman run --blkio-weight-device" {
+
+ skip_if_rootless "cannot create devices in rootless mode"
+
+ # create loopback device
+ lofile=${PODMAN_TMPDIR}/disk.img
+ fallocate -l 1k ${lofile}
+ losetup -f ${lofile}
+
+ run losetup -l --noheadings --output BACK-FILE,NAME,MAJ:MIN
+ is "$output" ".\+" "Empty output from losetup"
+
+ lodevice=$(awk "\$1 == \"$lofile\" { print \$2 }" <<<"$output")
+ lomajmin=$(awk "\$1 == \"$lofile\" { print \$3 }" <<<"$output")
+
+ is "$lodevice" ".\+" "Could not determine device for $lofile"
+ is "$lomajmin" ".\+" "Could not determine major/minor for $lofile"
+
+ # use bfq io scheduler
+ run grep -w bfq /sys/block/$(basename ${lodevice})/queue/scheduler
+ if [ $status -ne 0 ]; then
+ skip "BFQ scheduler is not supported on the system"
+ fi
+ echo bfq > /sys/block/$(basename ${lodevice})/queue/scheduler
+
+ # run podman
+ if is_cgroupsv2; then
+ if [ ! -f /sys/fs/cgroup/system.slice/io.bfq.weight ]; then
+ skip "Kernel does not support BFQ IO scheduler"
+ fi
+ run_podman run --device ${lodevice}:${lodevice} --blkio-weight-device ${lodevice}:123 --rm $IMAGE \
+ /bin/sh -c "cat /sys/fs/cgroup/\$(sed -e 's/0:://' < /proc/self/cgroup)/io.bfq.weight"
+ is "${lines[1]}" "${lomajmin}\s\+123"
+ else
+ if [ ! -f /sys/fs/cgroup/blkio/system.slice/blkio.bfq.weight_device ]; then
+ skip "Kernel does not support BFQ IO scheduler"
+ fi
+ if [ $(podman_runtime) = "crun" ]; then
+ # As of crun 1.2, crun doesn't support blkio.bfq.weight_device
+ skip "crun doesn't support blkio.bfq.weight_device"
+ fi
+ run_podman run --device ${lodevice}:${lodevice} --blkio-weight-device ${lodevice}:123 --rm $IMAGE \
+ /bin/sh -c "cat /sys/fs/cgroup/blkio/blkio.bfq.weight_device"
+ is "${lines[1]}" "${lomajmin}\s\+123"
+ fi
+}