summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OWNERS17
-rw-r--r--cmd/podman/common/completion.go6
-rw-r--r--cmd/podman/containers/mount.go14
-rw-r--r--cmd/podman/containers/ps.go24
-rw-r--r--cmd/podman/containers/stats.go33
-rw-r--r--cmd/podman/containers/top.go12
-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/bindings/images/build.go5
-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/checkpoint_test.go10
-rw-r--r--test/e2e/commit_test.go8
-rw-r--r--test/e2e/common_test.go61
-rw-r--r--test/e2e/containers_conf_test.go2
-rw-r--r--test/e2e/create_test.go18
-rw-r--r--test/e2e/generate_kube_test.go17
-rw-r--r--test/e2e/images_test.go5
-rw-r--r--test/e2e/libpod_suite_remote_test.go21
-rw-r--r--test/e2e/libpod_suite_test.go12
-rw-r--r--test/e2e/load_test.go3
-rw-r--r--test/e2e/network_test.go4
-rw-r--r--test/e2e/prune_test.go16
-rw-r--r--test/e2e/push_test.go32
-rw-r--r--test/e2e/restart_test.go4
-rw-r--r--test/e2e/rmi_test.go3
-rw-r--r--test/e2e/run_dns_test.go2
-rw-r--r--test/e2e/run_entrypoint_test.go2
-rw-r--r--test/e2e/run_networking_test.go6
-rw-r--r--test/e2e/run_passwd_test.go12
-rw-r--r--test/e2e/run_privileged_test.go4
-rw-r--r--test/e2e/run_signal_test.go6
-rw-r--r--test/e2e/run_test.go5
-rw-r--r--test/e2e/run_volume_test.go24
-rw-r--r--test/e2e/search_test.go23
-rw-r--r--test/e2e/top_test.go5
-rw-r--r--test/e2e/volume_rm_test.go2
-rw-r--r--test/system/180-blkio.bats69
-rw-r--r--test/utils/utils.go1
43 files changed, 338 insertions, 217 deletions
diff --git a/OWNERS b/OWNERS
index 8f5368b00..e4c4faebb 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,30 +1,35 @@
approvers:
+ - Luap99
+ - TomSweeneyRedHat
+ - ashley-cui
- baude
- edsantiago
+ - flouthoc
- giuseppe
- jwhonce
- - Luap99
+ - lsm5
- mheon
- mtrmac
- rhatdan
- saschagrunert
- - TomSweeneyRedHat
- umohnani8
- vrothberg
- zhangguanzhang
reviewers:
- - ashley-cui
+ - Luap99
+ - QiWang19
+ - TomSweeneyRedHat
- baude
+ - cdoern
- edsantiago
+ - flouthoc
- giuseppe
- jwhonce
- - Luap99
+ - lsm5
- mheon
- mtrmac
- - QiWang19
- rhatdan
- saschagrunert
- - TomSweeneyRedHat
- umohnani8
- vrothberg
- zhangguanzhang
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/containers/mount.go b/cmd/podman/containers/mount.go
index 0397b456f..271fc4c6b 100644
--- a/cmd/podman/containers/mount.go
+++ b/cmd/podman/containers/mount.go
@@ -81,7 +81,7 @@ func init() {
validate.AddLatestFlag(containerMountCommand, &mountOpts.Latest)
}
-func mount(_ *cobra.Command, args []string) error {
+func mount(cmd *cobra.Command, args []string) error {
if len(args) > 0 && mountOpts.Latest {
return errors.Errorf("--latest and containers cannot be used together")
}
@@ -116,18 +116,14 @@ func mount(_ *cobra.Command, args []string) error {
mrs = append(mrs, mountReporter{r})
}
- format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}"
- tmpl, err := report.NewTemplate("mounts").Parse(format)
- if err != nil {
- return err
- }
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- w, err := report.NewWriterDefault(os.Stdout)
+ rpt, err = rpt.Parse(report.OriginPodman, "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}")
if err != nil {
return err
}
- defer w.Flush()
- return tmpl.Execute(w, mrs)
+ return rpt.Execute(mrs)
}
func printJSON(reports []*entities.ContainerMountReport) error {
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index 712de327c..cebe61b5a 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -220,30 +220,28 @@ func ps(cmd *cobra.Command, _ []string) error {
hdrs, format := createPsOut()
+ var origin report.Origin
noHeading, _ := cmd.Flags().GetBool("noheading")
if cmd.Flags().Changed("format") {
noHeading = noHeading || !report.HasTable(listOpts.Format)
- format = report.NormalizeFormat(listOpts.Format)
- format = report.EnforceRange(format)
+ format = listOpts.Format
+ origin = report.OriginUser
+ } else {
+ origin = report.OriginPodman
}
ns := strings.NewReplacer(".Namespaces.", ".")
format = ns.Replace(format)
- tmpl, err := report.NewTemplate("list").Parse(format)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
+ rpt, err := report.New(os.Stdout, cmd.Name()).Parse(origin, format)
if err != nil {
return err
}
- defer w.Flush()
+ defer rpt.Flush()
headers := func() error { return nil }
if !noHeading {
headers = func() error {
- return tmpl.Execute(w, hdrs)
+ return rpt.Execute(hdrs)
}
}
@@ -268,10 +266,10 @@ func ps(cmd *cobra.Command, _ []string) error {
if err := headers(); err != nil {
return err
}
- if err := tmpl.Execute(w, responses); err != nil {
+ if err := rpt.Execute(responses); err != nil {
return err
}
- if err := w.Flush(); err != nil {
+ if err := rpt.Flush(); err != nil {
// we usually do not care about Flush() failures but here do not loop if Flush() has failed
return err
}
@@ -282,7 +280,7 @@ func ps(cmd *cobra.Command, _ []string) error {
if err := headers(); err != nil {
return err
}
- if err := tmpl.Execute(w, responses); err != nil {
+ if err := rpt.Execute(responses); err != nil {
return err
}
}
diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go
index d21feaabc..9fba51597 100644
--- a/cmd/podman/containers/stats.go
+++ b/cmd/podman/containers/stats.go
@@ -126,14 +126,14 @@ func stats(cmd *cobra.Command, args []string) error {
if report.Error != nil {
return report.Error
}
- if err := outputStats(report.Stats); err != nil {
+ if err := outputStats(cmd, report.Stats); err != nil {
return err
}
}
return nil
}
-func outputStats(reports []define.ContainerStats) error {
+func outputStats(cmd *cobra.Command, reports []define.ContainerStats) error {
headers := report.Headers(define.ContainerStats{}, map[string]string{
"ID": "ID",
"UpTime": "CPU TIME",
@@ -158,32 +158,27 @@ func outputStats(reports []define.ContainerStats) error {
if report.IsJSON(statsOptions.Format) {
return outputJSON(stats)
}
- format := "{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\t{{.UpTime}}\t{{.AVGCPU}}\n"
- if len(statsOptions.Format) > 0 {
- format = report.NormalizeFormat(statsOptions.Format)
- }
- format = report.EnforceRange(format)
- tmpl, err := report.NewTemplate("stats").Parse(format)
- if err != nil {
- return err
- }
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- w, err := report.NewWriterDefault(os.Stdout)
+ var err error
+ if cmd.Flags().Changed("format") {
+ rpt, err = rpt.Parse(report.OriginUser, statsOptions.Format)
+ } else {
+ format := "{{range .}}{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\t{{.UpTime}}\t{{.AVGCPU}}\n{{end -}}"
+ rpt, err = rpt.Parse(report.OriginPodman, format)
+ }
if err != nil {
return err
}
- defer w.Flush()
- if len(statsOptions.Format) < 1 {
- if err := tmpl.Execute(w, headers); err != nil {
+ if rpt.RenderHeaders {
+ if err := rpt.Execute(headers); err != nil {
return err
}
}
- if err := tmpl.Execute(w, stats); err != nil {
- return err
- }
- return nil
+ return rpt.Execute(stats)
}
type containerStats struct {
diff --git a/cmd/podman/containers/top.go b/cmd/podman/containers/top.go
index 808c6c494..963a251bb 100644
--- a/cmd/podman/containers/top.go
+++ b/cmd/podman/containers/top.go
@@ -77,7 +77,7 @@ func init() {
validate.AddLatestFlag(containerTopCommand, &topOptions.Latest)
}
-func top(_ *cobra.Command, args []string) error {
+func top(cmd *cobra.Command, args []string) error {
if topOptions.ListDescriptors {
descriptors, err := util.GetContainerPidInformationDescriptors()
if err != nil {
@@ -103,15 +103,13 @@ func top(_ *cobra.Command, args []string) error {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
+ rpt := report.New(os.Stdout, cmd.Name()).Init(os.Stdout, 12, 2, 2, ' ', 0)
+ defer rpt.Flush()
for _, proc := range topResponse.Value {
- if _, err := fmt.Fprintln(w, proc); err != nil {
+ if _, err := fmt.Fprintln(rpt.Writer(), proc); err != nil {
return err
}
}
- return w.Flush()
+ return nil
}
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/bindings/images/build.go b/pkg/bindings/images/build.go
index 25770fdfc..be6e5ab55 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -346,6 +346,11 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
c = tmpFile.Name()
}
+ cfDir := filepath.Dir(c)
+ if absDir, err := filepath.EvalSymlinks(cfDir); err == nil {
+ name := filepath.ToSlash(strings.TrimPrefix(c, cfDir+string(filepath.Separator)))
+ c = filepath.Join(absDir, name)
+ }
containerfile, err := filepath.Abs(c)
if err != nil {
logrus.Errorf("Cannot find absolute path of %v: %v", c, err)
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/checkpoint_test.go b/test/e2e/checkpoint_test.go
index e068a6582..5a2640f33 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -192,7 +192,7 @@ var _ = Describe("Podman checkpoint", func() {
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
Expect(ps.OutputToString()).To(ContainSubstring(session1.OutputToString()))
- Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse())
+ Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
result = podmanTest.Podman([]string{"container", "restore", "second"})
result.WaitWithDefaultTimeout()
@@ -228,8 +228,8 @@ var _ = Describe("Podman checkpoint", func() {
ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
- Expect(ps.LineInOutputContains(session1.OutputToString())).To(BeFalse())
- Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse())
+ Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
+ Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
result = podmanTest.Podman([]string{"container", "restore", "-a"})
result.WaitWithDefaultTimeout()
@@ -1297,8 +1297,8 @@ var _ = Describe("Podman checkpoint", func() {
})
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
- Expect(ps.LineInOutputContains(session1.OutputToString())).To(BeFalse())
- Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse())
+ Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
+ Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
result = podmanTest.Podman([]string{
"container",
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index b751c338f..a09666468 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -204,8 +204,7 @@ var _ = Describe("Podman commit", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
image := inspect.InspectImageJSON()
- _, ok := image[0].Config.Volumes["/foo"]
- Expect(ok).To(BeFalse())
+ Expect(image[0].Config.Volumes).To(Not(HaveKey("/foo")))
})
It("podman commit with volume mounts and --include-volumes", func() {
@@ -224,8 +223,7 @@ var _ = Describe("Podman commit", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
image := inspect.InspectImageJSON()
- _, ok := image[0].Config.Volumes["/foo"]
- Expect(ok).To(BeTrue(), ".Config.Volumes[/foo]")
+ Expect(image[0].Config.Volumes).To(HaveKey("/foo"))
r := podmanTest.Podman([]string{"run", "newimage"})
r.WaitWithDefaultTimeout()
@@ -250,7 +248,7 @@ var _ = Describe("Podman commit", func() {
for _, v := range image[0].Config.Env {
envMap[v] = true
}
- Expect(envMap["TEST=1=1-01=9.01"]).To(BeTrue(), "envMap[TEST=1=1-01=9.01]")
+ Expect(envMap).To(HaveKey("TEST=1=1-01=9.01"))
})
It("podman commit container and print id to external file", func() {
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 63cb4f091..a411a860b 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -36,7 +36,6 @@ var (
PODMAN_BINARY string //nolint:golint,stylecheck
INTEGRATION_ROOT string //nolint:golint,stylecheck
CGROUP_MANAGER = "systemd" //nolint:golint,stylecheck
- ARTIFACT_DIR = "/tmp/.artifacts" //nolint:golint,stylecheck
RESTORE_IMAGES = []string{ALPINE, BB, nginx} //nolint:golint,stylecheck
defaultWaitTimeout = 90
CGROUPSV2, _ = cgroups.IsCgroup2UnifiedMode() //nolint:golint,stylecheck
@@ -46,7 +45,7 @@ var (
type PodmanTestIntegration struct {
PodmanTest
ConmonBinary string
- CrioRoot string
+ Root string
CNIConfigDir string
OCIRuntime string
RunRoot string
@@ -111,13 +110,6 @@ var _ = SynchronizedBeforeSuite(func() []byte {
cwd, _ := os.Getwd()
INTEGRATION_ROOT = filepath.Join(cwd, "../../")
podman := PodmanTestSetup("/tmp")
- podman.ArtifactPath = ARTIFACT_DIR
- if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) {
- if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil {
- fmt.Printf("%q\n", err)
- os.Exit(1)
- }
- }
// Pull cirros but don't put it into the cache
pullImages := []string{cirros, fedoraToolbox, volumeTest}
@@ -130,7 +122,7 @@ var _ = SynchronizedBeforeSuite(func() []byte {
fmt.Printf("%q\n", err)
os.Exit(1)
}
- podman.CrioRoot = ImageCacheDir
+ podman.Root = ImageCacheDir
// If running localized tests, the cache dir is created and populated. if the
// tests are remote, this is a no-op
populateCache(podman)
@@ -170,7 +162,6 @@ var _ = SynchronizedBeforeSuite(func() []byte {
func (p *PodmanTestIntegration) Setup() {
cwd, _ := os.Getwd()
INTEGRATION_ROOT = filepath.Join(cwd, "../../")
- p.ArtifactPath = ARTIFACT_DIR
}
var _ = SynchronizedAfterSuite(func() {},
@@ -181,14 +172,14 @@ var _ = SynchronizedAfterSuite(func() {},
fmt.Printf("%s\t\t%f\n", result.name, result.length)
}
- // previous crio-run
+ // previous runroot
tempdir, err := CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest := PodmanTestCreate(tempdir)
- if err := os.RemoveAll(podmanTest.CrioRoot); err != nil {
+ if err := os.RemoveAll(podmanTest.Root); err != nil {
fmt.Printf("%q\n", err)
}
@@ -265,18 +256,17 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
PodmanTest: PodmanTest{
PodmanBinary: podmanBinary,
RemotePodmanBinary: podmanRemoteBinary,
- ArtifactPath: ARTIFACT_DIR,
TempDir: tempDir,
RemoteTest: remote,
ImageCacheFS: storageFs,
ImageCacheDir: ImageCacheDir,
},
ConmonBinary: conmonBinary,
- CrioRoot: filepath.Join(tempDir, "crio"),
+ Root: filepath.Join(tempDir, "root"),
TmpDir: tempDir,
CNIConfigDir: CNIConfigDir,
OCIRuntime: ociRuntime,
- RunRoot: filepath.Join(tempDir, "crio-run"),
+ RunRoot: filepath.Join(tempDir, "runroot"),
StorageOptions: storageOptions,
SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"),
CgroupManager: cgroupManager,
@@ -308,15 +298,29 @@ func (p PodmanTestIntegration) AddImageToRWStore(image string) {
}
}
-// createArtifact creates a cached image in the artifact dir
+func imageTarPath(image string) string {
+ cacheDir := os.Getenv("PODMAN_TEST_IMAGE_CACHE_DIR")
+ if cacheDir == "" {
+ cacheDir = os.Getenv("TMPDIR")
+ if cacheDir == "" {
+ cacheDir = "/tmp"
+ }
+ }
+
+ // e.g., registry.com/fubar:latest -> registry.com-fubar-latest.tar
+ imageCacheName := strings.Replace(strings.Replace(image, ":", "-", -1), "/", "-", -1) + ".tar"
+
+ return filepath.Join(cacheDir, imageCacheName)
+}
+
+// createArtifact creates a cached image tarball in a local directory
func (p *PodmanTestIntegration) createArtifact(image string) {
if os.Getenv("NO_TEST_CACHE") != "" {
return
}
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- fmt.Printf("Caching %s at %s...\n", image, destName)
+ destName := imageTarPath(image)
if _, err := os.Stat(destName); os.IsNotExist(err) {
+ fmt.Printf("Caching %s at %s...\n", image, destName)
pull := p.PodmanNoCache([]string{"pull", image})
pull.Wait(440)
Expect(pull).Should(Exit(0))
@@ -326,7 +330,7 @@ func (p *PodmanTestIntegration) createArtifact(image string) {
Expect(save).Should(Exit(0))
fmt.Printf("\n")
} else {
- fmt.Printf(" already exists.\n")
+ fmt.Printf("[image already cached: %s]\n", destName)
}
}
@@ -738,12 +742,13 @@ func (p *PodmanTestIntegration) RestartRemoteService() {
// RestoreArtifactToCache populates the imagecache from tarballs that were cached earlier
func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- p.CrioRoot = p.ImageCacheDir
- restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName})
- restore.WaitWithDefaultTimeout()
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ p.Root = p.ImageCacheDir
+ restore := p.PodmanNoEvents([]string{"load", "-q", "-i", tarball})
+ restore.WaitWithDefaultTimeout()
+ }
return nil
}
@@ -795,7 +800,7 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
}
podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s",
- debug, p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
+ debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index 6bc230aae..2a6f177f2 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -245,7 +245,7 @@ var _ = Describe("Podman run", func() {
session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputStartsWith("search")).To(BeFalse())
+ Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("search"))))
})
It("podman run use containers.conf search domain", func() {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 52d439f4a..321361382 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -107,9 +107,7 @@ var _ = Describe("Podman create", func() {
check := podmanTest.Podman([]string{"inspect", "annotate_test"})
check.WaitWithDefaultTimeout()
data := check.InspectContainerToJSON()
- value, ok := data[0].Config.Annotations["HELLO"]
- Expect(ok).To(BeTrue(), ".Config.Annotations[HELLO]")
- Expect(value).To(Equal("WORLD"))
+ Expect(data[0].Config.Annotations).To(HaveKeyWithValue("HELLO", "WORLD"))
})
It("podman create --entrypoint command", func() {
@@ -386,10 +384,8 @@ var _ = Describe("Podman create", func() {
data := inspect.InspectContainerToJSON()
Expect(len(data)).To(Equal(1), "len(InspectContainerToJSON)")
Expect(len(data[0].Config.Labels)).To(Equal(2))
- _, ok1 := data[0].Config.Labels["TESTKEY1"]
- Expect(ok1).To(BeTrue(), ".Config.Labels[TESTKEY1]")
- _, ok2 := data[0].Config.Labels["TESTKEY2"]
- Expect(ok2).To(BeTrue(), ".Config.Labels[TESTKEY2]")
+ Expect(data[0].Config.Labels).To(HaveKey("TESTKEY1"))
+ Expect(data[0].Config.Labels).To(HaveKey("TESTKEY2"))
})
It("podman create with set label", func() {
@@ -404,12 +400,8 @@ var _ = Describe("Podman create", func() {
data := inspect.InspectContainerToJSON()
Expect(len(data)).To(Equal(1))
Expect(len(data[0].Config.Labels)).To(Equal(2))
- val1, ok1 := data[0].Config.Labels["TESTKEY1"]
- Expect(ok1).To(BeTrue(), ".Config.Labels[TESTKEY1]")
- Expect(val1).To(Equal("value1"))
- val2, ok2 := data[0].Config.Labels["TESTKEY2"]
- Expect(ok2).To(BeTrue(), ".Config.Labels[TESTKEY2]")
- Expect(val2).To(Equal("bar"))
+ Expect(data[0].Config.Labels).To(HaveKeyWithValue("TESTKEY1", "value1"))
+ Expect(data[0].Config.Labels).To(HaveKeyWithValue("TESTKEY2", "bar"))
})
It("podman create with --restart=on-failure:5 parses correctly", func() {
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 62482598a..735334eec 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -606,9 +606,7 @@ var _ = Describe("Podman generate kube", func() {
pod := new(v1.Pod)
err = yaml.Unmarshal(b, pod)
Expect(err).To(BeNil())
- val, found := pod.Annotations[define.BindMountPrefix+vol1]
- Expect(found).To(BeTrue(), "pod.Annotations["+vol1+"]")
- Expect(val).To(HaveSuffix("z"))
+ Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix+vol1, HaveSuffix("z")))
rm := podmanTest.Podman([]string{"pod", "rm", "-t", "0", "-f", "test1"})
rm.WaitWithDefaultTimeout()
@@ -1071,9 +1069,7 @@ USER test1`
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- v, ok := pod.GetAnnotations()["io.containers.autoupdate/top"]
- Expect(ok).To(Equal(true))
- Expect(v).To(Equal("local"))
+ Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate/top", "local"))
})
It("podman generate kube on pod with auto update labels in all containers", func() {
@@ -1100,13 +1096,8 @@ USER test1`
Expect(pod.Spec.Containers[1].WorkingDir).To(Equal("/root"))
for _, ctr := range []string{"top1", "top2"} {
- v, ok := pod.GetAnnotations()["io.containers.autoupdate/"+ctr]
- Expect(ok).To(Equal(true))
- Expect(v).To(Equal("registry"))
-
- v, ok = pod.GetAnnotations()["io.containers.autoupdate.authfile/"+ctr]
- Expect(ok).To(Equal(true))
- Expect(v).To(Equal("/some/authfile.json"))
+ Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate/"+ctr, "registry"))
+ Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate.authfile/"+ctr, "/some/authfile.json"))
}
})
})
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 8e21ca606..9cc04e6b0 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -229,11 +229,10 @@ WORKDIR /test
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- found, _ := result.GrepString("<none>")
if noneTag {
- Expect(found).To(BeTrue())
+ Expect(result.OutputToString()).To(ContainSubstring("<none>"))
} else {
- Expect(found).To(BeFalse())
+ Expect(result.OutputToString()).To(Not(ContainSubstring("<none>")))
}
}
// No "<none>" tag as tagged alpine instances should be present.
diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go
index 2ecbd0eab..d60383029 100644
--- a/test/e2e/libpod_suite_remote_test.go
+++ b/test/e2e/libpod_suite_remote_test.go
@@ -148,7 +148,7 @@ func (p *PodmanTestIntegration) StopRemoteService() {
//MakeOptions assembles all the podman main options
func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s",
- p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
+ p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
@@ -164,15 +164,16 @@ func (p *PodmanTestIntegration) SeedImages() error {
// RestoreArtifact puts the cached image into our test store
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- args := []string{"load", "-q", "-i", destName}
- podmanOptions := getRemoteOptions(p, args)
- command := exec.Command(p.PodmanBinary, podmanOptions...)
- fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
- command.Start()
- command.Wait()
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ args := []string{"load", "-q", "-i", tarball}
+ podmanOptions := getRemoteOptions(p, args)
+ command := exec.Command(p.PodmanBinary, podmanOptions...)
+ fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
+ command.Start()
+ command.Wait()
+ }
return nil
}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 001a869b1..4147ba2c3 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -7,7 +7,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
- "strings"
"github.com/containers/podman/v3/pkg/rootless"
)
@@ -59,11 +58,12 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
// RestoreArtifact puts the cached image into our test store
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName})
- restore.Wait(90)
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ restore := p.PodmanNoEvents([]string{"load", "-q", "-i", tarball})
+ restore.Wait(90)
+ }
return nil
}
diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go
index ad5634e0c..ac70ebd8c 100644
--- a/test/e2e/load_test.go
+++ b/test/e2e/load_test.go
@@ -160,8 +160,7 @@ var _ = Describe("Podman load", func() {
Expect(result).Should(Exit(125))
errMsg := fmt.Sprintf("remote client supports archives only but %q is a directory", podmanTest.TempDir)
- found, _ := result.ErrorGrepString(errMsg)
- Expect(found).Should(BeTrue())
+ Expect(result.ErrorToString()).To(ContainSubstring(errMsg))
})
It("podman load bogus file", func() {
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index ff306f0f8..d56cde9db 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -140,7 +140,7 @@ var _ = Describe("Podman network", func() {
session := podmanTest.Podman([]string{"network", "ls", "--filter", "label=abc"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains(name)).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring(name)))
})
It("podman network ID test", func() {
@@ -208,7 +208,7 @@ var _ = Describe("Podman network", func() {
results := podmanTest.Podman([]string{"network", "ls", "--quiet"})
results.WaitWithDefaultTimeout()
Expect(results).Should(Exit(0))
- Expect(results.LineInOutputContains(name)).To(BeFalse())
+ Expect(results.OutputToString()).To(Not(ContainSubstring(name)))
})
}
diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go
index 223fcc5b2..6b0081171 100644
--- a/test/e2e/prune_test.go
+++ b/test/e2e/prune_test.go
@@ -98,8 +98,7 @@ var _ = Describe("Podman prune", func() {
session := podmanTest.Podman([]string{"images", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- hasNone, _ := session.GrepString("<none>")
- Expect(hasNone).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("<none>")))
numImages := len(session.OutputToStringArray())
// Since there's no dangling image, none should be removed.
@@ -125,8 +124,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"images", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- hasNone, _ = session.GrepString("<none>")
- Expect(hasNone).To(BeTrue()) // ! we have dangling ones
+ Expect(session.OutputToString()).To(ContainSubstring("<none>"))
numImages = len(session.OutputToStringArray())
// Since there's at least one dangling image, prune should
@@ -135,7 +133,7 @@ var _ = Describe("Podman prune", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
numPrunedImages := len(session.OutputToStringArray())
- Expect(numPrunedImages >= 1).To(BeTrue())
+ Expect(numPrunedImages).To(BeNumerically(">=", 1), "numPrunedImages")
// Now make sure that exactly the number of pruned images has
// been removed.
@@ -189,11 +187,11 @@ var _ = Describe("Podman prune", func() {
after := podmanTest.Podman([]string{"images", "-a"})
after.WaitWithDefaultTimeout()
- Expect(none).Should(Exit(0))
- hasNoneAfter, result := none.GrepString("<none>")
+ Expect(after).Should(Exit(0))
+ hasNoneAfter, result := after.GrepString("<none>")
Expect(hasNoneAfter).To(BeTrue())
- Expect(len(after.OutputToStringArray()) > 1).To(BeTrue())
- Expect(len(result) > 0).To(BeTrue())
+ Expect(len(after.OutputToStringArray())).To(BeNumerically(">", 1))
+ Expect(len(result)).To(BeNumerically(">", 0))
})
It("podman image prune unused images", func() {
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/restart_test.go b/test/e2e/restart_test.go
index 6a61c1292..f85a74f47 100644
--- a/test/e2e/restart_test.go
+++ b/test/e2e/restart_test.go
@@ -154,8 +154,8 @@ var _ = Describe("Podman restart", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
timeSince := time.Since(startTime)
- Expect(timeSince < 10*time.Second).To(BeTrue())
- Expect(timeSince > 2*time.Second).To(BeTrue())
+ Expect(timeSince).To(BeNumerically("<", 10*time.Second))
+ Expect(timeSince).To(BeNumerically(">", 2*time.Second))
})
It("Podman restart --all", func() {
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 4f6d974fd..2c2a9688e 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -276,8 +276,7 @@ RUN find $LOCAL
session := podmanTest.Podman([]string{"image", "rm"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(125))
- match, _ := session.ErrorGrepString("image name or ID must be specified")
- Expect(match).To(BeTrue())
+ Expect(session.ErrorToString()).To(ContainSubstring("image name or ID must be specified"))
})
It("podman image rm - concurrent with shared layers", func() {
diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go
index beb6390e0..8b6d535e5 100644
--- a/test/e2e/run_dns_test.go
+++ b/test/e2e/run_dns_test.go
@@ -44,7 +44,7 @@ var _ = Describe("Podman run dns", func() {
session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputStartsWith("search")).To(BeFalse())
+ Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("search"))))
})
It("podman run add bad dns server", func() {
diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go
index f500a3c7c..29f76bad1 100644
--- a/test/e2e/run_entrypoint_test.go
+++ b/test/e2e/run_entrypoint_test.go
@@ -129,6 +129,6 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
session := podmanTest.Podman([]string{"run", "--entrypoint=uname", "foobar.com/entrypoint:latest", "-r"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputStartsWith("Linux")).To(BeFalse())
+ Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("Linux"))))
})
})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index c0840c83b..22ec27346 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -551,8 +551,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "HOSTNAME"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- match, _ := session.GrepString(hostname)
- Expect(match).Should(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring(hostname)))
})
It("podman run --net host hostname test", func() {
@@ -866,7 +865,6 @@ EXPOSE 2004-2005/tcp`, ALPINE)
inspectOut := podmanTest.InspectContainer(ctrName)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Networks)).To(Equal(1))
- _, ok := inspectOut[0].NetworkSettings.Networks["podman"]
- Expect(ok).To(BeTrue())
+ Expect(inspectOut[0].NetworkSettings.Networks).To(HaveKey("podman"))
})
})
diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go
index 05cdc7d80..6d1d26914 100644
--- a/test/e2e/run_passwd_test.go
+++ b/test/e2e/run_passwd_test.go
@@ -38,20 +38,20 @@ var _ = Describe("Podman run passwd", func() {
session := podmanTest.Podman([]string{"run", "--read-only", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("passwd")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("passwd")))
})
It("podman run user specified in container", func() {
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "bin", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("passwd")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("passwd")))
})
It("podman run UID specified in container", func() {
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "2:1", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("passwd")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("passwd")))
})
It("podman run UID not specified in container", func() {
@@ -77,14 +77,14 @@ USER 1000`, ALPINE)
session := podmanTest.Podman([]string{"run", "--read-only", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("/etc/group")))
})
It("podman run group specified in container", func() {
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "root:bin", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("/etc/group")))
})
It("podman run non-numeric group not specified in container", func() {
@@ -97,7 +97,7 @@ USER 1000`, ALPINE)
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "root:11", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("/etc/group")))
})
It("podman run numeric group not specified in container", func() {
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 321bf27ac..f1084a3d2 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -63,9 +63,7 @@ var _ = Describe("Podman privileged container tests", func() {
session := podmanTest.Podman([]string{"run", "--privileged", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- ok, lines := session.GrepString("sysfs")
- Expect(ok).To(BeTrue())
- Expect(lines[0]).To(ContainSubstring("sysfs (rw,"))
+ Expect(session.OutputToString()).To(ContainSubstring("sysfs (rw,"))
})
It("podman privileged CapEff", func() {
diff --git a/test/e2e/run_signal_test.go b/test/e2e/run_signal_test.go
index 49f456366..6bb325155 100644
--- a/test/e2e/run_signal_test.go
+++ b/test/e2e/run_signal_test.go
@@ -116,8 +116,7 @@ var _ = Describe("Podman run with --sig-proxy", func() {
}
session, pid := podmanTest.PodmanPID([]string{"run", "--name", "test2", "--sig-proxy=false", fedoraMinimal, "bash", "-c", sigCatch2})
- ok := WaitForContainer(podmanTest)
- Expect(ok).To(BeTrue())
+ Expect(WaitForContainer(podmanTest)).To(BeTrue(), "WaitForContainer()")
// Kill with given signal
// Should be no output, SIGPOLL is usually ignored
@@ -132,8 +131,7 @@ var _ = Describe("Podman run with --sig-proxy", func() {
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
- ok, _ = session.GrepString("Received")
- Expect(ok).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("Received")))
})
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 6c47e9179..3d4c1240e 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -871,7 +871,7 @@ USER bin`, BB)
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.LineInOutputContains("27(video),777,65533(nogroup)")).To(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("27(video),777,65533(nogroup)")))
})
It("podman run with group-add", func() {
@@ -1151,8 +1151,7 @@ USER mail`, BB)
session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- match, _ := session.GrepString("shared")
- Expect(match).Should(BeFalse())
+ Expect(session.OutputToString()).To(Not(ContainSubstring("shared")))
})
It("podman run findmnt shared", func() {
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 10c191bd9..74aa69c96 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -103,10 +103,8 @@ var _ = Describe("Podman run with volumes", func() {
session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",consistency=delegated,shared", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- found, matches := session.GrepString(dest)
- Expect(found).Should(BeTrue())
- Expect(matches[0]).To(ContainSubstring("rw"))
- Expect(matches[0]).To(ContainSubstring("shared"))
+ Expect(session.OutputToString()).To(ContainSubstring("rw"))
+ Expect(session.OutputToString()).To(ContainSubstring("shared"))
session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=" + dest, ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
@@ -195,20 +193,18 @@ var _ = Describe("Podman run with volumes", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", mountPath + ":" + dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- found, matches := session.GrepString(dest)
- Expect(found).Should(BeTrue())
- Expect(matches[0]).To(Not(ContainSubstring("noexec")))
- Expect(matches[0]).To(Not(ContainSubstring("nodev")))
- Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
+ output := session.OutputToString()
+ Expect(output).To(Not(ContainSubstring("noexec")))
+ Expect(output).To(Not(ContainSubstring("nodev")))
+ Expect(output).To(Not(ContainSubstring("nosuid")))
session = podmanTest.Podman([]string{"run", "--rm", "--tmpfs", dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- found, matches = session.GrepString(dest)
- Expect(found).Should(BeTrue())
- Expect(matches[0]).To(Not(ContainSubstring("noexec")))
- Expect(matches[0]).To(Not(ContainSubstring("nodev")))
- Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
+ output = session.OutputToString()
+ Expect(output).To(Not(ContainSubstring("noexec")))
+ Expect(output).To(Not(ContainSubstring("nodev")))
+ Expect(output).To(Not(ContainSubstring("nosuid")))
})
// Container should start when workdir is overlay volume
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index 54bc5252e..c67ef7ed2 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -6,7 +6,6 @@ import (
"fmt"
"io/ioutil"
"os"
- "regexp"
"strconv"
"text/template"
@@ -107,10 +106,8 @@ registries = ['{{.Host}}:{{.Port}}']`
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
output := string(search.Out.Contents())
- match, _ := regexp.MatchString(`(?m)NAME\s+DESCRIPTION$`, output)
- Expect(match).To(BeTrue())
- match, _ = regexp.MatchString(`(?m)quay.io/libpod/whalesay\s+Static image used for automated testing.+$`, output)
- Expect(match).To(BeTrue())
+ Expect(output).To(MatchRegexp(`(?m)NAME\s+DESCRIPTION$`))
+ Expect(output).To(MatchRegexp(`(?m)quay.io/libpod/whalesay\s+Static image used for automated testing.+$`))
})
It("podman search image with --compatible", func() {
@@ -118,8 +115,7 @@ registries = ['{{.Host}}:{{.Port}}']`
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
output := string(search.Out.Contents())
- match, _ := regexp.MatchString(`(?m)NAME\s+DESCRIPTION\s+STARS\s+OFFICIAL\s+AUTOMATED$`, output)
- Expect(match).To(BeTrue())
+ Expect(output).To(MatchRegexp(`(?m)NAME\s+DESCRIPTION\s+STARS\s+OFFICIAL\s+AUTOMATED$`))
})
It("podman search format flag", func() {
@@ -354,8 +350,7 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search).Should(Exit(125))
Expect(search.OutputToString()).Should(BeEmpty())
- match, _ := search.ErrorGrepString("error")
- Expect(match).Should(BeTrue())
+ Expect(search.ErrorToString()).To(ContainSubstring("error"))
// cleanup
resetRegistriesConfigEnv()
@@ -397,8 +392,7 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search).Should(Exit(125))
Expect(search.OutputToString()).Should(BeEmpty())
- match, _ := search.ErrorGrepString("error")
- Expect(match).Should(BeTrue())
+ Expect(search.ErrorToString()).To(ContainSubstring("error"))
// cleanup
resetRegistriesConfigEnv()
@@ -451,8 +445,7 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search).Should(Exit(125))
Expect(search.OutputToString()).Should(BeEmpty())
- match, _ := search.ErrorGrepString("error")
- Expect(match).Should(BeTrue())
+ Expect(search.ErrorToString()).To(ContainSubstring("error"))
// cleanup
resetRegistriesConfigEnv()
@@ -474,7 +467,7 @@ registries = ['{{.Host}}:{{.Port}}']`
search = podmanTest.Podman([]string{"search", "registry.redhat.io/*openshift*"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray()) > 1).To(BeTrue())
+ Expect(len(search.OutputToStringArray())).To(BeNumerically(">", 1))
})
It("podman search repository tags", func() {
@@ -494,7 +487,7 @@ registries = ['{{.Host}}:{{.Port}}']`
search = podmanTest.Podman([]string{"search", "--list-tags", "docker.io/library/"})
search.WaitWithDefaultTimeout()
- Expect(len(search.OutputToStringArray()) == 0).To(BeTrue())
+ Expect(search.OutputToStringArray()).To(BeEmpty())
})
It("podman search with limit over 100", func() {
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/e2e/volume_rm_test.go b/test/e2e/volume_rm_test.go
index 0119e0f7a..a05c1b593 100644
--- a/test/e2e/volume_rm_test.go
+++ b/test/e2e/volume_rm_test.go
@@ -127,6 +127,6 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray()) >= 2).To(BeTrue())
+ Expect(len(session.OutputToStringArray())).To(BeNumerically(">=", 2))
})
})
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
+}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 944c1ac3c..f41024072 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -36,7 +36,6 @@ type PodmanTestCommon interface {
type PodmanTest struct {
PodmanMakeOptions func(args []string, noEvents, noCache bool) []string
PodmanBinary string
- ArtifactPath string
TempDir string
RemoteTest bool
RemotePodmanBinary string