mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
Merge pull request #15673 from Luap99/template
Fix go template parsing with "\n" in it
This commit is contained in:
@ -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)
|
||||
}
|
||||
|
@ -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{}
|
||||
|
@ -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 {
|
||||
|
@ -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 := rpt.Execute(vms); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if err := tmpl.Execute(w, vms); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
w.Flush()
|
||||
default:
|
||||
if err := printJSON(vms); err != nil {
|
||||
logrus.Error(err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
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)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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"))
|
||||
})
|
||||
})
|
||||
|
@ -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() {
|
||||
|
169
test/system/610-format.bats
Normal file
169
test/system/610-format.bats
Normal file
@ -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
|
Reference in New Issue
Block a user