aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/labeler.yml4
-rw-r--r--.github/workflows/labeler.yml15
-rw-r--r--cmd/podman/auto-update.go28
-rw-r--r--cmd/podman/inspect/inspect.go33
-rw-r--r--cmd/podman/machine/info.go12
-rw-r--r--cmd/podman/machine/inspect.go20
-rw-r--r--cmd/podman/machine/list.go40
-rw-r--r--cmd/podman/networks/list.go31
-rw-r--r--cmd/podman/secrets/inspect.go13
-rw-r--r--cmd/podman/secrets/list.go32
-rw-r--r--cmd/podman/system/info.go13
-rw-r--r--cmd/podman/system/version.go19
-rw-r--r--cmd/podman/volumes/list.go30
-rw-r--r--docs/source/markdown/.gitignore1
-rw-r--r--docs/source/markdown/options/ip.md8
-rw-r--r--docs/source/markdown/options/os.pull.md4
-rw-r--r--docs/source/markdown/options/publish-all.md12
-rw-r--r--docs/source/markdown/options/publish.md19
-rw-r--r--docs/source/markdown/options/tls-verify.md5
-rw-r--r--docs/source/markdown/podman-build.1.md.in5
-rw-r--r--docs/source/markdown/podman-container-runlabel.1.md.in4
-rw-r--r--docs/source/markdown/podman-create.1.md.in49
-rw-r--r--docs/source/markdown/podman-generate-systemd.1.md4
-rw-r--r--docs/source/markdown/podman-kube-play.1.md.in6
-rw-r--r--docs/source/markdown/podman-login.1.md.in6
-rw-r--r--docs/source/markdown/podman-manifest-add.1.md.in4
-rw-r--r--docs/source/markdown/podman-manifest-create.1.md.in (renamed from docs/source/markdown/podman-manifest-create.1.md)4
-rw-r--r--docs/source/markdown/podman-manifest-push.1.md.in4
-rw-r--r--docs/source/markdown/podman-pod-create.1.md.in29
-rw-r--r--docs/source/markdown/podman-pull.1.md.in11
-rw-r--r--docs/source/markdown/podman-push.1.md.in6
-rw-r--r--docs/source/markdown/podman-run.1.md.in50
-rw-r--r--docs/source/markdown/podman-search.1.md.in7
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/events/events_freebsd.go2
-rw-r--r--libpod/healthcheck_linux.go2
-rw-r--r--pkg/api/handlers/compat/system.go2
-rw-r--r--pkg/domain/infra/abi/system.go18
-rw-r--r--pkg/machine/e2e/inspect_test.go8
-rw-r--r--pkg/systemd/generate/containers.go12
-rw-r--r--pkg/systemd/generate/pods.go12
-rw-r--r--pkg/systemd/generate/pods_test.go63
-rw-r--r--test/apiv2/45-system.at18
-rw-r--r--test/e2e/generate_systemd_test.go2
-rw-r--r--test/e2e/volume_ls_test.go5
-rw-r--r--test/system/220-healthcheck.bats6
-rw-r--r--test/system/250-systemd.bats7
-rw-r--r--test/system/320-system-df.bats2
-rw-r--r--test/system/610-format.bats169
-rw-r--r--test/system/helpers.bash9
50 files changed, 501 insertions, 370 deletions
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 000000000..4d00baca9
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,4 @@
+# Add labels based on file paths in PR
+# https://github.com/actions/labeler
+kind/api-change:
+ - pkg/api/**/*
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 000000000..64505bbfe
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,15 @@
+# https://github.com/actions/labeler
+name: "Pull Request Labeler"
+on:
+- pull_request_target
+
+jobs:
+ triage:
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v4
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go
index 88ef0ec88..6a0446422 100644
--- a/cmd/podman/auto-update.go
+++ b/cmd/podman/auto-update.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
- "strings"
"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
@@ -104,15 +103,15 @@ func reportsToOutput(allReports []*entities.AutoUpdateReport) []autoUpdateOutput
}
func writeTemplate(allReports []*entities.AutoUpdateReport, inputFormat string) error {
- var format string
- var printHeader bool
+ rpt := report.New(os.Stdout, "auto-update")
+ defer rpt.Flush()
output := reportsToOutput(allReports)
+ var err error
switch inputFormat {
case "":
- rows := []string{"{{.Unit}}", "{{.Container}}", "{{.Image}}", "{{.Policy}}", "{{.Updated}}"}
- format = "{{range . }}" + strings.Join(rows, "\t") + "\n{{end -}}"
- printHeader = true
+ format := "{{range . }}\t{{.Unit}}\t{{.Container}}\t{{.Image}}\t{{.Policy}}\t{{.Updated}}\n{{end -}}"
+ rpt, err = rpt.Parse(report.OriginPodman, format)
case "json":
prettyJSON, err := json.MarshalIndent(output, "", " ")
if err != nil {
@@ -121,26 +120,17 @@ func writeTemplate(allReports []*entities.AutoUpdateReport, inputFormat string)
fmt.Println(string(prettyJSON))
return nil
default:
- format = "{{range . }}" + inputFormat + "\n{{end -}}"
+ rpt, err = rpt.Parse(report.OriginUser, inputFormat)
}
-
- tmpl, err := report.NewTemplate("auto-update").Parse(format)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
- defer w.Flush()
- if printHeader {
+ if rpt.RenderHeaders {
headers := report.Headers(autoUpdateOutput{}, nil)
- if err := tmpl.Execute(w, headers); err != nil {
+ if err := rpt.Execute(headers); err != nil {
return err
}
}
-
- return tmpl.Execute(w, output)
+ return rpt.Execute(output)
}
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index ccabd7614..22b2c9055 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -8,7 +8,6 @@ import (
"os"
"regexp"
"strings"
- "text/template"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
@@ -16,7 +15,6 @@ import (
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/validate"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -176,13 +174,18 @@ func (i *inspector) inspect(namesOrIDs []string) error {
}
default:
// Landing here implies user has given a custom --format
- row := inspectNormalize(i.options.Format, tmpType)
- row = report.NormalizeFormat(row)
- row = report.EnforceRange(row)
- err = printTmpl(tmpType, row, data)
+ var rpt *report.Formatter
+ format := inspectNormalize(i.options.Format, i.options.Type)
+ rpt, err = report.New(os.Stdout, "inspect").Parse(report.OriginUser, format)
+ if err != nil {
+ return err
+ }
+ defer rpt.Flush()
+
+ err = rpt.Execute(data)
}
if err != nil {
- logrus.Errorf("Printing inspect output: %v", err)
+ errs = append(errs, fmt.Errorf("printing inspect output: %w", err))
}
if len(errs) > 0 {
@@ -205,22 +208,6 @@ func printJSON(data interface{}) error {
return enc.Encode(data)
}
-func printTmpl(typ, row string, data []interface{}) error {
- // We cannot use c/common/reports here, too many levels of interface{}
- t, err := template.New(typ + " inspect").Funcs(template.FuncMap(report.DefaultFuncs)).Parse(row)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- err = t.Execute(w, data)
- w.Flush()
- return err
-}
-
func (i *inspector) inspectAll(ctx context.Context, namesOrIDs []string) ([]interface{}, []error, error) {
var data []interface{}
allErrs := []error{}
diff --git a/cmd/podman/machine/info.go b/cmd/podman/machine/info.go
index 1151f9e86..9c7454379 100644
--- a/cmd/podman/machine/info.go
+++ b/cmd/podman/machine/info.go
@@ -5,7 +5,6 @@ package machine
import (
"fmt"
- "html/template"
"os"
"runtime"
@@ -75,13 +74,16 @@ func info(cmd *cobra.Command, args []string) error {
}
fmt.Println(string(b))
case cmd.Flags().Changed("format"):
- tmpl := template.New(cmd.Name()).Funcs(template.FuncMap(report.DefaultFuncs))
- inFormat = report.NormalizeFormat(inFormat)
- tmpl, err := tmpl.Parse(inFormat)
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
+ // Use OriginUnknown so it does not add an extra range since it
+ // will only be called for a single element and not a slice.
+ rpt, err = rpt.Parse(report.OriginUnknown, inFormat)
if err != nil {
return err
}
- return tmpl.Execute(os.Stdout, info)
+ return rpt.Execute(info)
default:
b, err := yaml.Marshal(info)
if err != nil {
diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go
index d69c382f2..410bb3889 100644
--- a/cmd/podman/machine/inspect.go
+++ b/cmd/podman/machine/inspect.go
@@ -11,7 +11,6 @@ import (
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/pkg/machine"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -66,28 +65,23 @@ func inspect(cmd *cobra.Command, args []string) error {
}
vms = append(vms, *ii)
}
+
switch {
case cmd.Flag("format").Changed:
- row := report.NormalizeFormat(inspectFlag.format)
- row = report.EnforceRange(row)
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- tmpl, err := report.NewTemplate("Machine inspect").Parse(row)
+ rpt, err := rpt.Parse(report.OriginUser, inspectFlag.format)
if err != nil {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
-
- if err := tmpl.Execute(w, vms); err != nil {
- logrus.Error(err)
+ if err := rpt.Execute(vms); err != nil {
+ errs = append(errs, err)
}
- w.Flush()
default:
if err := printJSON(vms); err != nil {
- logrus.Error(err)
+ errs = append(errs, err)
}
}
return errs.PrintErrors()
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index dd4a86697..ddc9ce246 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -53,7 +53,7 @@ func init() {
flags := lsCmd.Flags()
formatFlagName := "format"
- flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n", "Format volume output using JSON or a Go template")
+ flags.StringVar(&listFlag.format, formatFlagName, "{{range .}}{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n{{end -}}", "Format volume output using JSON or a Go template")
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.ListReporter{}))
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
flags.BoolVarP(&listFlag.quiet, "quiet", "q", false, "Show only machine names")
@@ -66,10 +66,6 @@ func list(cmd *cobra.Command, args []string) error {
err error
)
- if listFlag.quiet {
- listFlag.format = "{{.Name}}\n"
- }
-
provider := GetSystemDefaultProvider()
listResponse, err = provider.List(opts)
if err != nil {
@@ -115,37 +111,29 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.ListReporter) erro
"Memory": "MEMORY",
"DiskSize": "DISK SIZE",
})
- printHeader := !listFlag.noHeading
- if listFlag.quiet {
- printHeader = false
- }
- var row string
+
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
+ var err error
switch {
- case cmd.Flags().Changed("format"):
- row = cmd.Flag("format").Value.String()
- printHeader = report.HasTable(row)
- row = report.NormalizeFormat(row)
+ case cmd.Flag("format").Changed:
+ rpt, err = rpt.Parse(report.OriginUser, listFlag.format)
+ case listFlag.quiet:
+ rpt, err = rpt.Parse(report.OriginUser, "{{.Name}}\n")
default:
- row = cmd.Flag("format").Value.String()
+ rpt, err = rpt.Parse(report.OriginPodman, listFlag.format)
}
- format := report.EnforceRange(row)
-
- tmpl, err := report.NewTemplate("list").Parse(format)
if err != nil {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- defer w.Flush()
- if printHeader {
- if err := tmpl.Execute(w, headers); err != nil {
+ if rpt.RenderHeaders && !listFlag.noHeading {
+ if err := rpt.Execute(headers); err != nil {
return fmt.Errorf("failed to write report column headers: %w", err)
}
}
- return tmpl.Execute(w, responses)
+ return rpt.Execute(responses)
}
func strTime(t time.Time) string {
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 5d4be2a81..951583cfb 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -122,36 +122,27 @@ func templateOut(cmd *cobra.Command, responses []types.Network) error {
"ID": "network id",
})
- renderHeaders := report.HasTable(networkListOptions.Format)
- var row string
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
+ var err error
switch {
- case cmd.Flags().Changed("format"):
- row = report.NormalizeFormat(networkListOptions.Format)
+ case cmd.Flag("format").Changed:
+ rpt, err = rpt.Parse(report.OriginUser, networkListOptions.Format)
default:
- // 'podman network ls' equivalent to 'podman network ls --format="table {{.ID}} {{.Name}} {{.Version}} {{.Plugins}}" '
- row = "{{.ID}}\t{{.Name}}\t{{.Driver}}\n"
- renderHeaders = true
+ rpt, err = rpt.Parse(report.OriginPodman, "{{range .}}{{.ID}}\t{{.Name}}\t{{.Driver}}\n{{end -}}")
}
- format := report.EnforceRange(row)
-
- tmpl, err := report.NewTemplate("list").Parse(format)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
- defer w.Flush()
noHeading, _ := cmd.Flags().GetBool("noheading")
- if !noHeading && renderHeaders {
- if err := tmpl.Execute(w, headers); err != nil {
- return err
+ if rpt.RenderHeaders && !noHeading {
+ if err := rpt.Execute(headers); err != nil {
+ return fmt.Errorf("failed to write report column headers: %w", err)
}
}
- return tmpl.Execute(w, nlprs)
+ return rpt.Execute(nlprs)
}
// ListPrintReports returns the network list report
diff --git a/cmd/podman/secrets/inspect.go b/cmd/podman/secrets/inspect.go
index c99e555ba..f4c395b0f 100644
--- a/cmd/podman/secrets/inspect.go
+++ b/cmd/podman/secrets/inspect.go
@@ -47,20 +47,15 @@ func inspect(cmd *cobra.Command, args []string) error {
}
if cmd.Flags().Changed("format") {
- row := report.NormalizeFormat(format)
- formatted := report.EnforceRange(row)
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- tmpl, err := report.NewTemplate("inspect").Parse(formatted)
+ rpt, err := rpt.Parse(report.OriginUser, format)
if err != nil {
return err
}
- w, err := report.NewWriterDefault(os.Stdout)
- if err != nil {
- return err
- }
- defer w.Flush()
- if err := tmpl.Execute(w, inspected); err != nil {
+ if err := rpt.Execute(inspected); err != nil {
return err
}
} else {
diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go
index afa9b8887..1833cc544 100644
--- a/cmd/podman/secrets/list.go
+++ b/cmd/podman/secrets/list.go
@@ -46,7 +46,7 @@ func init() {
flags := lsCmd.Flags()
formatFlagName := "format"
- flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template")
+ flags.StringVar(&listFlag.format, formatFlagName, "{{range .}}{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\n{{end -}}", "Format volume output using Go template")
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.SecretInfoReport{}))
filterFlagName := "filter"
@@ -105,31 +105,25 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.SecretListReport)
"UpdatedAt": "UPDATED",
})
- row := cmd.Flag("format").Value.String()
- if cmd.Flags().Changed("format") {
- row = report.NormalizeFormat(row)
- }
- format := report.EnforceRange(row)
+ 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
+ switch {
+ case cmd.Flag("format").Changed:
+ rpt, err = rpt.Parse(report.OriginUser, listFlag.format)
+ default:
+ rpt, err = rpt.Parse(report.OriginPodman, listFlag.format)
}
-
- w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
- 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 {
+ noHeading, _ := cmd.Flags().GetBool("noheading")
+ if rpt.RenderHeaders && !noHeading {
+ if err := rpt.Execute(headers); err != nil {
return fmt.Errorf("failed to write report column headers: %w", err)
}
}
- return tmpl.Execute(w, responses)
+ return rpt.Execute(responses)
}
diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go
index 296fa4def..9613d5e56 100644
--- a/cmd/podman/system/info.go
+++ b/cmd/podman/system/info.go
@@ -3,7 +3,6 @@ package system
import (
"fmt"
"os"
- "text/template"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
@@ -86,14 +85,16 @@ func info(cmd *cobra.Command, args []string) error {
}
fmt.Println(string(b))
case cmd.Flags().Changed("format"):
- // Cannot use report.New() as it enforces {{range .}} for OriginUser templates
- tmpl := template.New(cmd.Name()).Funcs(template.FuncMap(report.DefaultFuncs))
- inFormat = report.NormalizeFormat(inFormat)
- tmpl, err := tmpl.Parse(inFormat)
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
+ // Use OriginUnknown so it does not add an extra range since it
+ // will only be called for a single element and not a slice.
+ rpt, err = rpt.Parse(report.OriginUnknown, inFormat)
if err != nil {
return err
}
- return tmpl.Execute(os.Stdout, info)
+ return rpt.Execute(info)
default:
b, err := yaml.Marshal(info)
if err != nil {
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index 7202b2c08..33ab0f757 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -4,7 +4,6 @@ import (
"fmt"
"os"
"strings"
- "text/template"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
@@ -12,6 +11,7 @@ import (
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/validate"
"github.com/containers/podman/v4/pkg/domain/entities"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -53,22 +53,25 @@ func version(cmd *cobra.Command, args []string) error {
}
if cmd.Flag("format").Changed {
- // Cannot use report.New() as it enforces {{range .}} for OriginUser templates
- tmpl := template.New(cmd.Name()).Funcs(template.FuncMap(report.DefaultFuncs))
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
- versionFormat = report.NormalizeFormat(versionFormat)
- tmpl, err := tmpl.Parse(versionFormat)
+ // Use OriginUnknown so it does not add an extra range since it
+ // will only be called for a single element and not a slice.
+ rpt, err = rpt.Parse(report.OriginUnknown, versionFormat)
if err != nil {
return err
}
- if err := tmpl.Execute(os.Stdout, versions); err != nil {
+ if err := rpt.Execute(versions); err != nil {
+ // only log at debug since we fall back to the client only template
+ logrus.Debugf("Failed to execute template: %v", err)
// On Failure, assume user is using older version of podman version --format and check client
versionFormat = strings.ReplaceAll(versionFormat, ".Server.", ".")
- tmpl, err := tmpl.Parse(versionFormat)
+ rpt, err := rpt.Parse(report.OriginUnknown, versionFormat)
if err != nil {
return err
}
- if err := tmpl.Execute(os.Stdout, versions.Client); err != nil {
+ if err := rpt.Execute(versions.Client); err != nil {
return err
}
}
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index 06118513d..70041834b 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -55,7 +55,7 @@ func init() {
_ = lsCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteVolumeFilters)
formatFlagName := "format"
- flags.StringVar(&cliOpts.Format, formatFlagName, "{{.Driver}}\t{{.Name}}\n", "Format volume output using Go template")
+ flags.StringVar(&cliOpts.Format, formatFlagName, "{{range .}}{{.Driver}}\t{{.Name}}\n{{end -}}", "Format volume output using Go template")
_ = lsCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.VolumeListReport{}))
flags.Bool("noheading", false, "Do not print headers")
@@ -95,34 +95,28 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.VolumeListReport)
"Name": "VOLUME NAME",
})
- var row string
+ rpt := report.New(os.Stdout, cmd.Name())
+ defer rpt.Flush()
+
+ var err error
switch {
+ case cmd.Flag("format").Changed:
+ rpt, err = rpt.Parse(report.OriginUser, cliOpts.Format)
case cliOpts.Quiet:
- row = "{{.Name}}\n"
- case cmd.Flags().Changed("format"):
- row = report.NormalizeFormat(cliOpts.Format)
+ rpt, err = rpt.Parse(report.OriginUser, "{{.Name}}\n")
default:
- row = cmd.Flag("format").Value.String()
+ rpt, err = rpt.Parse(report.OriginPodman, cliOpts.Format)
}
- format := report.EnforceRange(row)
-
- tmpl, err := report.NewTemplate("list").Parse(format)
- if err != nil {
- return err
- }
-
- w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
- defer w.Flush()
- if !(noHeading || cliOpts.Quiet || cmd.Flag("format").Changed) {
- if err := tmpl.Execute(w, headers); err != nil {
+ if (rpt.RenderHeaders) && !noHeading {
+ if err := rpt.Execute(headers); err != nil {
return fmt.Errorf("failed to write report column headers: %w", err)
}
}
- return tmpl.Execute(w, responses)
+ return rpt.Execute(responses)
}
func outputJSON(vols []*entities.VolumeListReport) error {
diff --git a/docs/source/markdown/.gitignore b/docs/source/markdown/.gitignore
index 74e7fc075..552e6f520 100644
--- a/docs/source/markdown/.gitignore
+++ b/docs/source/markdown/.gitignore
@@ -11,6 +11,7 @@ podman-login.1.md
podman-logout.1.md
podman-logs.1.md
podman-manifest-add.1.md
+podman-manifest-create.1.md
podman-manifest-push.1.md
podman-pause.1.md
podman-pod-clone.1.md
diff --git a/docs/source/markdown/options/ip.md b/docs/source/markdown/options/ip.md
new file mode 100644
index 000000000..8f251ee2e
--- /dev/null
+++ b/docs/source/markdown/options/ip.md
@@ -0,0 +1,8 @@
+#### **--ip**=*ipv4*
+
+Specify a static IPv4 address for the <<container|pod>>, for example **10.88.64.128**.
+This option can only be used if the <<container|pod>> is joined to only a single network - i.e., **--network=network-name** is used at most once -
+and if the <<container|pod>> is not joining another container's network namespace via **--network=container:_id_**.
+The address must be within the network's IP address pool (default **10.88.0.0/16**).
+
+To specify multiple static IP addresses per <<container|pod>>, set multiple networks using the **--network** option with a static IP address specified for each using the `ip` mode for that option.
diff --git a/docs/source/markdown/options/os.pull.md b/docs/source/markdown/options/os.pull.md
new file mode 100644
index 000000000..547a9fff8
--- /dev/null
+++ b/docs/source/markdown/options/os.pull.md
@@ -0,0 +1,4 @@
+#### **--os**=*OS*
+
+Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
+Unless overridden, subsequent lookups of the same image in the local storage will match this OS, regardless of the host.
diff --git a/docs/source/markdown/options/publish-all.md b/docs/source/markdown/options/publish-all.md
new file mode 100644
index 000000000..6651599a0
--- /dev/null
+++ b/docs/source/markdown/options/publish-all.md
@@ -0,0 +1,12 @@
+#### **--publish-all**, **-P**
+
+Publish all exposed ports to random ports on the host interfaces. The default is **false**.
+
+When set to **true**, publish all exposed ports to the host interfaces. The
+default is **false**. If the operator uses **-P** (or **-p**) then Podman will make the
+exposed port accessible on the host and the ports will be available to any
+client that can reach the host.
+
+When using this option, Podman will bind any exposed port to a random port on the host
+within an ephemeral port range defined by */proc/sys/net/ipv4/ip_local_port_range*.
+To find the mapping between the host ports and the exposed ports, use **podman port**.
diff --git a/docs/source/markdown/options/publish.md b/docs/source/markdown/options/publish.md
new file mode 100644
index 000000000..a0394b692
--- /dev/null
+++ b/docs/source/markdown/options/publish.md
@@ -0,0 +1,19 @@
+#### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]*
+
+Publish a container's port, or range of ports,<<| within this pod>> to the host.
+
+Both *hostPort* and *containerPort* can be specified as a range of ports.
+When specifying ranges for both, the number of container ports in the
+range must match the number of host ports in the range.
+
+If host IP is set to 0.0.0.0 or not set at all, the port will be bound on all IPs on the host.
+
+By default, Podman will publish TCP ports. To publish a UDP port instead, give
+`udp` as protocol. To publish both TCP and UDP ports, set `--publish` twice,
+with `tcp`, and `udp` as protocols respectively. Rootful containers can also
+publish ports using the `sctp` protocol.
+
+Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`).
+If it is not, the container port will be randomly assigned a port on the host.
+
+Use **podman port** to see the actual mapping: `podman port $CONTAINER $CONTAINERPORT`.
diff --git a/docs/source/markdown/options/tls-verify.md b/docs/source/markdown/options/tls-verify.md
new file mode 100644
index 000000000..e3d6f491f
--- /dev/null
+++ b/docs/source/markdown/options/tls-verify.md
@@ -0,0 +1,5 @@
+#### **--tls-verify**
+
+Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
+then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
+TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
diff --git a/docs/source/markdown/podman-build.1.md.in b/docs/source/markdown/podman-build.1.md.in
index ab31c492c..2c636069f 100644
--- a/docs/source/markdown/podman-build.1.md.in
+++ b/docs/source/markdown/podman-build.1.md.in
@@ -627,10 +627,7 @@ timestamp.
If the only instruction in a Containerfile is `FROM`, this flag has no effect.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when talking to container registries
-(defaults to true). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
+@@option tls-verify
#### **--ulimit**=*type=soft-limit[:hard-limit]*
diff --git a/docs/source/markdown/podman-container-runlabel.1.md.in b/docs/source/markdown/podman-container-runlabel.1.md.in
index 36e021ce4..bdbd306f2 100644
--- a/docs/source/markdown/podman-container-runlabel.1.md.in
+++ b/docs/source/markdown/podman-container-runlabel.1.md.in
@@ -55,9 +55,7 @@ Suppress output information when pulling images
If a container exists of the default or given name, as needed it will be stopped, deleted and a new container will be created from this image.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, TLS verification will be used unless the target registry is listed as an insecure registry in containers-registries.conf(5).
+@@option tls-verify
## EXAMPLES
diff --git a/docs/source/markdown/podman-create.1.md.in b/docs/source/markdown/podman-create.1.md.in
index 6f6bb29e5..54afe3b16 100644
--- a/docs/source/markdown/podman-create.1.md.in
+++ b/docs/source/markdown/podman-create.1.md.in
@@ -228,14 +228,7 @@ pod when that pod is not running.
Keep STDIN open even if not attached. The default is *false*.
-#### **--ip**=*ipv4*
-
-Specify a static IPv4 address for the container, for example **10.88.64.128**.
-This option can only be used if the container is joined to only a single network - i.e., **--network=network-name** is used at most once -
-and if the container is not joining another container's network namespace via **--network=container:_id_**.
-The address must be within the network's IP address pool (default **10.88.0.0/16**).
-
-To specify multiple static IP addresses per container, set multiple networks using the **--network** option with a static IP address specified for each using the `ip` mode for that option.
+@@option ip
#### **--ip6**=*ipv6*
@@ -333,9 +326,7 @@ This option conflicts with **--add-host**.
@@option oom-score-adj
-#### **--os**=*OS*
-Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
-Unless overridden, subsequent lookups of the same image in the local storage will match this OS, regardless of the host.
+@@option os.pull
@@option passwd-entry
@@ -358,25 +349,7 @@ To make a pod with more granular options, use the `podman pod create` command be
@@option privileged
-#### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]*
-
-Publish a container's port, or range of ports, to the host.
-
-Both *hostPort* and *containerPort* can be specified as a range of ports.
-When specifying ranges for both, the number of container ports in the
-range must match the number of host ports in the range.
-
-If host IP is set to 0.0.0.0 or not set at all, the port will be bound on all IPs on the host.
-
-By default, Podman will publish TCP ports. To publish a UDP port instead, give
-`udp` as protocol. To publish both TCP and UDP ports, set `--publish` twice,
-with `tcp`, and `udp` as protocols respectively. Rootful containers can also
-publish ports using the `sctp` protocol.
-
-Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`).
-If it is not, the container port will be randomly assigned a port on the host.
-
-Use **podman port** to see the actual mapping: `podman port $CONTAINER $CONTAINERPORT`.
+@@option publish
**Note:** If a container will be run within a pod, it is not necessary to publish the port for
the containers in the pod. The port must only be published by the pod itself. Pod network
@@ -386,17 +359,7 @@ associated ports. If one container binds to a port, no other container can use t
within the pod while it is in use. Containers in the pod can also communicate over localhost
by having one container bind to localhost in the pod, and another connect to that port.
-#### **--publish-all**, **-P**
-
-Publish all exposed ports to random ports on the host interfaces. The default is *false*.
-
-When set to true publish all exposed ports to the host interfaces. The
-default is false. If the operator uses -P (or -p) then Podman will make the
-exposed port accessible on the host and the ports will be available to any
-client that can reach the host. When using -P, Podman will bind any exposed
-port to a random port on the host within an *ephemeral port range* defined by
-`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
-ports and the exposed ports, use `podman port`.
+@@option publish-all
@@option pull
@@ -479,9 +442,7 @@ When size is `0`, there is no limit on the amount of memory used for IPC by the
@@option timeout
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
@@option tmpfs
diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md
index ee649c95b..b733cff8d 100644
--- a/docs/source/markdown/podman-generate-systemd.1.md
+++ b/docs/source/markdown/podman-generate-systemd.1.md
@@ -85,7 +85,9 @@ Set the systemd unit requires (`Requires=`) option. Similar to wants, but declar
#### **--restart-policy**=*policy*
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*.
+"on-watchdog", "on-abort", or "always". The default policy is *on-failure* unless the container was created with a custom restart policy.
+
+Note that generating a unit without `--new` on a container with a custom restart policy can lead to issues on shutdown; systemd will attempt to stop the unit while Podman tries to restart it. It is recommended to to create the container without `--restart` and use the `--restart-policy` option instead when generating the unit file.
#### **--restart-sec**=*time*
diff --git a/docs/source/markdown/podman-kube-play.1.md.in b/docs/source/markdown/podman-kube-play.1.md.in
index 6bf3acc9b..e4e1199e6 100644
--- a/docs/source/markdown/podman-kube-play.1.md.in
+++ b/docs/source/markdown/podman-kube-play.1.md.in
@@ -219,11 +219,7 @@ Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (This
Start the pod after creating it, set to false to only create it.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
-then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
@@option userns.container
## EXAMPLES
diff --git a/docs/source/markdown/podman-login.1.md.in b/docs/source/markdown/podman-login.1.md.in
index c309395fb..63798ed99 100644
--- a/docs/source/markdown/podman-login.1.md.in
+++ b/docs/source/markdown/podman-login.1.md.in
@@ -48,11 +48,7 @@ Password for registry
Take the password from stdin
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
-then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
#### **--username**, **-u**=*username*
diff --git a/docs/source/markdown/podman-manifest-add.1.md.in b/docs/source/markdown/podman-manifest-add.1.md.in
index 0d957cd1e..6a9df69b4 100644
--- a/docs/source/markdown/podman-manifest-add.1.md.in
+++ b/docs/source/markdown/podman-manifest-add.1.md.in
@@ -56,9 +56,7 @@ configuration information.
Specify the OS version which the list or index records as a requirement for the
image. This option is rarely used.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when talking to container registries (defaults to true).
+@@option tls-verify
#### **--variant**
diff --git a/docs/source/markdown/podman-manifest-create.1.md b/docs/source/markdown/podman-manifest-create.1.md.in
index cb8ad41fb..6ebf8a055 100644
--- a/docs/source/markdown/podman-manifest-create.1.md
+++ b/docs/source/markdown/podman-manifest-create.1.md.in
@@ -28,9 +28,7 @@ If a manifest list named *listnameorindexname* already exists, modify the
preexisting list instead of exiting with an error. The contents of
*listnameorindexname* are not modified if no *imagename*s are given.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when talking to container registries. (defaults to true)
+@@option tls-verify
## EXAMPLES
diff --git a/docs/source/markdown/podman-manifest-push.1.md.in b/docs/source/markdown/podman-manifest-push.1.md.in
index e3d578d10..fe0a534c9 100644
--- a/docs/source/markdown/podman-manifest-push.1.md.in
+++ b/docs/source/markdown/podman-manifest-push.1.md.in
@@ -59,9 +59,7 @@ Sign the pushed images with a sigstore signature using a private key at the spec
If signing the image (using either **--sign-by** or **--sign-by-sigstore-private-key**), read the passphrase to use from the specified path.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when talking to container registries. (defaults to true)
+@@option tls-verify
## DESTINATION
diff --git a/docs/source/markdown/podman-pod-create.1.md.in b/docs/source/markdown/podman-pod-create.1.md.in
index f1fdc3e6b..7a2a3c78d 100644
--- a/docs/source/markdown/podman-pod-create.1.md.in
+++ b/docs/source/markdown/podman-pod-create.1.md.in
@@ -99,14 +99,7 @@ The custom image that will be used for the infra container. Unless specified, P
@@option infra-name
-#### **--ip**=*ip*
-
-Specify a static IP address for the pod, for example **10.88.64.128**.
-This option can only be used if the pod is joined to only a single network - i.e., **--network=network-name** is used at most once -
-and if the pod is not joining another container's network namespace via **--network=container:_id_**.
-The address must be within the network's IP address pool (default **10.88.0.0/16**).
-
-To specify multiple static IP addresses per pod, set multiple networks using the **--network** option with a static IP address specified for each using the `ip` mode for that option.
+@@option ip
#### **--ip6**=*ipv6*
@@ -176,25 +169,7 @@ This option conflicts with **--add-host**.
Write the pod ID to the file.
-#### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]*
-
-Publish a container's port, or range of ports, within this pod to the host.
-
-Both *hostPort* and *containerPort* can be specified as a range of ports.
-When specifying ranges for both, the number of container ports in the
-range must match the number of host ports in the range.
-
-If host IP is set to 0.0.0.0 or not set at all, the port will be bound on all IPs on the host.
-
-By default, Podman will publish TCP ports. To publish a UDP port instead, give
-`udp` as protocol. To publish both TCP and UDP ports, set `--publish` twice,
-with `tcp`, and `udp` as protocols respectively. Rootful containers can also
-publish ports using the `sctp` protocol.
-
-Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`).
-If it is not, the container port will be randomly assigned a port on the host.
-
-Use **podman port** to see the actual mapping: `podman port $CONTAINER $CONTAINERPORT`.
+@@option publish
**Note:** You must not publish ports of containers in the pod individually,
but only by the pod itself.
diff --git a/docs/source/markdown/podman-pull.1.md.in b/docs/source/markdown/podman-pull.1.md.in
index 5405d7a45..46adec97b 100644
--- a/docs/source/markdown/podman-pull.1.md.in
+++ b/docs/source/markdown/podman-pull.1.md.in
@@ -63,10 +63,7 @@ All tagged images in the repository will be pulled.
Print the usage statement.
-#### **--os**=*OS*
-
-Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
-Unless overridden, subsequent lookups of the same image in the local storage will match this OS, regardless of the host.
+@@option os.pull
@@option platform
@@ -74,11 +71,7 @@ Unless overridden, subsequent lookups of the same image in the local storage wil
Suppress output information when pulling images
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
-then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
#### **--variant**=*VARIANT*
diff --git a/docs/source/markdown/podman-push.1.md.in b/docs/source/markdown/podman-push.1.md.in
index 6e6eecfa2..c679950f7 100644
--- a/docs/source/markdown/podman-push.1.md.in
+++ b/docs/source/markdown/podman-push.1.md.in
@@ -90,11 +90,7 @@ Add a sigstore signature at the destination using a private key at the specified
If signing the image (using either **--sign-by** or **--sign-by-sigstore-private-key**), read the passphrase to use from the specified path.
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
-then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
-TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
## EXAMPLE
diff --git a/docs/source/markdown/podman-run.1.md.in b/docs/source/markdown/podman-run.1.md.in
index 53f7cfe99..fe947b1d0 100644
--- a/docs/source/markdown/podman-run.1.md.in
+++ b/docs/source/markdown/podman-run.1.md.in
@@ -249,14 +249,7 @@ Print usage statement
When set to **true**, keep stdin open even if not attached. The default is **false**.
-#### **--ip**=*ipv4*
-
-Specify a static IPv4 address for the container, for example **10.88.64.128**.
-This option can only be used if the container is joined to only a single network - i.e., **--network=network-name** is used at most once -
-and if the container is not joining another container's network namespace via **--network=container:_id_**.
-The address must be within the network's IP address pool (default **10.88.0.0/16**).
-
-To specify multiple static IP addresses per container, set multiple networks using the **--network** option with a static IP address specified for each using the `ip` mode for that option.
+@@option ip
#### **--ip6**=*ipv6*
@@ -353,9 +346,7 @@ This option conflicts with **--add-host**.
@@option oom-score-adj
-#### **--os**=*OS*
-Override the OS, defaults to hosts, of the image to be pulled. For example, `windows`.
-Unless overridden, subsequent lookups of the same image in the local storage will match this OS, regardless of the host.
+@@option os.pull
#### **--passwd**
@@ -389,25 +380,7 @@ The total FDs will be 3+N. (This option is not available with the remote Podman
@@option privileged
-#### **--publish**, **-p**=*[[ip:][hostPort]:]containerPort[/protocol]*
-
-Publish a container's port, or range of ports, to the host.
-
-Both *hostPort* and *containerPort* can be specified as a range of ports.
-When specifying ranges for both, the number of container ports in the
-range must match the number of host ports in the range.
-
-If host IP is set to 0.0.0.0 or not set at all, the port will be bound on all IPs on the host.
-
-By default, Podman will publish TCP ports. To publish a UDP port instead, give
-`udp` as protocol. To publish both TCP and UDP ports, set `--publish` twice,
-with `tcp`, and `udp` as protocols respectively. Rootful containers can also
-publish ports using the `sctp` protocol.
-
-Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`).
-If it is not, the container port will be randomly assigned a port on the host.
-
-Use **podman port** to see the actual mapping: `podman port $CONTAINER $CONTAINERPORT`.
+@@option publish
**Note:** If a container will be run within a pod, it is not necessary to publish the port for
the containers in the pod. The port must only be published by the pod itself. Pod network
@@ -417,18 +390,7 @@ associated ports. If one container binds to a port, no other container can use t
within the pod while it is in use. Containers in the pod can also communicate over localhost
by having one container bind to localhost in the pod, and another connect to that port.
-#### **--publish-all**, **-P**
-
-Publish all exposed ports to random ports on the host interfaces. The default is **false**.
-
-When set to **true**, publish all exposed ports to the host interfaces. The
-default is **false**. If the operator uses **-P** (or **-p**) then Podman will make the
-exposed port accessible on the host and the ports will be available to any
-client that can reach the host.
-
-When using this option, Podman will bind any exposed port to a random port on the host
-within an ephemeral port range defined by */proc/sys/net/ipv4/ip_local_port_range*.
-To find the mapping between the host ports and the exposed ports, use **podman port**.
+@@option publish-all
@@option pull
@@ -519,9 +481,7 @@ Sets whether the signals sent to the **podman run** command are proxied to the c
@@option timeout
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true, then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
+@@option tls-verify
@@option tmpfs
diff --git a/docs/source/markdown/podman-search.1.md.in b/docs/source/markdown/podman-search.1.md.in
index 102cf7ad7..89df8c29f 100644
--- a/docs/source/markdown/podman-search.1.md.in
+++ b/docs/source/markdown/podman-search.1.md.in
@@ -87,12 +87,7 @@ The result contains the Image name and its tag, one line for every tag associate
Do not truncate the output (default *false*).
-#### **--tls-verify**
-
-Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
-then TLS verification will be used. If set to false, then TLS verification will not be used if needed. If not specified,
-default registries will be searched through (in /etc/containers/registries.conf), and TLS will be skipped if a default
-registry is listed in the insecure registries.
+@@option tls-verify
## EXAMPLES
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index a7ea3c5c5..994243805 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1286,6 +1286,12 @@ func (c *Container) stop(timeout uint) error {
c.lock.Unlock()
}
+ if c.config.HealthCheckConfig != nil {
+ if err := c.removeTransientFiles(context.Background()); err != nil {
+ logrus.Error(err.Error())
+ }
+ }
+
stopErr := c.ociRuntime.StopContainer(c, timeout, all)
if !c.batched {
diff --git a/libpod/events/events_freebsd.go b/libpod/events/events_freebsd.go
index 17d410089..90933fa2c 100644
--- a/libpod/events/events_freebsd.go
+++ b/libpod/events/events_freebsd.go
@@ -14,7 +14,7 @@ func NewEventer(options EventerOptions) (Eventer, error) {
case strings.ToUpper(LogFile.String()):
return EventLogFile{options}, nil
case strings.ToUpper(Null.String()):
- return NewNullEventer(), nil
+ return newNullEventer(), nil
case strings.ToUpper(Memory.String()):
return NewMemoryEventer(), nil
default:
diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go
index 3fb6dfb91..6948f976a 100644
--- a/libpod/healthcheck_linux.go
+++ b/libpod/healthcheck_linux.go
@@ -70,7 +70,7 @@ func (c *Container) startTimer() error {
startFile := fmt.Sprintf("%s.service", c.ID())
startChan := make(chan string)
- if _, err := conn.StartUnitContext(context.Background(), startFile, "fail", startChan); err != nil {
+ if _, err := conn.RestartUnitContext(context.Background(), startFile, "fail", startChan); err != nil {
return err
}
if err := systemdOpSuccessful(startChan); err != nil {
diff --git a/pkg/api/handlers/compat/system.go b/pkg/api/handlers/compat/system.go
index 97bc9eac2..23f116d16 100644
--- a/pkg/api/handlers/compat/system.go
+++ b/pkg/api/handlers/compat/system.go
@@ -76,7 +76,7 @@ func GetDiskUsage(w http.ResponseWriter, r *http.Request) {
Scope: "local",
Status: nil,
UsageData: &docker.VolumeUsageData{
- RefCount: 1,
+ RefCount: int64(o.Links),
Size: o.Size,
},
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 3389abd88..da903df9e 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -11,7 +11,6 @@ import (
"github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/config"
- cutil "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/entities/reports"
@@ -321,19 +320,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
return nil, err
}
- running, err := ic.Libpod.GetRunningContainers()
- if err != nil {
- return nil, err
- }
- runningContainers := make([]string, 0, len(running))
- for _, c := range running {
- runningContainers = append(runningContainers, c.ID())
- }
-
dfVolumes := make([]*entities.SystemDfVolumeReport, 0, len(vols))
for _, v := range vols {
var reclaimableSize uint64
- var consInUse int
mountPoint, err := v.MountPoint()
if err != nil {
return nil, err
@@ -355,14 +344,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
if len(inUse) == 0 {
reclaimableSize = volSize
}
- for _, viu := range inUse {
- if cutil.StringInSlice(viu, runningContainers) {
- consInUse++
- }
- }
report := entities.SystemDfVolumeReport{
VolumeName: v.Name(),
- Links: consInUse,
+ Links: len(inUse),
Size: int64(volSize),
ReclaimableSize: int64(reclaimableSize),
}
diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go
index 0ab928205..fac9f7ebe 100644
--- a/pkg/machine/e2e/inspect_test.go
+++ b/pkg/machine/e2e/inspect_test.go
@@ -75,5 +75,13 @@ var _ = Describe("podman machine stop", func() {
Expect(err).To(BeNil())
Expect(inspectSession).To(Exit(0))
Expect(inspectSession.Bytes()).To(ContainSubstring(name))
+
+ // check invalid template returns error
+ inspect = new(inspectMachine)
+ inspect = inspect.withFormat("{{.Abcde}}")
+ inspectSession, err = mb.setName(name).setCmd(inspect).run()
+ Expect(err).To(BeNil())
+ Expect(inspectSession).To(Exit(125))
+ Expect(inspectSession.errorToString()).To(ContainSubstring("can't evaluate field Abcde in type machine.InspectInfo"))
})
})
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index 0274dd7b7..8510cfd42 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -148,6 +148,18 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste
return nil, errors.New("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
}
+ // #15284: old units generated without --new can lead to issues on
+ // shutdown when the containers are created with a custom restart
+ // policy.
+ if !options.New {
+ switch config.RestartPolicy {
+ case libpodDefine.RestartPolicyNo, libpodDefine.RestartPolicyNone:
+ // All good
+ default:
+ logrus.Warnf("Container %s has restart policy %q which can lead to issues on shutdown: consider recreating the container without a restart policy and use systemd's restart mechanism instead", ctr.ID(), config.RestartPolicy)
+ }
+ }
+
createCommand := []string{}
if config.CreateCommand != nil {
createCommand = config.CreateCommand
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 0ff3b8b7b..729a038a5 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -257,14 +257,14 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) (
return &info, nil
}
-// Unless already specified, the pod's exit policy to "stop".
-func setPodExitPolicy(cmd []string) []string {
+// Determine whether the command array includes an exit-policy setting
+func hasPodExitPolicy(cmd []string) bool {
for _, arg := range cmd {
if strings.HasPrefix(arg, "--exit-policy=") || arg == "--exit-policy" {
- return cmd
+ return true
}
}
- return append(cmd, "--exit-policy=stop")
+ return false
}
// executePodTemplate executes the pod template on the specified podInfo. Note
@@ -365,8 +365,10 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
podCreateArgs = append(podCreateArgs, "--replace")
}
+ if !hasPodExitPolicy(append(startCommand, podCreateArgs...)) {
+ startCommand = append(startCommand, "--exit-policy=stop")
+ }
startCommand = append(startCommand, podCreateArgs...)
- startCommand = setPodExitPolicy(startCommand)
startCommand = escapeSystemdArguments(startCommand)
info.ExecStartPre1 = "/bin/rm -f {{{{.PIDFile}}}} {{{{.PodIDFile}}}}"
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index d50fa9f48..45a2b9eeb 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -7,25 +7,26 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestSetPodExitPolicy(t *testing.T) {
+func TestHasPodExitPolicy(t *testing.T) {
tests := []struct {
- input, expected []string
+ input []string
+ expected bool
}{
{
[]string{"podman", "pod", "create"},
- []string{"podman", "pod", "create", "--exit-policy=stop"},
+ false,
},
{
[]string{"podman", "pod", "create", "--exit-policy=continue"},
- []string{"podman", "pod", "create", "--exit-policy=continue"},
+ true,
},
{
[]string{"podman", "pod", "create", "--exit-policy", "continue"},
- []string{"podman", "pod", "create", "--exit-policy", "continue"},
+ true,
},
}
for _, test := range tests {
- assert.Equalf(t, test.expected, setPodExitPolicy(test.input), "%v", test.input)
+ assert.Equalf(t, test.expected, hasPodExitPolicy(test.input), "%v", test.input)
}
}
@@ -229,6 +230,33 @@ Type=forking
[Install]
WantedBy=default.target
`
+ podNoExplicitName := `# 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=
+Before=
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
+ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop foo
+ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
+ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
+ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
+PIDFile=%t/pod-123abc.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
podGoodRestartSec := `# pod-123abc.service
# autogenerated by Podman CI
@@ -274,7 +302,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
-ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace --exit-policy=stop
+ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo "bar=arg with space" --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
@@ -302,7 +330,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
-ExecStartPre=/usr/bin/podman --events-backend none --runroot /root pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace --exit-policy=stop
+ExecStartPre=/usr/bin/podman --events-backend none --runroot /root pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo "bar=arg with space" --replace
ExecStart=/usr/bin/podman --events-backend none --runroot /root pod start --pod-id-file %t/pod-123abc.pod-id
ExecStop=/usr/bin/podman --events-backend none --runroot /root pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
ExecStopPost=/usr/bin/podman --events-backend none --runroot /root pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
@@ -330,7 +358,7 @@ Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
-ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo --replace --exit-policy=stop
+ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --exit-policy=stop --name foo --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
@@ -483,6 +511,23 @@ WantedBy=default.target
false,
false,
},
+ {"pod without --name",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ CreateCommand: []string{"podman", "pod", "create", "foo"},
+ },
+ podNoExplicitName,
+ true,
+ false,
+ false,
+ },
{"pod restartSec",
podInfo{
Executable: "/usr/bin/podman",
diff --git a/test/apiv2/45-system.at b/test/apiv2/45-system.at
index 364b87c56..096df5516 100644
--- a/test/apiv2/45-system.at
+++ b/test/apiv2/45-system.at
@@ -25,6 +25,24 @@ t GET system/df 200 '.Volumes[0].Name=foo1'
t GET libpod/system/df 200 '.Volumes[0].VolumeName=foo1'
+# Verify that no containers reference the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=0'
+
+# Make a container using the volume
+podman pull $IMAGE &>/dev/null
+t POST containers/create Image=$IMAGE Volumes='{"/test":{}}' HostConfig='{"Binds":["foo1:/test"]}' 201 \
+ .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+
+# Verify that one container references the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=1'
+
+# Remove the container
+t DELETE containers/$cid?v=true 204
+
+# Verify that no containers reference the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=0'
+
# Create two more volumes to test pruneing
t POST libpod/volumes/create \
Name=foo2 \
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index fe5a5e297..347440faf 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -564,7 +564,7 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.OutputToString()).To(ContainSubstring("# pod-foo.service"))
Expect(session.OutputToString()).To(ContainSubstring("Wants=container-foo-1.service container-foo-2.service"))
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=pod-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("pod create --infra-conmon-pidfile %t/pod-foo.pid --pod-id-file %t/pod-foo.pod-id --name foo"))
+ Expect(session.OutputToString()).To(ContainSubstring("pod create --infra-conmon-pidfile %t/pod-foo.pid --pod-id-file %t/pod-foo.pod-id --exit-policy=stop --name foo"))
Expect(session.OutputToString()).To(ContainSubstring("ExecStartPre=/bin/rm -f %t/pod-foo.pid %t/pod-foo.pod-id"))
Expect(session.OutputToString()).To(ContainSubstring("pod stop --ignore --pod-id-file %t/pod-foo.pod-id -t 10"))
Expect(session.OutputToString()).To(ContainSubstring("pod rm --ignore -f --pod-id-file %t/pod-foo.pod-id"))
diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go
index dcfb13f4e..24ea50b26 100644
--- a/test/e2e/volume_ls_test.go
+++ b/test/e2e/volume_ls_test.go
@@ -75,7 +75,10 @@ var _ = Describe("Podman volume ls", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToStringArray()).To(HaveLen(1), session.OutputToString())
+ arr := session.OutputToStringArray()
+ Expect(arr).To(HaveLen(2))
+ Expect(arr[0]).To(ContainSubstring("NAME"))
+ Expect(arr[1]).To(ContainSubstring("myvol"))
})
It("podman ls volume with --filter flag", func() {
diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats
index 00ec1dd79..a1b24d293 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -106,8 +106,7 @@ Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
# healthcheck should now fail, with exit status 1 and 'unhealthy' output
run_podman 1 healthcheck run $ctr
- # FIXME: #15691 - `healthcheck run` may emit an error log that the timer already exists
- is "$output" ".*unhealthy.*" "output from 'podman healthcheck run'"
+ is "$output" "unhealthy" "output from 'podman healthcheck run'"
run_podman inspect $ctr --format "{{.State.Status}} {{.Config.HealthcheckOnFailureAction}}"
if [[ $policy == "restart" ]];then
@@ -118,8 +117,7 @@ Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
# Container is still running and health check still broken
is "$output" "running $policy" "container continued running"
run_podman 1 healthcheck run $ctr
- # FIXME: #15691 - `healthcheck run` may emit an error log that the timer already exists
- is "$output" ".*unhealthy.*" "output from 'podman healthcheck run'"
+ is "$output" "unhealthy" "output from 'podman healthcheck run'"
else
# kill and stop yield the container into a non-running state
is "$output" ".* $policy" "container was stopped/killed"
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 0e1dc356d..ddec3a492 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -81,6 +81,13 @@ function service_cleanup() {
skip "FIXME: 2022-09-01: requires conmon-2.1.4, ubuntu has 2.1.3"
fi
+ # Warn when a custom restart policy is used without --new (see #15284)
+ run_podman create --restart=always $IMAGE
+ cid="$output"
+ run_podman generate systemd $cid
+ is "$output" ".*Container $cid has restart policy .*always.* which can lead to issues on shutdown.*" "generate systemd emits warning"
+ run_podman rm -f $cid
+
cname=$(random_string)
# See #7407 for --pull=always.
run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE \
diff --git a/test/system/320-system-df.bats b/test/system/320-system-df.bats
index 217357b37..35e121c62 100644
--- a/test/system/320-system-df.bats
+++ b/test/system/320-system-df.bats
@@ -27,7 +27,7 @@ function teardown() {
run_podman system df --format '{{ .Type }}:{{ .Total }}:{{ .Active }}'
is "${lines[0]}" "Images:1:1" "system df : Images line"
is "${lines[1]}" "Containers:2:1" "system df : Containers line"
- is "${lines[2]}" "Local Volumes:2:1" "system df : Volumes line"
+ is "${lines[2]}" "Local Volumes:2:2" "system df : Volumes line"
# Try -v. (Grrr. No way to specify individual formats)
#
diff --git a/test/system/610-format.bats b/test/system/610-format.bats
new file mode 100644
index 000000000..096d0228b
--- /dev/null
+++ b/test/system/610-format.bats
@@ -0,0 +1,169 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# PR #15673: For all commands that accept --format '{{.GoTemplate}}',
+# invoke with --format '{{"\n"}}' and make sure they don't choke.
+#
+
+load helpers
+
+function teardown() {
+ # In case test fails: standard teardown does not wipe machines or secrets
+ run_podman '?' machine rm -f mymachine
+ run_podman '?' secret rm mysecret
+
+ basic_teardown
+}
+
+# Most commands can't just be run with --format; they need an argument or
+# option. This table defines what those are.
+#
+# FIXME: once you've finished fixing them all, remove the SKIPs (just
+# remove the entire lines, except for pod-inspect, just remove the SKIP
+# but leave "mypod")
+extra_args_table="
+history | $IMAGE
+image history | $IMAGE
+image inspect | $IMAGE
+container inspect | mycontainer
+machine inspect | mymachine
+
+volume inspect | -a
+secret inspect | mysecret
+network inspect | podman
+ps | -a
+
+image search | sdfsdf
+search | sdfsdf
+
+pod inspect | mypod
+
+container stats | --no-stream
+pod stats | --no-stream
+stats | --no-stream
+events | --stream=false --events-backend=file
+"
+
+# Main test loop. Recursively runs 'podman [subcommand] help', looks for:
+# > '[command]', which indicates, recurse; or
+# > '--format', in which case we
+# > check autocompletion, look for Go templates, in which case we
+# > run the command with --format '{{"\n"}}' and make sure it passes
+function check_subcommand() {
+ for cmd in $(_podman_commands "$@"); do
+ # Special case: 'podman machine' can't be run as root. No override.
+ if [[ "$cmd" = "machine" ]]; then
+ if ! is_rootless; then
+ unset extra_args["podman machine inspect"]
+ continue
+ fi
+ fi
+
+ # Human-readable podman command string, with multiple spaces collapsed
+ command_string="podman $* $cmd"
+ command_string=${command_string// / } # 'podman x' -> 'podman x'
+
+ # Run --help, decide if this is a subcommand with subcommands
+ run_podman "$@" $cmd --help
+ local full_help="$output"
+
+ # The line immediately after 'Usage:' gives us a 1-line synopsis
+ usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1)
+ assert "$usage" != "" "podman $cmd: no Usage message found"
+
+ # Strip off the leading command string; we no longer need it
+ usage=$(sed -e "s/^ $command_string \?//" <<<"$usage")
+
+ # If usage ends in '[command]', recurse into subcommands
+ if expr "$usage" : '\[command\]' >/dev/null; then
+ # (except for 'podman help', which is a special case)
+ if [[ $cmd != "help" ]]; then
+ check_subcommand "$@" $cmd
+ fi
+ continue
+ fi
+
+ # Not a subcommand-subcommand. Look for --format option
+ if [[ ! "$output" =~ "--format" ]]; then
+ continue
+ fi
+
+ # Have --format. Make sure it's a Go-template option, not like --push
+ run_podman __completeNoDesc "$@" "$cmd" --format '{{.'
+ if [[ ! "$output" =~ \{\{\.[A-Z] ]]; then
+ continue
+ fi
+
+ # Got one.
+ dprint "$command_string has --format"
+
+ # Whatever is needed to make a runnable command
+ local extra=${extra_args[$command_string]}
+ if [[ -n "$extra" ]]; then
+ # Cross off our list
+ unset extra_args["$command_string"]
+ fi
+
+ # This is what does the work. We run with '?' so we can offer
+ # better error messages than just "exited with error status".
+ run_podman '?' "$@" "$cmd" $extra --format '{{"\n"}}'
+
+ # Output must always be empty.
+ #
+ # - If you see "unterminated quoted string" here, there's a
+ # regression, and you need to fix --format (see PR #15673)
+ #
+ # - If you see any other error, it probably means that someone
+ # added a new podman subcommand that supports --format but
+ # needs some sort of option or argument to actually run.
+ # See 'extra_args_table' at the top of this script.
+ #
+ assert "$output" = "" "$command_string --format '{{\"\n\"}}'"
+
+ # *Now* check exit status. This should never, ever, ever trigger!
+ # If it does, it means the podman command failed without an err msg!
+ assert "$status" = "0" \
+ "$command_string --format '{{\"\n\"}}' failed with no output!"
+ done
+}
+
+# Test entry point
+@test "check Go template formatting" {
+ skip_if_remote
+ if is_ubuntu; then
+ skip 'ubuntu VMs do not have qemu (exec: "qemu-system-x86_64": executable file not found in $PATH)'
+ fi
+
+ # Convert the table at top to an associative array, keyed on subcommand
+ declare -A extra_args
+ while read subcommand extra; do
+ extra_args["podman $subcommand"]=$extra
+ done < <(parse_table "$extra_args_table")
+
+ # Setup: some commands need a container, pod, machine, or secret
+ run_podman run -d --name mycontainer $IMAGE top
+ run_podman pod create mypod
+ run_podman secret create mysecret /etc/hosts
+ if is_rootless; then
+ run_podman machine init --image-path=/dev/null mymachine
+ fi
+
+ # Run the test
+ check_subcommand
+
+ # Clean up
+ run_podman pod rm mypod
+ run_podman rmi $(pause_image)
+ run_podman rm -f -t0 mycontainer
+ run_podman secret rm mysecret
+ if is_rootless; then
+ run_podman machine rm -f mymachine
+ fi
+
+ # Make sure there are no leftover commands in our table - this would
+ # indicate a typo in the table, or a flaw in our logic such that
+ # we're not actually recursing.
+ local leftovers="${!extra_args[@]}"
+ assert "$leftovers" = "" "Did not find (or test) subcommands:"
+}
+
+# vim: filetype=sh
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index b0d4b526a..4bc1ba78c 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -177,6 +177,15 @@ function run_podman() {
# without "quotes", multiple lines are glommed together into one
if [ -n "$output" ]; then
echo "$output"
+
+ # FIXME FIXME FIXME: instrumenting to track down #15488. Please
+ # remove once that's fixed. We include the args because, remember,
+ # bats only shows output on error; it's possible that the first
+ # instance of the metacopy warning happens in a test that doesn't
+ # check output, hence doesn't fail.
+ if [[ "$output" =~ Ignoring.global.metacopy.option ]]; then
+ echo "# YO! metacopy warning triggered by: podman $*" >&3
+ fi
fi
if [ "$status" -ne 0 ]; then
echo -n "[ rc=$status ";