summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.packit.yaml18
-rw-r--r--cmd/podman/images/pull.go5
-rw-r--r--cmd/podman/images/push.go4
-rw-r--r--cmd/podman/manifest/push.go5
-rw-r--r--docs/source/markdown/.gitignore1
-rw-r--r--docs/source/markdown/options/ignore.md5
-rw-r--r--docs/source/markdown/options/workdir.md7
-rw-r--r--docs/source/markdown/podman-create.1.md.in8
-rw-r--r--docs/source/markdown/podman-exec.1.md.in (renamed from docs/source/markdown/podman-exec.1.md)8
-rw-r--r--docs/source/markdown/podman-pod-rm.1.md.in6
-rw-r--r--docs/source/markdown/podman-pod-stop.1.md.in6
-rw-r--r--docs/source/markdown/podman-rm.1.md.in6
-rw-r--r--docs/source/markdown/podman-run.1.md.in8
-rw-r--r--docs/source/markdown/podman-stop.1.md.in6
-rw-r--r--libpod/info.go182
-rw-r--r--libpod/info_freebsd.go40
-rw-r--r--libpod/info_linux.go132
-rw-r--r--libpod/info_unsupported.go4
-rw-r--r--pkg/api/handlers/compat/auth.go3
-rw-r--r--pkg/api/handlers/compat/images_build.go2
-rw-r--r--pkg/api/handlers/libpod/containers_create.go5
-rw-r--r--pkg/api/handlers/libpod/images_pull.go31
-rw-r--r--pkg/api/handlers/libpod/images_push.go2
-rw-r--r--pkg/api/handlers/libpod/manifests.go4
-rw-r--r--pkg/api/handlers/types.go2
-rw-r--r--pkg/bindings/images/pull.go13
-rw-r--r--pkg/bindings/images/push.go9
-rw-r--r--pkg/bindings/images/types.go2
-rw-r--r--pkg/bindings/images/types_pull_options.go16
-rw-r--r--pkg/bindings/manifests/manifests.go6
-rw-r--r--pkg/bindings/test/images_test.go24
-rw-r--r--pkg/bindings/test/manifests_test.go23
-rw-r--r--pkg/domain/entities/images.go2
-rw-r--r--pkg/domain/infra/abi/images.go3
-rw-r--r--pkg/domain/infra/tunnel/images.go1
-rw-r--r--test/e2e/manifest_test.go27
-rw-r--r--test/e2e/pull_test.go14
-rw-r--r--test/e2e/run_memory_test.go18
38 files changed, 419 insertions, 239 deletions
diff --git a/.packit.yaml b/.packit.yaml
new file mode 100644
index 000000000..3d7b49297
--- /dev/null
+++ b/.packit.yaml
@@ -0,0 +1,18 @@
+# See the documentation for more information:
+# https://packit.dev/docs/configuration/
+
+upstream_package_name: podman
+downstream_package_name: podman
+
+actions:
+ post-upstream-clone:
+ - "curl -O https://src.fedoraproject.org/rpms/podman/raw/main/f/podman.spec"
+
+jobs:
+ - job: production_build
+ trigger: pull_request
+ targets: &production_dist_targets
+ - fedora-36
+ - fedora-37
+ - fedora-rawhide
+ scratch: true
diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go
index 8211ceba5..fe9d1e9b6 100644
--- a/cmd/podman/images/pull.go
+++ b/cmd/podman/images/pull.go
@@ -155,6 +155,11 @@ func imagePull(cmd *cobra.Command, args []string) error {
pullOptions.Username = creds.Username
pullOptions.Password = creds.Password
}
+
+ if !pullOptions.Quiet {
+ pullOptions.Writer = os.Stderr
+ }
+
// Let's do all the remaining Yoga in the API to prevent us from
// scattering logic across (too) many parts of the code.
var errs utils.OutputErrors
diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go
index 1734900de..fa60860db 100644
--- a/cmd/podman/images/push.go
+++ b/cmd/podman/images/push.go
@@ -164,6 +164,10 @@ func imagePush(cmd *cobra.Command, args []string) error {
pushOptions.Password = creds.Password
}
+ if !pushOptions.Quiet {
+ pushOptions.Writer = os.Stderr
+ }
+
if err := common.PrepareSigningPassphrase(&pushOptions.ImagePushOptions, pushOptions.SignPassphraseFileCLI); err != nil {
return err
}
diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go
index fd67769b8..c8893ff2e 100644
--- a/cmd/podman/manifest/push.go
+++ b/cmd/podman/manifest/push.go
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io/ioutil"
+ "os"
"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
@@ -122,6 +123,10 @@ func push(cmd *cobra.Command, args []string) error {
manifestPushOpts.Password = creds.Password
}
+ if !manifestPushOpts.Quiet {
+ manifestPushOpts.Writer = os.Stderr
+ }
+
if err := common.PrepareSigningPassphrase(&manifestPushOpts.ImagePushOptions, manifestPushOpts.SignPassphraseFileCLI); err != nil {
return err
}
diff --git a/docs/source/markdown/.gitignore b/docs/source/markdown/.gitignore
index 2bdcce197..85aed3be0 100644
--- a/docs/source/markdown/.gitignore
+++ b/docs/source/markdown/.gitignore
@@ -3,6 +3,7 @@ podman-build.1.md
podman-container-clone.1.md
podman-container-runlabel.1.md
podman-create.1.md
+podman-exec.1.md
podman-image-sign.1.md
podman-kill.1.md
podman-kube-play.1.md
diff --git a/docs/source/markdown/options/ignore.md b/docs/source/markdown/options/ignore.md
new file mode 100644
index 000000000..231d75957
--- /dev/null
+++ b/docs/source/markdown/options/ignore.md
@@ -0,0 +1,5 @@
+#### **--ignore**, **-i**
+
+Ignore errors when specified <<containers|pods>> are not in the container store. A user
+might have decided to manually remove a <<container|pod>> which would lead to a failure
+during the ExecStop directive of a systemd service referencing that <<container|pod>>.
diff --git a/docs/source/markdown/options/workdir.md b/docs/source/markdown/options/workdir.md
new file mode 100644
index 000000000..12f3ddd44
--- /dev/null
+++ b/docs/source/markdown/options/workdir.md
@@ -0,0 +1,7 @@
+#### **--workdir**, **-w**=*dir*
+
+Working directory inside the container.
+
+The default working directory for running binaries within a container is the root directory (**/**).
+The image developer can set a different default with the WORKDIR instruction. The operator
+can override the working directory by using the **-w** option.
diff --git a/docs/source/markdown/podman-create.1.md.in b/docs/source/markdown/podman-create.1.md.in
index 9518568bb..8710af110 100644
--- a/docs/source/markdown/podman-create.1.md.in
+++ b/docs/source/markdown/podman-create.1.md.in
@@ -975,13 +975,7 @@ If the location of the volume from the source container overlaps with
data residing on a target container, then the volume hides
that data on the target.
-#### **--workdir**, **-w**=*dir*
-
-Working directory inside the container
-
-The default working directory for running binaries within a container is the root directory (/).
-The image developer can set a different default with the WORKDIR instruction. The operator
-can override the working directory by using the **-w** option.
+@@option workdir
## EXAMPLES
diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md.in
index da61f3456..4f78f1c31 100644
--- a/docs/source/markdown/podman-exec.1.md
+++ b/docs/source/markdown/podman-exec.1.md.in
@@ -70,13 +70,7 @@ Sets the username or UID used and optionally the groupname or GID for the specif
The following examples are all valid:
--user [user | user:group | uid | uid:gid | user:gid | uid:group ]
-#### **--workdir**, **-w**=*path*
-
-Working directory inside the container
-
-The default working directory for running binaries within a container is the root directory (/).
-The image developer can set a different default with the WORKDIR instruction, which can be overridden
-when creating the container.
+@@option workdir
## Exit Status
diff --git a/docs/source/markdown/podman-pod-rm.1.md.in b/docs/source/markdown/podman-pod-rm.1.md.in
index 54646ebe3..82e28acb1 100644
--- a/docs/source/markdown/podman-pod-rm.1.md.in
+++ b/docs/source/markdown/podman-pod-rm.1.md.in
@@ -19,11 +19,7 @@ Remove all pods. Can be used in conjunction with \-f as well.
Stop running containers and delete all stopped containers before removal of pod.
-#### **--ignore**, **-i**
-
-Ignore errors when specified pods are not in the container store. A user might
-have decided to manually remove a pod which would lead to a failure during the
-ExecStop directive of a systemd service referencing that pod.
+@@option ignore
#### **--latest**, **-l**
diff --git a/docs/source/markdown/podman-pod-stop.1.md.in b/docs/source/markdown/podman-pod-stop.1.md.in
index 879645cd9..3655c3938 100644
--- a/docs/source/markdown/podman-pod-stop.1.md.in
+++ b/docs/source/markdown/podman-pod-stop.1.md.in
@@ -15,11 +15,7 @@ Stop containers in one or more pods. You may use pod IDs or names as input.
Stops all pods
-#### **--ignore**, **-i**
-
-Ignore errors when specified pods are not in the container store. A user might
-have decided to manually remove a pod which would lead to a failure during the
-ExecStop directive of a systemd service referencing that pod.
+@@option ignore
#### **--latest**, **-l**
diff --git a/docs/source/markdown/podman-rm.1.md.in b/docs/source/markdown/podman-rm.1.md.in
index fa3031b29..c0fa94d82 100644
--- a/docs/source/markdown/podman-rm.1.md.in
+++ b/docs/source/markdown/podman-rm.1.md.in
@@ -56,11 +56,7 @@ Containers could have been created by a different container engine.
In addition, forcing can be used to remove unusable containers, e.g. containers
whose OCI runtime has become unavailable.
-#### **--ignore**, **-i**
-
-Ignore errors when specified containers are not in the container store. A user
-might have decided to manually remove a container which would lead to a failure
-during the ExecStop directive of a systemd service referencing that container.
+@@option ignore
#### **--latest**, **-l**
diff --git a/docs/source/markdown/podman-run.1.md.in b/docs/source/markdown/podman-run.1.md.in
index 3e31ccc45..a0cd49d4e 100644
--- a/docs/source/markdown/podman-run.1.md.in
+++ b/docs/source/markdown/podman-run.1.md.in
@@ -1034,13 +1034,7 @@ If the location of the volume from the source container overlaps with
data residing on a target container, then the volume hides
that data on the target.
-#### **--workdir**, **-w**=*dir*
-
-Working directory inside the container.
-
-The default working directory for running binaries within a container is the root directory (**/**).
-The image developer can set a different default with the WORKDIR instruction. The operator
-can override the working directory by using the **-w** option.
+@@option workdir
## Exit Status
diff --git a/docs/source/markdown/podman-stop.1.md.in b/docs/source/markdown/podman-stop.1.md.in
index 04fc9387f..9aaccdfaa 100644
--- a/docs/source/markdown/podman-stop.1.md.in
+++ b/docs/source/markdown/podman-stop.1.md.in
@@ -47,11 +47,7 @@ Valid filters are listed below:
| pod | [Pod] name or full or partial ID of pod |
| network | [Network] name or full ID of network |
-#### **--ignore**, **-i**
-
-Ignore errors when specified containers are not in the container store. A user
-might have decided to manually remove a container which would lead to a failure
-during the ExecStop directive of a systemd service referencing that container.
+@@option ignore
#### **--latest**, **-l**
diff --git a/libpod/info.go b/libpod/info.go
index 8db6df8cc..1990dc044 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -1,6 +1,3 @@
-//go:build linux
-// +build linux
-
package libpod
import (
@@ -8,27 +5,21 @@ import (
"bytes"
"errors"
"fmt"
- "io/ioutil"
"math"
"os"
- "os/exec"
"runtime"
- "strconv"
"strings"
"syscall"
"time"
"github.com/containers/buildah"
- "github.com/containers/common/pkg/apparmor"
- "github.com/containers/common/pkg/cgroups"
- "github.com/containers/common/pkg/seccomp"
+ "github.com/containers/buildah/pkg/util"
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/libpod/linkmode"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/system"
- "github.com/opencontainers/selinux/go-selinux"
"github.com/sirupsen/logrus"
)
@@ -94,7 +85,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
hostDistributionInfo := r.GetHostDistributionInfo()
- kv, err := readKernelVersion()
+ kv, err := util.ReadKernelVersion()
if err != nil {
return nil, fmt.Errorf("error reading kernel version: %w", err)
}
@@ -104,94 +95,30 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
return nil, fmt.Errorf("error getting hostname: %w", err)
}
- seccompProfilePath, err := DefaultSeccompPath()
- if err != nil {
- return nil, fmt.Errorf("error getting Seccomp profile path: %w", err)
- }
-
- // Cgroups version
- unified, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return nil, fmt.Errorf("error reading cgroups mode: %w", err)
- }
-
- // Get Map of all available controllers
- availableControllers, err := cgroups.GetAvailableControllers(nil, unified)
- if err != nil {
- return nil, fmt.Errorf("error getting available cgroup controllers: %w", err)
- }
cpuUtil, err := getCPUUtilization()
if err != nil {
return nil, err
}
info := define.HostInfo{
- Arch: runtime.GOARCH,
- BuildahVersion: buildah.Version,
- CgroupManager: r.config.Engine.CgroupManager,
- CgroupControllers: availableControllers,
- Linkmode: linkmode.Linkmode(),
- CPUs: runtime.NumCPU(),
- CPUUtilization: cpuUtil,
- Distribution: hostDistributionInfo,
- LogDriver: r.config.Containers.LogDriver,
- EventLogger: r.eventer.String(),
- Hostname: host,
- IDMappings: define.IDMappings{},
- Kernel: kv,
- MemFree: mi.MemFree,
- MemTotal: mi.MemTotal,
- NetworkBackend: r.config.Network.NetworkBackend,
- OS: runtime.GOOS,
- Security: define.SecurityInfo{
- AppArmorEnabled: apparmor.IsEnabled(),
- DefaultCapabilities: strings.Join(r.config.Containers.DefaultCapabilities, ","),
- Rootless: rootless.IsRootless(),
- SECCOMPEnabled: seccomp.IsEnabled(),
- SECCOMPProfilePath: seccompProfilePath,
- SELinuxEnabled: selinux.GetEnabled(),
- },
- Slirp4NetNS: define.SlirpInfo{},
- SwapFree: mi.SwapFree,
- SwapTotal: mi.SwapTotal,
- }
-
- cgroupVersion := "v1"
- if unified {
- cgroupVersion = "v2"
- }
- info.CgroupsVersion = cgroupVersion
-
- slirp4netnsPath := r.config.Engine.NetworkCmdPath
- if slirp4netnsPath == "" {
- slirp4netnsPath, _ = exec.LookPath("slirp4netns")
- }
- if slirp4netnsPath != "" {
- version, err := programVersion(slirp4netnsPath)
- if err != nil {
- logrus.Warnf("Failed to retrieve program version for %s: %v", slirp4netnsPath, err)
- }
- program := define.SlirpInfo{
- Executable: slirp4netnsPath,
- Package: packageVersion(slirp4netnsPath),
- Version: version,
- }
- info.Slirp4NetNS = program
- }
-
- if rootless.IsRootless() {
- uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map")
- if err != nil {
- return nil, fmt.Errorf("error reading uid mappings: %w", err)
- }
- gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map")
- if err != nil {
- return nil, fmt.Errorf("error reading gid mappings: %w", err)
- }
- idmappings := define.IDMappings{
- GIDMap: gidmappings,
- UIDMap: uidmappings,
- }
- info.IDMappings = idmappings
+ Arch: runtime.GOARCH,
+ BuildahVersion: buildah.Version,
+ Linkmode: linkmode.Linkmode(),
+ CPUs: runtime.NumCPU(),
+ CPUUtilization: cpuUtil,
+ Distribution: hostDistributionInfo,
+ LogDriver: r.config.Containers.LogDriver,
+ EventLogger: r.eventer.String(),
+ Hostname: host,
+ Kernel: kv,
+ MemFree: mi.MemFree,
+ MemTotal: mi.MemTotal,
+ NetworkBackend: r.config.Network.NetworkBackend,
+ OS: runtime.GOOS,
+ SwapFree: mi.SwapFree,
+ SwapTotal: mi.SwapTotal,
+ }
+ if err := r.setPlatformHostInfo(&info); err != nil {
+ return nil, err
}
conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo()
@@ -202,7 +129,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
info.OCIRuntime = ociruntimeInfo
}
- duration, err := procUptime()
+ duration, err := util.ReadUptime()
if err != nil {
return nil, fmt.Errorf("error reading up time: %w", err)
}
@@ -332,31 +259,6 @@ func (r *Runtime) storeInfo() (*define.StoreInfo, error) {
return &info, nil
}
-func readKernelVersion() (string, error) {
- buf, err := ioutil.ReadFile("/proc/version")
- if err != nil {
- return "", err
- }
- f := bytes.Fields(buf)
- if len(f) < 3 {
- return string(bytes.TrimSpace(buf)), nil
- }
- return string(f[2]), nil
-}
-
-func procUptime() (time.Duration, error) {
- var zero time.Duration
- buf, err := ioutil.ReadFile("/proc/uptime")
- if err != nil {
- return zero, err
- }
- f := bytes.Fields(buf)
- if len(f) < 1 {
- return zero, errors.New("unable to parse uptime from /proc/uptime")
- }
- return time.ParseDuration(string(f[0]) + "s")
-}
-
// GetHostDistributionInfo returns a map containing the host's distribution and version
func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo {
// Populate values in case we cannot find the values
@@ -388,43 +290,3 @@ func (r *Runtime) GetHostDistributionInfo() define.DistributionInfo {
}
return dist
}
-
-// getCPUUtilization Returns a CPUUsage object that summarizes CPU
-// usage for userspace, system, and idle time.
-func getCPUUtilization() (*define.CPUUsage, error) {
- f, err := os.Open("/proc/stat")
- if err != nil {
- return nil, err
- }
- defer f.Close()
- scanner := bufio.NewScanner(f)
- // Read first line of /proc/stat that has entries for system ("cpu" line)
- for scanner.Scan() {
- break
- }
- // column 1 is user, column 3 is system, column 4 is idle
- stats := strings.Fields(scanner.Text())
- return statToPercent(stats)
-}
-
-func statToPercent(stats []string) (*define.CPUUsage, error) {
- userTotal, err := strconv.ParseFloat(stats[1], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse user value %q: %w", stats[1], err)
- }
- systemTotal, err := strconv.ParseFloat(stats[3], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse system value %q: %w", stats[3], err)
- }
- idleTotal, err := strconv.ParseFloat(stats[4], 64)
- if err != nil {
- return nil, fmt.Errorf("unable to parse idle value %q: %w", stats[4], err)
- }
- total := userTotal + systemTotal + idleTotal
- s := define.CPUUsage{
- UserPercent: math.Round((userTotal/total*100)*100) / 100,
- SystemPercent: math.Round((systemTotal/total*100)*100) / 100,
- IdlePercent: math.Round((idleTotal/total*100)*100) / 100,
- }
- return &s, nil
-}
diff --git a/libpod/info_freebsd.go b/libpod/info_freebsd.go
new file mode 100644
index 000000000..ef7b6817c
--- /dev/null
+++ b/libpod/info_freebsd.go
@@ -0,0 +1,40 @@
+package libpod
+
+import (
+ "fmt"
+ "unsafe"
+
+ "github.com/containers/podman/v4/libpod/define"
+ "golang.org/x/sys/unix"
+)
+
+func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error {
+ return nil
+}
+
+func timeToPercent(time uint64, total uint64) float64 {
+ return 100.0 * float64(time) / float64(total)
+}
+
+// getCPUUtilization Returns a CPUUsage object that summarizes CPU
+// usage for userspace, system, and idle time.
+func getCPUUtilization() (*define.CPUUsage, error) {
+ buf, err := unix.SysctlRaw("kern.cp_time")
+ if err != nil {
+ return nil, fmt.Errorf("error reading sysctl kern.cp_time: %w", err)
+ }
+
+ var total uint64 = 0
+ var times [unix.CPUSTATES]uint64
+
+ for i := 0; i < unix.CPUSTATES; i++ {
+ val := *(*uint64)(unsafe.Pointer(&buf[8*i]))
+ times[i] = val
+ total += val
+ }
+ return &define.CPUUsage{
+ UserPercent: timeToPercent(times[unix.CP_USER], total),
+ SystemPercent: timeToPercent(times[unix.CP_SYS], total),
+ IdlePercent: timeToPercent(times[unix.CP_IDLE], total),
+ }, nil
+}
diff --git a/libpod/info_linux.go b/libpod/info_linux.go
new file mode 100644
index 000000000..801dcdb43
--- /dev/null
+++ b/libpod/info_linux.go
@@ -0,0 +1,132 @@
+package libpod
+
+import (
+ "bufio"
+ "fmt"
+ "math"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+
+ "github.com/containers/common/pkg/apparmor"
+ "github.com/containers/common/pkg/cgroups"
+ "github.com/containers/common/pkg/seccomp"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/rootless"
+ "github.com/opencontainers/selinux/go-selinux"
+ "github.com/sirupsen/logrus"
+)
+
+func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error {
+ seccompProfilePath, err := DefaultSeccompPath()
+ if err != nil {
+ return fmt.Errorf("error getting Seccomp profile path: %w", err)
+ }
+
+ // Cgroups version
+ unified, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return fmt.Errorf("error reading cgroups mode: %w", err)
+ }
+
+ // Get Map of all available controllers
+ availableControllers, err := cgroups.GetAvailableControllers(nil, unified)
+ if err != nil {
+ return fmt.Errorf("error getting available cgroup controllers: %w", err)
+ }
+
+ info.CgroupManager = r.config.Engine.CgroupManager
+ info.CgroupControllers = availableControllers
+ info.IDMappings = define.IDMappings{}
+ info.Security = define.SecurityInfo{
+ AppArmorEnabled: apparmor.IsEnabled(),
+ DefaultCapabilities: strings.Join(r.config.Containers.DefaultCapabilities, ","),
+ Rootless: rootless.IsRootless(),
+ SECCOMPEnabled: seccomp.IsEnabled(),
+ SECCOMPProfilePath: seccompProfilePath,
+ SELinuxEnabled: selinux.GetEnabled(),
+ }
+ info.Slirp4NetNS = define.SlirpInfo{}
+
+ cgroupVersion := "v1"
+ if unified {
+ cgroupVersion = "v2"
+ }
+ info.CgroupsVersion = cgroupVersion
+
+ slirp4netnsPath := r.config.Engine.NetworkCmdPath
+ if slirp4netnsPath == "" {
+ slirp4netnsPath, _ = exec.LookPath("slirp4netns")
+ }
+ if slirp4netnsPath != "" {
+ version, err := programVersion(slirp4netnsPath)
+ if err != nil {
+ logrus.Warnf("Failed to retrieve program version for %s: %v", slirp4netnsPath, err)
+ }
+ program := define.SlirpInfo{
+ Executable: slirp4netnsPath,
+ Package: packageVersion(slirp4netnsPath),
+ Version: version,
+ }
+ info.Slirp4NetNS = program
+ }
+
+ if rootless.IsRootless() {
+ uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map")
+ if err != nil {
+ return fmt.Errorf("error reading uid mappings: %w", err)
+ }
+ gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map")
+ if err != nil {
+ return fmt.Errorf("error reading gid mappings: %w", err)
+ }
+ idmappings := define.IDMappings{
+ GIDMap: gidmappings,
+ UIDMap: uidmappings,
+ }
+ info.IDMappings = idmappings
+ }
+
+ return nil
+}
+
+func statToPercent(stats []string) (*define.CPUUsage, error) {
+ userTotal, err := strconv.ParseFloat(stats[1], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse user value %q: %w", stats[1], err)
+ }
+ systemTotal, err := strconv.ParseFloat(stats[3], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse system value %q: %w", stats[3], err)
+ }
+ idleTotal, err := strconv.ParseFloat(stats[4], 64)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse idle value %q: %w", stats[4], err)
+ }
+ total := userTotal + systemTotal + idleTotal
+ s := define.CPUUsage{
+ UserPercent: math.Round((userTotal/total*100)*100) / 100,
+ SystemPercent: math.Round((systemTotal/total*100)*100) / 100,
+ IdlePercent: math.Round((idleTotal/total*100)*100) / 100,
+ }
+ return &s, nil
+}
+
+// getCPUUtilization Returns a CPUUsage object that summarizes CPU
+// usage for userspace, system, and idle time.
+func getCPUUtilization() (*define.CPUUsage, error) {
+ f, err := os.Open("/proc/stat")
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+ // Read first line of /proc/stat that has entries for system ("cpu" line)
+ for scanner.Scan() {
+ break
+ }
+ // column 1 is user, column 3 is system, column 4 is idle
+ stats := strings.Fields(scanner.Text())
+ return statToPercent(stats)
+}
diff --git a/libpod/info_unsupported.go b/libpod/info_unsupported.go
index 53ee4b32f..0aed51247 100644
--- a/libpod/info_unsupported.go
+++ b/libpod/info_unsupported.go
@@ -1,5 +1,5 @@
-//go:build !linux
-// +build !linux
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
package libpod
diff --git a/pkg/api/handlers/compat/auth.go b/pkg/api/handlers/compat/auth.go
index 37d2b784d..ee478b9e3 100644
--- a/pkg/api/handlers/compat/auth.go
+++ b/pkg/api/handlers/compat/auth.go
@@ -1,7 +1,6 @@
package compat
import (
- "context"
"encoding/json"
"errors"
"fmt"
@@ -44,7 +43,7 @@ func Auth(w http.ResponseWriter, r *http.Request) {
fmt.Println("Authenticating with existing credentials...")
registry := stripAddressOfScheme(authConfig.ServerAddress)
- if err := DockerClient.CheckAuth(context.Background(), sysCtx, authConfig.Username, authConfig.Password, registry); err == nil {
+ if err := DockerClient.CheckAuth(r.Context(), sysCtx, authConfig.Username, authConfig.Password, registry); err == nil {
utils.WriteResponse(w, http.StatusOK, entities.AuthReport{
IdentityToken: "",
Status: "Login Succeeded",
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index a00f0b089..020991cc7 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -694,7 +694,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
success bool
)
- runCtx, cancel := context.WithCancel(context.Background())
+ runCtx, cancel := context.WithCancel(r.Context())
go func() {
defer cancel()
imageID, _, err = runtime.Build(r.Context(), buildOptions, containerFiles...)
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index 1307c267a..429f45f91 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -1,7 +1,6 @@
package libpod
import (
- "context"
"encoding/json"
"fmt"
"net/http"
@@ -63,12 +62,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), runtime, &sg, false, nil)
+ rtSpec, spec, opts, err := generate.MakeContainer(r.Context(), runtime, &sg, false, nil)
if err != nil {
utils.InternalServerError(w, err)
return
}
- ctr, err := generate.ExecuteCreate(context.Background(), runtime, rtSpec, spec, false, opts...)
+ ctr, err := generate.ExecuteCreate(r.Context(), runtime, rtSpec, spec, false, opts...)
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 7e24ae5ac..57b2e3a78 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -82,17 +82,32 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
pullOptions.IdentityToken = authConf.IdentityToken
}
- writer := channel.NewWriter(make(chan []byte))
- defer writer.Close()
-
- pullOptions.Writer = writer
-
pullPolicy, err := config.ParsePullPolicy(query.PullPolicy)
if err != nil {
utils.Error(w, http.StatusBadRequest, err)
return
}
+ // Let's keep thing simple when running in quiet mode and pull directly.
+ if query.Quiet {
+ images, err := runtime.LibimageRuntime().Pull(r.Context(), query.Reference, pullPolicy, pullOptions)
+ var report entities.ImagePullReport
+ if err != nil {
+ report.Error = err.Error()
+ }
+ for _, image := range images {
+ report.Images = append(report.Images, image.ID())
+ // Pull last ID from list and publish in 'id' stanza. This maintains previous API contract
+ report.ID = image.ID()
+ }
+ utils.WriteResponse(w, http.StatusOK, report)
+ return
+ }
+
+ writer := channel.NewWriter(make(chan []byte))
+ defer writer.Close()
+ pullOptions.Writer = writer
+
var pulledImages []*libimage.Image
var pullError error
runCtx, cancel := context.WithCancel(r.Context())
@@ -118,10 +133,8 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
select {
case s := <-writer.Chan():
report.Stream = string(s)
- if !query.Quiet {
- if err := enc.Encode(report); err != nil {
- logrus.Warnf("Failed to encode json: %v", err)
- }
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to encode json: %v", err)
}
flush()
case <-runCtx.Done():
diff --git a/pkg/api/handlers/libpod/images_push.go b/pkg/api/handlers/libpod/images_push.go
index e931fd2f9..be6f5b131 100644
--- a/pkg/api/handlers/libpod/images_push.go
+++ b/pkg/api/handlers/libpod/images_push.go
@@ -90,7 +90,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
// Let's keep thing simple when running in quiet mode and push directly.
if query.Quiet {
- if err := imageEngine.Push(context.Background(), source, destination, options); err != nil {
+ if err := imageEngine.Push(r.Context(), source, destination, options); err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
return
}
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index fa83bbfe1..8391def5c 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -293,7 +293,7 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) {
options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
}
imageEngine := abi.ImageEngine{Libpod: runtime}
- digest, err := imageEngine.ManifestPush(context.Background(), source, query.Destination, options)
+ digest, err := imageEngine.ManifestPush(r.Context(), source, query.Destination, options)
if err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", query.Destination, err))
return
@@ -367,7 +367,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
// Let's keep thing simple when running in quiet mode and push directly.
if query.Quiet {
- digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options)
+ digest, err := imageEngine.ManifestPush(r.Context(), source, destination, options)
if err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
return
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index b533e131c..6d245d950 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -162,7 +162,7 @@ type ExecStartConfig struct {
func ImageDataToImageInspect(ctx context.Context, l *libimage.Image) (*ImageInspect, error) {
options := &libimage.InspectOptions{WithParent: true, WithSize: true}
- info, err := l.Inspect(context.Background(), options)
+ info, err := l.Inspect(ctx, options)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go
index 1a4aa3038..109981c63 100644
--- a/pkg/bindings/images/pull.go
+++ b/pkg/bindings/images/pull.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"strconv"
@@ -57,10 +56,14 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string,
return nil, response.Process(err)
}
- // Historically pull writes status to stderr
- stderr := io.Writer(os.Stderr)
+ var writer io.Writer
if options.GetQuiet() {
- stderr = ioutil.Discard
+ writer = io.Discard
+ } else if progressWriter := options.GetProgressWriter(); progressWriter != nil {
+ writer = progressWriter
+ } else {
+ // Historically push writes status to stderr
+ writer = os.Stderr
}
dec := json.NewDecoder(response.Body)
@@ -84,7 +87,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string,
switch {
case report.Stream != "":
- fmt.Fprint(stderr, report.Stream)
+ fmt.Fprint(writer, report.Stream)
case report.Error != "":
pullErrors = append(pullErrors, errors.New(report.Error))
case len(report.Images) > 0:
diff --git a/pkg/bindings/images/push.go b/pkg/bindings/images/push.go
index 5069dd780..f1e059f8c 100644
--- a/pkg/bindings/images/push.go
+++ b/pkg/bindings/images/push.go
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"strconv"
@@ -58,12 +57,14 @@ func Push(ctx context.Context, source string, destination string, options *PushO
return response.Process(err)
}
- // Historically push writes status to stderr
- writer := io.Writer(os.Stderr)
+ var writer io.Writer
if options.GetQuiet() {
- writer = ioutil.Discard
+ writer = io.Discard
} else if progressWriter := options.GetProgressWriter(); progressWriter != nil {
writer = progressWriter
+ } else {
+ // Historically push writes status to stderr
+ writer = os.Stderr
}
dec := json.NewDecoder(response.Body)
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 7b28c499e..3ecfb9e09 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -182,6 +182,8 @@ type PullOptions struct {
Policy *string
// Password for authenticating against the registry.
Password *string
+ // ProgressWriter is a writer where pull progress are sent.
+ ProgressWriter *io.Writer
// Quiet can be specified to suppress pull progress when pulling. Ignored
// for remote calls.
Quiet *bool
diff --git a/pkg/bindings/images/types_pull_options.go b/pkg/bindings/images/types_pull_options.go
index 4cd525185..c1a88fd9e 100644
--- a/pkg/bindings/images/types_pull_options.go
+++ b/pkg/bindings/images/types_pull_options.go
@@ -2,6 +2,7 @@
package images
import (
+ "io"
"net/url"
"github.com/containers/podman/v4/pkg/bindings/internal/util"
@@ -107,6 +108,21 @@ func (o *PullOptions) GetPassword() string {
return *o.Password
}
+// WithProgressWriter set field ProgressWriter to given value
+func (o *PullOptions) WithProgressWriter(value io.Writer) *PullOptions {
+ o.ProgressWriter = &value
+ return o
+}
+
+// GetProgressWriter returns value of field ProgressWriter
+func (o *PullOptions) GetProgressWriter() io.Writer {
+ if o.ProgressWriter == nil {
+ var z io.Writer
+ return z
+ }
+ return *o.ProgressWriter
+}
+
// WithQuiet set field Quiet to given value
func (o *PullOptions) WithQuiet(value bool) *PullOptions {
o.Quiet = &value
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index 49e4089f5..0163d21a0 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -182,12 +182,14 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
return "", response.Process(err)
}
- // Historically push writes status to stderr
- writer := io.Writer(os.Stderr)
+ var writer io.Writer
if options.GetQuiet() {
writer = io.Discard
} else if progressWriter := options.GetProgressWriter(); progressWriter != nil {
writer = progressWriter
+ } else {
+ // Historically push writes status to stderr
+ writer = os.Stderr
}
dec := json.NewDecoder(response.Body)
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 9c9796661..53c5a1e83 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -1,11 +1,14 @@
package bindings_test
import (
+ "bytes"
+ "fmt"
"net/http"
"os"
"path/filepath"
"time"
+ podmanRegistry "github.com/containers/podman/v4/hack/podman-registry-go"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/bindings/containers"
"github.com/containers/podman/v4/pkg/bindings/images"
@@ -362,9 +365,14 @@ var _ = Describe("Podman images", func() {
It("Image Pull", func() {
rawImage := "docker.io/library/busybox:latest"
- pulledImages, err := images.Pull(bt.conn, rawImage, nil)
+ var writer bytes.Buffer
+ pullOpts := new(images.PullOptions).WithProgressWriter(&writer)
+ pulledImages, err := images.Pull(bt.conn, rawImage, pullOpts)
Expect(err).NotTo(HaveOccurred())
Expect(len(pulledImages)).To(Equal(1))
+ output := writer.String()
+ Expect(output).To(ContainSubstring("Trying to pull "))
+ Expect(output).To(ContainSubstring("Getting image source signatures"))
exists, err := images.Exists(bt.conn, rawImage, nil)
Expect(err).NotTo(HaveOccurred())
@@ -380,7 +388,19 @@ var _ = Describe("Podman images", func() {
})
It("Image Push", func() {
- Skip("TODO: implement test for image push to registry")
+ registry, err := podmanRegistry.Start()
+ Expect(err).To(BeNil())
+
+ var writer bytes.Buffer
+ pushOpts := new(images.PushOptions).WithUsername(registry.User).WithPassword(registry.Password).WithSkipTLSVerify(true).WithProgressWriter(&writer).WithQuiet(false)
+ err = images.Push(bt.conn, alpine.name, fmt.Sprintf("localhost:%s/test:latest", registry.Port), pushOpts)
+ Expect(err).ToNot(HaveOccurred())
+
+ output := writer.String()
+ Expect(output).To(ContainSubstring("Copying blob "))
+ Expect(output).To(ContainSubstring("Copying config "))
+ Expect(output).To(ContainSubstring("Writing manifest to image destination"))
+ Expect(output).To(ContainSubstring("Storing signatures"))
})
It("Build no options", func() {
diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go
index 6a34ef5a6..d6749f920 100644
--- a/pkg/bindings/test/manifests_test.go
+++ b/pkg/bindings/test/manifests_test.go
@@ -1,9 +1,12 @@
package bindings_test
import (
+ "bytes"
+ "fmt"
"net/http"
"time"
+ podmanRegistry "github.com/containers/podman/v4/hack/podman-registry-go"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/bindings/images"
"github.com/containers/podman/v4/pkg/bindings/manifests"
@@ -12,7 +15,7 @@ import (
"github.com/onsi/gomega/gexec"
)
-var _ = Describe("podman manifest", func() {
+var _ = Describe("Podman manifests", func() {
var (
bt *bindingTest
s *gexec.Session
@@ -172,7 +175,21 @@ var _ = Describe("podman manifest", func() {
Expect(list.Manifests[0].Platform.OS).To(Equal("foo"))
})
- It("push manifest", func() {
- Skip("TODO: implement test for manifest push to registry")
+ It("Manifest Push", func() {
+ registry, err := podmanRegistry.Start()
+ Expect(err).To(BeNil())
+
+ name := "quay.io/libpod/foobar:latest"
+ _, err = manifests.Create(bt.conn, name, []string{alpine.name}, nil)
+ Expect(err).ToNot(HaveOccurred())
+
+ var writer bytes.Buffer
+ pushOpts := new(images.PushOptions).WithUsername(registry.User).WithPassword(registry.Password).WithAll(true).WithSkipTLSVerify(true).WithProgressWriter(&writer).WithQuiet(false)
+ _, err = manifests.Push(bt.conn, name, fmt.Sprintf("localhost:%s/test:latest", registry.Port), pushOpts)
+ Expect(err).ToNot(HaveOccurred())
+
+ output := writer.String()
+ Expect(output).To(ContainSubstring("Writing manifest list to image destination"))
+ Expect(output).To(ContainSubstring("Storing list signatures"))
})
})
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 21c1372b9..cad11b0ab 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -156,6 +156,8 @@ type ImagePullOptions struct {
SkipTLSVerify types.OptionalBool
// PullPolicy whether to pull new image
PullPolicy config.PullPolicy
+ // Writer is used to display copy information including progress bars.
+ Writer io.Writer
}
// ImagePullReport is the response from pulling one or more images.
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 77d1bf0db..f9839f62f 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -237,8 +237,9 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
pullOptions.Variant = options.Variant
pullOptions.SignaturePolicyPath = options.SignaturePolicy
pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+ pullOptions.Writer = options.Writer
- if !options.Quiet {
+ if !options.Quiet && pullOptions.Writer == nil {
pullOptions.Writer = os.Stderr
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index bb3014099..2716aaf2a 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -110,6 +110,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities.
options.WithAllTags(opts.AllTags).WithAuthfile(opts.Authfile).WithArch(opts.Arch).WithOS(opts.OS)
options.WithVariant(opts.Variant).WithPassword(opts.Password)
options.WithQuiet(opts.Quiet).WithUsername(opts.Username).WithPolicy(opts.PullPolicy.String())
+ options.WithProgressWriter(opts.Writer)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
options.WithSkipTLSVerify(true)
diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go
index 1c4aad710..60b72dcaa 100644
--- a/test/e2e/manifest_test.go
+++ b/test/e2e/manifest_test.go
@@ -350,6 +350,33 @@ var _ = Describe("Podman manifest", func() {
Expect(foundZstdFile).To(BeTrue())
})
+ It("push progress", func() {
+ SkipIfRemote("manifest push to dir not supported in remote mode")
+
+ session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ dest := filepath.Join(podmanTest.TempDir, "pushed")
+ err := os.MkdirAll(dest, os.ModePerm)
+ Expect(err).To(BeNil())
+ defer func() {
+ os.RemoveAll(dest)
+ }()
+
+ session = podmanTest.Podman([]string{"push", "foo", "-q", "dir:" + dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.ErrorToString()).To(BeEmpty())
+
+ session = podmanTest.Podman([]string{"push", "foo", "dir:" + dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ output := session.ErrorToString()
+ Expect(output).To(ContainSubstring("Writing manifest list to image destination"))
+ Expect(output).To(ContainSubstring("Storing list signatures"))
+ })
+
It("authenticated push", func() {
registryOptions := &podmanRegistry.Options{
Image: "docker-archive:" + imageTarPath(REGISTRY_IMAGE),
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index 12f14fdc8..ba717f393 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -545,4 +545,18 @@ var _ = Describe("Podman pull", func() {
Expect(data[0]).To(HaveField("Os", runtime.GOOS))
Expect(data[0]).To(HaveField("Architecture", "arm64"))
})
+
+ It("podman pull progress", func() {
+ session := podmanTest.Podman([]string{"pull", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ output := session.ErrorToString()
+ Expect(output).To(ContainSubstring("Getting image source signatures"))
+ Expect(output).To(ContainSubstring("Copying blob "))
+
+ session = podmanTest.Podman([]string{"pull", "-q", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.ErrorToString()).To(BeEmpty())
+ })
})
diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go
index 083020f08..3f611040b 100644
--- a/test/e2e/run_memory_test.go
+++ b/test/e2e/run_memory_test.go
@@ -66,6 +66,24 @@ var _ = Describe("Podman run memory", func() {
Expect(session.OutputToString()).To(Equal("41943040"))
})
+ It("podman run memory-swap test", func() {
+ var (
+ session *PodmanSessionIntegration
+ expect string
+ )
+
+ if CGROUPSV2 {
+ session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.swap.max"})
+ expect = "10485760"
+ } else {
+ session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"})
+ expect = "31457280"
+ }
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(expect))
+ })
+
for _, limit := range []string{"0", "15", "100"} {
limit := limit // Keep this value in a proper scope
testName := fmt.Sprintf("podman run memory-swappiness test(%s)", limit)