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/generate/systemd.go8
-rw-r--r--cmd/podman/images/history.go36
-rw-r--r--cmd/podman/images/list.go33
-rw-r--r--cmd/podman/images/mount.go15
-rw-r--r--cmd/podman/images/push.go4
-rw-r--r--cmd/podman/images/search.go35
-rw-r--r--cmd/podman/images/trust_show.go27
-rw-r--r--cmd/podman/inspect/inspect.go4
-rw-r--r--cmd/podman/machine/list.go14
-rw-r--r--cmd/podman/networks/list.go16
-rw-r--r--cmd/podman/pods/inspect.go2
-rw-r--r--cmd/podman/pods/ps.go3
-rw-r--r--cmd/podman/pods/stats.go8
-rw-r--r--cmd/podman/secrets/list.go5
-rw-r--r--cmd/podman/system/connection/list.go9
-rw-r--r--cmd/podman/system/version.go2
-rw-r--r--cmd/podman/volumes/list.go9
-rwxr-xr-xcontrib/cirrus/logformatter34
-rwxr-xr-xcontrib/cirrus/logformatter.t72
-rw-r--r--docs/source/markdown/podman-generate-systemd.1.md5
-rw-r--r--docs/source/markdown/podman-push.1.md4
-rw-r--r--docs/source/markdown/podman-save.1.md25
-rw-r--r--docs/source/markdown/podman-unshare.1.md5
-rw-r--r--docs/tutorials/remote_client.md10
-rw-r--r--go.mod6
-rw-r--r--go.sum18
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/container_top_linux.go18
-rw-r--r--libpod/kube.go65
-rw-r--r--libpod/networking_linux.go26
-rw-r--r--pkg/api/handlers/compat/images.go12
-rw-r--r--pkg/api/handlers/compat/images_push.go10
-rw-r--r--pkg/api/handlers/libpod/generate.go2
-rw-r--r--pkg/api/server/register_generate.go5
-rw-r--r--pkg/bindings/generate/types.go2
-rw-r--r--pkg/bindings/generate/types_systemd_options.go15
-rw-r--r--pkg/bindings/images/build.go5
-rw-r--r--pkg/domain/entities/generate.go2
-rw-r--r--pkg/domain/entities/images.go2
-rw-r--r--pkg/domain/infra/abi/generate.go12
-rw-r--r--pkg/domain/infra/abi/images.go17
-rw-r--r--pkg/domain/infra/abi/play.go71
-rw-r--r--pkg/domain/infra/abi/system.go7
-rw-r--r--pkg/domain/infra/tunnel/generate.go3
-rw-r--r--pkg/specgen/generate/kube/kube.go12
-rw-r--r--pkg/specgen/generate/kube/volume.go64
-rw-r--r--pkg/specgen/generate/oci.go8
-rw-r--r--pkg/specgenutil/specgen.go17
-rw-r--r--pkg/systemd/generate/pods.go9
-rw-r--r--pkg/systemd/generate/pods_test.go46
-rw-r--r--test/apiv2/10-images.at7
-rw-r--r--test/e2e/build_test.go8
-rw-r--r--test/e2e/checkpoint_test.go18
-rw-r--r--test/e2e/commit_test.go12
-rw-r--r--test/e2e/common_test.go61
-rw-r--r--test/e2e/container_create_volume_test.go10
-rw-r--r--test/e2e/containers_conf_test.go2
-rw-r--r--test/e2e/create_test.go54
-rw-r--r--test/e2e/diff_test.go12
-rw-r--r--test/e2e/events_test.go4
-rw-r--r--test/e2e/exec_test.go4
-rw-r--r--test/e2e/generate_kube_test.go47
-rw-r--r--test/e2e/generate_systemd_test.go13
-rw-r--r--test/e2e/healthcheck_run_test.go2
-rw-r--r--test/e2e/history_test.go2
-rw-r--r--test/e2e/image_scp_test.go2
-rw-r--r--test/e2e/images_test.go40
-rw-r--r--test/e2e/inspect_test.go36
-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/logs_test.go24
-rw-r--r--test/e2e/mount_test.go2
-rw-r--r--test/e2e/network_test.go16
-rw-r--r--test/e2e/pause_test.go6
-rw-r--r--test/e2e/play_build_test.go12
-rw-r--r--test/e2e/play_kube_test.go130
-rw-r--r--test/e2e/pod_create_test.go10
-rw-r--r--test/e2e/pod_infra_container_test.go20
-rw-r--r--test/e2e/pod_inspect_test.go2
-rw-r--r--test/e2e/pod_pod_namespaces_test.go4
-rw-r--r--test/e2e/pod_prune_test.go4
-rw-r--r--test/e2e/pod_ps_test.go6
-rw-r--r--test/e2e/pod_rm_test.go2
-rw-r--r--test/e2e/pod_top_test.go4
-rw-r--r--test/e2e/prune_test.go54
-rw-r--r--test/e2e/ps_test.go56
-rw-r--r--test/e2e/pull_test.go14
-rw-r--r--test/e2e/push_test.go32
-rw-r--r--test/e2e/restart_test.go4
-rw-r--r--test/e2e/rmi_test.go17
-rw-r--r--test/e2e/run_dns_test.go2
-rw-r--r--test/e2e/run_entrypoint_test.go10
-rw-r--r--test/e2e/run_env_test.go2
-rw-r--r--test/e2e/run_networking_test.go146
-rw-r--r--test/e2e/run_passwd_test.go12
-rw-r--r--test/e2e/run_privileged_test.go6
-rw-r--r--test/e2e/run_signal_test.go6
-rw-r--r--test/e2e/run_test.go17
-rw-r--r--test/e2e/run_userns_test.go2
-rw-r--r--test/e2e/run_volume_test.go40
-rw-r--r--test/e2e/search_test.go31
-rw-r--r--test/e2e/secret_test.go8
-rw-r--r--test/e2e/stats_test.go2
-rw-r--r--test/e2e/system_connection_test.go2
-rw-r--r--test/e2e/system_df_test.go2
-rw-r--r--test/e2e/system_reset_test.go6
-rw-r--r--test/e2e/systemd_test.go6
-rw-r--r--test/e2e/top_test.go5
-rw-r--r--test/e2e/trust_test.go6
-rw-r--r--test/e2e/volume_create_test.go4
-rw-r--r--test/e2e/volume_inspect_test.go2
-rw-r--r--test/e2e/volume_ls_test.go22
-rw-r--r--test/e2e/volume_plugin_test.go8
-rw-r--r--test/e2e/volume_prune_test.go22
-rw-r--r--test/e2e/volume_rm_test.go10
-rw-r--r--test/system/010-images.bats2
-rw-r--r--test/system/110-history.bats8
-rw-r--r--test/system/180-blkio.bats69
-rw-r--r--test/utils/utils.go1
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go2
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go3
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf6
-rw-r--r--vendor/github.com/containers/common/pkg/config/nosystemd.go4
-rw-r--r--vendor/github.com/containers/common/pkg/config/systemd.go20
-rw-r--r--vendor/github.com/containers/common/pkg/manifests/manifests.go2
-rw-r--r--vendor/github.com/containers/storage/.cirrus.yml4
-rw-r--r--vendor/github.com/containers/storage/Vagrantfile25
-rw-r--r--vendor/github.com/containers/storage/go.mod1
-rw-r--r--vendor/github.com/containers/storage/go.sum2
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/archive.go7
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/storage_linux.go327
-rw-r--r--vendor/github.com/containers/storage/types/options.go4
-rw-r--r--vendor/github.com/jinzhu/copier/copier.go13
-rw-r--r--vendor/github.com/jinzhu/copier/go.mod2
-rw-r--r--vendor/github.com/mitchellh/mapstructure/CHANGELOG.md4
-rw-r--r--vendor/github.com/mitchellh/mapstructure/mapstructure.go8
-rw-r--r--vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go3
-rw-r--r--vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go3
-rw-r--r--vendor/github.com/opencontainers/image-spec/specs-go/version.go2
-rw-r--r--vendor/modules.txt10
147 files changed, 1719 insertions, 931 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/generate/systemd.go b/cmd/podman/generate/systemd.go
index 173b3656b..a363b7e94 100644
--- a/cmd/podman/generate/systemd.go
+++ b/cmd/podman/generate/systemd.go
@@ -23,6 +23,7 @@ const (
stopTimeoutFlagName = "stop-timeout"
stopTimeoutCompatFlagName = "time"
restartPolicyFlagName = "restart-policy"
+ restartSecFlagName = "restart-sec"
newFlagName = "new"
)
@@ -30,6 +31,7 @@ var (
files bool
format string
systemdRestart string
+ systemdRestartSec uint
startTimeout uint
stopTimeout uint
systemdOptions = entities.GenerateSystemdOptions{}
@@ -88,6 +90,9 @@ func init() {
flags.StringVar(&systemdRestart, restartPolicyFlagName, systemDefine.DefaultRestartPolicy, "Systemd restart-policy")
_ = systemdCmd.RegisterFlagCompletionFunc(restartPolicyFlagName, common.AutocompleteSystemdRestartOptions)
+ flags.UintVarP(&systemdRestartSec, restartSecFlagName, "", 0, "Systemd restart-sec")
+ _ = systemdCmd.RegisterFlagCompletionFunc(restartSecFlagName, completion.AutocompleteNone)
+
formatFlagName := "format"
flags.StringVar(&format, formatFlagName, "", "Print the created units in specified format (json)")
_ = systemdCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(nil))
@@ -111,6 +116,9 @@ func systemd(cmd *cobra.Command, args []string) error {
systemdOptions.New = true
}
+ if cmd.Flags().Changed(restartSecFlagName) {
+ systemdOptions.RestartSec = &systemdRestartSec
+ }
if cmd.Flags().Changed(startTimeoutFlagName) {
systemdOptions.StartTimeout = &startTimeout
}
diff --git a/cmd/podman/images/history.go b/cmd/podman/images/history.go
index cc7b1b4eb..ac693a87b 100644
--- a/cmd/podman/images/history.go
+++ b/cmd/podman/images/history.go
@@ -1,7 +1,6 @@
package images
import (
- "context"
"fmt"
"os"
"strings"
@@ -79,7 +78,7 @@ func historyFlags(cmd *cobra.Command) {
}
func history(cmd *cobra.Command, args []string) error {
- results, err := registry.ImageEngine().History(context.Background(), args[0], entities.ImageHistoryOptions{})
+ results, err := registry.ImageEngine().History(registry.Context(), args[0], entities.ImageHistoryOptions{})
if err != nil {
return err
}
@@ -111,37 +110,32 @@ func history(cmd *cobra.Command, args []string) error {
hr = append(hr, historyReporter{l})
}
- hdrs := report.Headers(historyReporter{}, map[string]string{
- "CreatedBy": "CREATED BY",
- })
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- // Defaults
- row := "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
switch {
- case cmd.Flags().Changed("format"):
- row = report.NormalizeFormat(opts.format)
case opts.quiet:
- row = "{{.ID}}\n"
+ rpt, err = rpt.Parse(report.OriginUser, "{{range .}}{{.ID}}\n{{end -}}")
+ case cmd.Flags().Changed("format"):
+ rpt, err = rpt.Parse(report.OriginUser, cmd.Flag("format").Value.String())
+ default:
+ format := "{{range .}}{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n{{end -}}"
+ rpt, err = rpt.Parse(report.OriginPodman, format)
}
- format := report.EnforceRange(row)
-
- tmpl, err := report.NewTemplate("history").Parse(format)
if err != nil {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- defer w.Flush()
+ if rpt.RenderHeaders {
+ hdrs := report.Headers(historyReporter{}, map[string]string{
+ "CreatedBy": "CREATED BY",
+ })
- if !opts.quiet && !cmd.Flags().Changed("format") {
- if err := tmpl.Execute(w, hdrs); err != nil {
+ if err := rpt.Execute(hdrs); err != nil {
return errors.Wrapf(err, "failed to write report column headers")
}
}
- return tmpl.Execute(w, hr)
+ return rpt.Execute(hr)
}
type historyReporter struct {
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go
index 01286daf2..61514daa7 100644
--- a/cmd/podman/images/list.go
+++ b/cmd/podman/images/list.go
@@ -117,7 +117,7 @@ func images(cmd *cobra.Command, args []string) error {
listOptions.Filter = append(listOptions.Filter, "reference="+args[0])
}
- if cmd.Flag("sort").Changed && !sortFields.Contains(listFlag.sort) {
+ if cmd.Flags().Changed("sort") && !sortFields.Contains(listFlag.sort) {
return fmt.Errorf("\"%s\" is not a valid field for sorting. Choose from: %s",
listFlag.sort, sortFields.String())
}
@@ -140,7 +140,7 @@ func images(cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) {
listFlag.noHeading = true
}
- return writeTemplate(imgs)
+ return writeTemplate(cmd, imgs)
}
}
@@ -186,38 +186,31 @@ func writeJSON(images []imageReporter) error {
return nil
}
-func writeTemplate(imgs []imageReporter) error {
+func writeTemplate(cmd *cobra.Command, imgs []imageReporter) error {
hdrs := report.Headers(imageReporter{}, map[string]string{
"ID": "IMAGE ID",
"ReadOnly": "R/O",
})
- var format string
- if listFlag.format == "" {
- format = lsFormatFromFlags(listFlag)
- } else {
- format = report.NormalizeFormat(listFlag.format)
- format = report.EnforceRange(format)
- }
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- tmpl, err := report.NewTemplate("list").Parse(format)
- if err != nil {
- return err
+ var err error
+ if cmd.Flags().Changed("format") {
+ rpt, err = rpt.Parse(report.OriginUser, cmd.Flag("format").Value.String())
+ } else {
+ rpt, err = rpt.Parse(report.OriginPodman, lsFormatFromFlags(listFlag))
}
-
- w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
- defer w.Flush()
- if !listFlag.noHeading {
- if err := tmpl.Execute(w, hdrs); err != nil {
+ if rpt.RenderHeaders && !listFlag.noHeading {
+ if err := rpt.Execute(hdrs); err != nil {
return err
}
}
-
- return tmpl.Execute(w, imgs)
+ return rpt.Execute(imgs)
}
func sortImages(imageS []*entities.ImageSummary) ([]imageReporter, error) {
diff --git a/cmd/podman/images/mount.go b/cmd/podman/images/mount.go
index 89c00cb70..cdeb9eecf 100644
--- a/cmd/podman/images/mount.go
+++ b/cmd/podman/images/mount.go
@@ -87,7 +87,7 @@ func mount(cmd *cobra.Command, args []string) error {
case report.IsJSON(mountOpts.Format):
return printJSON(reports)
case mountOpts.Format == "":
- break // default format
+ break // see default format below
default:
return errors.Errorf("unknown --format argument: %q", mountOpts.Format)
}
@@ -97,19 +97,12 @@ func mount(cmd *cobra.Command, args []string) error {
mrs = append(mrs, mountReporter{r})
}
- row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}"
- tmpl, err := report.NewTemplate("mounts").Parse(row)
+ rpt, err := report.New(os.Stdout, cmd.Name()).Parse(report.OriginPodman, "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}")
if err != nil {
return err
}
-
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- defer w.Flush()
-
- return tmpl.Execute(w, mrs)
+ defer rpt.Flush()
+ return rpt.Execute(mrs)
}
func printJSON(reports []*entities.ImageMountReport) error {
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/cmd/podman/images/search.go b/cmd/podman/images/search.go
index c9a4793aa..0791ac02c 100644
--- a/cmd/podman/images/search.go
+++ b/cmd/podman/images/search.go
@@ -149,9 +149,9 @@ func imageSearch(cmd *cobra.Command, args []string) error {
searchReport[i].Description = d
}
- hdrs := report.Headers(entities.ImageSearchReport{}, nil)
- renderHeaders := true
- var row string
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
switch {
case searchOptions.ListTags:
if len(searchOptions.Filters) != 0 {
@@ -161,39 +161,30 @@ func imageSearch(cmd *cobra.Command, args []string) error {
listTagsEntries := buildListTagsJSON(searchReport)
return printArbitraryJSON(listTagsEntries)
}
- row = "{{.Name}}\t{{.Tag}}\n"
+ rpt, err = rpt.Parse(report.OriginPodman, "{{range .}}{{.Name}}\t{{.Tag}}\n{{end -}}")
case isJSON:
return printArbitraryJSON(searchReport)
case cmd.Flags().Changed("format"):
- renderHeaders = report.HasTable(searchOptions.Format)
- row = report.NormalizeFormat(searchOptions.Format)
+ rpt, err = rpt.Parse(report.OriginUser, searchOptions.Format)
default:
- row = "{{.Name}}\t{{.Description}}"
+ row := "{{.Name}}\t{{.Description}}"
if searchOptions.Compatible {
row += "\t{{.Stars}}\t{{.Official}}\t{{.Automated}}"
}
- row += "\n"
+ row = "{{range . }}" + row + "\n{{end -}}"
+ rpt, err = rpt.Parse(report.OriginPodman, row)
}
- format := report.EnforceRange(row)
-
- tmpl, err := report.NewTemplate("search").Parse(format)
if err != nil {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- defer w.Flush()
-
- if renderHeaders {
- if err := tmpl.Execute(w, hdrs); err != nil {
- return errors.Wrapf(err, "failed to write search column headers")
+ if rpt.RenderHeaders {
+ hdrs := report.Headers(entities.ImageSearchReport{}, nil)
+ if err := rpt.Execute(hdrs); err != nil {
+ return errors.Wrapf(err, "failed to write report column headers")
}
}
-
- return tmpl.Execute(w, searchReport)
+ return rpt.Execute(searchReport)
}
func printArbitraryJSON(v interface{}) error {
diff --git a/cmd/podman/images/trust_show.go b/cmd/podman/images/trust_show.go
index c0e56f504..04ea24ca5 100644
--- a/cmd/podman/images/trust_show.go
+++ b/cmd/podman/images/trust_show.go
@@ -48,11 +48,12 @@ func showTrust(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- if showTrustOptions.Raw {
+
+ switch {
+ case showTrustOptions.Raw:
fmt.Println(string(trust.Raw))
return nil
- }
- if showTrustOptions.JSON {
+ case showTrustOptions.JSON:
b, err := json.MarshalIndent(trust.Policies, "", " ")
if err != nil {
return err
@@ -60,23 +61,13 @@ func showTrust(cmd *cobra.Command, args []string) error {
fmt.Println(string(b))
return nil
}
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- format := "{{range . }}{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}"
- tmpl, err := report.NewTemplate("list").Parse(format)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
+ rpt, err = rpt.Parse(report.OriginPodman,
+ "{{range . }}{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}")
if err != nil {
return err
}
-
- if err := tmpl.Execute(w, trust.Policies); err != nil {
- return err
- }
- if err := w.Flush(); err != nil {
- return err
- }
- return nil
+ return rpt.Execute(trust.Policies)
}
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index 64b586388..c982b1b7f 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -215,8 +215,10 @@ func (i *inspector) inspect(namesOrIDs []string) error {
case report.IsJSON(i.options.Format) || i.options.Format == "":
err = printJSON(data)
default:
+ // Landing here implies user has given a custom --format
row := inspectNormalize(i.options.Format)
- row = "{{range . }}" + report.NormalizeFormat(row) + "{{end -}}"
+ row = report.NormalizeFormat(row)
+ row = report.EnforceRange(row)
err = printTmpl(tmpType, row, data)
}
if err != nil {
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index d569f4db0..774ab4fd0 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -116,7 +116,15 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
"DiskSize": "DISK SIZE",
})
- row := report.NormalizeFormat(listFlag.format)
+ var row string
+ switch {
+ case cmd.Flags().Changed("format"):
+ row = cmd.Flag("format").Value.String()
+ listFlag.noHeading = !report.HasTable(row)
+ row = report.NormalizeFormat(row)
+ default:
+ row = cmd.Flag("format").Value.String()
+ }
format := report.EnforceRange(row)
tmpl, err := report.NewTemplate("list").Parse(format)
@@ -130,10 +138,6 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
}
defer w.Flush()
- if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) {
- listFlag.noHeading = true
- }
-
if !listFlag.noHeading {
if err := tmpl.Execute(w, headers); err != nil {
return errors.Wrapf(err, "failed to write report column headers")
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 124a17d5d..6f1a7742a 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -84,7 +84,7 @@ func networkList(cmd *cobra.Command, args []string) error {
// table or other format output
default:
- err = templateOut(responses, cmd)
+ err = templateOut(cmd, responses)
}
return err
@@ -105,7 +105,7 @@ func jsonOut(responses []types.Network) error {
return nil
}
-func templateOut(responses []types.Network, cmd *cobra.Command) error {
+func templateOut(cmd *cobra.Command, responses []types.Network) error {
nlprs := make([]ListPrintReports, 0, len(responses))
for _, r := range responses {
nlprs = append(nlprs, ListPrintReports{r})
@@ -120,14 +120,16 @@ func templateOut(responses []types.Network, cmd *cobra.Command) error {
})
renderHeaders := report.HasTable(networkListOptions.Format)
- var row, format string
- if cmd.Flags().Changed("format") {
+ var row string
+ switch {
+ case cmd.Flags().Changed("format"):
row = report.NormalizeFormat(networkListOptions.Format)
- } else { // 'podman network ls' equivalent to 'podman network ls --format="table {{.ID}} {{.Name}} {{.Version}} {{.Plugins}}" '
- renderHeaders = true
+ default:
+ // 'podman network ls' equivalent to 'podman network ls --format="table {{.ID}} {{.Name}} {{.Version}} {{.Plugins}}" '
row = "{{.ID}}\t{{.Name}}\t{{.Driver}}\n"
+ renderHeaders = true
}
- format = report.EnforceRange(row)
+ format := report.EnforceRange(row)
tmpl, err := report.NewTemplate("list").Parse(format)
if err != nil {
diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go
index 96eaec3b9..d4b8df90e 100644
--- a/cmd/podman/pods/inspect.go
+++ b/cmd/podman/pods/inspect.go
@@ -64,11 +64,13 @@ func inspect(cmd *cobra.Command, args []string) error {
}
if report.IsJSON(inspectOptions.Format) {
+ json.MarshalIndent(responses, "", " ")
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(responses)
}
+ // cmd.Flags().Changed("format") must be true to reach this code
row := report.NormalizeFormat(inspectOptions.Format)
t, err := report.NewTemplate("inspect").Parse(row)
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 60aadf224..808ec31b3 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -136,11 +136,12 @@ func pods(cmd *cobra.Command, _ []string) error {
renderHeaders = report.HasTable(psInput.Format)
row = report.NormalizeFormat(psInput.Format)
}
+ format := report.EnforceRange(row)
+
noHeading, _ := cmd.Flags().GetBool("noheading")
if noHeading {
renderHeaders = false
}
- format := report.EnforceRange(row)
tmpl, err := report.NewTemplate("list").Parse(format)
if err != nil {
diff --git a/cmd/podman/pods/stats.go b/cmd/podman/pods/stats.go
index ba2c1495b..a7bba3064 100644
--- a/cmd/podman/pods/stats.go
+++ b/cmd/podman/pods/stats.go
@@ -67,9 +67,7 @@ func stats(cmd *cobra.Command, args []string) error {
return err
}
- row := report.NormalizeFormat(statsOptions.Format)
- doJSON := report.IsJSON(row)
-
+ doJSON := report.IsJSON(cmd.Flag("format").Value.String())
headers := report.Headers(entities.PodStatsReport{}, map[string]string{
"CPU": "CPU %",
"MemUsage": "MEM USAGE/ LIMIT",
@@ -96,6 +94,8 @@ func stats(cmd *cobra.Command, args []string) error {
goterm.Flush()
}
if cmd.Flags().Changed("format") {
+ row := report.NormalizeFormat(statsOptions.Format)
+ row = report.EnforceRange(row)
if err := printFormattedPodStatsLines(headers, row, reports); err != nil {
return err
}
@@ -143,8 +143,6 @@ func printFormattedPodStatsLines(headerNames []map[string]string, row string, st
return nil
}
- row = report.EnforceRange(row)
-
tmpl, err := report.NewTemplate("stats").Parse(row)
if err != nil {
return err
diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go
index f136de4ab..255d9ae1a 100644
--- a/cmd/podman/secrets/list.go
+++ b/cmd/podman/secrets/list.go
@@ -71,7 +71,10 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.SecretListReport)
"UpdatedAt": "UPDATED",
})
- row := report.NormalizeFormat(listFlag.format)
+ row := cmd.Flag("format").Value.String()
+ if cmd.Flags().Changed("format") {
+ row = report.NormalizeFormat(row)
+ }
format := report.EnforceRange(row)
tmpl, err := report.NewTemplate("list").Parse(format)
diff --git a/cmd/podman/system/connection/list.go b/cmd/podman/system/connection/list.go
index f1f7657ad..2710142a8 100644
--- a/cmd/podman/system/connection/list.go
+++ b/cmd/podman/system/connection/list.go
@@ -82,7 +82,7 @@ func list(cmd *cobra.Command, _ []string) error {
return rows[i].Name < rows[j].Name
})
- format := "{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.Default}}\n"
+ var format string
switch {
case report.IsJSON(cmd.Flag("format").Value.String()):
buf, err := registry.JSONLibrary().MarshalIndent(rows, "", " ")
@@ -90,11 +90,10 @@ func list(cmd *cobra.Command, _ []string) error {
fmt.Println(string(buf))
}
return err
+ case cmd.Flags().Changed("format"):
+ format = report.NormalizeFormat(cmd.Flag("format").Value.String())
default:
- if cmd.Flag("format").Changed {
- format = cmd.Flag("format").Value.String()
- format = report.NormalizeFormat(format)
- }
+ format = "{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.Default}}\n"
}
format = report.EnforceRange(format)
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index 3443978d6..87b806503 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -59,7 +59,7 @@ func version(cmd *cobra.Command, args []string) error {
}
defer w.Flush()
- if cmd.Flag("format").Changed {
+ if cmd.Flags().Changed("format") {
row := report.NormalizeFormat(versionFormat)
tmpl, err := report.NewTemplate("version 2.0.0").Parse(row)
if err != nil {
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index 0243054af..c372527de 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -97,9 +97,14 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.VolumeListReport)
"Name": "VOLUME NAME",
})
- row := report.NormalizeFormat(cliOpts.Format)
- if cliOpts.Quiet {
+ var row string
+ switch {
+ case cliOpts.Quiet:
row = "{{.Name}}\n"
+ case cmd.Flags().Changed("format"):
+ row = report.NormalizeFormat(cliOpts.Format)
+ default:
+ row = cmd.Flag("format").Value.String()
}
format := report.EnforceRange(row)
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter
index 5156f9f8a..70f119b5b 100755
--- a/contrib/cirrus/logformatter
+++ b/contrib/cirrus/logformatter
@@ -37,12 +37,15 @@ table.synopsis { border: none; border-collapse: collapse; margin-left: 2em; marg
.synopsis td { font-weight: bold; font-size: 120%; font-family: monospace; }
/* test results */
+.testname { font-size: 125%; color: #444; }
.boring { color: #999; }
.timestamp { color: #999; }
.log-debug { color: #999; }
.log-info { color: #333; }
.log-warn { color: #f60; }
.log-error { color: #900; font-weight: bold; }
+.log-skip { color: #F90; }
+.log-slow { background: #FF0; color: #000; font-weight: bold; }
.subtest { background: #eee; }
.subsubtest { color: #F39; font-weight: bold; }
.string { color: #00c; }
@@ -205,11 +208,17 @@ END_HTML
print { $out_fh } "<pre> <!-- begin processed output -->\n";
+ # Assume rootful prompt, check for rootless (here and in log itself, below)
+ my $Prompt = '#';
+ $Prompt = '$' if $test_name =~ /rootless/;
+
# Main loop: read input, one line at a time, and write out reformatted
LINE:
while (my $line = <STDIN>) {
print $line; # Immediately dump back to stdout
+ $Prompt = '$' if $line =~ /Runner executing .* as rootless /;
+
# Remain robust in face of errors: always write stdout even if no HTML
next LINE if ! $out_fh;
@@ -328,7 +337,7 @@ END_HTML
next LINE;
}
# (bindings test sometimes emits 'Running' with leading bullet char)
- elsif ($line =~ /^•?Running:/) {
+ elsif ($line =~ s!^•?Running:!<span class="boring">$Prompt</span>!) {
# Highlight the important (non-boilerplate) podman command.
$line =~ s/\s+--remote\s+/ /g; # --remote takes no args
# Strip out the global podman options, but show them on hover
@@ -365,19 +374,27 @@ END_HTML
# an anchor so we can link to it later.
if ($after_divider++ == 2) {
# Sigh. There is no actual marker. Assume that anything with
- ## two leading spaces then alpha (not slashes) is a test name.
- if ($line =~ /^ [a-zA-Z]/) {
+ ## two leading spaces then alpha or hyphen (not slashes) is
+ ## a test name.
+ if ($line =~ /^ [a-zA-Z-]/) {
my $id = make_id($line, 'anchor');
$line = "<a name='t--$id'><h2>$line</h2></a>";
}
}
+ # Make SKIPPING and SLOW TEST visible
+ $line =~ s!(\[SKIPPING\].*)!<span class="log-skip">$1</span>!;
+ $line =~ s!(\[SLOW TEST.*\])!<span class="log-slow">$1</span>!;
+
+ # Highlight test name when it appears in the middle of commands.
+ # But make it boring, because we already have the test name in large
+ # bold just above. (Except in skipped tests).
+ $line =~ s!^(\s*)(\[It\]\s+.*)!$1<span class="testname">$2</span>!;
+
# Failure name corresponds to a previously-seen block.
- ## FIXME: sometimes there are three failures with the same name.
- ## ...I have no idea why or how to link to the right ones.
- # 1 2 2 3 3 14 4
- if ($line =~ /^(\[(Fail|Panic!)\] .* \[(It|BeforeEach)\] )([A-Za-z].*)/) {
+ # 1 2 2 3 3 14 4
+ if ($line =~ /^(\[(Fail|Panic!)\] .* \[(It|BeforeEach)\] )([A-Za-z-].*)/) {
my ($lhs, $type, $ginkgo_fluff, $testname) = ($1, $2, $3, $4);
my $id = make_id($testname, 'link');
@@ -486,7 +503,10 @@ sub make_id {
state %counter;
$name =~ s/^\s+|\s+$//g; # strip leading/trailing whitespace
+ $name =~ s/\&#\d+;//g; # 'doesn&#39;t' -> 'doesnt'
+ $name =~ s/\&quot;/-/g; # '&quot;path&quot;' -> '-path-'
$name =~ s/[^a-zA-Z0-9_-]/-/g; # Convert non-alphanumeric to dash
+ $name =~ s/-{3,}/-/g; # '------' to just '-'
# Keep a running tally of how many times we've seen this identifier
# for this given type! This lets us cross-match, in the bottom of
diff --git a/contrib/cirrus/logformatter.t b/contrib/cirrus/logformatter.t
index bd4179b5e..d905693ad 100755
--- a/contrib/cirrus/logformatter.t
+++ b/contrib/cirrus/logformatter.t
@@ -134,9 +134,35 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}
[+0103s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
[+0104s] Running: /var/tmp/go/src/github.com/containers/libpod/bin/podman-remote --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --cni-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs --remote --url unix:/run/user/12345/podman-xyz.sock pod rm -fa
[+0104s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 again
+
+
[+0107s] •
-[+0107s] ------------------------------
-[+0107s] podman system reset
+[+0523s] ------------------------------
+[+0523s] Podman play kube with build
+[+0523s] --build should override image in store
+[+0523s] /var/tmp/go/src/github.com/containers/podman/test/e2e/play_build_test.go:215
+
+
+[+0479s] •
+[+0479s] ------------------------------
+[+0479s] Podman pod rm
+[+0479s] podman pod rm -a doesn't remove a running container
+[+0479s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_rm_test.go:119
+
+
+[+1405s] •
+[+1405s] ------------------------------
+[+1405s] Podman run entrypoint
+[+1405s] podman run entrypoint == [""]
+[+1405s] /var/tmp/go/src/github.com/containers/podman/test/e2e/run_entrypoint_test.go:47
+
+[+0184s] S [SKIPPING] [3.086 seconds]
+[+1385s] S [SKIPPING] in Spec Setup (BeforeEach) [0.001 seconds]
+
+[+1512s] Summarizing 6 Failures:
+[+1512s]
+[+1512s] [Fail] Podman play kube with build [It] --build should override image in store
+[+1512s] /var/tmp/go/src/github.com/containers/podman/test/e2e/play_build_test.go:259
>>>
$SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
[08:26:19] START - All [+xxxx] lines that follow are relative to right now.
@@ -150,9 +176,9 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/podman/test/e2e/pod_restart_test.go:41</a>
<span class="timestamp"> </span>[BeforeEach] Podman pod restart
<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L18'>/containers/podman/test/e2e/pod_restart_test.go:18</a>
-<span class="timestamp"> </span>[It] podman pod restart single empty pod
+<span class="timestamp"> </span><span class="testname">[It] podman pod restart single empty pod</span>
<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/podman/test/e2e/pod_restart_test.go:41</a>
-<span class="timestamp"> </span>Running: <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
+<span class="timestamp"> </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
--root /tmp/podman_test553496330/crio
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
@@ -163,7 +189,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--events-backend file
--storage-driver vfs">[options]</span><b> pod create --infra=false --share</b>
<span class="timestamp"> </span>4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
-<span class="timestamp"> </span>Running: <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
+<span class="timestamp"> </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
--root /tmp/podman_test553496330/crio
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
@@ -177,7 +203,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
<span class="timestamp"> </span>output:
<span class="timestamp"> </span>[AfterEach] Podman pod restart
<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L28'>/containers/podman/test/e2e/pod_restart_test.go:28</a>
-<span class="timestamp"> </span>Running: <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
+<span class="timestamp"> </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
--root /tmp/podman_test553496330/crio
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
@@ -189,7 +215,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--storage-driver vfs">[options]</span><b> pod rm -fa</b>
<span class="timestamp"> </span>4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
-<span class="timestamp">[+0104s] </span>Running: <span title="/var/tmp/go/src/github.com/containers/libpod/bin/podman-remote"><b>podman-remote</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
+<span class="timestamp">[+0104s] </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/libpod/bin/podman-remote"><b>podman-remote</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir
--root /tmp/podman_test553496330/crio
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
@@ -207,4 +233,34 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
</pre>
<hr />
<pre>
-<span class="timestamp">[+0107s] </span>podman system reset
+<span class="timestamp">[+0523s] </span>Podman play kube with build
+<span class="timestamp"> </span><a name='t----build-should-override-image-in-store--1'><h2> --build should override image in store</h2></a>
+<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/play_build_test.go#L215'>/containers/podman/test/e2e/play_build_test.go:215</a>
+
+
+<span class="timestamp">[+0479s] </span>•
+</pre>
+<hr />
+<pre>
+<span class="timestamp">[+0479s] </span>Podman pod rm
+<span class="timestamp"> </span><a name='t--podman-pod-rm--a-doesnt-remove-a-running-container--1'><h2> podman pod rm -a doesn&#39;t remove a running container</h2></a>
+<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_rm_test.go#L119'>/containers/podman/test/e2e/pod_rm_test.go:119</a>
+
+
+<span class="timestamp">[+1405s] </span>•
+</pre>
+<hr />
+<pre>
+<span class="timestamp">[+1405s] </span>Podman run entrypoint
+<span class="timestamp"> </span><a name='t--podman-run-entrypoint---1'><h2> podman run entrypoint == [&quot;&quot;]</h2></a>
+<span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/run_entrypoint_test.go#L47'>/containers/podman/test/e2e/run_entrypoint_test.go:47</a>
+
+
+<span class="timestamp">[+0184s] </span>S <span class="log-skip">[SKIPPING] [3.086 seconds]</span>
+<span class="timestamp">[+1385s] </span>S <span class="log-skip">[SKIPPING] in Spec Setup (BeforeEach) [0.001 seconds]</span>
+
+
+<span class="timestamp">[+1512s] </span>Summarizing 6 Failures:
+[+1512s]
+<span class="timestamp"> </span><b>[Fail] Podman play kube with build [It] <a href='#t----build-should-override-image-in-store--1'>--build should override image in store</a></b>
+<span class="timestamp"> </span>/var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/play_build_test.go#L259'>/containers/podman/test/e2e/play_build_test.go:259</a>
diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md
index bdcaa8ef1..363d042ae 100644
--- a/docs/source/markdown/podman-generate-systemd.1.md
+++ b/docs/source/markdown/podman-generate-systemd.1.md
@@ -51,6 +51,11 @@ Override the default stop timeout for the container with the given value in seco
Set the systemd restart policy. The restart-policy must be one of: "no", "on-success", "on-failure", "on-abnormal",
"on-watchdog", "on-abort", or "always". The default policy is *on-failure*.
+#### **--restart-sec**=*time*
+
+Set the systemd service restartsec value. Configures the time to sleep before restarting a service (as configured with restart-policy).
+Takes a value in seconds.
+
#### **--container-prefix**=*prefix*
Set the systemd unit name prefix for containers. The default is *container*.
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/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md
index 3fe99e911..0de64e518 100644
--- a/docs/source/markdown/podman-save.1.md
+++ b/docs/source/markdown/podman-save.1.md
@@ -9,8 +9,8 @@ podman\-save - Save image(s) to an archive
**podman image save** [*options*] *name*[:*tag*]
## DESCRIPTION
-**podman save** saves an image to either **docker-archive**, **oci-archive**, **oci-dir** (directory with oci manifest type), or **docker-dir** (directory with v2s2 manifest type) on the local machine,
-default is **docker-archive**. **podman save** writes to STDOUT by default and can be redirected to a
+**podman save** saves an image to a local file or directory.
+**podman save** writes to STDOUT by default and can be redirected to a
file using the **output** flag. The **quiet** flag suppresses the output when set.
**podman save** will save parent layers of the image(s) and the image(s) can be loaded using **podman load**.
To export the containers, use the **podman export**.
@@ -27,11 +27,11 @@ Note: `:` is a restricted character and cannot be part of the file name.
#### **--compress**
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 i.e --format=oci-dir or --format=docker-dir
+Note: This flag can only be set with **--format=docker-dir**.
#### **--uncompressed**
-Accept uncompressed layers when copying OCI images.
+Accept uncompressed layers when using one of the OCI formats.
#### **--output**, **-o**=*file*
@@ -39,17 +39,18 @@ Write to a file, default is STDOUT
#### **--format**=*format*
-Save image to **docker-archive**, **oci-archive** (see `containers-transports(5)`), **oci-dir** (`oci` transport), or **docker-dir** (`dir` transport with v2s2 manifest type).
-```
---format docker-archive
---format oci-archive
---format oci-dir
---format docker-dir
-```
+An image format to produce, one of:
+
+| Format | Description |
+| ------------------ | ---------------------------------------------------------------------------- |
+| **docker-archive** | A tar archive interoperable with **docker load(1)** (the default) |
+| **oci-archive** | A tar archive using the OCI Image Format |
+| **oci-dir** | A directory using the OCI Image Format |
+| **docker-dir** | **dir** transport (see **containers-transports(5)**) with v2s2 manifest type |
#### **--multi-image-archive**, **-m**
-Allow for creating archives with more than one image. Additional names will be interpreted as images instead of tags. Only supported for **docker-archive**.
+Allow for creating archives with more than one image. Additional names will be interpreted as images instead of tags. Only supported for **--format=docker-archive**.
The default for this option can be modified via the `multi_image_archive="true"|"false"` flag in containers.conf.
#### **--quiet**, **-q**
diff --git a/docs/source/markdown/podman-unshare.1.md b/docs/source/markdown/podman-unshare.1.md
index 5676b1be7..01393a862 100644
--- a/docs/source/markdown/podman-unshare.1.md
+++ b/docs/source/markdown/podman-unshare.1.md
@@ -35,7 +35,6 @@ Print usage statement
Join the rootless network namespace used for CNI and netavark networking. It can be used to
connect to a rootless container via IP address (bridge networking). This is otherwise
not possible from the host network namespace.
-_Note: Using this option with more than one unshare session can have unexpected results._
## Exit Codes
@@ -57,13 +56,13 @@ the exit codes follow the `chroot` standard, see below:
**127** Executing a _contained command_ and the _command_ cannot be found
- $ podman run busybox foo; echo $?
+ $ podman unshare foo; echo $?
Error: fork/exec /usr/bin/bogus: no such file or directory
127
**Exit code** _contained command_ exit code
- $ podman run busybox /bin/sh -c 'exit 3'; echo $?
+ $ podman unshare /bin/sh -c 'exit 3'; echo $?
3
## EXAMPLE
diff --git a/docs/tutorials/remote_client.md b/docs/tutorials/remote_client.md
index 889947397..0370b0329 100644
--- a/docs/tutorials/remote_client.md
+++ b/docs/tutorials/remote_client.md
@@ -58,11 +58,11 @@ sudo systemctl enable --now -s sshd
```
#### Setting up SSH
-Remote Podman uses SSH to communicate between the client and server. The remote client works considerably smoother using SSH keys. To set up your ssh connection, you need to generate an ssh key pair from your client machine.
+Remote Podman uses SSH to communicate between the client and server. The remote client works considerably smoother using SSH keys. To set up your ssh connection, you need to generate an ssh key pair from your client machine. *NOTE:* in some instances, using a `rsa` key will cause connection issues, be sure to create an `ed25519` key.
```
-ssh-keygen
+ssh-keygen -t ed25519
```
-Your public key by default should be in your home directory under ~/.ssh/id_rsa.pub. You then need to copy the contents of id_rsa.pub and append it into ~/.ssh/authorized_keys on the Linux server. You can automate this using ssh-copy-id.
+Your public key by default should be in your home directory under ~/.ssh/id_ed25519.pub. You then need to copy the contents of id_ed25519.pub and append it into ~/.ssh/authorized_keys on the Linux server. You can automate this using ssh-copy-id.
If you do not wish to use SSH keys, you will be prompted with each Podman command for your login password.
@@ -75,7 +75,7 @@ The first step in using the Podman remote client is to configure a connection.
You can add a connection by using the `podman-remote system connection add` command.
```
-podman-remote system connection add myuser --identity ~/.ssh/id_rsa ssh://192.168.122.1/run/user/1000/podman/podman.sock
+podman-remote system connection add myuser --identity ~/.ssh/id_ed25519 ssh://192.168.122.1/run/user/1000/podman/podman.sock
```
This will add a remote connection to Podman and if it is the first connection added, it will mark the connection as the default. You can observe your connections with `podman-remote system connection list`:
@@ -83,7 +83,7 @@ This will add a remote connection to Podman and if it is the first connection ad
```
podman-remote system connection list
Name Identity URI
-myuser* id_rsa ssh://myuser@192.168.122.1/run/user/1000/podman/podman.sock
+myuser* id_ed25519 ssh://myuser@192.168.122.1/run/user/1000/podman/podman.sock
```
Now we can test the connection with `podman info`:
diff --git a/go.mod b/go.mod
index 82dc3dfc3..2bdb97244 100644
--- a/go.mod
+++ b/go.mod
@@ -12,12 +12,12 @@ require (
github.com/containernetworking/cni v1.0.1
github.com/containernetworking/plugins v1.0.1
github.com/containers/buildah v1.23.1
- github.com/containers/common v0.46.1-0.20211125160015-ccf46abecd91
+ github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.17.1-0.20211129144953-4f6d0b45be6c
github.com/containers/ocicrypt v1.1.2
github.com/containers/psgo v1.7.1
- github.com/containers/storage v1.37.1-0.20211122214631-59ba58582415
+ github.com/containers/storage v1.37.1-0.20211130181259-1a158c89a518
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3
@@ -46,7 +46,7 @@ require (
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.17.0
github.com/opencontainers/go-digest v1.0.0
- github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283
+ github.com/opencontainers/image-spec v1.0.2-0.20211123152302-43a7dee1ec31
github.com/opencontainers/runc v1.0.2
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7
diff --git a/go.sum b/go.sum
index 09a30d2a7..1bda27de7 100644
--- a/go.sum
+++ b/go.sum
@@ -262,8 +262,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB
github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY=
github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ=
github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
-github.com/containers/common v0.46.1-0.20211125160015-ccf46abecd91 h1:h9SrSLSQkvluH/sEJ8X1rlBqCoGJtLvSOu4OGK0Qtuw=
-github.com/containers/common v0.46.1-0.20211125160015-ccf46abecd91/go.mod h1:PHwsa3UBgbvn2/MwpTQvyHXvVpuwfBrlDBx3GpIRPDQ=
+github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976 h1:xVOGL69ge+1RirZvnrEl9nATL75udt/Hy2BN8qcmeNY=
+github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976/go.mod h1:J8MxXan58zAWbNgpj4ODPlzsuJnYvNc2zKJCZPIMHYQ=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4=
@@ -284,8 +284,8 @@ github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0ozn
github.com/containers/storage v1.36.0/go.mod h1:vbd3SKVQNHdmU5qQI6hTEcKPxnZkGqydG4f6uwrI5a8=
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
github.com/containers/storage v1.37.1-0.20211119174841-bf170b3ddac0/go.mod h1:XjCNlt5JUUmRuTJXhFxHb9hHGPho7DNg3o4N/14prdQ=
-github.com/containers/storage v1.37.1-0.20211122214631-59ba58582415 h1:iqTDpYOxZibrkC7Mo7gCXuJDIT7wyIU432RTmRhlZqY=
-github.com/containers/storage v1.37.1-0.20211122214631-59ba58582415/go.mod h1:hvKpaiPRALDI7oz4Jx+AEch8iS/viRnc22HPilQROWU=
+github.com/containers/storage v1.37.1-0.20211130181259-1a158c89a518 h1:p44O35V8XCefRxOxU1aY6eT9XNMxkWA1drtJpsl211c=
+github.com/containers/storage v1.37.1-0.20211130181259-1a158c89a518/go.mod h1:T5DX08T/eKKRs0WGDhC/ztngMSth6YuHq15eF8C/Y5A=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -592,8 +592,9 @@ github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5y
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
-github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
+github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
+github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
@@ -693,8 +694,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
-github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
@@ -761,8 +762,9 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 h1:TVzvdjOalkJBNkbpPVMAr4KV9QRf2IjfxdyxwAK78Gs=
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.0.2-0.20211123152302-43a7dee1ec31 h1:Wh4aR2I6JFwySre9m3iHJYuMnvUFE/HT6qAXozRWi/E=
+github.com/opencontainers/image-spec v1.0.2-0.20211123152302-43a7dee1ec31/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
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/libpod/kube.go b/libpod/kube.go
index 351c49c9a..4e61b5377 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -79,7 +79,11 @@ func (p *Pod) GenerateForKube(ctx context.Context) (*v1.Pod, []v1.ServicePort, e
if err != nil {
return nil, servicePorts, err
}
- servicePorts = containerPortsToServicePorts(ports)
+ spState := newServicePortState()
+ servicePorts, err = spState.containerPortsToServicePorts(ports)
+ if err != nil {
+ return nil, servicePorts, err
+ }
hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host))
}
pod, err := p.podWithContainers(ctx, allContainers, ports, hostNetwork)
@@ -242,13 +246,17 @@ func ConvertV1PodToYAMLPod(pod *v1.Pod) *YAMLPod {
}
// GenerateKubeServiceFromV1Pod creates a v1 service object from a v1 pod object
-func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) YAMLService {
+func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) (YAMLService, error) {
service := YAMLService{}
selector := make(map[string]string)
selector["app"] = pod.Labels["app"]
ports := servicePorts
if len(ports) == 0 {
- ports = containersToServicePorts(pod.Spec.Containers)
+ p, err := containersToServicePorts(pod.Spec.Containers)
+ if err != nil {
+ return service, err
+ }
+ ports = p
}
serviceSpec := v1.ServiceSpec{
Ports: ports,
@@ -262,15 +270,43 @@ func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) YA
APIVersion: pod.TypeMeta.APIVersion,
}
service.TypeMeta = tm
- return service
+ return service, nil
+}
+
+// servicePortState allows calling containerPortsToServicePorts for a single service
+type servicePortState struct {
+ // A program using the shared math/rand state with the default seed will produce the same sequence of pseudo-random numbers
+ // for each execution. Use a private RNG state not to interfere with other users.
+ rng *rand.Rand
+ usedPorts map[int]struct{}
+}
+
+func newServicePortState() servicePortState {
+ return servicePortState{
+ rng: rand.New(rand.NewSource(time.Now().UnixNano())),
+ usedPorts: map[int]struct{}{},
+ }
}
// containerPortsToServicePorts takes a slice of containerports and generates a
// slice of service ports
-func containerPortsToServicePorts(containerPorts []v1.ContainerPort) []v1.ServicePort {
+func (state *servicePortState) containerPortsToServicePorts(containerPorts []v1.ContainerPort) ([]v1.ServicePort, error) {
sps := make([]v1.ServicePort, 0, len(containerPorts))
for _, cp := range containerPorts {
- nodePort := 30000 + rand.Intn(32767-30000+1)
+ var nodePort int
+ attempt := 0
+ for {
+ // Legal nodeport range is 30000-32767
+ nodePort = 30000 + state.rng.Intn(32767-30000+1)
+ if _, found := state.usedPorts[nodePort]; !found {
+ state.usedPorts[nodePort] = struct{}{}
+ break
+ }
+ attempt++
+ if attempt >= 100 {
+ return nil, fmt.Errorf("too many attempts trying to generate a unique NodePort number")
+ }
+ }
servicePort := v1.ServicePort{
Protocol: cp.Protocol,
Port: cp.ContainerPort,
@@ -280,21 +316,22 @@ func containerPortsToServicePorts(containerPorts []v1.ContainerPort) []v1.Servic
}
sps = append(sps, servicePort)
}
- return sps
+ return sps, nil
}
// containersToServicePorts takes a slice of v1.Containers and generates an
// inclusive list of serviceports to expose
-func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
- // Without the call to rand.Seed, a program will produce the same sequence of pseudo-random numbers
- // for each execution. Legal nodeport range is 30000-32767
- rand.Seed(time.Now().UnixNano())
-
+func containersToServicePorts(containers []v1.Container) ([]v1.ServicePort, error) {
+ state := newServicePortState()
sps := make([]v1.ServicePort, 0, len(containers))
for _, ctr := range containers {
- sps = append(sps, containerPortsToServicePorts(ctr.Ports)...)
+ ports, err := state.containerPortsToServicePorts(ctr.Ports)
+ if err != nil {
+ return nil, err
+ }
+ sps = append(sps, ports...)
}
- return sps
+ return sps, nil
}
func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) {
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 7d1214183..b734b9c95 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -322,17 +322,14 @@ func (r *RootlessNetNS) Do(toRun func() error) error {
// Cleanup the rootless network namespace if needed.
// It checks if we have running containers with the bridge network mode.
-// Cleanup() will try to lock RootlessNetNS, therefore you have to call
-// it with an unlocked lock.
+// Cleanup() expects that r.Lock is locked
func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
_, err := os.Stat(r.dir)
if os.IsNotExist(err) {
// the directory does not exists no need for cleanup
return nil
}
- r.Lock.Lock()
- defer r.Lock.Unlock()
- running := func(c *Container) bool {
+ activeNetns := func(c *Container) bool {
// no bridge => no need to check
if !c.config.NetMode.IsBridge() {
return false
@@ -352,15 +349,18 @@ func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
return false
}
- state := c.state.State
- return state == define.ContainerStateRunning
+ // only check for an active netns, we cannot use the container state
+ // because not running does not mean that the netns does not need cleanup
+ // only if the netns is empty we know that we do not need cleanup
+ return c.state.NetNS != nil
}
- ctrs, err := runtime.GetContainersWithoutLock(running)
+ ctrs, err := runtime.GetContainersWithoutLock(activeNetns)
if err != nil {
return err
}
- // no cleanup if we found containers
- if len(ctrs) > 0 {
+ // no cleanup if we found no other containers with a netns
+ // we will always find one container (the container cleanup that is currently calling us)
+ if len(ctrs) > 1 {
return nil
}
logrus.Debug("Cleaning up rootless network namespace")
@@ -809,10 +809,10 @@ func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error {
if rootlessNetNS != nil {
// execute the cni setup in the rootless net ns
err = rootlessNetNS.Do(tearDownPod)
- rootlessNetNS.Lock.Unlock()
- if err == nil {
- err = rootlessNetNS.Cleanup(r)
+ if cerr := rootlessNetNS.Cleanup(r); cerr != nil {
+ logrus.WithError(err).Error("failed to cleanup rootless netns")
}
+ rootlessNetNS.Lock.Unlock()
} else {
err = tearDownPod()
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index af8b6b63d..4533fddeb 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -409,14 +409,20 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed get images"))
return
}
- var summaries = make([]*entities.ImageSummary, len(images))
- for j, img := range images {
+
+ summaries := make([]*entities.ImageSummary, 0, len(images))
+ for _, img := range images {
+ // If the image is a manifest list, extract as much as we can.
+ if isML, _ := img.IsManifestList(r.Context()); isML {
+ continue
+ }
+
is, err := handlers.ImageToImageSummary(img)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed transform image summaries"))
return
}
- summaries[j] = is
+ summaries = append(summaries, is)
}
utils.WriteResponse(w, http.StatusOK, summaries)
}
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index 5ecb429ae..3a84b5799 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -74,10 +74,16 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
return
}
imageName = possiblyNormalizedName
- if _, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil); err != nil {
+ localImage, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil)
+ if err != nil {
utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName))
return
}
+ rawManifest, _, err := localImage.Manifest(r.Context())
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, err)
+ return
+ }
authconf, authfile, key, err := auth.GetCredentials(r)
if err != nil {
@@ -196,7 +202,7 @@ loop: // break out of for/select infinite loop
if tag == "" {
tag = "latest"
}
- report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
+ report.Status = fmt.Sprintf("%s: digest: %s size: %d", tag, string(digestBytes), len(rawManifest))
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index 1411c680e..88fd69d45 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -22,6 +22,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
NoHeader bool `schema:"noHeader"`
TemplateUnitFile bool `schema:"templateUnitFile"`
RestartPolicy *string `schema:"restartPolicy"`
+ RestartSec uint `schema:"restartSec"`
StopTimeout uint `schema:"stopTimeout"`
StartTimeout uint `schema:"startTimeout"`
ContainerPrefix string `schema:"containerPrefix"`
@@ -53,6 +54,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
ContainerPrefix: query.ContainerPrefix,
PodPrefix: query.PodPrefix,
Separator: query.Separator,
+ RestartSec: &query.RestartSec,
}
report, err := containerEngine.GenerateSystemd(r.Context(), utils.GetName(r), options)
diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go
index 0e36394cf..65340bf56 100644
--- a/pkg/api/server/register_generate.go
+++ b/pkg/api/server/register_generate.go
@@ -67,6 +67,11 @@ func (s *APIServer) registerGenerateHandlers(r *mux.Router) error {
// type: string
// default: "-"
// description: Systemd unit name separator between name/id and prefix.
+ // - in: query
+ // name: restartSec
+ // type: integer
+ // default: 0
+ // description: Configures the time to sleep before restarting a service.
// produces:
// - application/json
// responses:
diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go
index 092474e4a..ce560c547 100644
--- a/pkg/bindings/generate/types.go
+++ b/pkg/bindings/generate/types.go
@@ -20,6 +20,8 @@ type SystemdOptions struct {
TemplateUnitFile *bool
// RestartPolicy - systemd restart policy.
RestartPolicy *string
+ // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service.
+ RestartSec *uint
// StartTimeout - time when starting the container.
StartTimeout *uint
// StopTimeout - time when stopping the container.
diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go
index d60f1d70e..504d4da7f 100644
--- a/pkg/bindings/generate/types_systemd_options.go
+++ b/pkg/bindings/generate/types_systemd_options.go
@@ -92,6 +92,21 @@ func (o *SystemdOptions) GetRestartPolicy() string {
return *o.RestartPolicy
}
+// WithRestartSec set field RestartSec to given value
+func (o *SystemdOptions) WithRestartSec(value uint) *SystemdOptions {
+ o.RestartSec = &value
+ return o
+}
+
+// GetRestartSec returns value of field RestartSec
+func (o *SystemdOptions) GetRestartSec() uint {
+ if o.RestartSec == nil {
+ var z uint
+ return z
+ }
+ return *o.RestartSec
+}
+
// WithStartTimeout set field StartTimeout to given value
func (o *SystemdOptions) WithStartTimeout(value uint) *SystemdOptions {
o.StartTimeout = &value
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/generate.go b/pkg/domain/entities/generate.go
index 7e80e5d2d..e431a70af 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -10,6 +10,8 @@ type GenerateSystemdOptions struct {
New bool
// RestartPolicy - systemd restart policy.
RestartPolicy *string
+ // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service.
+ RestartSec *uint
// StartTimeout - time when starting the container.
StartTimeout *uint
// StopTimeout - time when stopping the container.
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 54f7b5d45..8b0fd2b85 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -208,6 +208,8 @@ type ImagePushOptions struct {
SkipTLSVerify types.OptionalBool
// Progress to get progress notifications
Progress chan types.ProgressProperties
+ // CompressionFormat is the format to use for the compression of the blobs
+ CompressionFormat string
}
// ImageSearchOptions are the arguments for searching images.
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 0defa1923..68bb351bf 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -139,7 +139,11 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
podContent = append(podContent, b)
if options.Service {
- b, err := generateKubeYAML(libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{}))
+ svc, err := libpod.GenerateKubeServiceFromV1Pod(po, []k8sAPI.ServicePort{})
+ if err != nil {
+ return nil, err
+ }
+ b, err := generateKubeYAML(svc)
if err != nil {
return nil, err
}
@@ -177,7 +181,11 @@ func getKubePods(ctx context.Context, pods []*libpod.Pod, getService bool) ([][]
pos = append(pos, b)
if getService {
- b, err := generateKubeYAML(libpod.GenerateKubeServiceFromV1Pod(po, sp))
+ svc, err := libpod.GenerateKubeServiceFromV1Pod(po, sp)
+ if err != nil {
+ return nil, nil, err
+ }
+ b, err := generateKubeYAML(svc)
if err != nil {
return nil, nil, err
}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 8b44b869a..4346182d6 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,22 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.SignBy = options.SignBy
pushOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+ compressionFormat := options.CompressionFormat
+ if compressionFormat == "" {
+ config, err := ir.Libpod.GetConfigNoCopy()
+ if err != nil {
+ return err
+ }
+ compressionFormat = config.Engine.CompressionFormat
+ }
+ if compressionFormat != "" {
+ algo, err := compression.AlgorithmByName(compressionFormat)
+ if err != nil {
+ return err
+ }
+ pushOptions.CompressionFormat = &algo
+ }
+
if !options.Quiet {
pushOptions.Writer = os.Stderr
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index ed70078b2..4c024a3d8 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -239,27 +239,6 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
podSpec := entities.PodSpec{PodSpecGen: *p}
- volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes)
- if err != nil {
- return nil, err
- }
-
- seccompPaths, err := kube.InitializeSeccompPaths(podYAML.ObjectMeta.Annotations, options.SeccompProfileRoot)
- if err != nil {
- return nil, err
- }
-
- var ctrRestartPolicy string
- switch podYAML.Spec.RestartPolicy {
- case v1.RestartPolicyAlways:
- ctrRestartPolicy = define.RestartPolicyAlways
- case v1.RestartPolicyOnFailure:
- ctrRestartPolicy = define.RestartPolicyOnFailure
- case v1.RestartPolicyNever:
- ctrRestartPolicy = define.RestartPolicyNo
- default: // Default to Always
- ctrRestartPolicy = define.RestartPolicyAlways
- }
configMapIndex := make(map[string]struct{})
for _, configMap := range configMaps {
@@ -284,6 +263,56 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
configMaps = append(configMaps, cm)
}
+ volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes, configMaps)
+ if err != nil {
+ return nil, err
+ }
+
+ // Go through the volumes and create a podman volume for all volumes that have been
+ // defined by a configmap
+ for _, v := range volumes {
+ if v.Type == kube.KubeVolumeTypeConfigMap && !v.Optional {
+ vol, err := ic.Libpod.NewVolume(ctx, libpod.WithVolumeName(v.Source))
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot create a local volume for volume from configmap %q", v.Source)
+ }
+ mountPoint, err := vol.MountPoint()
+ if err != nil || mountPoint == "" {
+ return nil, errors.Wrapf(err, "unable to get mountpoint of volume %q", vol.Name())
+ }
+ // Create files and add data to the volume mountpoint based on the Items in the volume
+ for k, v := range v.Items {
+ dataPath := filepath.Join(mountPoint, k)
+ f, err := os.Create(dataPath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot create file %q at volume mountpoint %q", k, mountPoint)
+ }
+ defer f.Close()
+ _, err = f.WriteString(v)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ }
+
+ seccompPaths, err := kube.InitializeSeccompPaths(podYAML.ObjectMeta.Annotations, options.SeccompProfileRoot)
+ if err != nil {
+ return nil, err
+ }
+
+ var ctrRestartPolicy string
+ switch podYAML.Spec.RestartPolicy {
+ case v1.RestartPolicyAlways:
+ ctrRestartPolicy = define.RestartPolicyAlways
+ case v1.RestartPolicyOnFailure:
+ ctrRestartPolicy = define.RestartPolicyOnFailure
+ case v1.RestartPolicyNever:
+ ctrRestartPolicy = define.RestartPolicyNo
+ default: // Default to Always
+ ctrRestartPolicy = define.RestartPolicyAlways
+ }
+
if podOpt.Infra {
infraImage := util.DefaultContainerConfig().Engine.InfraImage
infraOptions := entities.NewInfraContainerCreateOptions()
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 7da7754f2..e6c9d850b 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -365,9 +365,12 @@ func (ic *ContainerEngine) Unshare(ctx context.Context, args []string, options e
if err != nil {
return err
}
- // make sure to unlock, unshare can run for a long time
+ // Make sure to unlock, unshare can run for a long time.
rootlessNetNS.Lock.Unlock()
- defer rootlessNetNS.Cleanup(ic.Libpod)
+ // We do not want to cleanup the netns after unshare.
+ // The problem is that we cannot know if we need to cleanup and
+ // secondly unshare should allow user to setup the namespace with
+ // special things, e.g. potentially macvlan or something like that.
return rootlessNetNS.Do(unshare)
}
return unshare()
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index d62a318d6..dd895b61f 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -19,6 +19,9 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
if opts.RestartPolicy != nil {
options.WithRestartPolicy(*opts.RestartPolicy)
}
+ if opts.RestartSec != nil {
+ options.WithRestartSec(*opts.RestartSec)
+ }
return generate.Systemd(ic.ClientCtx, nameOrID, options)
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index c502a6e62..6d9f598c9 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -310,6 +310,11 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
if !exists {
return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
}
+ // Skip if the volume is optional. This means that a configmap for a configmap volume was not found but it was
+ // optional so we can move on without throwing an error
+ if exists && volumeSource.Optional {
+ continue
+ }
dest, options, err := parseMountPath(volume.MountPath, volume.ReadOnly)
if err != nil {
@@ -341,6 +346,13 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Options: options,
}
s.Volumes = append(s.Volumes, &namedVolume)
+ case KubeVolumeTypeConfigMap:
+ cmVolume := specgen.NamedVolume{
+ Dest: volume.MountPath,
+ Name: volumeSource.Source,
+ Options: options,
+ }
+ s.Volumes = append(s.Volumes, &cmVolume)
default:
return nil, errors.Errorf("Unsupported volume source type")
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index a8042b532..76ec0a390 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -23,6 +23,7 @@ type KubeVolumeType int
const (
KubeVolumeTypeBindMount KubeVolumeType = iota
KubeVolumeTypeNamed KubeVolumeType = iota
+ KubeVolumeTypeConfigMap KubeVolumeType = iota
)
// nolint:golint
@@ -31,6 +32,14 @@ type KubeVolume struct {
Type KubeVolumeType
// Path for bind mount or volume name for named volume
Source string
+ // Items to add to a named volume created where the key is the file name and the value is the data
+ // This is only used when there are volumes in the yaml that refer to a configmap
+ // Example: if configmap has data "SPECIAL_LEVEL: very" then the file name is "SPECIAL_LEVEL" and the
+ // data in that file is "very".
+ Items map[string]string
+ // If the volume is optional, we can move on if it is not found
+ // Only used when there are volumes in a yaml that refer to a configmap
+ Optional bool
}
// Create a KubeVolume from an HostPathVolumeSource
@@ -98,23 +107,64 @@ func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource
}, nil
}
+func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, configMaps []v1.ConfigMap) (*KubeVolume, error) {
+ var configMap *v1.ConfigMap
+ kv := &KubeVolume{Type: KubeVolumeTypeConfigMap, Items: map[string]string{}}
+ for _, cm := range configMaps {
+ if cm.Name == configMapVolumeSource.Name {
+ matchedCM := cm
+ // Set the source to the config map name
+ kv.Source = cm.Name
+ configMap = &matchedCM
+ break
+ }
+ }
+
+ if configMap == nil {
+ // If the volumeSource was optional, move on even if a matching configmap wasn't found
+ if *configMapVolumeSource.Optional {
+ kv.Source = configMapVolumeSource.Name
+ kv.Optional = *configMapVolumeSource.Optional
+ return kv, nil
+ }
+ return nil, errors.Errorf("no such ConfigMap %q", configMapVolumeSource.Name)
+ }
+
+ // If there are Items specified in the volumeSource, that overwrites the Data from the configmap
+ if len(configMapVolumeSource.Items) > 0 {
+ for _, item := range configMapVolumeSource.Items {
+ if val, ok := configMap.Data[item.Key]; ok {
+ kv.Items[item.Path] = val
+ }
+ }
+ } else {
+ for k, v := range configMap.Data {
+ kv.Items[k] = v
+ }
+ }
+ return kv, nil
+}
+
// Create a KubeVolume from one of the supported VolumeSource
-func VolumeFromSource(volumeSource v1.VolumeSource) (*KubeVolume, error) {
- if volumeSource.HostPath != nil {
+func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) (*KubeVolume, error) {
+ switch {
+ case volumeSource.HostPath != nil:
return VolumeFromHostPath(volumeSource.HostPath)
- } else if volumeSource.PersistentVolumeClaim != nil {
+ case volumeSource.PersistentVolumeClaim != nil:
return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim)
- } else {
- return nil, errors.Errorf("HostPath and PersistentVolumeClaim are currently the only supported VolumeSource")
+ case volumeSource.ConfigMap != nil:
+ return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps)
+ default:
+ return nil, errors.Errorf("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
}
}
// Create a map of volume name to KubeVolume
-func InitializeVolumes(specVolumes []v1.Volume) (map[string]*KubeVolume, error) {
+func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap) (map[string]*KubeVolume, error) {
volumes := make(map[string]*KubeVolume)
for _, specVolume := range specVolumes {
- volume, err := VolumeFromSource(specVolume.VolumeSource)
+ volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps)
if err != nil {
return nil, errors.Wrapf(err, "failed to create volume %q", specVolume.Name)
}
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/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 48252c737..f2d04dadc 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -30,6 +30,8 @@ type podInfo struct {
StopTimeout uint
// RestartPolicy of the systemd unit (e.g., no, on-failure, always).
RestartPolicy string
+ // RestartSec of the systemd unit. Configures the time to sleep before restarting a service.
+ RestartSec uint
// PIDFile of the service. Required for forking services. Must point to the
// PID of the associated conmon process.
PIDFile string
@@ -89,6 +91,9 @@ Before={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{
[Service]
Environment={{{{.EnvVariable}}}}=%n
Restart={{{{.RestartPolicy}}}}
+{{{{- if .RestartSec}}}}
+RestartSec={{{{.RestartSec}}}}
+{{{{- end}}}}
TimeoutStopSec={{{{.TimeoutStopSec}}}}
{{{{- if .ExecStartPre1}}}}
ExecStartPre={{{{.ExecStartPre1}}}}
@@ -242,6 +247,10 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
info.RestartPolicy = *options.RestartPolicy
}
+ if options.RestartSec != nil {
+ info.RestartSec = *options.RestartSec
+ }
+
// Make sure the executable is set.
if info.Executable == "" {
executable, err := os.Executable()
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 612908991..0889507a5 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -67,6 +67,33 @@ WantedBy=default.target
podGood := serviceInfo + headerInfo + podContent
podGoodNoHeaderInfo := serviceInfo + podContent
+ podGoodRestartSec := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+RestartSec=15
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
podGoodNamedNew := `# pod-123abc.service
# autogenerated by Podman CI
@@ -205,6 +232,25 @@ WantedBy=default.target
false,
false,
},
+ {"pod restartSec",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"},
+ RestartSec: 15,
+ },
+ podGoodRestartSec,
+ false,
+ false,
+ false,
+ },
{"pod noHeader",
podInfo{
Executable: "/usr/bin/podman",
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index b7bcaf81d..e67f559f3 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -10,6 +10,13 @@ t GET libpod/images/json 200 \
.[0].Id~[0-9a-f]\\{64\\}
iid=$(jq -r '.[0].Id' <<<"$output")
+# Create an empty manifest and make sure it is not listed
+# in the compat endpoint.
+t GET images/json 200 length=1
+podman manifest create foo
+t GET images/json 200 length=1
+t GET libpod/images/json 200 length=2
+
t GET libpod/images/$iid/exists 204
t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/exists 204
t GET libpod/images/${iid}abcdef/exists 404 \
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 5e93f9078..9a9dec191 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -139,7 +139,7 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// Check for two layers
- Expect(len(strings.Fields(session.OutputToString()))).To(Equal(2))
+ Expect(strings.Fields(session.OutputToString())).To(HaveLen(2))
session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-b", "--squash", "-t", "test-squash-b:latest", "build/squash"})
session.WaitWithDefaultTimeout()
@@ -149,7 +149,7 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// Check for three layers
- Expect(len(strings.Fields(session.OutputToString()))).To(Equal(3))
+ Expect(strings.Fields(session.OutputToString())).To(HaveLen(3))
session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash", "-t", "test-squash-c:latest", "build/squash"})
session.WaitWithDefaultTimeout()
@@ -159,7 +159,7 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// Check for two layers
- Expect(len(strings.Fields(session.OutputToString()))).To(Equal(2))
+ Expect(strings.Fields(session.OutputToString())).To(HaveLen(2))
session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "-t", "test-squash-d:latest", "build/squash"})
session.WaitWithDefaultTimeout()
@@ -169,7 +169,7 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// Check for one layers
- Expect(len(strings.Fields(session.OutputToString()))).To(Equal(1))
+ Expect(strings.Fields(session.OutputToString())).To(HaveLen(1))
session = podmanTest.Podman([]string{"rm", "-a"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index e068a6582..064c82621 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()
@@ -568,7 +568,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
- Expect(len(result.OutputToStringArray())).To(Equal(3))
+ Expect(result.OutputToStringArray()).To(HaveLen(3))
// Checkpoint the container
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
@@ -599,7 +599,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
- Expect(len(result.OutputToStringArray())).To(Equal(3))
+ Expect(result.OutputToStringArray()).To(HaveLen(3))
// Remove exported checkpoint
os.Remove(fileName)
@@ -1280,7 +1280,7 @@ var _ = Describe("Podman checkpoint", func() {
err := json.Unmarshal([]byte(result.OutputToString()), cS)
Expect(err).ShouldNot(HaveOccurred())
- Expect(len(cS.ContainerStatistics)).To(Equal(2))
+ Expect(cS.ContainerStatistics).To(HaveLen(2))
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
@@ -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",
@@ -1322,7 +1322,7 @@ var _ = Describe("Podman checkpoint", func() {
err = json.Unmarshal([]byte(result.OutputToString()), rS)
Expect(err).ShouldNot(HaveOccurred())
- Expect(len(cS.ContainerStatistics)).To(Equal(2))
+ Expect(cS.ContainerStatistics).To(HaveLen(2))
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index b751c338f..d9411b146 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -146,8 +146,8 @@ var _ = Describe("Podman commit", func() {
check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"})
check.WaitWithDefaultTimeout()
data := check.InspectImageJSON()
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].Config.Entrypoint)).To(Equal(2))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].Config.Entrypoint).To(HaveLen(2))
Expect(data[0].Config.Entrypoint[0]).To(Equal("foo"))
Expect(data[0].Config.Entrypoint[1]).To(Equal("bar=baz"))
})
@@ -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/container_create_volume_test.go b/test/e2e/container_create_volume_test.go
index 0dac96a5e..df1d9a371 100644
--- a/test/e2e/container_create_volume_test.go
+++ b/test/e2e/container_create_volume_test.go
@@ -45,8 +45,8 @@ func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, d
Expect(create).Should(Exit(0))
inspect := pTest.InspectContainer(cont)
- Expect(len(inspect)).To(Equal(1))
- Expect(len(inspect[0].Mounts)).To(Equal(1))
+ Expect(inspect).To(HaveLen(1))
+ Expect(inspect[0].Mounts).To(HaveLen(1))
Expect(inspect[0].Mounts[0].Destination).To(Equal(dest))
mntName, mntSource := inspect[0].Mounts[0].Name, inspect[0].Mounts[0].Source
@@ -54,7 +54,7 @@ func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, d
volList := pTest.Podman([]string{"volume", "list", "--quiet"})
volList.WaitWithDefaultTimeout()
Expect(volList).Should(Exit(0))
- Expect(len(volList.OutputToStringArray())).To(Equal(1))
+ Expect(volList.OutputToStringArray()).To(HaveLen(1))
Expect(volList.OutputToStringArray()[0]).To(Equal(mntName))
// Check the mount source directory
@@ -62,9 +62,9 @@ func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, d
Expect(err).To(BeNil())
if data == "" {
- Expect(len(files)).To(Equal(0))
+ Expect(files).To(BeEmpty())
} else {
- Expect(len(files)).To(Equal(1))
+ Expect(files).To(HaveLen(1))
Expect(files[0].Name()).To(Equal(data))
}
}
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..9126303cd 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() {
@@ -281,8 +279,8 @@ var _ = Describe("Podman create", func() {
Expect(create).Should(Exit(0))
ctrJSON := podmanTest.InspectContainer(name)
- Expect(len(ctrJSON)).To(Equal(1))
- Expect(len(ctrJSON[0].Config.Cmd)).To(Equal(1))
+ Expect(ctrJSON).To(HaveLen(1))
+ Expect(ctrJSON[0].Config.Cmd).To(HaveLen(1))
Expect(ctrJSON[0].Config.Cmd[0]).To(Equal("redis-server"))
Expect(ctrJSON[0].Config.Entrypoint).To(Equal("docker-entrypoint.sh"))
})
@@ -384,12 +382,10 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
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).To(HaveLen(1), "len(InspectContainerToJSON)")
+ Expect(data[0].Config.Labels).To(HaveLen(2))
+ Expect(data[0].Config.Labels).To(HaveKey("TESTKEY1"))
+ Expect(data[0].Config.Labels).To(HaveKey("TESTKEY2"))
})
It("podman create with set label", func() {
@@ -402,14 +398,10 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
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).To(HaveLen(1))
+ Expect(data[0].Config.Labels).To(HaveLen(2))
+ 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() {
@@ -421,7 +413,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].HostConfig.RestartPolicy.Name).To(Equal("on-failure"))
Expect(data[0].HostConfig.RestartPolicy.MaximumRetryCount).To(Equal(uint(5)))
})
@@ -442,7 +434,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].HostConfig.RestartPolicy.Name).To(Equal(unlessStopped))
})
@@ -456,7 +448,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].HostConfig.MemorySwap).To(Equal(int64(2 * numMem)))
})
@@ -471,7 +463,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].HostConfig.NanoCpus).To(Equal(int64(nanoCPUs)))
})
@@ -499,7 +491,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", ctrName})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.StopSignal).To(Equal(uint(15)))
})
@@ -517,7 +509,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", "zone"})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Timezone).To(Equal("Pacific/Honolulu"))
session = podmanTest.Podman([]string{"create", "--tz", "local", "--name", "lcl", ALPINE, "date"})
@@ -525,7 +517,7 @@ var _ = Describe("Podman create", func() {
inspect = podmanTest.Podman([]string{"inspect", "lcl"})
inspect.WaitWithDefaultTimeout()
data = inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Timezone).To(Equal("local"))
})
@@ -539,7 +531,7 @@ var _ = Describe("Podman create", func() {
inspect := podmanTest.Podman([]string{"inspect", "default"})
inspect.WaitWithDefaultTimeout()
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Umask).To(Equal("0022"))
session = podmanTest.Podman([]string{"create", "--umask", "0002", "--name", "umask", ALPINE})
@@ -547,7 +539,7 @@ var _ = Describe("Podman create", func() {
inspect = podmanTest.Podman([]string{"inspect", "umask"})
inspect.WaitWithDefaultTimeout()
data = inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Umask).To(Equal("0002"))
session = podmanTest.Podman([]string{"create", "--umask", "0077", "--name", "fedora", fedoraMinimal})
@@ -555,7 +547,7 @@ var _ = Describe("Podman create", func() {
inspect = podmanTest.Podman([]string{"inspect", "fedora"})
inspect.WaitWithDefaultTimeout()
data = inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Umask).To(Equal("0077"))
session = podmanTest.Podman([]string{"create", "--umask", "22", "--name", "umask-short", ALPINE})
@@ -563,7 +555,7 @@ var _ = Describe("Podman create", func() {
inspect = podmanTest.Podman([]string{"inspect", "umask-short"})
inspect.WaitWithDefaultTimeout()
data = inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Config.Umask).To(Equal("0022"))
session = podmanTest.Podman([]string{"create", "--umask", "9999", "--name", "bad", ALPINE})
@@ -697,7 +689,7 @@ var _ = Describe("Podman create", func() {
Expect(setup).Should(Exit(0))
idata := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(idata)).To(Equal(1))
+ Expect(idata).To(HaveLen(1))
Expect(idata[0].Os).To(Equal(runtime.GOOS))
Expect(idata[0].Architecture).To(Equal("arm64"))
})
diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go
index 80647c6f5..a872a9713 100644
--- a/test/e2e/diff_test.go
+++ b/test/e2e/diff_test.go
@@ -120,13 +120,13 @@ RUN echo test
session := podmanTest.Podman([]string{"image", "diff", image})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
Expect(session.OutputToString()).To(Equal("A " + file3))
session = podmanTest.Podman([]string{"image", "diff", image, baseImage})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
Expect(session.OutputToString()).To(ContainSubstring("A " + file1))
Expect(session.OutputToString()).To(ContainSubstring("A " + file2))
Expect(session.OutputToString()).To(ContainSubstring("A " + file3))
@@ -149,7 +149,7 @@ RUN echo test
session := podmanTest.Podman([]string{"image", "diff", ALPINE, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman diff container and image with same name", func() {
@@ -172,20 +172,20 @@ RUN touch %s`, ALPINE, imagefile)
session = podmanTest.Podman([]string{"diff", name})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring(imagefile))
session = podmanTest.Podman([]string{"image", "diff", name})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring(imagefile))
// container diff has to show the container
session = podmanTest.Podman([]string{"container", "diff", name})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring(confile))
})
diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go
index 2b9b0f575..39f495460 100644
--- a/test/e2e/events_test.go
+++ b/test/e2e/events_test.go
@@ -74,7 +74,7 @@ var _ = Describe("Podman events", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
events := result.OutputToStringArray()
- Expect(len(events)).To(Equal(1), "number of events")
+ Expect(events).To(HaveLen(1), "number of events")
Expect(events[0]).To(ContainSubstring(cid), "event log includes CID")
Expect(events[0]).To(Not(ContainSubstring(cid2)), "event log does not include second CID")
})
@@ -86,7 +86,7 @@ var _ = Describe("Podman events", func() {
result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod", "--filter", fmt.Sprintf("container=%s", cid)})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(0))
+ Expect(result.OutputToStringArray()).To(BeEmpty())
})
It("podman events with a type", func() {
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 65d60b24d..121d0b234 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -527,8 +527,8 @@ RUN useradd -u 1000 auser`, fedoraMinimal)
Expect(ctr).Should(Exit(0))
data := podmanTest.InspectContainer(ctrName)
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].ExecIDs)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].ExecIDs).To(HaveLen(1))
Expect(exec1.OutputToString()).To(ContainSubstring(data[0].ExecIDs[0]))
exec2 := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "ps", "-a"})
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 62482598a..cfa264de2 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -137,12 +137,12 @@ var _ = Describe("Podman generate kube", func() {
// Separate out the Service and Pod yaml
arr := strings.Split(string(kube.Out.Contents()), "---")
- Expect(len(arr)).To(Equal(2))
+ Expect(arr).To(HaveLen(2))
svc := new(v1.Service)
err := yaml.Unmarshal([]byte(arr[0]), svc)
Expect(err).To(BeNil())
- Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports).To(HaveLen(1))
Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(3890))
pod := new(v1.Pod)
@@ -324,7 +324,7 @@ var _ = Describe("Podman generate kube", func() {
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- Expect(len(pod.Spec.HostAliases)).To(Equal(2))
+ Expect(pod.Spec.HostAliases).To(HaveLen(2))
Expect(pod.Spec.HostAliases[0].IP).To(Equal(testIP))
Expect(pod.Spec.HostAliases[1].IP).To(Equal(testIP))
})
@@ -340,12 +340,12 @@ var _ = Describe("Podman generate kube", func() {
// Separate out the Service and Pod yaml
arr := strings.Split(string(kube.Out.Contents()), "---")
- Expect(len(arr)).To(Equal(2))
+ Expect(arr).To(HaveLen(2))
svc := new(v1.Service)
err := yaml.Unmarshal([]byte(arr[0]), svc)
Expect(err).To(BeNil())
- Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports).To(HaveLen(1))
Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(4000))
Expect(svc.Spec.Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
@@ -504,8 +504,8 @@ var _ = Describe("Podman generate kube", func() {
Expect(err).To(BeNil())
containers := pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
- Expect(len(containers[0].Ports)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
+ Expect(containers[0].Ports).To(HaveLen(1))
Expect(containers[0].Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
})
@@ -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()
@@ -643,7 +641,7 @@ var _ = Describe("Podman generate kube", func() {
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- Expect(len(pod.Spec.Volumes)).To(Equal(2))
+ Expect(pod.Spec.Volumes).To(HaveLen(2))
})
@@ -841,7 +839,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(err).To(BeNil())
containers := pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
Expect(containers[0].Command).To(Equal([]string{"/bin/sleep"}))
Expect(containers[0].Args).To(Equal([]string{"10s"}))
@@ -863,8 +861,8 @@ var _ = Describe("Podman generate kube", func() {
Expect(err).To(BeNil())
containers := pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
- Expect(len(containers[0].Command)).To(Equal(0))
+ Expect(containers).To(HaveLen(1))
+ Expect(containers[0].Command).To(BeEmpty())
cmd := []string{"echo", "hi"}
session = podmanTest.Podman(append([]string{"create", "--name", "test1", ALPINE}, cmd...))
@@ -882,7 +880,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(err).To(BeNil())
containers = pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
Expect(containers[0].Command).To(Equal(cmd))
})
@@ -917,7 +915,7 @@ ENTRYPOINT ["sleep"]`
Expect(err).To(BeNil())
containers := pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
Expect(containers[0].Args).To(Equal([]string{"10s"}))
session = podmanTest.Podman([]string{"create", "--pod", "new:testpod-2", "--entrypoint", "echo", image, "hello"})
@@ -935,7 +933,7 @@ ENTRYPOINT ["sleep"]`
Expect(err).To(BeNil())
containers = pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
Expect(containers[0].Command).To(Equal([]string{"echo"}))
Expect(containers[0].Args).To(Equal([]string{"hello"}))
})
@@ -955,7 +953,7 @@ ENTRYPOINT ["sleep"]`
Expect(err).To(BeNil())
containers := pod.Spec.Containers
- Expect(len(containers)).To(Equal(1))
+ Expect(containers).To(HaveLen(1))
Expect(containers[0].SecurityContext.Capabilities).To(BeNil())
// Now make sure we can also `play` it.
@@ -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/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 1cffdc62e..fd9ae5037 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -282,6 +282,19 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.OutputToString()).To(ContainSubstring(" pod create "))
})
+ It("podman generate systemd --restart-sec 15 --name foo", func() {
+ n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "--restart-sec", "15", "--name", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // Grepping the output (in addition to unit tests)
+ Expect(session.OutputToString()).To(ContainSubstring("RestartSec=15"))
+ })
+
It("podman generate systemd --new=false pod", func() {
n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
n.WaitWithDefaultTimeout()
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index c9a6f926f..6e4dc5bbf 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -239,7 +239,7 @@ var _ = Describe("Podman healthcheck run", func() {
ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"})
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
- Expect(len(ps.OutputToStringArray())).To(Equal(2))
+ Expect(ps.OutputToStringArray()).To(HaveLen(2))
Expect(ps.OutputToString()).To(ContainSubstring("hc"))
})
})
diff --git a/test/e2e/history_test.go b/test/e2e/history_test.go
index 1f8faa6c2..c6e9579ae 100644
--- a/test/e2e/history_test.go
+++ b/test/e2e/history_test.go
@@ -73,7 +73,7 @@ var _ = Describe("Podman history", func() {
lines := session.OutputToStringArray()
Expect(len(lines)).To(BeNumerically(">", 0))
// the image id must be 64 chars long
- Expect(len(lines[0])).To(BeNumerically("==", 64))
+ Expect(lines[0]).To(HaveLen(64))
session = podmanTest.Podman([]string{"history", "--no-trunc", "--format", "{{.CreatedBy}}", ALPINE})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/image_scp_test.go b/test/e2e/image_scp_test.go
index 6c6c85bc3..6651a04b5 100644
--- a/test/e2e/image_scp_test.go
+++ b/test/e2e/image_scp_test.go
@@ -109,7 +109,7 @@ var _ = Describe("podman image scp", func() {
cfg, err := config.ReadCustomConfig()
Expect(err).ShouldNot(HaveOccurred())
Expect(cfg.Engine.ActiveService).To(Equal("QA"))
- Expect(cfg.Engine.ServiceDestinations["QA"]).To(Equal(
+ Expect(cfg.Engine.ServiceDestinations).To(HaveKeyWithValue("QA",
config.Destination{
URI: "ssh://root@server.fubar.com:2222/run/podman/podman.sock",
},
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 8e21ca606..efa9f399b 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -78,7 +78,7 @@ var _ = Describe("Podman images", func() {
session = podmanTest.Podman([]string{"images", "-qn"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", len(CACHE_IMAGES)))
+ Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
})
It("podman images with digests", func() {
@@ -125,7 +125,7 @@ var _ = Describe("Podman images", func() {
session := podmanTest.Podman([]string{"images", "-q", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
session = podmanTest.Podman([]string{"tag", ALPINE, "foo:a"})
session.WaitWithDefaultTimeout()
@@ -137,31 +137,31 @@ var _ = Describe("Podman images", func() {
session = podmanTest.Podman([]string{"images", "-q", "foo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman images filter reference", func() {
result := podmanTest.Podman([]string{"images", "-q", "-f", "reference=quay.io*"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(7))
+ Expect(result.OutputToStringArray()).To(HaveLen(7))
retalpine := podmanTest.Podman([]string{"images", "-f", "reference=a*pine"})
retalpine.WaitWithDefaultTimeout()
Expect(retalpine).Should(Exit(0))
- Expect(len(retalpine.OutputToStringArray())).To(Equal(6))
+ Expect(retalpine.OutputToStringArray()).To(HaveLen(6))
Expect(retalpine.OutputToString()).To(ContainSubstring("alpine"))
retalpine = podmanTest.Podman([]string{"images", "-f", "reference=alpine"})
retalpine.WaitWithDefaultTimeout()
Expect(retalpine).Should(Exit(0))
- Expect(len(retalpine.OutputToStringArray())).To(Equal(6))
+ Expect(retalpine.OutputToStringArray()).To(HaveLen(6))
Expect(retalpine.OutputToString()).To(ContainSubstring("alpine"))
retnone := podmanTest.Podman([]string{"images", "-q", "-f", "reference=bogus"})
retnone.WaitWithDefaultTimeout()
Expect(retnone).Should(Exit(0))
- Expect(len(retnone.OutputToStringArray())).To(Equal(0))
+ Expect(retnone.OutputToStringArray()).To(BeEmpty())
})
It("podman images filter before image", func() {
@@ -172,8 +172,7 @@ RUN apk update && apk add strace
result := podmanTest.Podman([]string{"images", "-q", "-f", "before=foobar.com/before:latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray()) >= 1).To(BeTrue())
-
+ Expect(len(result.OutputToStringArray())).To(BeNumerically(">=", 1))
})
It("podman images workingdir from image", func() {
@@ -194,7 +193,7 @@ WORKDIR /test
result := podmanTest.Podman([]string{"images", "-q", "-f", "since=quay.io/libpod/alpine:latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(9))
+ Expect(result.OutputToStringArray()).To(HaveLen(9))
})
It("podman image list filter after image", func() {
@@ -229,11 +228,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.
@@ -327,12 +325,12 @@ ENV foo=bar
session := podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(len(CACHE_IMAGES) + 2))
+ Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 2))
session2 := podmanTest.Podman([]string{"images", "--all"})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
- Expect(len(session2.OutputToStringArray())).To(Equal(len(CACHE_IMAGES) + 4))
+ Expect(session2.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 4))
})
It("podman images filter by label", func() {
@@ -344,7 +342,7 @@ LABEL "com.example.vendor"="Example Vendor"
session := podmanTest.Podman([]string{"images", "-f", "label=version=1.0"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman with images with no layers", func() {
@@ -381,7 +379,7 @@ LABEL "com.example.vendor"="Example Vendor"
session = podmanTest.Podman([]string{"history", "--quiet", "foo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(6))
+ Expect(session.OutputToStringArray()).To(HaveLen(6))
session = podmanTest.Podman([]string{"image", "list", "foo"})
session.WaitWithDefaultTimeout()
@@ -438,11 +436,11 @@ RUN > file2
result := podmanTest.Podman([]string{"image", "prune", "--filter", "label=abc", "--force"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
//check if really abc is removed
result = podmanTest.Podman([]string{"image", "list", "--filter", "label=abc"})
- Expect(len(result.OutputToStringArray())).To(Equal(0))
+ Expect(result.OutputToStringArray()).To(BeEmpty())
})
@@ -459,11 +457,11 @@ RUN > file2
result := podmanTest.Podman([]string{"builder", "prune", "--filter", "label=abc", "--force"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
//check if really abc is removed
result = podmanTest.Podman([]string{"image", "list", "--filter", "label=abc"})
- Expect(len(result.OutputToStringArray())).To(Equal(0))
+ Expect(result.OutputToStringArray()).To(BeEmpty())
})
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index 0f0237adc..127e26b11 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -113,7 +113,7 @@ var _ = Describe("Podman inspect", func() {
result := podmanTest.Podman([]string{"inspect", "--format={{.ID}}", cid, ALPINE})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(2))
+ Expect(result.OutputToStringArray()).To(HaveLen(2))
})
It("podman inspect container and filter for Image{ID}", func() {
@@ -124,12 +124,12 @@ var _ = Describe("Podman inspect", func() {
result := podmanTest.Podman([]string{"inspect", "--format={{.ImageID}}", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
result = podmanTest.Podman([]string{"inspect", "--format={{.Image}}", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
})
It("podman inspect container and filter for CreateCommand", func() {
@@ -140,7 +140,7 @@ var _ = Describe("Podman inspect", func() {
result := podmanTest.Podman([]string{"inspect", "--format={{.Config.CreateCommand}}", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
})
It("podman inspect -l with additional input should fail", func() {
@@ -200,7 +200,7 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).Should(Exit(0))
baseJSON := baseInspect.InspectImageJSON()
- Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON).To(HaveLen(1))
ctrInspect := podmanTest.Podman([]string{"container", "inspect", ALPINE})
ctrInspect.WaitWithDefaultTimeout()
@@ -210,7 +210,7 @@ var _ = Describe("Podman inspect", func() {
imageInspect.WaitWithDefaultTimeout()
Expect(imageInspect).Should(Exit(0))
imageJSON := imageInspect.InspectImageJSON()
- Expect(len(imageJSON)).To(Equal(1))
+ Expect(imageJSON).To(HaveLen(1))
Expect(baseJSON[0].ID).To(Equal(imageJSON[0].ID))
})
@@ -225,13 +225,13 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).Should(Exit(0))
baseJSON := baseInspect.InspectContainerToJSON()
- Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON).To(HaveLen(1))
ctrInspect := podmanTest.Podman([]string{"container", "inspect", ctrName})
ctrInspect.WaitWithDefaultTimeout()
Expect(ctrInspect).Should(Exit(0))
ctrJSON := ctrInspect.InspectContainerToJSON()
- Expect(len(ctrJSON)).To(Equal(1))
+ Expect(ctrJSON).To(HaveLen(1))
imageInspect := podmanTest.Podman([]string{"image", "inspect", ctrName})
imageInspect.WaitWithDefaultTimeout()
@@ -245,7 +245,7 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).To(ExitWithError())
emptyJSON := baseInspect.InspectContainerToJSON()
- Expect(len(emptyJSON)).To(Equal(0))
+ Expect(emptyJSON).To(BeEmpty())
})
It("podman inspect one container with not exist returns 1-length valid array", func() {
@@ -258,7 +258,7 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).To(ExitWithError())
baseJSON := baseInspect.InspectContainerToJSON()
- Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON).To(HaveLen(1))
Expect(baseJSON[0].Name).To(Equal(ctrName))
})
@@ -277,7 +277,7 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).Should(Exit(0))
baseJSON := baseInspect.InspectContainerToJSON()
- Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON).To(HaveLen(1))
Expect(baseJSON[0].Name).To(Equal(ctrName))
})
@@ -301,7 +301,7 @@ var _ = Describe("Podman inspect", func() {
baseInspect.WaitWithDefaultTimeout()
Expect(baseInspect).Should(Exit(0))
baseJSON := baseInspect.InspectContainerToJSON()
- Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON).To(HaveLen(1))
Expect(baseJSON[0].HostConfig.SecurityOpt).To(Equal([]string{"label=type:spc_t,label=level:s0", "seccomp=unconfined"}))
})
@@ -468,8 +468,8 @@ var _ = Describe("Podman inspect", func() {
Expect(session).Should(Exit(0))
inspect := podmanTest.InspectContainer(ctrName)
- Expect(len(inspect)).To(Equal(1))
- Expect(len(inspect[0].NetworkSettings.Networks)).To(Equal(1))
+ Expect(inspect).To(HaveLen(1))
+ Expect(inspect[0].NetworkSettings.Networks).To(HaveLen(1))
})
It("Verify stopped container still has default network in inspect", func() {
@@ -480,8 +480,8 @@ var _ = Describe("Podman inspect", func() {
Expect(session).Should(Exit(0))
inspect := podmanTest.InspectContainer(ctrName)
- Expect(len(inspect)).To(Equal(1))
- Expect(len(inspect[0].NetworkSettings.Networks)).To(Equal(1))
+ Expect(inspect).To(HaveLen(1))
+ Expect(inspect[0].NetworkSettings.Networks).To(HaveLen(1))
})
It("Container inspect with unlimited uilimits should be -1", func() {
@@ -519,8 +519,8 @@ var _ = Describe("Podman inspect", func() {
Expect(inspect).Should(Exit(0))
data := inspect.InspectContainerToJSON()
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].HostConfig.CapDrop)).To(Equal(3))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].HostConfig.CapDrop).To(HaveLen(3))
Expect(data[0].HostConfig.CapDrop[0]).To(Equal("CAP_AUDIT_WRITE"))
Expect(data[0].HostConfig.CapDrop[1]).To(Equal("CAP_MKNOD"))
Expect(data[0].HostConfig.CapDrop[2]).To(Equal("CAP_NET_RAW"))
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/logs_test.go b/test/e2e/logs_test.go
index 2558af0eb..dc00491cd 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -68,7 +68,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
Expect(results.OutputToString()).To(Equal("podman podman podman"))
})
@@ -83,7 +83,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--tail", "2", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(2))
+ Expect(results.OutputToStringArray()).To(HaveLen(2))
})
It("tail zero lines: "+log, func() {
@@ -97,7 +97,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--tail", "0", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(0))
+ Expect(results.OutputToStringArray()).To(BeEmpty())
})
It("tail 99 lines: "+log, func() {
@@ -111,7 +111,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--tail", "99", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
})
It("tail 800 lines: "+log, func() {
@@ -125,7 +125,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--tail", "800", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(800))
+ Expect(results.OutputToStringArray()).To(HaveLen(800))
})
It("tail 2 lines with timestamps: "+log, func() {
@@ -139,7 +139,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--tail", "2", "-t", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(2))
+ Expect(results.OutputToStringArray()).To(HaveLen(2))
})
It("since time 2017-08-07: "+log, func() {
@@ -153,7 +153,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--since", "2017-08-07T10:10:09.056611202-04:00", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
})
It("since duration 10m: "+log, func() {
@@ -167,7 +167,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--since", "10m", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
})
It("until duration 10m: "+log, func() {
@@ -181,7 +181,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--until", "10m", cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
})
It("until time NOW: "+log, func() {
@@ -198,7 +198,7 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "--until", nowS, cid})
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
- Expect(len(results.OutputToStringArray())).To(Equal(3))
+ Expect(results.OutputToStringArray()).To(HaveLen(3))
})
It("latest and container name should fail: "+log, func() {
@@ -228,7 +228,7 @@ var _ = Describe("Podman logs", func() {
Expect(results).Should(Exit(0))
output := results.OutputToStringArray()
- Expect(len(output)).To(Equal(6))
+ Expect(output).To(HaveLen(6))
Expect(strings.Contains(output[0], cid1[:12]) || strings.Contains(output[0], cid2[:12])).To(BeTrue())
})
@@ -342,7 +342,7 @@ var _ = Describe("Podman logs", func() {
results.WaitWithDefaultTimeout()
Expect(results).To(Exit(0))
outlines := results.OutputToStringArray()
- Expect(len(outlines)).To(Equal(2))
+ Expect(outlines).To(HaveLen(2))
Expect(outlines[0]).To(Equal("1\r"))
Expect(outlines[1]).To(Equal("2\r"))
})
diff --git a/test/e2e/mount_test.go b/test/e2e/mount_test.go
index 0555a0749..cd7f73337 100644
--- a/test/e2e/mount_test.go
+++ b/test/e2e/mount_test.go
@@ -348,7 +348,7 @@ var _ = Describe("Podman mount", func() {
umount := podmanTest.Podman([]string{"image", "umount", "--all"})
umount.WaitWithDefaultTimeout()
Expect(umount).Should(Exit(0))
- Expect(len(umount.OutputToStringArray())).To(Equal(1))
+ Expect(umount.OutputToStringArray()).To(HaveLen(1))
})
It("podman mount many", func() {
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index ff306f0f8..92f962abc 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)))
})
}
@@ -262,8 +262,8 @@ var _ = Describe("Podman network", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
conData := inspect.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
- Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(1))
+ Expect(conData).To(HaveLen(1))
+ Expect(conData[0].NetworkSettings.Networks).To(HaveLen(1))
net, ok := conData[0].NetworkSettings.Networks[netName]
Expect(ok).To(BeTrue())
Expect(net.NetworkID).To(Equal(netName))
@@ -298,8 +298,8 @@ var _ = Describe("Podman network", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
conData := inspect.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
- Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(2))
+ Expect(conData).To(HaveLen(1))
+ Expect(conData[0].NetworkSettings.Networks).To(HaveLen(2))
net1, ok := conData[0].NetworkSettings.Networks[netName1]
Expect(ok).To(BeTrue())
Expect(net1.NetworkID).To(Equal(netName1))
@@ -335,8 +335,8 @@ var _ = Describe("Podman network", func() {
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
conData := inspect.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
- Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(2))
+ Expect(conData).To(HaveLen(1))
+ Expect(conData[0].NetworkSettings.Networks).To(HaveLen(2))
net1, ok := conData[0].NetworkSettings.Networks[netName1]
Expect(ok).To(BeTrue())
Expect(net1.NetworkID).To(Equal(netName1))
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index 99488a507..c9182960a 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -282,7 +282,7 @@ var _ = Describe("Podman pause", func() {
running := podmanTest.Podman([]string{"ps", "-q"})
running.WaitWithDefaultTimeout()
Expect(running).Should(Exit(0))
- Expect(len(running.OutputToStringArray())).To(Equal(3))
+ Expect(running.OutputToStringArray()).To(HaveLen(3))
pause := podmanTest.Podman([]string{"pause", "--all"})
pause.WaitWithDefaultTimeout()
@@ -291,7 +291,7 @@ var _ = Describe("Podman pause", func() {
running = podmanTest.Podman([]string{"ps", "-q"})
running.WaitWithDefaultTimeout()
Expect(running).Should(Exit(0))
- Expect(len(running.OutputToStringArray())).To(Equal(0))
+ Expect(running.OutputToStringArray()).To(BeEmpty())
unpause := podmanTest.Podman([]string{"unpause", "--all"})
unpause.WaitWithDefaultTimeout()
@@ -317,7 +317,7 @@ var _ = Describe("Podman pause", func() {
running := podmanTest.Podman([]string{"ps", "-q"})
running.WaitWithDefaultTimeout()
Expect(running).Should(Exit(0))
- Expect(len(running.OutputToStringArray())).To(Equal(3))
+ Expect(running.OutputToStringArray()).To(HaveLen(3))
})
})
diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go
index 9bdf9d06b..a56560634 100644
--- a/test/e2e/play_build_test.go
+++ b/test/e2e/play_build_test.go
@@ -125,7 +125,7 @@ LABEL marge=mom
Expect(inspect).Should(Exit(0))
inspectData := inspect.InspectContainerToJSON()
Expect(len(inspectData)).To(BeNumerically(">", 0))
- Expect(inspectData[0].Config.Labels["homer"]).To(Equal("dad"))
+ Expect(inspectData[0].Config.Labels).To(HaveKeyWithValue("homer", "dad"))
})
It("Check that image is built using Containerfile", func() {
@@ -162,7 +162,7 @@ LABEL marge=mom
Expect(inspect).Should(Exit(0))
inspectData := inspect.InspectContainerToJSON()
Expect(len(inspectData)).To(BeNumerically(">", 0))
- Expect(inspectData[0].Config.Labels["homer"]).To(Equal("dad"))
+ Expect(inspectData[0].Config.Labels).To(HaveKeyWithValue("homer", "dad"))
})
It("Do not build image if already in the local store", func() {
@@ -208,8 +208,8 @@ LABEL marge=mom
Expect(inspect).Should(Exit(0))
inspectData := inspect.InspectContainerToJSON()
Expect(len(inspectData)).To(BeNumerically(">", 0))
- Expect(inspectData[0].Config.Labels["homer"]).To(Equal(""))
- Expect(inspectData[0].Config.Labels["marge"]).To(Equal("mom"))
+ Expect(inspectData[0].Config.Labels).To(Not(HaveKey("homer")))
+ Expect(inspectData[0].Config.Labels).To(HaveKeyWithValue("marge", "mom"))
})
It("--build should override image in store", func() {
@@ -255,8 +255,8 @@ LABEL marge=mom
Expect(inspect).Should(Exit(0))
inspectData := inspect.InspectContainerToJSON()
Expect(len(inspectData)).To(BeNumerically(">", 0))
- Expect(inspectData[0].Config.Labels["homer"]).To(Equal("dad"))
- Expect(inspectData[0].Config.Labels["marge"]).To(Equal(""))
+ Expect(inspectData[0].Config.Labels).To(HaveKeyWithValue("homer", "dad"))
+ Expect(inspectData[0].Config.Labels).To(Not(HaveKey("marge")))
})
})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 1e15b50a7..36010704f 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -380,6 +380,18 @@ spec:
persistentVolumeClaim:
claimName: {{ .PersistentVolumeClaim.ClaimName }}
{{- end }}
+ {{- if (eq .VolumeType "ConfigMap") }}
+ configMap:
+ name: {{ .ConfigMap.Name }}
+ optional: {{ .ConfigMap.Optional }}
+ {{- with .ConfigMap.Items }}
+ items:
+ {{- range . }}
+ - key: {{ .key }}
+ path: {{ .path }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
{{ end }}
{{ end }}
status: {}
@@ -619,14 +631,14 @@ func createSecret(podmanTest *PodmanTestIntegration, name string, value []byte)
Expect(secret).Should(Exit(0))
}
-// ConfigMap describes the options a kube yaml can be configured at configmap level
-type ConfigMap struct {
+// CM describes the options a kube yaml can be configured at configmap level
+type CM struct {
Name string
Data map[string]string
}
-func getConfigMap(options ...configMapOption) *ConfigMap {
- cm := ConfigMap{
+func getConfigMap(options ...configMapOption) *CM {
+ cm := CM{
Name: defaultConfigMapName,
Data: map[string]string{},
}
@@ -638,16 +650,16 @@ func getConfigMap(options ...configMapOption) *ConfigMap {
return &cm
}
-type configMapOption func(*ConfigMap)
+type configMapOption func(*CM)
func withConfigMapName(name string) configMapOption {
- return func(configmap *ConfigMap) {
+ return func(configmap *CM) {
configmap.Name = name
}
}
func withConfigMapData(k, v string) configMapOption {
- return func(configmap *ConfigMap) {
+ return func(configmap *CM) {
configmap.Data[k] = v
}
}
@@ -1047,11 +1059,18 @@ type PersistentVolumeClaim struct {
ClaimName string
}
+type ConfigMap struct {
+ Name string
+ Items []map[string]string
+ Optional bool
+}
+
type Volume struct {
VolumeType string
Name string
HostPath
PersistentVolumeClaim
+ ConfigMap
}
// getHostPathVolume takes a type and a location for a HostPath
@@ -1079,6 +1098,20 @@ func getPersistentVolumeClaimVolume(vName string) *Volume {
}
}
+// getConfigMap returns a new ConfigMap Volume given the name and items
+// of the ConfigMap.
+func getConfigMapVolume(vName string, items []map[string]string, optional bool) *Volume {
+ return &Volume{
+ VolumeType: "ConfigMap",
+ Name: defaultVolName,
+ ConfigMap: ConfigMap{
+ Name: vName,
+ Items: items,
+ Optional: optional,
+ },
+ }
+}
+
type Env struct {
Name string
Value string
@@ -2017,8 +2050,8 @@ spec:
ctr := inspect.InspectContainerToJSON()
Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc"))
- Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
- Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
+ Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1")))
+ Expect(ctr[0].Config.Labels).To(HaveKeyWithValue("key1", ContainSubstring("value1")))
Expect(ctr[0].Config.StopSignal).To(Equal(uint(51)))
})
@@ -2291,7 +2324,7 @@ VOLUME %s`, ALPINE, hostPathDir+"/")
// If two volumes are specified and share the same destination,
// only one will be mounted. Host path volumes take precedence.
ctrJSON := inspect.InspectContainerToJSON()
- Expect(len(ctrJSON[0].Mounts)).To(Equal(1))
+ Expect(ctrJSON[0].Mounts).To(HaveLen(1))
Expect(ctrJSON[0].Mounts[0].Type).To(Equal("bind"))
})
@@ -2316,6 +2349,75 @@ VOLUME %s`, ALPINE, hostPathDir+"/")
Expect(inspect.OutputToString()).To(Equal(correct))
})
+ It("podman play kube ConfigMap volume with no items", func() {
+ volumeName := "cmVol"
+ cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar"))
+ cmYaml, err := getKubeYaml("configmap", cm)
+ Expect(err).To(BeNil())
+
+ ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
+ pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, false)), withCtr(ctr))
+ podYaml, err := getKubeYaml("pod", pod)
+ Expect(err).To(BeNil())
+ yamls := []string{cmYaml, podYaml}
+ err = generateMultiDocKubeYaml(yamls, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"})
+ cmData.WaitWithDefaultTimeout()
+ Expect(cmData).Should(Exit(0))
+ Expect(cmData.OutputToString()).To(Equal("foobar"))
+ })
+
+ It("podman play kube ConfigMap volume with items", func() {
+ volumeName := "cmVol"
+ cm := getConfigMap(withConfigMapName(volumeName), withConfigMapData("FOO", "foobar"))
+ cmYaml, err := getKubeYaml("configmap", cm)
+ Expect(err).To(BeNil())
+ volumeContents := []map[string]string{{
+ "key": "FOO",
+ "path": "BAR",
+ }}
+
+ ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
+ pod := getPod(withVolume(getConfigMapVolume(volumeName, volumeContents, false)), withCtr(ctr))
+ podYaml, err := getKubeYaml("pod", pod)
+ Expect(err).To(BeNil())
+ yamls := []string{cmYaml, podYaml}
+ err = generateMultiDocKubeYaml(yamls, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ cmData := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/BAR"})
+ cmData.WaitWithDefaultTimeout()
+ Expect(cmData).Should(Exit(0))
+ Expect(cmData.OutputToString()).To(Equal("foobar"))
+
+ cmData = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/test/FOO"})
+ cmData.WaitWithDefaultTimeout()
+ Expect(cmData).Should(Not(Exit(0)))
+ })
+
+ It("podman play kube with a missing optional ConfigMap volume", func() {
+ volumeName := "cmVol"
+
+ ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
+ pod := getPod(withVolume(getConfigMapVolume(volumeName, []map[string]string{}, true)), withCtr(ctr))
+ err = generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+ })
+
It("podman play kube applies labels to pods", func() {
var numReplicas int32 = 5
expectedLabelKey := "key1"
@@ -2775,7 +2877,7 @@ invalid kube kind
ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"})
ls.WaitWithDefaultTimeout()
Expect(ls).Should(Exit(0))
- Expect(len(ls.OutputToStringArray())).To(Equal(1))
+ Expect(ls.OutputToStringArray()).To(HaveLen(1))
// teardown
teardown := podmanTest.Podman([]string{"play", "kube", "--down", kubeYaml})
@@ -2785,7 +2887,7 @@ invalid kube kind
checkls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"})
checkls.WaitWithDefaultTimeout()
Expect(checkls).Should(Exit(0))
- Expect(len(checkls.OutputToStringArray())).To(Equal(0))
+ Expect(checkls.OutputToStringArray()).To(BeEmpty())
})
It("podman play kube teardown pod does not exist", func() {
@@ -2867,7 +2969,7 @@ invalid kube kind
ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"})
ls.WaitWithDefaultTimeout()
Expect(ls).Should(Exit(0))
- Expect(len(ls.OutputToStringArray())).To(Equal(1))
+ Expect(ls.OutputToStringArray()).To(HaveLen(1))
containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{len .Containers}}'"})
@@ -2906,7 +3008,7 @@ invalid kube kind
ls := podmanTest.Podman([]string{"pod", "ps", "--format", "'{{.ID}}'"})
ls.WaitWithDefaultTimeout()
Expect(ls).Should(Exit(0))
- Expect(len(ls.OutputToStringArray())).To(Equal(1))
+ Expect(ls.OutputToStringArray()).To(HaveLen(1))
})
Describe("verify environment variables", func() {
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 186688b93..41a017a52 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -49,7 +49,7 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc"})
check.WaitWithDefaultTimeout()
Expect(check.OutputToString()).To(ContainSubstring(podID))
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman create pod with name", func() {
@@ -72,7 +72,7 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"pod", "ps", "-q"})
check.WaitWithDefaultTimeout()
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman create pod with same name as ctr", func() {
@@ -86,7 +86,7 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"pod", "ps", "-q"})
check.WaitWithDefaultTimeout()
- Expect(len(check.OutputToStringArray())).To(Equal(0))
+ Expect(check.OutputToStringArray()).To(BeEmpty())
})
It("podman create pod without network portbindings", func() {
@@ -517,7 +517,7 @@ entrypoint ["/fromimage"]
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("inet 127.0.0.1/8 scope host lo"))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
})
It("podman pod create --infra-image w/untagged image", func() {
@@ -729,7 +729,7 @@ ENTRYPOINT ["sleep","99999"]
m[l] = l
}
// check for no duplicates
- Expect(len(m)).To(Equal(5))
+ Expect(m).To(HaveLen(5))
})
It("podman pod create --userns=auto:size=%d", func() {
diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go
index 6d57c3887..4a5a8c6b0 100644
--- a/test/e2e/pod_infra_container_test.go
+++ b/test/e2e/pod_infra_container_test.go
@@ -43,11 +43,11 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc"})
check.WaitWithDefaultTimeout()
Expect(check.OutputToString()).To(ContainSubstring(podID))
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
check = podmanTest.Podman([]string{"ps", "-qa", "--no-trunc"})
check.WaitWithDefaultTimeout()
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman start infra container", func() {
@@ -63,7 +63,7 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"ps", "-qa", "--no-trunc", "--filter", "status=running"})
check.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman start infra container different image", func() {
@@ -95,13 +95,13 @@ var _ = Describe("Podman pod create", func() {
check := podmanTest.Podman([]string{"ps", "-a", "--no-trunc", "--ns", "--format", "{{.Namespaces.IPC}} {{.Namespaces.NET}}"})
check.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(check.OutputToStringArray())).To(Equal(2))
+ Expect(check.OutputToStringArray()).To(HaveLen(2))
Expect(check.OutputToStringArray()[0]).To(Equal(check.OutputToStringArray()[1]))
check = podmanTest.Podman([]string{"ps", "-a", "--no-trunc", "--ns", "--format", "{{.IPC}} {{.NET}}"})
check.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(check.OutputToStringArray())).To(Equal(2))
+ Expect(check.OutputToStringArray()).To(HaveLen(2))
Expect(check.OutputToStringArray()[0]).To(Equal(check.OutputToStringArray()[1]))
})
@@ -169,7 +169,7 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
PIDs := check.OutputToStringArray()
- Expect(len(PIDs)).To(Equal(3))
+ Expect(PIDs).To(HaveLen(3))
ctrPID, _ := strconv.Atoi(PIDs[1])
infraPID, _ := strconv.Atoi(PIDs[2])
@@ -243,13 +243,13 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray := check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
check = podmanTest.Podman([]string{"ps", "-a", "--ns", "--format", "{{.PIDNS}}"})
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray = check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
PID1 := outputArray[0]
PID2 := outputArray[1]
@@ -274,7 +274,7 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray := check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
PID1 := outputArray[0]
PID2 := outputArray[1]
@@ -299,7 +299,7 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray := check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
PID1 := outputArray[0]
PID2 := outputArray[1]
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 8a6f2a367..0fc16b507 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -97,7 +97,7 @@ var _ = Describe("Podman pod inspect", func() {
err := json.Unmarshal(inspectOut.Out.Contents(), inspectJSON)
Expect(err).To(BeNil())
Expect(inspectJSON.InfraConfig).To(Not(BeNil()))
- Expect(len(inspectJSON.InfraConfig.PortBindings["80/tcp"])).To(Equal(1))
+ Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"]).To(HaveLen(1))
Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8383"))
})
diff --git a/test/e2e/pod_pod_namespaces_test.go b/test/e2e/pod_pod_namespaces_test.go
index 9e9b9b2d3..293fd02ae 100644
--- a/test/e2e/pod_pod_namespaces_test.go
+++ b/test/e2e/pod_pod_namespaces_test.go
@@ -52,7 +52,7 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray := check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
NAMESPACE1 := outputArray[0]
fmt.Println("NAMESPACE1:", NAMESPACE1)
@@ -98,7 +98,7 @@ var _ = Describe("Podman pod create", func() {
check.WaitWithDefaultTimeout()
Expect(check).Should(Exit(0))
outputArray := check.OutputToStringArray()
- Expect(len(outputArray)).To(Equal(2))
+ Expect(outputArray).To(HaveLen(2))
NAMESPACE1 := outputArray[0]
fmt.Println("NAMESPACE1:", NAMESPACE1)
diff --git a/test/e2e/pod_prune_test.go b/test/e2e/pod_prune_test.go
index 6273fcec3..84348f30c 100644
--- a/test/e2e/pod_prune_test.go
+++ b/test/e2e/pod_prune_test.go
@@ -56,7 +56,7 @@ var _ = Describe("Podman pod prune", func() {
result = podmanTest.Podman([]string{"ps", "-qa"})
result.WaitWithDefaultTimeout()
- Expect(len(result.OutputToStringArray())).To(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
})
It("podman pod prune removes a pod with a stopped container", func() {
@@ -72,6 +72,6 @@ var _ = Describe("Podman pod prune", func() {
result = podmanTest.Podman([]string{"ps", "-qa"})
result.WaitWithDefaultTimeout()
- Expect(len(result.OutputToStringArray())).To(Equal(0))
+ Expect(result.OutputToStringArray()).To(BeEmpty())
})
})
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index b4a0df904..4b2a3b66d 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -135,14 +135,14 @@ var _ = Describe("Podman ps", func() {
Expect(result).Should(Exit(0))
output := result.OutputToStringArray()
- Expect(len(output)).To(Equal(2))
+ Expect(output).To(HaveLen(2))
result = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "name=mypod$"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
output = result.OutputToStringArray()
- Expect(len(output)).To(Equal(1))
+ Expect(output).To(HaveLen(1))
Expect(output[0]).To(Equal(podid))
})
@@ -368,7 +368,7 @@ var _ = Describe("Podman ps", func() {
infra := podmanTest.Podman([]string{"pod", "ps", "--format", "{{.InfraId}}"})
infra.WaitWithDefaultTimeout()
- Expect(len(infra.OutputToString())).To(BeZero())
+ Expect(infra.OutputToString()).To(BeEmpty())
})
It("podman pod ps format with labels", func() {
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index d9b0761fa..636503a0c 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -96,7 +96,7 @@ var _ = Describe("Podman pod rm", func() {
result = podmanTest.Podman([]string{"ps", "-qa"})
result.WaitWithDefaultTimeout()
- Expect(len(result.OutputToStringArray())).To(Equal(0))
+ Expect(result.OutputToStringArray()).To(BeEmpty())
})
It("podman pod rm -f does remove a running container", func() {
diff --git a/test/e2e/pod_top_test.go b/test/e2e/pod_top_test.go
index 253d4adf5..602546141 100644
--- a/test/e2e/pod_top_test.go
+++ b/test/e2e/pod_top_test.go
@@ -120,7 +120,7 @@ var _ = Describe("Podman top", func() {
result := podmanTest.Podman([]string{"pod", "top", podid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(3))
+ Expect(result.OutputToStringArray()).To(HaveLen(3))
})
It("podman pod top on pod with containers in different namespace", func() {
@@ -145,6 +145,6 @@ var _ = Describe("Podman top", func() {
result := podmanTest.Podman([]string{"pod", "top", podid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(3))
+ Expect(result.OutputToStringArray()).To(HaveLen(3))
})
})
diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go
index 223fcc5b2..6a70fd556 100644
--- a/test/e2e/prune_test.go
+++ b/test/e2e/prune_test.go
@@ -98,22 +98,21 @@ 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.
session = podmanTest.Podman([]string{"image", "prune", "-f"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
// Let's be extra sure that the same number of images is
// reported.
session = podmanTest.Podman([]string{"images", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(numImages))
+ Expect(session.OutputToStringArray()).To(HaveLen(numImages))
// Now build an image and untag it. The (intermediate) images
// should be removed recursively during pruning.
@@ -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,14 +133,14 @@ 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.
session = podmanTest.Podman([]string{"images", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(numImages - numPrunedImages))
+ Expect(session.OutputToStringArray()).To(HaveLen(numImages - numPrunedImages))
})
It("podman image prune - handle empty images", func() {
@@ -159,7 +157,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"image", "prune", "-f"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
// Now the image will be untagged, and its parent images will
// be removed recursively.
@@ -170,7 +168,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"image", "prune", "-f"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman image prune dangling images", func() {
@@ -180,7 +178,7 @@ var _ = Describe("Podman prune", func() {
none.WaitWithDefaultTimeout()
Expect(none).Should(Exit(0))
hasNone, result := none.GrepString("<none>")
- Expect(len(result)).To(Equal(2))
+ Expect(result).To(HaveLen(2))
Expect(hasNone).To(BeTrue())
prune := podmanTest.Podman([]string{"image", "prune", "-f"})
@@ -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() {
@@ -212,7 +210,7 @@ var _ = Describe("Podman prune", func() {
images.WaitWithDefaultTimeout()
Expect(images).Should(Exit(0))
// all images are unused, so they all should be deleted!
- Expect(len(images.OutputToStringArray())).To(Equal(len(CACHE_IMAGES)))
+ Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
})
It("podman system image prune unused images", func() {
@@ -225,7 +223,7 @@ var _ = Describe("Podman prune", func() {
images := podmanTest.Podman([]string{"images", "-aq"})
images.WaitWithDefaultTimeout()
// all images are unused, so they all should be deleted!
- Expect(len(images.OutputToStringArray())).To(Equal(len(CACHE_IMAGES)))
+ Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
})
It("podman system prune pods", func() {
@@ -249,7 +247,7 @@ var _ = Describe("Podman prune", func() {
pods := podmanTest.Podman([]string{"pod", "ps"})
pods.WaitWithDefaultTimeout()
Expect(pods).Should(Exit(0))
- Expect(len(pods.OutputToStringArray())).To(Equal(3))
+ Expect(pods.OutputToStringArray()).To(HaveLen(3))
prune := podmanTest.Podman([]string{"system", "prune", "-f"})
prune.WaitWithDefaultTimeout()
@@ -258,7 +256,7 @@ var _ = Describe("Podman prune", func() {
pods = podmanTest.Podman([]string{"pod", "ps"})
pods.WaitWithDefaultTimeout()
Expect(pods).Should(Exit(0))
- Expect(len(pods.OutputToStringArray())).To(Equal(2))
+ Expect(pods.OutputToStringArray()).To(HaveLen(2))
})
It("podman system prune - pod,container stopped", func() {
@@ -346,7 +344,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes"})
session.WaitWithDefaultTimeout()
@@ -356,7 +354,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
// One Pod should not be pruned as it was running
Expect(podmanTest.NumberOfPods()).To(Equal(1))
@@ -367,7 +365,7 @@ var _ = Describe("Podman prune", func() {
// Image should not be pruned and number should be same.
images := podmanTest.Podman([]string{"images"})
images.WaitWithDefaultTimeout()
- Expect(len(images.OutputToStringArray())).To(Equal(numberOfImages))
+ Expect(images.OutputToStringArray()).To(HaveLen(numberOfImages))
})
It("podman system prune - with dangling images true", func() {
@@ -410,12 +408,12 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
images := podmanTest.Podman([]string{"images", "-aq"})
images.WaitWithDefaultTimeout()
// all images are unused, so they all should be deleted!
- Expect(len(images.OutputToStringArray())).To(Equal(len(CACHE_IMAGES)))
+ Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
})
It("podman system prune --volumes --filter", func() {
@@ -446,7 +444,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(7))
+ Expect(session.OutputToStringArray()).To(HaveLen(7))
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=label1=value1"})
session.WaitWithDefaultTimeout()
@@ -455,7 +453,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(6))
+ Expect(session.OutputToStringArray()).To(HaveLen(6))
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=sharedlabel1=slv1"})
session.WaitWithDefaultTimeout()
@@ -464,7 +462,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(5))
+ Expect(session.OutputToStringArray()).To(HaveLen(5))
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=sharedlabel1"})
session.WaitWithDefaultTimeout()
@@ -473,7 +471,7 @@ var _ = Describe("Podman prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
podmanTest.Cleanup()
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 3334250db..a9f334f5c 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -118,7 +118,7 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "-q", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).Should(Equal(1))
+ Expect(result.OutputToStringArray()).To(HaveLen(1))
})
It("podman ps last flag", func() {
@@ -133,7 +133,7 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "--last", "2"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).Should(Equal(2)) // 1 container
+ Expect(result.OutputToStringArray()).Should(HaveLen(2)) // 1 container
_, ec, _ := podmanTest.RunLsContainer("test1")
Expect(ec).To(Equal(0))
@@ -147,17 +147,17 @@ var _ = Describe("Podman ps", func() {
result = podmanTest.Podman([]string{"ps", "--last", "2"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).Should(Equal(3)) // 2 containers
+ Expect(result.OutputToStringArray()).Should(HaveLen(3)) // 2 containers
result = podmanTest.Podman([]string{"ps", "--last", "3"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).Should(Equal(4)) // 3 containers
+ Expect(result.OutputToStringArray()).Should(HaveLen(4)) // 3 containers
result = podmanTest.Podman([]string{"ps", "--last", "100"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).Should(Equal(5)) // 4 containers (3 running + 1 created)
+ Expect(result.OutputToStringArray()).Should(HaveLen(5)) // 4 containers (3 running + 1 created)
})
It("podman ps no-trunc", func() {
@@ -357,7 +357,7 @@ var _ = Describe("Podman ps", func() {
Expect(result).Should(Exit(0))
output := result.OutputToStringArray()
- Expect(len(output)).To(Equal(1))
+ Expect(output).To(HaveLen(1))
Expect(output[0]).To(Equal(fullCid))
})
@@ -580,14 +580,14 @@ var _ = Describe("Podman ps", func() {
Expect(result).Should(Exit(0))
output := result.OutputToStringArray()
- Expect(len(output)).To(Equal(2))
+ Expect(output).To(HaveLen(2))
result = podmanTest.Podman([]string{"ps", "-aq", "--no-trunc", "--filter", "name=test1$"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
output = result.OutputToStringArray()
- Expect(len(output)).To(Equal(1))
+ Expect(output).To(HaveLen(1))
Expect(output[0]).To(Equal(fullCid))
})
@@ -602,7 +602,7 @@ var _ = Describe("Podman ps", func() {
Expect(result).Should(Exit(0))
output := result.OutputToStringArray()
- Expect(len(output)).To(Equal(1))
+ Expect(output).To(HaveLen(1))
Expect(output[0]).To(Equal(ctrName))
})
@@ -669,7 +669,7 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "name=test"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(5))
+ Expect(session.OutputToStringArray()).To(HaveLen(5))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
Expect(session.OutputToString()).To(ContainSubstring("test3"))
@@ -678,7 +678,7 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "name=test1", "--filter", "name=test2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
@@ -686,19 +686,19 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "id=" + cid1[:40], "--filter", "id=" + cid1 + "$"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
session = podmanTest.Podman([]string{"ps", "--filter", "status=created"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test3"))
session = podmanTest.Podman([]string{"ps", "--filter", "status=created", "--filter", "status=exited"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
Expect(session.OutputToString()).To(ContainSubstring("test3"))
Expect(session.OutputToString()).To(ContainSubstring("test4"))
@@ -706,63 +706,63 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "label=foo=1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
session = podmanTest.Podman([]string{"ps", "--filter", "label=foo=1", "--filter", "status=exited"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "label=foo=1", "--filter", "label=non=1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "label=foo=1", "--filter", "label=bar=2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "exited=1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "exited=1", "--filter", "exited=0"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToString()).To(ContainSubstring("test2"))
Expect(session.OutputToString()).To(ContainSubstring("test4"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "volume=volume1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
Expect(session.OutputToString()).To(ContainSubstring("test4"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "volume=/:/test2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test4"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "before=test2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToString()).To(ContainSubstring("test1"))
session = podmanTest.Podman([]string{"ps", "--all", "--filter", "since=test2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToString()).To(ContainSubstring("test3"))
Expect(session.OutputToString()).To(ContainSubstring("test4"))
})
@@ -790,28 +790,28 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "-q", "--no-trunc", "--filter", "pod=pod1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()).To(ContainElement(con1.OutputToString()))
// filter by full pod id
session = podmanTest.Podman([]string{"ps", "-q", "--no-trunc", "--filter", "pod=" + pod1.OutputToString()})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()).To(ContainElement(con1.OutputToString()))
// filter by partial pod id
session = podmanTest.Podman([]string{"ps", "-q", "--no-trunc", "--filter", "pod=" + pod1.OutputToString()[0:12]})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()).To(ContainElement(con1.OutputToString()))
// filter by multiple pods is inclusive
session = podmanTest.Podman([]string{"ps", "-q", "--no-trunc", "--filter", "pod=pod1", "--filter", "pod=pod2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
Expect(session.OutputToStringArray()).To(ContainElement(con1.OutputToString()))
Expect(session.OutputToStringArray()).To(ContainElement(con2.OutputToString()))
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index b2474b223..f22acca6e 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -443,7 +443,7 @@ var _ = Describe("Podman pull", func() {
Expect(setup).Should(Exit(0))
data := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
return data[0].ID
}
@@ -457,8 +457,8 @@ var _ = Describe("Podman pull", func() {
Expect(setup).Should(Exit(0))
data := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].RepoTags)).To(Equal(0))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].RepoTags).To(BeEmpty())
}
tag := func(image, tag string) {
@@ -511,8 +511,8 @@ var _ = Describe("Podman pull", func() {
Expect(setup).Should(Exit(0))
data := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].RepoTags)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].RepoTags).To(HaveLen(1))
Expect(data[0].RepoTags[0]).To(Equal(t.tag1))
Expect(data[0].ID).To(Equal(image1))
}
@@ -540,7 +540,7 @@ var _ = Describe("Podman pull", func() {
Expect(setup).Should(Exit(0))
data := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Os).To(Equal(runtime.GOOS))
Expect(data[0].Architecture).To(Equal("arm64"))
})
@@ -567,7 +567,7 @@ var _ = Describe("Podman pull", func() {
Expect(setup).Should(Exit(0))
data := setup.InspectImageJSON() // returns []inspect.ImageData
- Expect(len(data)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
Expect(data[0].Os).To(Equal(runtime.GOOS))
Expect(data[0].Architecture).To(Equal("arm64"))
})
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..658155587 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -136,13 +136,13 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(12))
+ Expect(session.OutputToStringArray()).To(HaveLen(12))
session = podmanTest.Podman([]string{"images", "--sort", "created", "--format", "{{.Id}}", "--all"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(13),
- "Output from 'podman images -q -a':'%s'", session.Out.Contents())
+ Expect(session.OutputToStringArray()).To(HaveLen(13),
+ "Output from 'podman images -q -a'")
untaggedImg := session.OutputToStringArray()[1]
session = podmanTest.Podman([]string{"rmi", "-f", untaggedImg})
@@ -179,7 +179,7 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(len(CACHE_IMAGES) + 1))
+ Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 1))
})
It("podman rmi with cached images", func() {
@@ -221,7 +221,7 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(len(CACHE_IMAGES) + 1))
+ Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 1))
podmanTest.BuildImage(dockerfile, "test3", "true")
@@ -236,7 +236,7 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToString())).To(Equal(155))
+ Expect(session.OutputToString()).To(HaveLen(155))
})
It("podman rmi -a with no images should be exit 0", func() {
@@ -267,7 +267,7 @@ RUN find $LOCAL
images := podmanTest.Podman([]string{"images", "-aq"})
images.WaitWithDefaultTimeout()
Expect(images).Should(Exit(0))
- Expect(len(images.OutputToStringArray())).To(Equal(len(CACHE_IMAGES)))
+ Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
})
// Don't rerun all tests; just assume that if we get that diagnostic,
@@ -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..23c343332 100644
--- a/test/e2e/run_entrypoint_test.go
+++ b/test/e2e/run_entrypoint_test.go
@@ -64,7 +64,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman run entrypoint with cmd", func() {
@@ -76,7 +76,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
})
It("podman run entrypoint with user cmd overrides image cmd", func() {
@@ -88,7 +88,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(5))
+ Expect(session.OutputToStringArray()).To(HaveLen(5))
})
It("podman run entrypoint with user cmd no image cmd", func() {
@@ -99,7 +99,7 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(5))
+ Expect(session.OutputToStringArray()).To(HaveLen(5))
})
It("podman run user entrypoint overrides image entrypoint and image cmd", func() {
@@ -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_env_test.go b/test/e2e/run_env_test.go
index 5a62db809..f27f5eda7 100644
--- a/test/e2e/run_env_test.go
+++ b/test/e2e/run_env_test.go
@@ -68,7 +68,7 @@ var _ = Describe("Podman run", func() {
session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO", ALPINE, "printenv", "FOO"})
session.WaitWithDefaultTimeout()
- Expect(len(session.OutputToString())).To(Equal(0))
+ Expect(session.OutputToString()).To(BeEmpty())
Expect(session).Should(Exit(1))
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv"})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index c0840c83b..00db9b727 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -91,9 +91,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -103,18 +103,18 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "80-82", "-p", "8090:8090", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(4))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["81/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81")))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["82/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostPort).To(Not(Equal("82")))
Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8090/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostPort).To(Equal("8090"))
Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostIP).To(Equal(""))
})
@@ -124,18 +124,18 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "80-81", "-p", "8180-8181", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(4))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["81/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81")))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8180/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostPort).To(Not(Equal("8180")))
Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181")))
Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal(""))
})
@@ -145,18 +145,18 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "-p", "8280-8282:8280-8282", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(4))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(4))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8280/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostPort).To(Equal("8280"))
Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8281/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostPort).To(Equal("8281"))
Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8282/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostPort).To(Equal("8282"))
Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostIP).To(Equal(""))
})
@@ -166,9 +166,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "8380:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8380"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -179,10 +179,10 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "8480:80/TCP", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
// "tcp" in lower characters
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8480"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -192,9 +192,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "80/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal(""))
})
@@ -204,9 +204,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8580:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8580"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("127.0.0.1"))
})
@@ -216,9 +216,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8680:80/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8680"))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("127.0.0.1"))
})
@@ -228,9 +228,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8780:80/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8780"))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("::1"))
})
@@ -240,9 +240,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8880:80/tcp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8880"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("::1"))
})
@@ -252,9 +252,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "--expose", "80", "-P", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("0")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -264,9 +264,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "--expose", "80/udp", "-P", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Not(Equal("0")))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal(""))
})
@@ -276,9 +276,9 @@ var _ = Describe("Podman run networking", func() {
session := podmanTest.Podman([]string{"create", "-t", "--expose", "80", "-p", "80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -297,8 +297,8 @@ EXPOSE 2004-2005/tcp`, ALPINE)
inspect := podmanTest.Podman([]string{"inspect", imageName})
inspect.WaitWithDefaultTimeout()
image := inspect.InspectImageJSON()
- Expect(len(image)).To(Equal(1))
- Expect(len(image[0].Config.ExposedPorts)).To(Equal(3))
+ Expect(image).To(HaveLen(1))
+ Expect(image[0].Config.ExposedPorts).To(HaveLen(3))
Expect(image[0].Config.ExposedPorts).To(HaveKey("2002/tcp"))
Expect(image[0].Config.ExposedPorts).To(HaveKey("2001-2003/tcp"))
Expect(image[0].Config.ExposedPorts).To(HaveKey("2004-2005/tcp"))
@@ -307,11 +307,11 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"create", "--name", containerName, imageName, "true"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(containerName)
- Expect(len(inspectOut)).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
// Inspect the network settings with available ports to be mapped to the host
// Don't need to verity HostConfig.PortBindings since we used --publish-all
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(5))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(5))
Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2001/tcp"))
Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2002/tcp"))
Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2003/tcp"))
@@ -324,9 +324,9 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8980/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8980/udp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostPort).To(Not(Equal("8980")))
Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostIP).To(Equal("127.0.0.1"))
})
@@ -336,9 +336,9 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"create", "-t", "-p", ":8181", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181")))
Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal(""))
})
@@ -348,9 +348,9 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"create", "-t", "-p", "4444:8080", "-p", "5555:8080", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(2))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"]).To(HaveLen(2))
hp1 := inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort
hp2 := inspectOut[0].NetworkSettings.Ports["8080/tcp"][1].HostPort
@@ -364,9 +364,9 @@ EXPOSE 2004-2005/tcp`, ALPINE)
session := podmanTest.Podman([]string{"create", "-t", "-p", "0.0.0.0:9280:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
- Expect(len(inspectOut)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"]).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("9280"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -526,7 +526,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
containerConfig := inspect.InspectContainerToJSON()
Expect(containerConfig[0].NetworkSettings.Ports).To(Not(BeNil()))
- Expect(containerConfig[0].NetworkSettings.Ports["80/tcp"]).To(Not(BeNil()))
+ Expect(containerConfig[0].NetworkSettings.Ports).To(HaveKeyWithValue("80/tcp", Not(BeNil())))
Expect(containerConfig[0].NetworkSettings.Ports["80/tcp"][0].HostPort).ToNot(Equal(80))
})
@@ -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() {
@@ -864,9 +863,8 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(ctr).Should(Exit(0))
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).To(HaveLen(1))
+ Expect(inspectOut[0].NetworkSettings.Networks).To(HaveLen(1))
+ 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..b894c7b1c 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() {
@@ -124,7 +122,7 @@ var _ = Describe("Podman privileged container tests", func() {
session := podmanTest.Podman([]string{"run", "-t", BB, "ls", "-l", "/dev"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(17))
+ Expect(session.OutputToStringArray()).To(HaveLen(17))
})
It("podman privileged should inherit host devices", 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..f063c79e9 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -289,7 +289,7 @@ var _ = Describe("Podman run", func() {
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
Expect(conData[0].Path).To(Equal("/dev/init"))
- Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("TRUE"))
+ Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE"))
})
It("podman run a container with --init and --init-path", func() {
@@ -301,7 +301,7 @@ var _ = Describe("Podman run", func() {
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
Expect(conData[0].Path).To(Equal("/dev/init"))
- Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("TRUE"))
+ Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE"))
})
It("podman run a container without --init", func() {
@@ -313,7 +313,7 @@ var _ = Describe("Podman run", func() {
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
Expect(conData[0].Path).To(Equal("ls"))
- Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("FALSE"))
+ Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "FALSE"))
})
forbidGetCWDSeccompProfile := func() string {
@@ -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() {
@@ -1187,7 +1186,7 @@ USER mail`, BB)
session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
})
It("podman run --mount type=devpts,target=/foo/bar", func() {
@@ -1445,7 +1444,7 @@ USER mail`, BB)
// Get PID and get cgroups of that PID
inspectOut := podmanTest.InspectContainer(ctrName)
- Expect(len(inspectOut)).To(Equal(1))
+ Expect(inspectOut).To(HaveLen(1))
pid := inspectOut[0].State.Pid
Expect(pid).To(Not(Equal(0)))
@@ -1898,7 +1897,7 @@ WORKDIR /madethis`, BB)
running := podmanTest.Podman([]string{"ps", "-q"})
running.WaitWithDefaultTimeout()
Expect(running).Should(Exit(0))
- Expect(len(running.OutputToStringArray())).To(Equal(2))
+ Expect(running.OutputToStringArray()).To(HaveLen(2))
})
It("podman run with pidfile", func() {
diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go
index 50f8087f1..c1645af06 100644
--- a/test/e2e/run_userns_test.go
+++ b/test/e2e/run_userns_test.go
@@ -157,7 +157,7 @@ var _ = Describe("Podman UserNS support", func() {
m[l] = l
}
// check for no duplicates
- Expect(len(m)).To(Equal(5))
+ Expect(m).To(HaveLen(5))
})
It("podman --userns=auto:size=%d", func() {
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 10c191bd9..3d05e0f70 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
@@ -414,7 +410,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE)
list2.WaitWithDefaultTimeout()
Expect(list2).Should(Exit(0))
arr := list2.OutputToStringArray()
- Expect(len(arr)).To(Equal(1))
+ Expect(arr).To(HaveLen(1))
Expect(arr[0]).To(Not(Equal("")))
})
@@ -433,7 +429,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE)
list2.WaitWithDefaultTimeout()
Expect(list2).Should(Exit(0))
arr := list2.OutputToStringArray()
- Expect(len(arr)).To(Equal(1))
+ Expect(arr).To(HaveLen(1))
Expect(arr[0]).To(Not(Equal("")))
remove := podmanTest.Podman([]string{"rm", "-v", ctrName})
@@ -462,7 +458,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE)
list2.WaitWithDefaultTimeout()
Expect(list2).Should(Exit(0))
arr := list2.OutputToStringArray()
- Expect(len(arr)).To(Equal(1))
+ Expect(arr).To(HaveLen(1))
Expect(arr[0]).To(Equal(volName))
remove := podmanTest.Podman([]string{"rm", "-v", ctrName})
@@ -473,7 +469,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE)
list3.WaitWithDefaultTimeout()
Expect(list3).Should(Exit(0))
arr2 := list3.OutputToStringArray()
- Expect(len(arr2)).To(Equal(1))
+ Expect(arr2).To(HaveLen(1))
Expect(arr2[0]).To(Equal(volName))
})
@@ -515,7 +511,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE)
runLs.WaitWithDefaultTimeout()
Expect(runLs).Should(Exit(0))
outputArr := runLs.OutputToStringArray()
- Expect(len(outputArr)).To(Equal(1))
+ Expect(outputArr).To(HaveLen(1))
Expect(outputArr[0]).To(ContainSubstring(fileName))
})
@@ -531,8 +527,8 @@ VOLUME /test/`, ALPINE)
Expect(create).Should(Exit(0))
data := podmanTest.InspectContainer(ctrName)
- Expect(len(data)).To(Equal(1))
- Expect(len(data[0].Mounts)).To(Equal(1))
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].Mounts).To(HaveLen(1))
Expect(data[0].Mounts[0].Source).To(Equal("/tmp"))
Expect(data[0].Mounts[0].Destination).To(Equal("/test"))
})
@@ -630,7 +626,7 @@ VOLUME /test/`, ALPINE)
session := podmanTest.Podman([]string{"run", "-t", "-i", "-v", fmt.Sprintf("%s:/test1", volName), "-v", fmt.Sprintf("%s:/test2", volName), "--rm", ALPINE, "sh", "-c", "mount | grep /test"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman run with --volume and U flag", func() {
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index 54bc5252e..5c8e7c064 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() {
@@ -179,12 +175,12 @@ registries = ['{{.Host}}:{{.Port}}']`
search = podmanTest.Podman([]string{"search", "--limit", "3", "docker.io/alpine"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray())).To(Equal(4))
+ Expect(search.OutputToStringArray()).To(HaveLen(4))
search = podmanTest.Podman([]string{"search", "--limit", "30", "docker.io/alpine"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray())).To(Equal(31))
+ Expect(search.OutputToStringArray()).To(HaveLen(31))
})
It("podman search with filter stars", 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()
@@ -469,19 +462,19 @@ registries = ['{{.Host}}:{{.Port}}']`
search := podmanTest.Podman([]string{"search", "--limit", "30", "registry.redhat.io/*"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray())).To(Equal(31))
+ Expect(search.OutputToStringArray()).To(HaveLen(31))
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() {
search := podmanTest.Podman([]string{"search", "--list-tags", "--limit", "30", "docker.io/library/alpine"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray())).To(Equal(31))
+ Expect(search.OutputToStringArray()).To(HaveLen(31))
search = podmanTest.Podman([]string{"search", "--list-tags", "docker.io/library/alpine"})
search.WaitWithDefaultTimeout()
@@ -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/secret_test.go b/test/e2e/secret_test.go
index 758ed7edc..661ebbdc0 100644
--- a/test/e2e/secret_test.go
+++ b/test/e2e/secret_test.go
@@ -141,7 +141,7 @@ var _ = Describe("Podman secret", func() {
list := podmanTest.Podman([]string{"secret", "ls"})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(len(list.OutputToStringArray())).To(Equal(2))
+ Expect(list.OutputToStringArray()).To(HaveLen(2))
})
@@ -158,7 +158,7 @@ var _ = Describe("Podman secret", func() {
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(len(list.OutputToStringArray())).To(Equal(2), list.OutputToString())
+ Expect(list.OutputToStringArray()).To(HaveLen(2), list.OutputToString())
})
It("podman secret rm", func() {
@@ -179,7 +179,7 @@ var _ = Describe("Podman secret", func() {
session = podmanTest.Podman([]string{"secret", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
})
It("podman secret rm --all", func() {
@@ -201,7 +201,7 @@ var _ = Describe("Podman secret", func() {
session = podmanTest.Podman([]string{"secret", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1))
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
})
It("podman secret creates from environment variable", func() {
diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go
index a58e2485c..83a4896d5 100644
--- a/test/e2e/stats_test.go
+++ b/test/e2e/stats_test.go
@@ -213,7 +213,7 @@ var _ = Describe("Podman stats", func() {
// We have three containers. The unlimited ones need to have
// the same limit, the limited one a lower one.
limits := session.OutputToStringArray()
- Expect(len(limits)).To(BeNumerically("==", 3))
+ Expect(limits).To(HaveLen(3))
Expect(limits[0]).To(Equal(limits[1]))
Expect(limits[0]).ToNot(Equal(limits[2]))
diff --git a/test/e2e/system_connection_test.go b/test/e2e/system_connection_test.go
index 76b442ce8..95c2fe5b6 100644
--- a/test/e2e/system_connection_test.go
+++ b/test/e2e/system_connection_test.go
@@ -236,7 +236,7 @@ var _ = Describe("podman system connection", func() {
session := podmanTest.Podman(cmd)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).Should(Equal(1))
+ Expect(session.OutputToStringArray()).Should(HaveLen(1))
Expect(session.Err.Contents()).Should(BeEmpty())
})
})
diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go
index 4dc1f3591..acb6530cf 100644
--- a/test/e2e/system_df_test.go
+++ b/test/e2e/system_df_test.go
@@ -57,7 +57,7 @@ var _ = Describe("podman system df", func() {
session = podmanTest.Podman([]string{"system", "df"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
images := strings.Fields(session.OutputToStringArray()[1])
containers := strings.Fields(session.OutputToStringArray()[2])
volumes := strings.Fields(session.OutputToStringArray()[3])
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
index 93ab166cd..812e98cfd 100644
--- a/test/e2e/system_reset_test.go
+++ b/test/e2e/system_reset_test.go
@@ -69,16 +69,16 @@ var _ = Describe("podman system reset", func() {
session = podmanTest.Podman([]string{"images", "-n"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(l))
+ Expect(session.OutputToStringArray()).To(HaveLen(l))
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
session = podmanTest.Podman([]string{"container", "ls", "-q"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
})
diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go
index bbbec1648..1f237fc9e 100644
--- a/test/e2e/systemd_test.go
+++ b/test/e2e/systemd_test.go
@@ -99,7 +99,7 @@ WantedBy=default.target
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
+ Expect(conData).To(HaveLen(1))
Expect(conData[0].Config.SystemdMode).To(BeTrue())
// stats not supported w/ CGv1 rootless or containerized
@@ -126,7 +126,7 @@ WantedBy=default.target
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
+ Expect(conData).To(HaveLen(1))
Expect(conData[0].Config.SystemdMode).To(BeTrue())
})
@@ -155,7 +155,7 @@ WantedBy=default.target
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON()
- Expect(len(conData)).To(Equal(1))
+ Expect(conData).To(HaveLen(1))
Expect(conData[0].Config.SystemdMode).To(BeTrue())
})
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/trust_test.go b/test/e2e/trust_test.go
index 9a0d57d7a..9909c0653 100644
--- a/test/e2e/trust_test.go
+++ b/test/e2e/trust_test.go
@@ -43,7 +43,7 @@ var _ = Describe("Podman trust", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
outArray := session.OutputToStringArray()
- Expect(len(outArray)).To(Equal(3))
+ Expect(outArray).To(HaveLen(3))
// Repository order is not guaranteed. So, check that
// all expected lines appear in output; we also check total number of lines, so that handles all of them.
@@ -69,7 +69,7 @@ var _ = Describe("Podman trust", func() {
if err != nil {
os.Exit(1)
}
- Expect(teststruct["default"][0]["type"]).To(Equal("insecureAcceptAnything"))
+ Expect(teststruct["default"][0]).To(HaveKeyWithValue("type", "insecureAcceptAnything"))
})
It("podman image trust show --json", func() {
@@ -79,7 +79,7 @@ var _ = Describe("Podman trust", func() {
Expect(session.OutputToString()).To(BeValidJSON())
var teststruct []map[string]string
json.Unmarshal(session.Out.Contents(), &teststruct)
- Expect(len(teststruct)).To(Equal(3))
+ Expect(teststruct).To(HaveLen(3))
// To ease comparison, group the unordered array of repos by repo (and we expect only one entry by repo, so order within groups doesn’t matter)
repoMap := map[string][]map[string]string{}
for _, e := range teststruct {
diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go
index 90a9bfb0b..bd609943c 100644
--- a/test/e2e/volume_create_test.go
+++ b/test/e2e/volume_create_test.go
@@ -43,7 +43,7 @@ var _ = Describe("Podman volume create", func() {
check := podmanTest.Podman([]string{"volume", "ls", "-q"})
check.WaitWithDefaultTimeout()
Expect(check.OutputToString()).To(ContainSubstring(volName))
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman create volume with name", func() {
@@ -55,7 +55,7 @@ var _ = Describe("Podman volume create", func() {
check := podmanTest.Podman([]string{"volume", "ls", "-q"})
check.WaitWithDefaultTimeout()
Expect(check.OutputToString()).To(ContainSubstring(volName))
- Expect(len(check.OutputToStringArray())).To(Equal(1))
+ Expect(check.OutputToStringArray()).To(HaveLen(1))
})
It("podman create and export volume", func() {
diff --git a/test/e2e/volume_inspect_test.go b/test/e2e/volume_inspect_test.go
index 172063b90..3fcdb7728 100644
--- a/test/e2e/volume_inspect_test.go
+++ b/test/e2e/volume_inspect_test.go
@@ -71,7 +71,7 @@ var _ = Describe("Podman volume inspect", func() {
session = podmanTest.Podman([]string{"volume", "inspect", "--format", "{{.Name}}", "--all"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()[0]).To(Equal(volName1))
Expect(session.OutputToStringArray()[1]).To(Equal(volName2))
})
diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go
index c1214366b..52b805718 100644
--- a/test/e2e/volume_ls_test.go
+++ b/test/e2e/volume_ls_test.go
@@ -42,7 +42,7 @@ var _ = Describe("Podman volume ls", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman ls volume filter with a key pattern", func() {
@@ -53,7 +53,7 @@ var _ = Describe("Podman volume ls", func() {
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=hello*"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
})
It("podman ls volume with JSON format", func() {
@@ -76,7 +76,7 @@ var _ = Describe("Podman volume ls", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(1), session.OutputToString())
+ Expect(session.OutputToStringArray()).To(HaveLen(1), session.OutputToString())
})
It("podman ls volume with --filter flag", func() {
@@ -92,24 +92,24 @@ var _ = Describe("Podman volume ls", func() {
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo=foo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo=bar"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo=baz"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman ls volume with --filter until flag", func() {
@@ -120,12 +120,12 @@ var _ = Describe("Podman volume ls", func() {
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "until=5000000000"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "until=50000"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman volume ls with --filter dangling", func() {
@@ -171,14 +171,14 @@ var _ = Describe("Podman volume ls", func() {
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo", "--filter", "label=foo2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
Expect(session.OutputToStringArray()[2]).To(ContainSubstring(anotherVol))
session = podmanTest.Podman([]string{"volume", "ls", "--filter", "label=foo=bar", "--filter", "label=foo2=bar2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
Expect(session.OutputToStringArray()[2]).To(ContainSubstring(anotherVol))
})
diff --git a/test/e2e/volume_plugin_test.go b/test/e2e/volume_plugin_test.go
index cdf635b14..a3a445866 100644
--- a/test/e2e/volume_plugin_test.go
+++ b/test/e2e/volume_plugin_test.go
@@ -72,7 +72,7 @@ var _ = Describe("Podman volume plugins", func() {
ls1.WaitWithDefaultTimeout()
Expect(ls1).Should(Exit(0))
arrOutput := ls1.OutputToStringArray()
- Expect(len(arrOutput)).To(Equal(1))
+ Expect(arrOutput).To(HaveLen(1))
Expect(arrOutput[0]).To(ContainSubstring(volName))
remove := podmanTest.Podman([]string{"volume", "rm", volName})
@@ -82,7 +82,7 @@ var _ = Describe("Podman volume plugins", func() {
ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
ls2.WaitWithDefaultTimeout()
Expect(ls2).Should(Exit(0))
- Expect(len(ls2.OutputToStringArray())).To(Equal(0))
+ Expect(ls2.OutputToStringArray()).To(BeEmpty())
})
It("volume inspect with running plugin succeeds", func() {
@@ -130,7 +130,7 @@ var _ = Describe("Podman volume plugins", func() {
ls1.WaitWithDefaultTimeout()
Expect(ls1).Should(Exit(0))
arrOutput := ls1.OutputToStringArray()
- Expect(len(arrOutput)).To(Equal(1))
+ Expect(arrOutput).To(HaveLen(1))
Expect(arrOutput[0]).To(ContainSubstring(volName))
stop := podmanTest.Podman([]string{"stop", "--timeout", "0", ctrName})
@@ -146,7 +146,7 @@ var _ = Describe("Podman volume plugins", func() {
ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
ls2.WaitWithDefaultTimeout()
Expect(ls2).Should(Exit(0))
- Expect(len(ls2.OutputToStringArray())).To(Equal(0))
+ Expect(ls2.OutputToStringArray()).To(BeEmpty())
})
It("use plugin in containers", func() {
diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go
index 364ca0ab7..9ea8b1d25 100644
--- a/test/e2e/volume_prune_test.go
+++ b/test/e2e/volume_prune_test.go
@@ -49,7 +49,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
session = podmanTest.Podman([]string{"volume", "prune", "--force"})
session.WaitWithDefaultTimeout()
@@ -58,7 +58,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
podmanTest.Cleanup()
})
@@ -71,7 +71,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "until=50"})
session.WaitWithDefaultTimeout()
@@ -80,7 +80,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(2))
+ Expect(session.OutputToStringArray()).To(HaveLen(2))
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "until=5000000000"})
session.WaitWithDefaultTimeout()
@@ -89,7 +89,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
podmanTest.Cleanup()
})
@@ -122,7 +122,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(7))
+ Expect(session.OutputToStringArray()).To(HaveLen(7))
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=label1=value1"})
session.WaitWithDefaultTimeout()
@@ -131,7 +131,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(6))
+ Expect(session.OutputToStringArray()).To(HaveLen(6))
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=sharedlabel1=slv1"})
session.WaitWithDefaultTimeout()
@@ -140,7 +140,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(5))
+ Expect(session.OutputToStringArray()).To(HaveLen(5))
session = podmanTest.Podman([]string{"volume", "prune", "--force", "--filter", "label=sharedlabel1"})
session.WaitWithDefaultTimeout()
@@ -149,7 +149,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(3))
+ Expect(session.OutputToStringArray()).To(HaveLen(3))
podmanTest.Cleanup()
})
@@ -170,7 +170,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(session.OutputToStringArray()).To(HaveLen(4))
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes"})
session.WaitWithDefaultTimeout()
@@ -179,7 +179,7 @@ var _ = Describe("Podman volume prune", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
podmanTest.Cleanup()
})
diff --git a/test/e2e/volume_rm_test.go b/test/e2e/volume_rm_test.go
index 0119e0f7a..68d94963a 100644
--- a/test/e2e/volume_rm_test.go
+++ b/test/e2e/volume_rm_test.go
@@ -45,7 +45,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman volume rm with --force flag", func() {
@@ -66,7 +66,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
podmanTest.Cleanup()
})
@@ -93,7 +93,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman volume rm by partial name", func() {
@@ -108,7 +108,7 @@ var _ = Describe("Podman volume rm", func() {
session = podmanTest.Podman([]string{"volume", "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
It("podman volume rm by nonunique partial name", func() {
@@ -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/010-images.bats b/test/system/010-images.bats
index 1e9d5f181..9de31f96c 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -221,9 +221,7 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
iid=${output:0:12}
# Run the test: this will output three column-aligned rows. Test them.
- # Tab character (\t) should have the same effect as the 'table' directive
_run_format_test 'table' 'table {{.Repository}} {{.Tag}} {{.ID}}'
- _run_format_test 'tabs' '{{.Repository}}\t{{.Tag}}\t{{.ID}}'
# Clean up.
run_podman rmi ${aaa_name}:${aaa_tag} ${zzz_name}:${zzz_tag}
diff --git a/test/system/110-history.bats b/test/system/110-history.bats
index 75c15b088..0f6d75cb3 100644
--- a/test/system/110-history.bats
+++ b/test/system/110-history.bats
@@ -21,6 +21,14 @@ load helpers
done
}
+@test "podman history - custom format" {
+ run_podman history --format "{{.ID}}\t{{.ID}}" $IMAGE
+ od -c <<<$output
+ while IFS= read -r row; do
+ is "$row" ".* .*$"
+ done <<<$output
+}
+
@test "podman history - json" {
# Sigh. Timestamp in .created can be '...Z' or '...-06:00'
tests="
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
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index 1d1bc201b..59221d935 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -454,7 +454,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
// NOTE that this is will even override --pull={false,never}. This is
// very likely a bug but a consistent one in Podman/Buildah and should
// be addressed at a later point.
- if pullPolicy != config.PullPolicyAlways {
+ if pullPolicy != config.PullPolicyAlways && pullPolicy != config.PullPolicyNever {
switch {
// User input clearly refer to a local image.
case strings.HasPrefix(imageName, "localhost/"):
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index 7ce0e5022..29c505e9c 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -420,6 +420,9 @@ type EngineConfig struct {
// ChownCopiedFiles tells the container engine whether to chown files copied
// into a container to the container's primary uid/gid.
ChownCopiedFiles bool `toml:"chown_copied_files,omitempty"`
+
+ // CompressionFormat is the compression format used to compress image layers.
+ CompressionFormat string `toml:"compression_format,omitempty"`
}
// SetOptions contains a subset of options in a Config. It's used to indicate if
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index 8e305b57e..84b49b7e4 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -294,6 +294,12 @@ default_sysctls = [
#
#active_service = production
+# The compression format to use when pushing an image.
+# Valid options are: `gzip`, `zstd` and `zstd:chunked`.
+#
+#compression_format = "gzip"
+
+
# Cgroup management implementation used for the runtime.
# Valid options "systemd" or "cgroupfs"
#
diff --git a/vendor/github.com/containers/common/pkg/config/nosystemd.go b/vendor/github.com/containers/common/pkg/config/nosystemd.go
index 2a3b6fb35..f64b2dfc6 100644
--- a/vendor/github.com/containers/common/pkg/config/nosystemd.go
+++ b/vendor/github.com/containers/common/pkg/config/nosystemd.go
@@ -22,3 +22,7 @@ func defaultLogDriver() string {
func useSystemd() bool {
return false
}
+
+func useJournald() bool {
+ return false
+}
diff --git a/vendor/github.com/containers/common/pkg/config/systemd.go b/vendor/github.com/containers/common/pkg/config/systemd.go
index fab3ea437..186e8b343 100644
--- a/vendor/github.com/containers/common/pkg/config/systemd.go
+++ b/vendor/github.com/containers/common/pkg/config/systemd.go
@@ -4,12 +4,12 @@ package config
import (
"io/ioutil"
+ "path/filepath"
"strings"
"sync"
"github.com/containers/common/pkg/cgroupv2"
"github.com/containers/storage/pkg/unshare"
- "github.com/coreos/go-systemd/v22/sdjournal"
)
var (
@@ -67,12 +67,20 @@ func useJournald() bool {
if !useSystemd() {
return
}
- journal, err := sdjournal.NewJournal()
- if err != nil {
- return
+ for _, root := range []string{"/run/log/journal", "/var/log/journal"} {
+ dirs, err := ioutil.ReadDir(root)
+ if err != nil {
+ continue
+ }
+ for _, d := range dirs {
+ if d.IsDir() {
+ if _, err := ioutil.ReadDir(filepath.Join(root, d.Name())); err == nil {
+ usesJournald = true
+ return
+ }
+ }
+ }
}
- journal.Close()
- usesJournald = true
return
})
return usesJournald
diff --git a/vendor/github.com/containers/common/pkg/manifests/manifests.go b/vendor/github.com/containers/common/pkg/manifests/manifests.go
index ea9495ee7..5c2836893 100644
--- a/vendor/github.com/containers/common/pkg/manifests/manifests.go
+++ b/vendor/github.com/containers/common/pkg/manifests/manifests.go
@@ -74,6 +74,7 @@ func Create() List {
},
oci: v1.Index{
Versioned: imgspec.Versioned{SchemaVersion: 2},
+ MediaType: v1.MediaTypeImageIndex,
},
}
}
@@ -373,6 +374,7 @@ func FromBlob(manifestBytes []byte) (List, error) {
},
oci: v1.Index{
Versioned: imgspec.Versioned{SchemaVersion: 2},
+ MediaType: v1.MediaTypeImageIndex,
},
}
switch manifestType {
diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml
index d080d790c..726acc3ae 100644
--- a/vendor/github.com/containers/storage/.cirrus.yml
+++ b/vendor/github.com/containers/storage/.cirrus.yml
@@ -17,8 +17,8 @@ env:
####
#### Cache-image names to test with (double-quotes around names are critical)
###
- FEDORA_NAME: "fedora-34"
- PRIOR_FEDORA_NAME: "fedora-33"
+ FEDORA_NAME: "fedora-35"
+ PRIOR_FEDORA_NAME: "fedora-34"
UBUNTU_NAME: "ubuntu-2104"
# GCE project where images live
diff --git a/vendor/github.com/containers/storage/Vagrantfile b/vendor/github.com/containers/storage/Vagrantfile
deleted file mode 100644
index c82c1f81b..000000000
--- a/vendor/github.com/containers/storage/Vagrantfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- mode: ruby -*-
-# vi: set ft=ruby :
-#
-# The fedora/28-cloud-base and debian/jessie64 boxes are also available for
-# the "virtualbox" provider. Set the VAGRANT_PROVIDER environment variable to
-# "virtualbox" to use them instead.
-#
-Vagrant.configure("2") do |config|
- config.vm.define "fedora" do |c|
- c.vm.box = "fedora/28-cloud-base"
- c.vm.synced_folder ".", "/vagrant", type: "rsync",
- rsync__exclude: "bundles", rsync__args: ["-vadz", "--delete"]
- c.vm.provision "shell", inline: <<-SHELL
- sudo /vagrant/vagrant/provision.sh
- SHELL
- end
- config.vm.define "debian" do |c|
- c.vm.box = "debian/jessie64"
- c.vm.synced_folder ".", "/vagrant", type: "rsync",
- rsync__exclude: "bundles", rsync__args: ["-vadz", "--delete"]
- c.vm.provision "shell", inline: <<-SHELL
- sudo /vagrant/vagrant/provision.sh
- SHELL
- end
-end
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 04d5adac4..57b634f17 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -7,6 +7,7 @@ require (
github.com/Microsoft/go-winio v0.5.1
github.com/Microsoft/hcsshim v0.9.1
github.com/containerd/stargz-snapshotter/estargz v0.10.1
+ github.com/cyphar/filepath-securejoin v0.2.3
github.com/docker/go-units v0.4.0
github.com/google/go-intervals v0.0.2
github.com/hashicorp/go-multierror v1.1.1
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index 35328e287..94d46b21a 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -218,6 +218,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go
index 76544ff28..e7c4cfcf1 100644
--- a/vendor/github.com/containers/storage/pkg/archive/archive.go
+++ b/vendor/github.com/containers/storage/pkg/archive/archive.go
@@ -77,6 +77,10 @@ const (
containersOverrideXattr = "user.containers.override_stat"
)
+var xattrsToIgnore = map[string]interface{}{
+ "security.selinux": true,
+}
+
// Archiver allows the reuse of most utility functions of this package with a
// pluggable Untar function. To facilitate the passing of specific id mappings
// for untar, an archiver can be created with maps which will then be passed to
@@ -743,6 +747,9 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
var errs []string
for key, value := range hdr.Xattrs {
+ if _, found := xattrsToIgnore[key]; found {
+ continue
+ }
if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil {
if errors.Is(err, syscall.ENOTSUP) || (inUserns && errors.Is(err, syscall.EPERM)) {
// We ignore errors here because not all graphdrivers support
diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
index d18ab299b..52d21d689 100644
--- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
+++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
@@ -13,6 +13,7 @@ import (
"reflect"
"sort"
"strings"
+ "sync/atomic"
"syscall"
"time"
@@ -25,6 +26,7 @@ import (
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/system"
"github.com/containers/storage/types"
+ securejoin "github.com/cyphar/filepath-securejoin"
"github.com/klauspost/compress/zstd"
"github.com/klauspost/pgzip"
digest "github.com/opencontainers/go-digest"
@@ -57,6 +59,10 @@ type chunkedDiffer struct {
gzipReader *pgzip.Reader
}
+var xattrsToIgnore = map[string]interface{}{
+ "security.selinux": true,
+}
+
func timeToTimespec(time time.Time) (ts unix.Timespec) {
if time.IsZero() {
// Return UTIME_OMIT special value
@@ -89,7 +95,7 @@ func copyFileContent(srcFd int, destFile string, dirfd int, mode os.FileMode, us
src := fmt.Sprintf("/proc/self/fd/%d", srcFd)
st, err := os.Stat(src)
if err != nil {
- return nil, -1, err
+ return nil, -1, fmt.Errorf("copy file content for %q: %w", destFile, err)
}
copyWithFileRange, copyWithFileClone := true, true
@@ -111,15 +117,15 @@ func copyFileContent(srcFd int, destFile string, dirfd int, mode os.FileMode, us
// If the destination file already exists, we shouldn't blow it away
dstFile, err := openFileUnderRoot(destFile, dirfd, newFileFlags, mode)
if err != nil {
- return nil, -1, err
+ return nil, -1, fmt.Errorf("open file %q under rootfs for copy: %w", destFile, err)
}
err = driversCopy.CopyRegularToFile(src, dstFile, st, &copyWithFileRange, &copyWithFileClone)
if err != nil {
dstFile.Close()
- return nil, -1, err
+ return nil, -1, fmt.Errorf("copy to file %q under rootfs: %w", destFile, err)
}
- return dstFile, st.Size(), err
+ return dstFile, st.Size(), nil
}
func prepareOtherLayersCache(layersMetadata map[string][]internal.FileMetadata) map[string]map[string][]*internal.FileMetadata {
@@ -153,7 +159,7 @@ func getLayersCache(store storage.Store) (map[string][]internal.FileMetadata, ma
defer manifestReader.Close()
manifest, err := ioutil.ReadAll(manifestReader)
if err != nil {
- return nil, nil, err
+ return nil, nil, fmt.Errorf("open manifest file for layer %q: %w", r.ID, err)
}
var toc internal.TOC
if err := json.Unmarshal(manifest, &toc); err != nil {
@@ -162,7 +168,7 @@ func getLayersCache(store storage.Store) (map[string][]internal.FileMetadata, ma
layersMetadata[r.ID] = toc.Entries
target, err := store.DifferTarget(r.ID)
if err != nil {
- return nil, nil, err
+ return nil, nil, fmt.Errorf("get checkout directory layer %q: %w", r.ID, err)
}
layersTarget[r.ID] = target
}
@@ -184,7 +190,7 @@ func GetDiffer(ctx context.Context, store storage.Store, blobSize int64, annotat
func makeZstdChunkedDiffer(ctx context.Context, store storage.Store, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (*chunkedDiffer, error) {
manifest, tocOffset, err := readZstdChunkedManifest(iss, blobSize, annotations)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
}
layersMetadata, layersTarget, err := getLayersCache(store)
if err != nil {
@@ -204,7 +210,7 @@ func makeZstdChunkedDiffer(ctx context.Context, store storage.Store, blobSize in
func makeEstargzChunkedDiffer(ctx context.Context, store storage.Store, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (*chunkedDiffer, error) {
manifest, tocOffset, err := readEstargzChunkedManifest(iss, blobSize, annotations)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
}
layersMetadata, layersTarget, err := getLayersCache(store)
if err != nil {
@@ -230,21 +236,21 @@ func makeEstargzChunkedDiffer(ctx context.Context, store storage.Store, blobSize
func copyFileFromOtherLayer(file *internal.FileMetadata, source string, otherFile *internal.FileMetadata, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
srcDirfd, err := unix.Open(source, unix.O_RDONLY, 0)
if err != nil {
- return false, nil, 0, err
+ return false, nil, 0, fmt.Errorf("open source file %q: %w", source, err)
}
defer unix.Close(srcDirfd)
srcFile, err := openFileUnderRoot(otherFile.Name, srcDirfd, unix.O_RDONLY, 0)
if err != nil {
- return false, nil, 0, err
+ return false, nil, 0, fmt.Errorf("open source file %q under target rootfs: %w", otherFile.Name, err)
}
defer srcFile.Close()
dstFile, written, err := copyFileContent(int(srcFile.Fd()), file.Name, dirfd, 0, useHardLinks)
if err != nil {
- return false, nil, 0, err
+ return false, nil, 0, fmt.Errorf("copy content to %q: %w", file.Name, err)
}
- return true, dstFile, written, err
+ return true, dstFile, written, nil
}
// canDedupMetadataWithHardLink says whether it is possible to deduplicate file with otherFile.
@@ -280,10 +286,6 @@ func canDedupFileWithHardLink(file *internal.FileMetadata, fd int, s os.FileInfo
return false
}
- xattrsToIgnore := map[string]interface{}{
- "security.selinux": true,
- }
-
xattrs := make(map[string]string)
for _, x := range listXattrs {
v, err := system.Lgetxattr(path, x)
@@ -510,7 +512,7 @@ type missingChunk struct {
}
// setFileAttrs sets the file attributes for file given metadata
-func setFileAttrs(file *os.File, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) error {
+func setFileAttrs(dirfd int, file *os.File, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions, usePath bool) error {
if file == nil || file.Fd() < 0 {
return errors.Errorf("invalid file")
}
@@ -520,54 +522,237 @@ func setFileAttrs(file *os.File, mode os.FileMode, metadata *internal.FileMetada
if err != nil {
return err
}
+
+ // If it is a symlink, force to use the path
if t == tar.TypeSymlink {
- return nil
+ usePath = true
+ }
+
+ baseName := ""
+ if usePath {
+ dirName := filepath.Dir(metadata.Name)
+ if dirName != "" {
+ parentFd, err := openFileUnderRoot(dirName, dirfd, unix.O_PATH|unix.O_DIRECTORY, 0)
+ if err != nil {
+ return err
+ }
+ defer parentFd.Close()
+
+ dirfd = int(parentFd.Fd())
+ }
+ baseName = filepath.Base(metadata.Name)
+ }
+
+ doChown := func() error {
+ if usePath {
+ return unix.Fchownat(dirfd, baseName, metadata.UID, metadata.GID, unix.AT_SYMLINK_NOFOLLOW)
+ }
+ return unix.Fchown(fd, metadata.UID, metadata.GID)
+ }
+
+ doSetXattr := func(k string, v []byte) error {
+ return unix.Fsetxattr(fd, k, v, 0)
+ }
+
+ doUtimes := func() error {
+ ts := []unix.Timespec{timeToTimespec(metadata.AccessTime), timeToTimespec(metadata.ModTime)}
+ if usePath {
+ return unix.UtimesNanoAt(dirfd, baseName, ts, unix.AT_SYMLINK_NOFOLLOW)
+ }
+ return unix.UtimesNanoAt(unix.AT_FDCWD, fmt.Sprintf("/proc/self/fd/%d", fd), ts, 0)
+ }
+
+ doChmod := func() error {
+ if usePath {
+ return unix.Fchmodat(dirfd, baseName, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
+ }
+ return unix.Fchmod(fd, uint32(mode))
}
- if err := unix.Fchown(fd, metadata.UID, metadata.GID); err != nil {
+ if err := doChown(); err != nil {
if !options.IgnoreChownErrors {
- return err
+ return fmt.Errorf("chown %q to %d:%d: %w", metadata.Name, metadata.UID, metadata.GID, err)
}
}
+ canIgnore := func(err error) bool {
+ return err == nil || errors.Is(err, unix.ENOSYS) || errors.Is(err, unix.ENOTSUP)
+ }
+
for k, v := range metadata.Xattrs {
+ if _, found := xattrsToIgnore[k]; found {
+ continue
+ }
data, err := base64.StdEncoding.DecodeString(v)
if err != nil {
- return err
+ return fmt.Errorf("decode xattr %q: %w", v, err)
}
- if err := unix.Fsetxattr(fd, k, data, 0); err != nil {
- return err
+ if err := doSetXattr(k, data); !canIgnore(err) {
+ return fmt.Errorf("set xattr %s=%q for %q: %w", k, data, metadata.Name, err)
}
}
- ts := []unix.Timespec{timeToTimespec(metadata.AccessTime), timeToTimespec(metadata.ModTime)}
- if err := unix.UtimesNanoAt(fd, "", ts, 0); err != nil && errors.Is(err, unix.ENOSYS) {
- return err
+ if err := doUtimes(); !canIgnore(err) {
+ return fmt.Errorf("set utimes for %q: %w", metadata.Name, err)
}
- if err := unix.Fchmod(fd, uint32(mode)); err != nil {
- return err
+ if err := doChmod(); !canIgnore(err) {
+ return fmt.Errorf("chmod %q: %w", metadata.Name, err)
}
return nil
}
+func openFileUnderRootFallback(dirfd int, name string, flags uint64, mode os.FileMode) (int, error) {
+ root := fmt.Sprintf("/proc/self/fd/%d", dirfd)
+
+ targetRoot, err := os.Readlink(root)
+ if err != nil {
+ return -1, err
+ }
+
+ hasNoFollow := (flags & unix.O_NOFOLLOW) != 0
+
+ fd := -1
+ // If O_NOFOLLOW is specified in the flags, then resolve only the parent directory and use the
+ // last component as the path to openat().
+ if hasNoFollow {
+ dirName := filepath.Dir(name)
+ if dirName != "" {
+ newRoot, err := securejoin.SecureJoin(root, filepath.Dir(name))
+ if err != nil {
+ return -1, err
+ }
+ root = newRoot
+ }
+
+ parentDirfd, err := unix.Open(root, unix.O_PATH, 0)
+ if err != nil {
+ return -1, err
+ }
+ defer unix.Close(parentDirfd)
+
+ fd, err = unix.Openat(parentDirfd, filepath.Base(name), int(flags), uint32(mode))
+ if err != nil {
+ return -1, err
+ }
+ } else {
+ newPath, err := securejoin.SecureJoin(root, name)
+ if err != nil {
+ return -1, err
+ }
+ fd, err = unix.Openat(dirfd, newPath, int(flags), uint32(mode))
+ if err != nil {
+ return -1, err
+ }
+ }
+
+ target, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", fd))
+ if err != nil {
+ unix.Close(fd)
+ return -1, err
+ }
+
+ // Add an additional check to make sure the opened fd is inside the rootfs
+ if !strings.HasPrefix(target, targetRoot) {
+ unix.Close(fd)
+ return -1, fmt.Errorf("error while resolving %q. It resolves outside the root directory", name)
+ }
+
+ return fd, err
+}
+
+func openFileUnderRootOpenat2(dirfd int, name string, flags uint64, mode os.FileMode) (int, error) {
+ how := unix.OpenHow{
+ Flags: flags,
+ Mode: uint64(mode & 07777),
+ Resolve: unix.RESOLVE_IN_ROOT,
+ }
+ return unix.Openat2(dirfd, name, &how)
+}
+
+// skipOpenat2 is set when openat2 is not supported by the underlying kernel and avoid
+// using it again.
+var skipOpenat2 int32
+
+// openFileUnderRootRaw tries to open a file using openat2 and if it is not supported fallbacks to a
+// userspace lookup.
+func openFileUnderRootRaw(dirfd int, name string, flags uint64, mode os.FileMode) (int, error) {
+ var fd int
+ var err error
+ if atomic.LoadInt32(&skipOpenat2) > 0 {
+ fd, err = openFileUnderRootFallback(dirfd, name, flags, mode)
+ } else {
+ fd, err = openFileUnderRootOpenat2(dirfd, name, flags, mode)
+ // If the function failed with ENOSYS, switch off the support for openat2
+ // and fallback to using safejoin.
+ if err != nil && errors.Is(err, unix.ENOSYS) {
+ atomic.StoreInt32(&skipOpenat2, 1)
+ fd, err = openFileUnderRootFallback(dirfd, name, flags, mode)
+ }
+ }
+ return fd, err
+}
+
// openFileUnderRoot safely opens a file under the specified root directory using openat2
// name is the path to open relative to dirfd.
// dirfd is an open file descriptor to the target checkout directory.
-// flags are the flags top pass to the open syscall.
+// flags are the flags to pass to the open syscall.
// mode specifies the mode to use for newly created files.
func openFileUnderRoot(name string, dirfd int, flags uint64, mode os.FileMode) (*os.File, error) {
- how := unix.OpenHow{
- Flags: flags,
- Mode: uint64(mode & 07777),
- Resolve: unix.RESOLVE_IN_ROOT,
+ fd, err := openFileUnderRootRaw(dirfd, name, flags, mode)
+ if err == nil {
+ return os.NewFile(uintptr(fd), name), nil
+ }
+
+ hasCreate := (flags & unix.O_CREAT) != 0
+ if errors.Is(err, unix.ENOENT) && hasCreate {
+ parent := filepath.Dir(name)
+ if parent != "" {
+ newDirfd, err2 := openOrCreateDirUnderRoot(parent, dirfd, 0)
+ if err2 == nil {
+ defer newDirfd.Close()
+ fd, err := openFileUnderRootRaw(dirfd, name, flags, mode)
+ if err == nil {
+ return os.NewFile(uintptr(fd), name), nil
+ }
+ }
+ }
}
+ return nil, fmt.Errorf("open %q under the rootfs: %w", name, err)
+}
- fd, err := unix.Openat2(dirfd, name, &how)
- if err != nil {
- return nil, err
+// openOrCreateDirUnderRoot safely opens a directory or create it if it is missing.
+// name is the path to open relative to dirfd.
+// dirfd is an open file descriptor to the target checkout directory.
+// mode specifies the mode to use for newly created files.
+func openOrCreateDirUnderRoot(name string, dirfd int, mode os.FileMode) (*os.File, error) {
+ fd, err := openFileUnderRootRaw(dirfd, name, unix.O_DIRECTORY|unix.O_RDONLY, mode)
+ if err == nil {
+ return os.NewFile(uintptr(fd), name), nil
+ }
+
+ if errors.Is(err, unix.ENOENT) {
+ parent := filepath.Dir(name)
+ if parent != "" {
+ pDir, err2 := openOrCreateDirUnderRoot(parent, dirfd, mode)
+ if err2 != nil {
+ return nil, err
+ }
+ defer pDir.Close()
+
+ baseName := filepath.Base(name)
+
+ if err2 := unix.Mkdirat(int(pDir.Fd()), baseName, 0755); err2 != nil {
+ return nil, err
+ }
+
+ fd, err = openFileUnderRootRaw(int(pDir.Fd()), baseName, unix.O_DIRECTORY|unix.O_RDONLY, mode)
+ if err == nil {
+ return os.NewFile(uintptr(fd), name), nil
+ }
+ }
}
- return os.NewFile(uintptr(fd), name), nil
+ return nil, err
}
func (c *chunkedDiffer) createFileFromCompressedStream(dest string, dirfd int, reader io.Reader, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) (err error) {
@@ -631,7 +816,7 @@ func (c *chunkedDiffer) createFileFromCompressedStream(dest string, dirfd int, r
if digester.Digest() != manifestChecksum {
return fmt.Errorf("checksum mismatch for %q", dest)
}
- return setFileAttrs(file, mode, metadata, options)
+ return setFileAttrs(dirfd, file, mode, metadata, options, false)
}
func (c *chunkedDiffer) storeMissingFiles(streams chan io.ReadCloser, errs chan error, dest string, dirfd int, missingChunks []missingChunk, options *archive.TarOptions) error {
@@ -755,13 +940,13 @@ func (c *chunkedDiffer) retrieveMissingFiles(dest string, dirfd int, missingChun
return nil
}
-func safeMkdir(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) error {
- parent := filepath.Dir(metadata.Name)
- base := filepath.Base(metadata.Name)
+func safeMkdir(dirfd int, mode os.FileMode, name string, metadata *internal.FileMetadata, options *archive.TarOptions) error {
+ parent := filepath.Dir(name)
+ base := filepath.Base(name)
parentFd := dirfd
if parent != "." {
- parentFile, err := openFileUnderRoot(parent, dirfd, unix.O_DIRECTORY|unix.O_PATH|unix.O_RDONLY, 0)
+ parentFile, err := openOrCreateDirUnderRoot(parent, dirfd, 0)
if err != nil {
return err
}
@@ -771,21 +956,21 @@ func safeMkdir(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, opt
if err := unix.Mkdirat(parentFd, base, uint32(mode)); err != nil {
if !os.IsExist(err) {
- return err
+ return fmt.Errorf("mkdir %q: %w", name, err)
}
}
- file, err := openFileUnderRoot(metadata.Name, dirfd, unix.O_RDONLY, 0)
+ file, err := openFileUnderRoot(name, dirfd, unix.O_DIRECTORY|unix.O_RDONLY, 0)
if err != nil {
return err
}
defer file.Close()
- return setFileAttrs(file, mode, metadata, options)
+ return setFileAttrs(dirfd, file, mode, metadata, options, false)
}
func safeLink(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) error {
- sourceFile, err := openFileUnderRoot(metadata.Linkname, dirfd, unix.O_RDONLY, 0)
+ sourceFile, err := openFileUnderRoot(metadata.Linkname, dirfd, unix.O_PATH|unix.O_RDONLY|unix.O_NOFOLLOW, 0)
if err != nil {
return err
}
@@ -794,7 +979,7 @@ func safeLink(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, opti
destDir, destBase := filepath.Dir(metadata.Name), filepath.Base(metadata.Name)
destDirFd := dirfd
if destDir != "." {
- f, err := openFileUnderRoot(destDir, dirfd, unix.O_RDONLY, 0)
+ f, err := openOrCreateDirUnderRoot(destDir, dirfd, 0)
if err != nil {
return err
}
@@ -804,23 +989,33 @@ func safeLink(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, opti
err = doHardLink(int(sourceFile.Fd()), destDirFd, destBase)
if err != nil {
- return err
+ return fmt.Errorf("create hardlink %q pointing to %q: %w", metadata.Name, metadata.Linkname, err)
}
- newFile, err := openFileUnderRoot(metadata.Name, dirfd, unix.O_WRONLY, 0)
+ newFile, err := openFileUnderRoot(metadata.Name, dirfd, unix.O_WRONLY|unix.O_NOFOLLOW, 0)
if err != nil {
+ // If the target is a symlink, open the file with O_PATH.
+ if errors.Is(err, unix.ELOOP) {
+ newFile, err := openFileUnderRoot(metadata.Name, dirfd, unix.O_PATH|unix.O_NOFOLLOW, 0)
+ if err != nil {
+ return err
+ }
+ defer newFile.Close()
+
+ return setFileAttrs(dirfd, newFile, mode, metadata, options, true)
+ }
return err
}
defer newFile.Close()
- return setFileAttrs(newFile, mode, metadata, options)
+ return setFileAttrs(dirfd, newFile, mode, metadata, options, false)
}
func safeSymlink(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) error {
destDir, destBase := filepath.Dir(metadata.Name), filepath.Base(metadata.Name)
destDirFd := dirfd
if destDir != "." {
- f, err := openFileUnderRoot(destDir, dirfd, unix.O_RDONLY, 0)
+ f, err := openOrCreateDirUnderRoot(destDir, dirfd, 0)
if err != nil {
return err
}
@@ -828,7 +1023,10 @@ func safeSymlink(dirfd int, mode os.FileMode, metadata *internal.FileMetadata, o
destDirFd = int(f.Fd())
}
- return unix.Symlinkat(metadata.Linkname, destDirFd, destBase)
+ if err := unix.Symlinkat(metadata.Linkname, destDirFd, destBase); err != nil {
+ return fmt.Errorf("create symlink %q pointing to %q: %w", metadata.Name, metadata.Linkname, err)
+ }
+ return nil
}
type whiteoutHandler struct {
@@ -837,13 +1035,16 @@ type whiteoutHandler struct {
}
func (d whiteoutHandler) Setxattr(path, name string, value []byte) error {
- file, err := openFileUnderRoot(path, d.Dirfd, unix.O_RDONLY, 0)
+ file, err := openOrCreateDirUnderRoot(path, d.Dirfd, 0)
if err != nil {
return err
}
defer file.Close()
- return unix.Fsetxattr(int(file.Fd()), name, value, 0)
+ if err := unix.Fsetxattr(int(file.Fd()), name, value, 0); err != nil {
+ return fmt.Errorf("set xattr %s=%q for %q: %w", name, value, path, err)
+ }
+ return nil
}
func (d whiteoutHandler) Mknod(path string, mode uint32, dev int) error {
@@ -852,7 +1053,7 @@ func (d whiteoutHandler) Mknod(path string, mode uint32, dev int) error {
dirfd := d.Dirfd
if dir != "" {
- dir, err := openFileUnderRoot(dir, d.Dirfd, unix.O_RDONLY, 0)
+ dir, err := openOrCreateDirUnderRoot(dir, d.Dirfd, 0)
if err != nil {
return err
}
@@ -861,12 +1062,16 @@ func (d whiteoutHandler) Mknod(path string, mode uint32, dev int) error {
dirfd = int(dir.Fd())
}
- return unix.Mknodat(dirfd, base, mode, dev)
+ if err := unix.Mknodat(dirfd, base, mode, dev); err != nil {
+ return fmt.Errorf("mknod %q: %w", path, err)
+ }
+
+ return nil
}
func checkChownErr(err error, name string, uid, gid int) error {
if errors.Is(err, syscall.EINVAL) {
- return errors.Wrapf(err, "potentially insufficient UIDs or GIDs available in user namespace (requested %d:%d for %s): Check /etc/subuid and /etc/subgid if configured locally", uid, gid, name)
+ return fmt.Errorf("potentially insufficient UIDs or GIDs available in user namespace (requested %d:%d for %s): Check /etc/subuid and /etc/subgid if configured locally: %w", uid, gid, name, err)
}
return err
}
@@ -961,7 +1166,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
dirfd, err := unix.Open(dest, unix.O_RDONLY|unix.O_PATH, 0)
if err != nil {
- return output, err
+ return output, fmt.Errorf("cannot open %q: %w", dest, err)
}
defer unix.Close(dirfd)
@@ -1021,7 +1226,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
return err
}
defer file.Close()
- if err := setFileAttrs(file, mode, &r, options); err != nil {
+ if err := setFileAttrs(dirfd, file, mode, &r, options, false); err != nil {
return err
}
return nil
@@ -1033,7 +1238,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
}
case tar.TypeDir:
- if err := safeMkdir(dirfd, mode, &r, options); err != nil {
+ if err := safeMkdir(dirfd, mode, r.Name, &r, options); err != nil {
return output, err
}
continue
@@ -1070,7 +1275,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
finalizeFile := func(dstFile *os.File) error {
if dstFile != nil {
defer dstFile.Close()
- if err := setFileAttrs(dstFile, mode, &r, options); err != nil {
+ if err := setFileAttrs(dirfd, dstFile, mode, &r, options, false); err != nil {
return err
}
}
diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go
index 8a3858d9f..fe4274efd 100644
--- a/vendor/github.com/containers/storage/types/options.go
+++ b/vendor/github.com/containers/storage/types/options.go
@@ -42,6 +42,10 @@ func init() {
defaultStoreOptions.GraphDriverName = ""
if _, err := os.Stat(defaultOverrideConfigFile); err == nil {
+ // The DefaultConfigFile(rootless) function returns the path
+ // of the used storage.conf file, by returning defaultConfigFile
+ // If override exists containers/storage uses it by default.
+ defaultConfigFile = defaultOverrideConfigFile
ReloadConfigurationFileIfNeeded(defaultOverrideConfigFile, &defaultStoreOptions)
} else {
if !os.IsNotExist(err) {
diff --git a/vendor/github.com/jinzhu/copier/copier.go b/vendor/github.com/jinzhu/copier/copier.go
index 412ff5497..6d21da869 100644
--- a/vendor/github.com/jinzhu/copier/copier.go
+++ b/vendor/github.com/jinzhu/copier/copier.go
@@ -348,10 +348,15 @@ func deepFields(reflectType reflect.Type) []reflect.StructField {
for i := 0; i < reflectType.NumField(); i++ {
v := reflectType.Field(i)
- if v.Anonymous {
- fields = append(fields, deepFields(v.Type)...)
- } else {
- fields = append(fields, v)
+ // PkgPath is the package path that qualifies a lower case (unexported)
+ // field name. It is empty for upper case (exported) field names.
+ // See https://golang.org/ref/spec#Uniqueness_of_identifiers
+ if v.PkgPath == "" {
+ if v.Anonymous {
+ fields = append(fields, deepFields(v.Type)...)
+ } else {
+ fields = append(fields, v)
+ }
}
}
diff --git a/vendor/github.com/jinzhu/copier/go.mod b/vendor/github.com/jinzhu/copier/go.mod
index 531422dcb..309801e9b 100644
--- a/vendor/github.com/jinzhu/copier/go.mod
+++ b/vendor/github.com/jinzhu/copier/go.mod
@@ -1,3 +1,3 @@
module github.com/jinzhu/copier
-go 1.15
+go 1.13
diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
index 9fe803a5e..38a099162 100644
--- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.4.3
+
+* Fix cases where `json.Number` didn't decode properly [GH-261]
+
## 1.4.2
* Custom name matchers to support any sort of casing, formatting, etc. for
diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
index dcee0f2d6..6b81b0067 100644
--- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
@@ -684,16 +684,12 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
- i, err := jn.Int64()
+ i, err := strconv.ParseUint(string(jn), 0, 64)
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
- if i < 0 && !d.config.WeaklyTypedInput {
- return fmt.Errorf("cannot parse '%s', %d overflows uint",
- name, i)
- }
- val.SetUint(uint64(i))
+ val.SetUint(i)
default:
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
index 4e6c4b236..82da6c6a8 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
@@ -21,6 +21,9 @@ import "github.com/opencontainers/image-spec/specs-go"
type Index struct {
specs.Versioned
+ // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
+ MediaType string `json:"mediaType,omitempty"`
+
// Manifests references platform specific manifests.
Manifests []Descriptor `json:"manifests"`
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
index 7ff32c40b..d72d15ce4 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
@@ -20,6 +20,9 @@ import "github.com/opencontainers/image-spec/specs-go"
type Manifest struct {
specs.Versioned
+ // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
+ MediaType string `json:"mediaType,omitempty"`
+
// Config references a configuration object for a container, by digest.
// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
Config Descriptor `json:"config"`
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
index 58f1095ab..31f99cf64 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
@@ -22,7 +22,7 @@ const (
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 0
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 1
+ VersionPatch = 2
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = "-dev"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index a104465c6..04f15620c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -106,7 +106,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
-# github.com/containers/common v0.46.1-0.20211125160015-ccf46abecd91
+# github.com/containers/common v0.46.1-0.20211202172647-e77d74bd1976
## explicit
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
@@ -219,7 +219,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.37.1-0.20211122214631-59ba58582415
+# github.com/containers/storage v1.37.1-0.20211130181259-1a158c89a518
## explicit
github.com/containers/storage
github.com/containers/storage/drivers
@@ -437,7 +437,7 @@ github.com/imdario/mergo
github.com/inconshreveable/mousetrap
# github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee
github.com/ishidawataru/sctp
-# github.com/jinzhu/copier v0.3.2
+# github.com/jinzhu/copier v0.3.4
github.com/jinzhu/copier
# github.com/json-iterator/go v1.1.12
## explicit
@@ -469,7 +469,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
github.com/miekg/pkcs11
# github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/mistifyio/go-zfs
-# github.com/mitchellh/mapstructure v1.4.2
+# github.com/mitchellh/mapstructure v1.4.3
github.com/mitchellh/mapstructure
# github.com/moby/sys/mount v0.2.0
github.com/moby/sys/mount
@@ -545,7 +545,7 @@ github.com/onsi/gomega/types
# github.com/opencontainers/go-digest v1.0.0
## explicit
github.com/opencontainers/go-digest
-# github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283
+# github.com/opencontainers/image-spec v1.0.2-0.20211123152302-43a7dee1ec31
## explicit
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1