From bd9987239dae148bfd3eea8540d21ae7715faff7 Mon Sep 17 00:00:00 2001
From: Jhon Honce <jhonce@redhat.com>
Date: Tue, 15 Jun 2021 10:08:34 -0700
Subject: Scrub podman commands to use report package

Refactor podman commands that have drifted from using
c/common report pkg. Report pkg is needed to implement
go template functions.

Removed obsolete code from podman which exists in c/common.

Latest template library added default newlines and method to
remove them. Incorporated needed changes in c/common PR below.

Depends on https://github.com/containers/common/pull/624
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1855983

Signed-off-by: Jhon Honce <jhonce@redhat.com>
---
 cmd/podman/containers/mount.go       | 12 +++++++-----
 cmd/podman/containers/ps.go          | 17 ++++++++---------
 cmd/podman/containers/stats.go       | 13 +++++++------
 cmd/podman/containers/top.go         | 10 +++++++---
 cmd/podman/images/history.go         | 13 +++++++------
 cmd/podman/images/list.go            | 22 +++++++++++-----------
 cmd/podman/images/mount.go           | 13 ++++++++-----
 cmd/podman/images/search.go          | 15 ++++++++-------
 cmd/podman/images/trust_show.go      | 23 +++++++++++++----------
 cmd/podman/inspect/inspect.go        |  9 ++++++---
 cmd/podman/machine/list.go           | 15 ++++++++-------
 cmd/podman/networks/list.go          | 10 ++++++----
 cmd/podman/parse/template.go         | 22 ----------------------
 cmd/podman/parse/template_test.go    | 30 ------------------------------
 cmd/podman/pods/inspect.go           |  9 +++++----
 cmd/podman/pods/ps.go                | 15 ++++++++-------
 cmd/podman/pods/stats.go             | 23 ++++++++++++++---------
 cmd/podman/pods/top.go               |  8 ++++++--
 cmd/podman/secrets/inspect.go        | 13 +++++++------
 cmd/podman/secrets/list.go           | 15 ++++++++-------
 cmd/podman/system/connection/list.go | 12 +++++++-----
 cmd/podman/system/df.go              | 18 +++++++++---------
 cmd/podman/system/events.go          |  5 ++---
 cmd/podman/system/info.go            |  3 +--
 cmd/podman/system/version.go         | 11 ++++++-----
 cmd/podman/volumes/list.go           | 13 +++++++------
 26 files changed, 176 insertions(+), 193 deletions(-)
 delete mode 100644 cmd/podman/parse/template.go
 delete mode 100644 cmd/podman/parse/template_test.go

(limited to 'cmd')

diff --git a/cmd/podman/containers/mount.go b/cmd/podman/containers/mount.go
index 8a7c542ba..55f6a1c34 100644
--- a/cmd/podman/containers/mount.go
+++ b/cmd/podman/containers/mount.go
@@ -3,8 +3,6 @@ package containers
 import (
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
@@ -117,12 +115,16 @@ func mount(_ *cobra.Command, args []string) error {
 		mrs = append(mrs, mountReporter{r})
 	}
 
-	format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}"
-	tmpl, err := template.New("mounts").Parse(format)
+	format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}"
+	tmpl, err := report.NewTemplate("mounts").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 	return tmpl.Execute(w, mrs)
 }
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index 352f67f4e..a5b0795cd 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -6,15 +6,12 @@ import (
 	"sort"
 	"strconv"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 	"time"
 
 	tm "github.com/buger/goterm"
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/utils"
 	"github.com/containers/podman/v3/cmd/podman/validate"
@@ -226,18 +223,20 @@ func ps(cmd *cobra.Command, _ []string) error {
 	hdrs, format := createPsOut()
 	if cmd.Flags().Changed("format") {
 		format = report.NormalizeFormat(listOpts.Format)
-		format = parse.EnforceRange(format)
+		format = report.EnforceRange(format)
 	}
 	ns := strings.NewReplacer(".Namespaces.", ".")
 	format = ns.Replace(format)
 
-	tmpl, err := template.New("listContainers").
-		Funcs(template.FuncMap(report.DefaultFuncs)).
-		Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	headers := func() error { return nil }
@@ -320,7 +319,7 @@ func createPsOut() ([]map[string]string, string) {
 			row += "\t{{.Size}}"
 		}
 	}
-	return hdrs, "{{range .}}" + row + "\n{{end}}"
+	return hdrs, "{{range .}}" + row + "\n{{end -}}"
 }
 
 type psReporter struct {
diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go
index 568e410d2..27c5147a5 100644
--- a/cmd/podman/containers/stats.go
+++ b/cmd/podman/containers/stats.go
@@ -3,13 +3,10 @@ package containers
 import (
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	tm "github.com/buger/goterm"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/libpod/define"
@@ -170,13 +167,17 @@ func outputStats(reports []define.ContainerStats) error {
 	if len(statsOptions.Format) > 0 {
 		format = report.NormalizeFormat(statsOptions.Format)
 	}
-	format = parse.EnforceRange(format)
+	format = report.EnforceRange(format)
 
-	tmpl, err := template.New("stats").Parse(format)
+	tmpl, err := report.NewTemplate("stats").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	if len(statsOptions.Format) < 1 {
diff --git a/cmd/podman/containers/top.go b/cmd/podman/containers/top.go
index 3fde2e954..808c6c494 100644
--- a/cmd/podman/containers/top.go
+++ b/cmd/podman/containers/top.go
@@ -5,8 +5,8 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
 
+	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
@@ -77,7 +77,7 @@ func init() {
 	validate.AddLatestFlag(containerTopCommand, &topOptions.Latest)
 }
 
-func top(cmd *cobra.Command, args []string) error {
+func top(_ *cobra.Command, args []string) error {
 	if topOptions.ListDescriptors {
 		descriptors, err := util.GetContainerPidInformationDescriptors()
 		if err != nil {
@@ -103,7 +103,11 @@ func top(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
+
 	for _, proc := range topResponse.Value {
 		if _, err := fmt.Fprintln(w, proc); err != nil {
 			return err
diff --git a/cmd/podman/images/history.go b/cmd/podman/images/history.go
index 69268c261..c065acfad 100644
--- a/cmd/podman/images/history.go
+++ b/cmd/podman/images/history.go
@@ -5,14 +5,11 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 	"time"
 	"unicode"
 
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/domain/entities"
 	"github.com/docker/go-units"
@@ -125,13 +122,17 @@ func history(cmd *cobra.Command, args []string) error {
 	case opts.quiet:
 		row = "{{.ID}}\n"
 	}
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("report").Parse(format)
+	tmpl, err := report.NewTemplate("history").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	if !opts.quiet && !cmd.Flags().Changed("format") {
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go
index cc38a45c7..01286daf2 100644
--- a/cmd/podman/images/list.go
+++ b/cmd/podman/images/list.go
@@ -5,8 +5,6 @@ import (
 	"os"
 	"sort"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 	"time"
 	"unicode"
 
@@ -14,7 +12,6 @@ import (
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/image/v5/docker/reference"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/domain/entities"
 	"github.com/docker/go-units"
@@ -140,7 +137,7 @@ func images(cmd *cobra.Command, args []string) error {
 	case listFlag.quiet:
 		return writeID(imgs)
 	default:
-		if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
+		if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) {
 			listFlag.noHeading = true
 		}
 		return writeTemplate(imgs)
@@ -195,20 +192,23 @@ func writeTemplate(imgs []imageReporter) error {
 		"ReadOnly": "R/O",
 	})
 
-	var row string
+	var format string
 	if listFlag.format == "" {
-		row = lsFormatFromFlags(listFlag)
+		format = lsFormatFromFlags(listFlag)
 	} else {
-		row = report.NormalizeFormat(listFlag.format)
+		format = report.NormalizeFormat(listFlag.format)
+		format = report.EnforceRange(format)
 	}
-	format := parse.EnforceRange(row)
 
-	tmpl, err := template.New("list").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
 	if err != nil {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 	defer w.Flush()
 
 	if !listFlag.noHeading {
@@ -337,7 +337,7 @@ func lsFormatFromFlags(flags listFlagType) string {
 		row = append(row, "{{.ReadOnly}}")
 	}
 
-	return strings.Join(row, "\t") + "\n"
+	return "{{range . }}" + strings.Join(row, "\t") + "\n{{end -}}"
 }
 
 type imageReporter struct {
diff --git a/cmd/podman/images/mount.go b/cmd/podman/images/mount.go
index efcff8264..89c00cb70 100644
--- a/cmd/podman/images/mount.go
+++ b/cmd/podman/images/mount.go
@@ -3,8 +3,6 @@ package images
 import (
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
@@ -99,13 +97,18 @@ func mount(cmd *cobra.Command, args []string) error {
 		mrs = append(mrs, mountReporter{r})
 	}
 
-	row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}"
-	tmpl, err := template.New("mounts").Parse(row)
+	row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}"
+	tmpl, err := report.NewTemplate("mounts").Parse(row)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
+
 	return tmpl.Execute(w, mrs)
 }
 
diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go
index 08bf3cf6b..11e54578a 100644
--- a/cmd/podman/images/search.go
+++ b/cmd/podman/images/search.go
@@ -3,14 +3,11 @@ package images
 import (
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/auth"
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/image/v5/types"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/domain/entities"
 	"github.com/pkg/errors"
@@ -156,18 +153,22 @@ func imageSearch(cmd *cobra.Command, args []string) error {
 	case report.IsJSON(searchOptions.Format):
 		return printArbitraryJSON(searchReport)
 	case cmd.Flags().Changed("format"):
-		renderHeaders = parse.HasTable(searchOptions.Format)
+		renderHeaders = report.HasTable(searchOptions.Format)
 		row = report.NormalizeFormat(searchOptions.Format)
 	default:
 		row = "{{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\n"
 	}
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("search").Parse(format)
+	tmpl, err := report.NewTemplate("search").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	if renderHeaders {
diff --git a/cmd/podman/images/trust_show.go b/cmd/podman/images/trust_show.go
index 5d9376068..c0e56f504 100644
--- a/cmd/podman/images/trust_show.go
+++ b/cmd/podman/images/trust_show.go
@@ -3,9 +3,8 @@ package images
 import (
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
+	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/domain/entities"
@@ -45,16 +44,16 @@ func init() {
 }
 
 func showTrust(cmd *cobra.Command, args []string) error {
-	report, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions)
+	trust, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions)
 	if err != nil {
 		return err
 	}
 	if showTrustOptions.Raw {
-		fmt.Println(string(report.Raw))
+		fmt.Println(string(trust.Raw))
 		return nil
 	}
 	if showTrustOptions.JSON {
-		b, err := json.MarshalIndent(report.Policies, "", "  ")
+		b, err := json.MarshalIndent(trust.Policies, "", "  ")
 		if err != nil {
 			return err
 		}
@@ -62,14 +61,18 @@ func showTrust(cmd *cobra.Command, args []string) error {
 		return nil
 	}
 
-	row := "{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n"
-	format := "{{range . }}" + row + "{{end}}"
-	tmpl, err := template.New("listContainers").Parse(format)
+	format := "{{range . }}{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}"
+	tmpl, err := report.NewTemplate("list").Parse(format)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
-	if err := tmpl.Execute(w, report.Policies); err != nil {
+
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
+
+	if err := tmpl.Execute(w, trust.Policies); err != nil {
 		return err
 	}
 	if err := w.Flush(); err != nil {
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index 351684af1..bd3060882 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -7,7 +7,6 @@ import (
 	"os"
 	"regexp"
 	"strings"
-	"text/tabwriter"
 	"text/template"
 
 	"github.com/containers/common/pkg/completion"
@@ -217,7 +216,7 @@ func (i *inspector) inspect(namesOrIDs []string) error {
 		err = printJSON(data)
 	default:
 		row := inspectNormalize(i.options.Format)
-		row = "{{range . }}" + report.NormalizeFormat(row) + "{{end}}"
+		row = "{{range . }}" + report.NormalizeFormat(row) + "{{end -}}"
 		err = printTmpl(tmpType, row, data)
 	}
 	if err != nil {
@@ -250,7 +249,11 @@ func printTmpl(typ, row string, data []interface{}) error {
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 	return t.Execute(w, data)
 }
 
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index 77b47161a..134a081ab 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -5,14 +5,11 @@ package machine
 import (
 	"os"
 	"sort"
-	"text/tabwriter"
-	"text/template"
 	"time"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/config"
 	"github.com/containers/common/pkg/report"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/machine"
@@ -93,16 +90,20 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
 	})
 
 	row := report.NormalizeFormat(listFlag.format)
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("list machines").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
 	defer w.Flush()
 
-	if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
+	if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) {
 		listFlag.noHeading = true
 	}
 
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 46872d078..0ac637ea5 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -4,8 +4,6 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
@@ -133,11 +131,15 @@ func templateOut(responses []*entities.NetworkListReport, cmd *cobra.Command) er
 	}
 	format = report.EnforceRange(row)
 
-	tmpl, err := template.New("listNetworks").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	noHeading, _ := cmd.Flags().GetBool("noheading")
diff --git a/cmd/podman/parse/template.go b/cmd/podman/parse/template.go
deleted file mode 100644
index 0b80f1b3a..000000000
--- a/cmd/podman/parse/template.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package parse
-
-import (
-	"regexp"
-	"strings"
-)
-
-var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*}}`)
-
-// TODO move to github.com/containers/common/pkg/report
-// EnforceRange ensures that the format string contains a range
-func EnforceRange(format string) string {
-	if !rangeRegex.MatchString(format) {
-		return "{{range .}}" + format + "{{end}}"
-	}
-	return format
-}
-
-// EnforceRange ensures that the format string contains a range
-func HasTable(format string) bool {
-	return strings.HasPrefix(format, "table ")
-}
diff --git a/cmd/podman/parse/template_test.go b/cmd/podman/parse/template_test.go
deleted file mode 100644
index 7880d9bec..000000000
--- a/cmd/podman/parse/template_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package parse
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestEnforceRange(t *testing.T) {
-	tests := []struct {
-		input    string
-		expected string
-	}{
-		{"{{range .}}{{.ID}}{{end}}", "{{range .}}{{.ID}}{{end}}"},
-		{"{{.ID}}", "{{range .}}{{.ID}}{{end}}"},
-		{"{{ range . }}{{ .ID }}{{ end }}", "{{ range . }}{{ .ID }}{{ end }}"},
-		// EnforceRange does not verify syntax or semantics, that will happen later
-		{"{{range .}}{{.ID}}", "{{range .}}{{range .}}{{.ID}}{{end}}"},
-		{".ID", "{{range .}}.ID{{end}}"},
-	}
-
-	for _, tc := range tests {
-		tc := tc
-		label := "TestEnforceRange_" + tc.input
-		t.Run(label, func(t *testing.T) {
-			t.Parallel()
-			assert.Equal(t, tc.expected, EnforceRange(tc.input))
-		})
-	}
-}
diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go
index d38f0062c..4bb88f48a 100644
--- a/cmd/podman/pods/inspect.go
+++ b/cmd/podman/pods/inspect.go
@@ -3,8 +3,6 @@ package pods
 import (
 	"context"
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
@@ -73,11 +71,14 @@ func inspect(cmd *cobra.Command, args []string) error {
 
 	row := report.NormalizeFormat(inspectOptions.Format)
 
-	t, err := template.New("pod inspect").Parse(row)
+	t, err := report.NewTemplate("inspect").Parse(row)
 	if err != nil {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 	return t.Execute(w, *responses)
 }
diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 0271930e8..3e5ab86f4 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -6,14 +6,11 @@ import (
 	"os"
 	"sort"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 	"time"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/domain/entities"
@@ -131,20 +128,24 @@ func pods(cmd *cobra.Command, _ []string) error {
 	renderHeaders := true
 	row := podPsFormat()
 	if cmd.Flags().Changed("format") {
-		renderHeaders = parse.HasTable(psInput.Format)
+		renderHeaders = report.HasTable(psInput.Format)
 		row = report.NormalizeFormat(psInput.Format)
 	}
 	noHeading, _ := cmd.Flags().GetBool("noheading")
 	if noHeading {
 		renderHeaders = false
 	}
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("listPods").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	if renderHeaders {
diff --git a/cmd/podman/pods/stats.go b/cmd/podman/pods/stats.go
index 057b3dead..ba2c1495b 100644
--- a/cmd/podman/pods/stats.go
+++ b/cmd/podman/pods/stats.go
@@ -4,14 +4,11 @@ import (
 	"context"
 	"fmt"
 	"os"
-	"text/tabwriter"
-	"text/template"
 	"time"
 
 	"github.com/buger/goterm"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/domain/entities"
@@ -123,8 +120,12 @@ func printJSONPodStats(stats []*entities.PodStatsReport) error {
 	return nil
 }
 
-func printPodStatsLines(stats []*entities.PodStatsReport) {
-	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
+func printPodStatsLines(stats []*entities.PodStatsReport) error {
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
+
 	outFormat := "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
 	fmt.Fprintf(w, outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
 	if len(stats) == 0 {
@@ -134,7 +135,7 @@ func printPodStatsLines(stats []*entities.PodStatsReport) {
 			fmt.Fprintf(w, outFormat, i.Pod, i.CID, i.Name, i.CPU, i.MemUsage, i.Mem, i.NetIO, i.BlockIO, i.PIDS)
 		}
 	}
-	w.Flush()
+	return w.Flush()
 }
 
 func printFormattedPodStatsLines(headerNames []map[string]string, row string, stats []*entities.PodStatsReport) error {
@@ -142,13 +143,17 @@ func printFormattedPodStatsLines(headerNames []map[string]string, row string, st
 		return nil
 	}
 
-	row = parse.EnforceRange(row)
+	row = report.EnforceRange(row)
+
+	tmpl, err := report.NewTemplate("stats").Parse(row)
+	if err != nil {
+		return err
+	}
 
-	tmpl, err := template.New("pod stats").Parse(row)
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
 	defer w.Flush()
 
 	if err := tmpl.Execute(w, headerNames); err != nil {
diff --git a/cmd/podman/pods/top.go b/cmd/podman/pods/top.go
index e26e281c8..a6e442b96 100644
--- a/cmd/podman/pods/top.go
+++ b/cmd/podman/pods/top.go
@@ -5,8 +5,8 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
 
+	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
@@ -82,7 +82,11 @@ func top(_ *cobra.Command, args []string) error {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
+
 	for _, proc := range topResponse.Value {
 		if _, err := fmt.Fprintln(w, proc); err != nil {
 			return err
diff --git a/cmd/podman/secrets/inspect.go b/cmd/podman/secrets/inspect.go
index 874456f29..d0a5328d8 100644
--- a/cmd/podman/secrets/inspect.go
+++ b/cmd/podman/secrets/inspect.go
@@ -4,13 +4,10 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"html/template"
 	"os"
-	"text/tabwriter"
 
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/domain/entities"
 	"github.com/pkg/errors"
@@ -52,13 +49,17 @@ func inspect(cmd *cobra.Command, args []string) error {
 
 	if cmd.Flags().Changed("format") {
 		row := report.NormalizeFormat(format)
-		formatted := parse.EnforceRange(row)
+		formatted := report.EnforceRange(row)
 
-		tmpl, err := template.New("inspect secret").Parse(formatted)
+		tmpl, err := report.NewTemplate("inspect").Parse(formatted)
+		if err != nil {
+			return err
+		}
+
+		w, err := report.NewWriterDefault(os.Stdout)
 		if err != nil {
 			return err
 		}
-		w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
 		defer w.Flush()
 		tmpl.Execute(w, inspected)
 	} else {
diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go
index 448a69994..e64990c6f 100644
--- a/cmd/podman/secrets/list.go
+++ b/cmd/podman/secrets/list.go
@@ -2,15 +2,12 @@ package secrets
 
 import (
 	"context"
-	"html/template"
 	"os"
-	"text/tabwriter"
 	"time"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/domain/entities"
@@ -75,16 +72,20 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.SecretListReport)
 	})
 
 	row := report.NormalizeFormat(listFlag.format)
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("list secret").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
 	defer w.Flush()
 
-	if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
+	if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) {
 		listFlag.noHeading = true
 	}
 
diff --git a/cmd/podman/system/connection/list.go b/cmd/podman/system/connection/list.go
index ae88b0b30..b0b15b57d 100644
--- a/cmd/podman/system/connection/list.go
+++ b/cmd/podman/system/connection/list.go
@@ -2,11 +2,10 @@ package connection
 
 import (
 	"os"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/config"
+	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/system"
 	"github.com/containers/podman/v3/cmd/podman/validate"
@@ -73,13 +72,16 @@ func list(_ *cobra.Command, _ []string) error {
 	}
 
 	// TODO: Allow user to override format
-	format := "{{range . }}{{.Name}}\t{{.Identity}}\t{{.URI}}\n{{end}}"
-	tmpl, err := template.New("connection").Parse(format)
+	format := "{{range . }}{{.Name}}\t{{.Identity}}\t{{.URI}}\n{{end -}}"
+	tmpl, err := report.NewTemplate("list").Parse(format)
 	if err != nil {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 	defer w.Flush()
 
 	_ = tmpl.Execute(w, hdrs)
diff --git a/cmd/podman/system/df.go b/cmd/podman/system/df.go
index de56c57d0..dfde3bc07 100644
--- a/cmd/podman/system/df.go
+++ b/cmd/podman/system/df.go
@@ -4,13 +4,10 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 	"time"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/domain/entities"
@@ -57,7 +54,10 @@ func df(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 
 	if dfOptions.Verbose {
 		return printVerbose(w, cmd, reports)
@@ -65,7 +65,7 @@ func df(cmd *cobra.Command, args []string) error {
 	return printSummary(w, cmd, reports)
 }
 
-func printSummary(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
+func printSummary(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
 	var (
 		dfSummaries       []*dfSummary
 		active            int
@@ -143,7 +143,7 @@ func printSummary(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.Sys
 	return writeTemplate(w, cmd, hdrs, row, dfSummaries)
 }
 
-func printVerbose(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
+func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error {
 	defer w.Flush()
 
 	fmt.Fprint(w, "Images space usage:\n\n")
@@ -191,11 +191,11 @@ func printVerbose(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.Sys
 	return writeTemplate(w, cmd, hdrs, volumeRow, dfVolumes)
 }
 
-func writeTemplate(w *tabwriter.Writer, cmd *cobra.Command, hdrs []map[string]string, format string, output interface{}) error {
+func writeTemplate(w *report.Writer, cmd *cobra.Command, hdrs []map[string]string, format string, output interface{}) error {
 	defer w.Flush()
 
-	format = parse.EnforceRange(format)
-	tmpl, err := template.New("df").Parse(format)
+	format = report.EnforceRange(format)
+	tmpl, err := report.NewTemplate("df").Parse(format)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/podman/system/events.go b/cmd/podman/system/events.go
index 4aa413ec6..677504cfc 100644
--- a/cmd/podman/system/events.go
+++ b/cmd/podman/system/events.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"fmt"
 	"os"
-	"text/template"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
@@ -75,7 +74,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
 	errChannel := make(chan error)
 
 	var (
-		tmpl   *template.Template
+		tmpl   *report.Template
 		doJSON bool
 	)
 
@@ -83,7 +82,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
 		doJSON = report.IsJSON(eventFormat)
 		if !doJSON {
 			var err error
-			tmpl, err = template.New("events").Parse(eventFormat)
+			tmpl, err = report.NewTemplate("events").Parse(eventFormat)
 			if err != nil {
 				return err
 			}
diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go
index 1dc90f79a..c3f543e6a 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"
@@ -85,7 +84,7 @@ func info(cmd *cobra.Command, args []string) error {
 		}
 		fmt.Println(string(b))
 	case cmd.Flags().Changed("format"):
-		tmpl, err := template.New("info").Parse(inFormat)
+		tmpl, err := report.NewTemplate("info").Parse(inFormat)
 		if err != nil {
 			return err
 		}
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index 5575fc87d..4502b156c 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -5,8 +5,6 @@ import (
 	"io"
 	"os"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
@@ -55,19 +53,22 @@ func version(cmd *cobra.Command, args []string) error {
 		return nil
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
+	w, err := report.NewWriterDefault(os.Stdout)
+	if err != nil {
+		return err
+	}
 	defer w.Flush()
 
 	if cmd.Flag("format").Changed {
 		row := report.NormalizeFormat(versionFormat)
-		tmpl, err := template.New("version 2.0.0").Parse(row)
+		tmpl, err := report.NewTemplate("version 2.0.0").Parse(row)
 		if err != nil {
 			return err
 		}
 		if err := tmpl.Execute(w, versions); err != nil {
 			// On Failure, assume user is using older version of podman version --format and check client
 			row = strings.Replace(row, ".Server.", ".", 1)
-			tmpl, err := template.New("version 1.0.0").Parse(row)
+			tmpl, err := report.NewTemplate("version 1.0.0").Parse(row)
 			if err != nil {
 				return err
 			}
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index 990b39435..0243054af 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -5,13 +5,10 @@ import (
 	"fmt"
 	"os"
 	"strings"
-	"text/tabwriter"
-	"text/template"
 
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/common/pkg/report"
 	"github.com/containers/podman/v3/cmd/podman/common"
-	"github.com/containers/podman/v3/cmd/podman/parse"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/libpod/define"
@@ -104,13 +101,17 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.VolumeListReport)
 	if cliOpts.Quiet {
 		row = "{{.Name}}\n"
 	}
-	format := parse.EnforceRange(row)
+	format := report.EnforceRange(row)
 
-	tmpl, err := template.New("list volume").Parse(format)
+	tmpl, err := report.NewTemplate("list").Parse(format)
+	if err != nil {
+		return err
+	}
+
+	w, err := report.NewWriterDefault(os.Stdout)
 	if err != nil {
 		return err
 	}
-	w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
 	defer w.Flush()
 
 	if !(noHeading || cliOpts.Quiet || cmd.Flag("format").Changed) {
-- 
cgit v1.2.3-54-g00ecf