mirror of
https://github.com/containers/podman.git
synced 2025-06-24 11:28:24 +08:00
Merge pull request #12487 from jwhonce/issues/10974-2
Refactor podman system to report.Formatter
This commit is contained in:
@ -53,13 +53,6 @@ func list(cmd *cobra.Command, _ []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hdrs := []map[string]string{{
|
|
||||||
"Identity": "Identity",
|
|
||||||
"Name": "Name",
|
|
||||||
"URI": "URI",
|
|
||||||
"Default": "Default",
|
|
||||||
}}
|
|
||||||
|
|
||||||
rows := make([]namedDestination, 0)
|
rows := make([]namedDestination, 0)
|
||||||
for k, v := range cfg.Engine.ServiceDestinations {
|
for k, v := range cfg.Engine.ServiceDestinations {
|
||||||
def := false
|
def := false
|
||||||
@ -82,35 +75,37 @@ func list(cmd *cobra.Command, _ []string) error {
|
|||||||
return rows[i].Name < rows[j].Name
|
return rows[i].Name < rows[j].Name
|
||||||
})
|
})
|
||||||
|
|
||||||
var format string
|
rpt := report.New(os.Stdout, cmd.Name())
|
||||||
switch {
|
defer rpt.Flush()
|
||||||
case report.IsJSON(cmd.Flag("format").Value.String()):
|
|
||||||
|
if report.IsJSON(cmd.Flag("format").Value.String()) {
|
||||||
buf, err := registry.JSONLibrary().MarshalIndent(rows, "", " ")
|
buf, err := registry.JSONLibrary().MarshalIndent(rows, "", " ")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Println(string(buf))
|
fmt.Println(string(buf))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
case cmd.Flags().Changed("format"):
|
|
||||||
format = report.NormalizeFormat(cmd.Flag("format").Value.String())
|
|
||||||
default:
|
|
||||||
format = "{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.Default}}\n"
|
|
||||||
}
|
}
|
||||||
format = report.EnforceRange(format)
|
|
||||||
|
|
||||||
tmpl, err := report.NewTemplate("list").Parse(format)
|
if cmd.Flag("format").Changed {
|
||||||
|
rpt, err = rpt.Parse(report.OriginUser, cmd.Flag("format").Value.String())
|
||||||
|
} else {
|
||||||
|
rpt, err = rpt.Parse(report.OriginPodman,
|
||||||
|
"{{range .}}{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.Default}}\n{{end -}}")
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := report.NewWriterDefault(os.Stdout)
|
if rpt.RenderHeaders {
|
||||||
if err != nil {
|
err = rpt.Execute([]map[string]string{{
|
||||||
return err
|
"Default": "Default",
|
||||||
|
"Identity": "Identity",
|
||||||
|
"Name": "Name",
|
||||||
|
"URI": "URI",
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defer w.Flush()
|
return rpt.Execute(rows)
|
||||||
|
|
||||||
isTable := report.HasTable(cmd.Flag("format").Value.String())
|
|
||||||
if !cmd.Flag("format").Changed || isTable {
|
|
||||||
_ = tmpl.Execute(w, hdrs)
|
|
||||||
}
|
|
||||||
return tmpl.Execute(w, rows)
|
|
||||||
}
|
}
|
||||||
|
@ -54,23 +54,19 @@ func df(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := report.NewWriterDefault(os.Stdout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if dfOptions.Verbose {
|
if dfOptions.Verbose {
|
||||||
return printVerbose(w, cmd, reports)
|
return printVerbose(cmd, reports)
|
||||||
}
|
}
|
||||||
return printSummary(w, cmd, reports)
|
return printSummary(cmd, reports)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printSummary(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
|
func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error {
|
||||||
var (
|
var (
|
||||||
dfSummaries []*dfSummary
|
dfSummaries []*dfSummary
|
||||||
active int
|
active int
|
||||||
size, reclaimable int64
|
size, reclaimable int64
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, i := range reports.Images {
|
for _, i := range reports.Images {
|
||||||
if i.Containers > 0 {
|
if i.Containers > 0 {
|
||||||
active++
|
active++
|
||||||
@ -136,17 +132,28 @@ func printSummary(w *report.Writer, cmd *cobra.Command, reports *entities.System
|
|||||||
"Size": "SIZE",
|
"Size": "SIZE",
|
||||||
"Reclaimable": "RECLAIMABLE",
|
"Reclaimable": "RECLAIMABLE",
|
||||||
})
|
})
|
||||||
row := "{{.Type}}\t{{.Total}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}\n"
|
|
||||||
|
rpt := report.New(os.Stdout, cmd.Name())
|
||||||
|
defer rpt.Flush()
|
||||||
|
|
||||||
|
var err error
|
||||||
if cmd.Flags().Changed("format") {
|
if cmd.Flags().Changed("format") {
|
||||||
row = report.NormalizeFormat(dfOptions.Format)
|
rpt, err = rpt.Parse(report.OriginUser, dfOptions.Format)
|
||||||
|
} else {
|
||||||
|
row := "{{range . }}{{.Type}}\t{{.Total}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}\n{{end -}}"
|
||||||
|
rpt, err = rpt.Parse(report.OriginPodman, row)
|
||||||
}
|
}
|
||||||
return writeTemplate(w, cmd, hdrs, row, dfSummaries)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return writeTemplate(rpt, hdrs, dfSummaries)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
|
func printVerbose(cmd *cobra.Command, reports *entities.SystemDfReport) error { // nolint:interfacer
|
||||||
defer w.Flush()
|
rpt := report.New(os.Stdout, cmd.Name())
|
||||||
|
defer rpt.Flush()
|
||||||
|
|
||||||
fmt.Fprint(w, "Images space usage:\n\n")
|
fmt.Fprint(rpt.Writer(), "Images space usage:\n\n")
|
||||||
// convert to dfImage for output
|
// convert to dfImage for output
|
||||||
dfImages := make([]*dfImage, 0, len(reports.Images))
|
dfImages := make([]*dfImage, 0, len(reports.Images))
|
||||||
for _, d := range reports.Images {
|
for _, d := range reports.Images {
|
||||||
@ -157,12 +164,16 @@ func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.System
|
|||||||
"SharedSize": "SHARED SIZE",
|
"SharedSize": "SHARED SIZE",
|
||||||
"UniqueSize": "UNIQUE SIZE",
|
"UniqueSize": "UNIQUE SIZE",
|
||||||
})
|
})
|
||||||
imageRow := "{{.Repository}}\t{{.Tag}}\t{{.ImageID}}\t{{.Created}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}\n"
|
imageRow := "{{range .}}{{.Repository}}\t{{.Tag}}\t{{.ImageID}}\t{{.Created}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}\n{{end -}}"
|
||||||
if err := writeTemplate(w, cmd, hdrs, imageRow, dfImages); err != nil {
|
rpt, err := rpt.Parse(report.OriginPodman, imageRow)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeTemplate(rpt, hdrs, dfImages); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, "\nContainers space usage:\n\n")
|
fmt.Fprint(rpt.Writer(), "\nContainers space usage:\n\n")
|
||||||
// convert to dfContainers for output
|
// convert to dfContainers for output
|
||||||
dfContainers := make([]*dfContainer, 0, len(reports.Containers))
|
dfContainers := make([]*dfContainer, 0, len(reports.Containers))
|
||||||
for _, d := range reports.Containers {
|
for _, d := range reports.Containers {
|
||||||
@ -173,12 +184,16 @@ func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.System
|
|||||||
"LocalVolumes": "LOCAL VOLUMES",
|
"LocalVolumes": "LOCAL VOLUMES",
|
||||||
"RWSize": "SIZE",
|
"RWSize": "SIZE",
|
||||||
})
|
})
|
||||||
containerRow := "{{.ContainerID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.RWSize}}\t{{.Created}}\t{{.Status}}\t{{.Names}}\n"
|
containerRow := "{{range .}}{{.ContainerID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.RWSize}}\t{{.Created}}\t{{.Status}}\t{{.Names}}\n{{end -}}"
|
||||||
if err := writeTemplate(w, cmd, hdrs, containerRow, dfContainers); err != nil {
|
rpt, err = rpt.Parse(report.OriginPodman, containerRow)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writeTemplate(rpt, hdrs, dfContainers); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, "\nLocal Volumes space usage:\n\n")
|
fmt.Fprint(rpt.Writer(), "\nLocal Volumes space usage:\n\n")
|
||||||
dfVolumes := make([]*dfVolume, 0, len(reports.Volumes))
|
dfVolumes := make([]*dfVolume, 0, len(reports.Volumes))
|
||||||
// convert to dfVolume for output
|
// convert to dfVolume for output
|
||||||
for _, d := range reports.Volumes {
|
for _, d := range reports.Volumes {
|
||||||
@ -187,25 +202,21 @@ func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.System
|
|||||||
hdrs = report.Headers(entities.SystemDfVolumeReport{}, map[string]string{
|
hdrs = report.Headers(entities.SystemDfVolumeReport{}, map[string]string{
|
||||||
"VolumeName": "VOLUME NAME",
|
"VolumeName": "VOLUME NAME",
|
||||||
})
|
})
|
||||||
volumeRow := "{{.VolumeName}}\t{{.Links}}\t{{.Size}}\n"
|
volumeRow := "{{range .}}{{.VolumeName}}\t{{.Links}}\t{{.Size}}\n{{end -}}"
|
||||||
return writeTemplate(w, cmd, hdrs, volumeRow, dfVolumes)
|
rpt, err = rpt.Parse(report.OriginPodman, volumeRow)
|
||||||
}
|
|
||||||
|
|
||||||
func writeTemplate(w *report.Writer, cmd *cobra.Command, hdrs []map[string]string, format string, output interface{}) error {
|
|
||||||
defer w.Flush()
|
|
||||||
|
|
||||||
format = report.EnforceRange(format)
|
|
||||||
tmpl, err := report.NewTemplate("df").Parse(format)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return writeTemplate(rpt, hdrs, dfVolumes)
|
||||||
|
}
|
||||||
|
|
||||||
if !cmd.Flags().Changed("format") {
|
func writeTemplate(rpt *report.Formatter, hdrs []map[string]string, output interface{}) error {
|
||||||
if err := tmpl.Execute(w, hdrs); err != nil {
|
if rpt.RenderHeaders {
|
||||||
|
if err := rpt.Execute(hdrs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tmpl.Execute(w, output)
|
return rpt.Execute(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
type dfImage struct {
|
type dfImage struct {
|
||||||
|
@ -77,7 +77,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
|
|||||||
errChannel := make(chan error)
|
errChannel := make(chan error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tmpl *report.Template
|
rpt *report.Formatter
|
||||||
doJSON bool
|
doJSON bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
|
|||||||
doJSON = report.IsJSON(eventFormat)
|
doJSON = report.IsJSON(eventFormat)
|
||||||
if !doJSON {
|
if !doJSON {
|
||||||
var err error
|
var err error
|
||||||
tmpl, err = report.NewTemplate("events").Parse(eventFormat)
|
rpt, err = report.New(os.Stdout, cmd.Name()).Parse(report.OriginUser, eventFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -108,10 +108,10 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
|
|||||||
}
|
}
|
||||||
fmt.Println(jsonStr)
|
fmt.Println(jsonStr)
|
||||||
case cmd.Flags().Changed("format"):
|
case cmd.Flags().Changed("format"):
|
||||||
if err := tmpl.Execute(os.Stdout, event); err != nil {
|
if err := rpt.Execute(event); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("")
|
os.Stdout.WriteString("\n")
|
||||||
default:
|
default:
|
||||||
fmt.Println(event.ToHumanReadable(!noTrunc))
|
fmt.Println(event.ToHumanReadable(!noTrunc))
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package system
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/common/pkg/report"
|
"github.com/containers/common/pkg/report"
|
||||||
@ -84,7 +85,10 @@ func info(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
fmt.Println(string(b))
|
fmt.Println(string(b))
|
||||||
case cmd.Flags().Changed("format"):
|
case cmd.Flags().Changed("format"):
|
||||||
tmpl, err := report.NewTemplate("info").Parse(inFormat)
|
// 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)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,15 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/common/pkg/report"
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/podman/v3/cmd/podman/common"
|
"github.com/containers/podman/v3/cmd/podman/common"
|
||||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v3/cmd/podman/validate"
|
"github.com/containers/podman/v3/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v3/libpod/define"
|
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -53,54 +52,60 @@ func version(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := report.NewWriterDefault(os.Stdout)
|
if cmd.Flag("format").Changed {
|
||||||
if err != nil {
|
// Cannot use report.New() as it enforces {{range .}} for OriginUser templates
|
||||||
return err
|
tmpl := template.New(cmd.Name()).Funcs(template.FuncMap(report.DefaultFuncs))
|
||||||
}
|
|
||||||
defer w.Flush()
|
|
||||||
|
|
||||||
if cmd.Flags().Changed("format") {
|
versionFormat = report.NormalizeFormat(versionFormat)
|
||||||
row := report.NormalizeFormat(versionFormat)
|
tmpl, err := tmpl.Parse(versionFormat)
|
||||||
tmpl, err := report.NewTemplate("version 2.0.0").Parse(row)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(w, versions); err != nil {
|
if err := tmpl.Execute(os.Stdout, versions); err != nil {
|
||||||
// On Failure, assume user is using older version of podman version --format and check client
|
// On Failure, assume user is using older version of podman version --format and check client
|
||||||
row = strings.ReplaceAll(row, ".Server.", ".")
|
versionFormat = strings.ReplaceAll(versionFormat, ".Server.", ".")
|
||||||
tmpl, err := report.NewTemplate("version 1.0.0").Parse(row)
|
tmpl, err := tmpl.Parse(versionFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := tmpl.Execute(w, versions.Client); err != nil {
|
if err := tmpl.Execute(os.Stdout, versions.Client); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if versions.Server != nil {
|
rpt := report.New(os.Stdout, cmd.Name())
|
||||||
if _, err := fmt.Fprintf(w, "Client:\n"); err != nil {
|
defer rpt.Flush()
|
||||||
return err
|
rpt, err = rpt.Parse(report.OriginPodman, versionTemplate)
|
||||||
}
|
if err != nil {
|
||||||
formatVersion(w, versions.Client)
|
return err
|
||||||
if _, err := fmt.Fprintf(w, "\nServer:\n"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
formatVersion(w, versions.Server)
|
|
||||||
} else {
|
|
||||||
formatVersion(w, versions.Client)
|
|
||||||
}
|
}
|
||||||
return nil
|
return rpt.Execute(versions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatVersion(w io.Writer, version *define.Version) {
|
const versionTemplate = `{{with .Client -}}
|
||||||
fmt.Fprintf(w, "Version:\t%s\n", version.Version)
|
Client:\tPodman Engine
|
||||||
fmt.Fprintf(w, "API Version:\t%s\n", version.APIVersion)
|
Version:\t{{.Version}}
|
||||||
fmt.Fprintf(w, "Go Version:\t%s\n", version.GoVersion)
|
API Version:\t{{.APIVersion}}
|
||||||
if version.GitCommit != "" {
|
Go Version:\t{{.GoVersion}}
|
||||||
fmt.Fprintf(w, "Git Commit:\t%s\n", version.GitCommit)
|
{{if .GitCommit -}}
|
||||||
}
|
Git Commit:\t{{.GitCommit}}
|
||||||
fmt.Fprintf(w, "Built:\t%s\n", version.BuiltTime)
|
{{- end}}
|
||||||
fmt.Fprintf(w, "OS/Arch:\t%s\n", version.OsArch)
|
Built:\t{{.BuiltTime}}
|
||||||
}
|
OS/Arch:\t{{.OsArch}}
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
|
{{- if .Server }}{{with .Server}}
|
||||||
|
|
||||||
|
Server:\tPodman Engine
|
||||||
|
Version:\t{{.Version}}
|
||||||
|
API Version:\t{{.APIVersion}}
|
||||||
|
Go Version:\t{{.GoVersion}}
|
||||||
|
{{if .GitCommit -}}
|
||||||
|
Git Commit:\t{{.GitCommit}}
|
||||||
|
{{- end}}
|
||||||
|
Built:\t{{.BuiltTime}}
|
||||||
|
OS/Arch:\t{{.OsArch}}
|
||||||
|
{{- end}}{{- end}}
|
||||||
|
`
|
||||||
|
@ -15,12 +15,10 @@ function setup() {
|
|||||||
@test "podman version emits reasonable output" {
|
@test "podman version emits reasonable output" {
|
||||||
run_podman version
|
run_podman version
|
||||||
|
|
||||||
# First line of podman-remote is "Client:<blank>".
|
# First line of podman version is "Client: *Podman Engine".
|
||||||
# Just delete it (i.e. remove the first entry from the 'lines' array)
|
# Just delete it (i.e. remove the first entry from the 'lines' array)
|
||||||
if is_remote; then
|
if expr "${lines[0]}" : "Client: *" >/dev/null; then
|
||||||
if expr "${lines[0]}" : "Client:" >/dev/null; then
|
lines=("${lines[@]:1}")
|
||||||
lines=("${lines[@]:1}")
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
is "${lines[0]}" "Version:[ ]\+[1-9][0-9.]\+" "Version line 1"
|
is "${lines[0]}" "Version:[ ]\+[1-9][0-9.]\+" "Version line 1"
|
||||||
|
Reference in New Issue
Block a user