Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore V1 --format "table..." support #7932

Merged
merged 1 commit into from
Oct 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions cmd/podman/containers/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"text/tabwriter"
"text/template"

"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/utils"
"github.com/containers/podman/v2/cmd/podman/validate"
Expand Down Expand Up @@ -75,17 +76,16 @@ func init() {
}

func mount(_ *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
if len(args) > 0 && mountOpts.Latest {
return errors.Errorf("--latest and containers cannot be used together")
}
reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts)
if err != nil {
return err
}

if len(args) > 0 || mountOpts.Latest || mountOpts.All {
var errs utils.OutputErrors
for _, r := range reports {
if r.Err == nil {
fmt.Println(r.Path)
Expand All @@ -96,21 +96,21 @@ func mount(_ *cobra.Command, args []string) error {
return errs.PrintErrors()
}

switch mountOpts.Format {
case "json":
switch {
case parse.MatchesJSONFormat(mountOpts.Format):
return printJSON(reports)
case "":
// do nothing
case mountOpts.Format == "":
break // print defaults
default:
return errors.Errorf("unknown --format argument: %s", mountOpts.Format)
return errors.Errorf("unknown --format argument: %q", mountOpts.Format)
}

mrs := make([]mountReporter, 0, len(reports))
for _, r := range reports {
mrs = append(mrs, mountReporter{r})
}
row := "{{.ID}} {{.Path}}\n"
format := "{{range . }}" + row + "{{end}}"

format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}"
tmpl, err := template.New("mounts").Parse(format)
if err != nil {
return err
Expand Down Expand Up @@ -139,6 +139,7 @@ func printJSON(reports []*entities.ContainerMountReport) error {
if err != nil {
return err
}

fmt.Println(string(b))
return nil
}
Expand Down
57 changes: 28 additions & 29 deletions cmd/podman/images/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"time"
"unicode"

"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/report"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/docker/go-units"
"github.com/pkg/errors"
Expand All @@ -28,9 +30,9 @@ var (
Use: "history [flags] IMAGE",
Short: "Show history of a specified image",
Long: long,
Example: "podman history quay.io/fedora/fedora",
Args: cobra.ExactArgs(1),
RunE: history,
Example: "podman history quay.io/fedora/fedora",
}

imageHistoryCmd = &cobra.Command{
Expand All @@ -39,7 +41,7 @@ var (
Short: historyCmd.Short,
Long: historyCmd.Long,
RunE: historyCmd.RunE,
Example: `podman image history imageID`,
Example: `podman image history quay.io/fedora/fedora`,
}

opts = struct {
Expand Down Expand Up @@ -79,7 +81,7 @@ func history(cmd *cobra.Command, args []string) error {
return err
}

if opts.format == "json" {
if parse.MatchesJSONFormat(opts.format) {
var err error
if len(results.Layers) == 0 {
_, err = fmt.Fprintf(os.Stdout, "[]\n")
Expand All @@ -100,69 +102,66 @@ func history(cmd *cobra.Command, args []string) error {
}
return err
}
hr := make([]historyreporter, 0, len(results.Layers))

hr := make([]historyReporter, 0, len(results.Layers))
for _, l := range results.Layers {
hr = append(hr, historyreporter{l})
hr = append(hr, historyReporter{l})
}

hdrs := report.Headers(historyReporter{}, map[string]string{
"CreatedBy": "CREATED BY",
})

// Defaults
hdr := "ID\tCREATED\tCREATED BY\tSIZE\tCOMMENT\n"
row := "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"

switch {
case len(opts.format) > 0:
hdr = ""
row = opts.format
if !strings.HasSuffix(opts.format, "\n") {
row += "\n"
}
case cmd.Flags().Changed("format"):
row = report.NormalizeFormat(opts.format)
case opts.quiet:
hdr = ""
row = "{{.ID}}\n"
case opts.human:
row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
case opts.noTrunc:
row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n"
}
format := hdr + "{{range . }}" + row + "{{end}}"
format := "{{range . }}" + row + "{{end}}"

tmpl, err := template.New("report").Parse(format)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
err = tmpl.Execute(w, hr)
if err != nil {
fmt.Fprintln(os.Stderr, errors.Wrapf(err, "failed to print report"))
defer w.Flush()

if !opts.quiet && !cmd.Flags().Changed("format") {
if err := tmpl.Execute(w, hdrs); err != nil {
return errors.Wrapf(err, "failed to write report column headers")
}
}
w.Flush()
return nil
return tmpl.Execute(w, hr)
}

type historyreporter struct {
type historyReporter struct {
entities.ImageHistoryLayer
}

func (h historyreporter) Created() string {
func (h historyReporter) Created() string {
if opts.human {
return units.HumanDuration(time.Since(h.ImageHistoryLayer.Created)) + " ago"
}
return h.ImageHistoryLayer.Created.Format(time.RFC3339)
}

func (h historyreporter) Size() string {
func (h historyReporter) Size() string {
s := units.HumanSizeWithPrecision(float64(h.ImageHistoryLayer.Size), 3)
i := strings.LastIndexFunc(s, unicode.IsNumber)
return s[:i+1] + " " + s[i+1:]
}

func (h historyreporter) CreatedBy() string {
func (h historyReporter) CreatedBy() string {
if len(h.ImageHistoryLayer.CreatedBy) > 45 {
return h.ImageHistoryLayer.CreatedBy[:45-3] + "..."
}
return h.ImageHistoryLayer.CreatedBy
}

func (h historyreporter) ID() string {
func (h historyReporter) ID() string {
if !opts.noTrunc && len(h.ImageHistoryLayer.ID) >= 12 {
return h.ImageHistoryLayer.ID[0:12]
}
Expand Down
27 changes: 14 additions & 13 deletions cmd/podman/images/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"text/tabwriter"
"text/template"

"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/utils"
"github.com/containers/podman/v2/pkg/domain/entities"
Expand All @@ -24,7 +25,7 @@ var (

mountCommand = &cobra.Command{
Use: "mount [flags] [IMAGE...]",
Short: "Mount an images's root filesystem",
Short: "Mount an image's root filesystem",
Long: mountDescription,
RunE: mount,
Example: `podman image mount imgID
Expand Down Expand Up @@ -56,18 +57,18 @@ func init() {
mountFlags(mountCommand.Flags())
}

func mount(_ *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
func mount(cmd *cobra.Command, args []string) error {
if len(args) > 0 && mountOpts.All {
return errors.New("when using the --all switch, you may not pass any image names or IDs")
}

reports, err := registry.ImageEngine().Mount(registry.GetContext(), args, mountOpts)
if err != nil {
return err
}

if len(args) > 0 || mountOpts.All {
var errs utils.OutputErrors
for _, r := range reports {
if r.Err == nil {
fmt.Println(r.Path)
Expand All @@ -78,22 +79,22 @@ func mount(_ *cobra.Command, args []string) error {
return errs.PrintErrors()
}

switch mountOpts.Format {
case "json":
switch {
case parse.MatchesJSONFormat(mountOpts.Format):
return printJSON(reports)
case "":
// do nothing
case mountOpts.Format == "":
break // default format
default:
return errors.Errorf("unknown --format argument: %s", mountOpts.Format)
return errors.Errorf("unknown --format argument: %q", mountOpts.Format)
}

mrs := make([]mountReporter, 0, len(reports))
for _, r := range reports {
mrs = append(mrs, mountReporter{r})
}
row := "{{.ID}} {{.Path}}\n"
format := "{{range . }}" + row + "{{end}}"
tmpl, err := template.New("mounts").Parse(format)

row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}"
tmpl, err := template.New("mounts").Parse(row)
if err != nil {
return err
}
Expand Down
51 changes: 19 additions & 32 deletions cmd/podman/images/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package images

import (
"os"
"reflect"
"strings"
"text/tabwriter"
"text/template"

"github.com/containers/buildah/pkg/formats"
"github.com/containers/common/pkg/auth"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/report"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/util/camelcase"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -120,41 +119,29 @@ func imageSearch(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}

format := genSearchFormat(searchOptions.Format)
if len(searchReport) == 0 {
return nil
}
out := formats.StdoutTemplateArray{Output: searchToGeneric(searchReport), Template: format, Fields: searchHeaderMap()}
return out.Out()
}

// searchHeaderMap returns the headers of a SearchResult.
func searchHeaderMap() map[string]string {
s := new(entities.ImageSearchReport)
v := reflect.Indirect(reflect.ValueOf(s))
values := make(map[string]string, v.NumField())

for i := 0; i < v.NumField(); i++ {
key := v.Type().Field(i).Name
value := key
values[key] = strings.ToUpper(strings.Join(camelcase.Split(value), " "))
hdrs := report.Headers(entities.ImageSearchReport{}, nil)
row := "{{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\n"
if cmd.Flags().Changed("format") {
row = report.NormalizeFormat(searchOptions.Format)
}
return values
}
row = "{{range .}}" + row + "{{end}}"

func genSearchFormat(format string) string {
if format != "" {
// "\t" from the command line is not being recognized as a tab
// replacing the string "\t" to a tab character if the user passes in "\t"
return strings.Replace(format, `\t`, "\t", -1)
tmpl, err := template.New("search").Parse(row)
if err != nil {
return err
}
return "table {{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\t"
}
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
defer w.Flush()

func searchToGeneric(params []entities.ImageSearchReport) (genericParams []interface{}) {
for _, v := range params {
genericParams = append(genericParams, interface{}(v))
if !cmd.Flags().Changed("format") {
if err := tmpl.Execute(w, hdrs); err != nil {
return errors.Wrapf(err, "failed to write search column headers")
}
}
return genericParams

return tmpl.Execute(w, searchReport)
}
6 changes: 3 additions & 3 deletions test/e2e/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ registries = ['{{.Host}}:{{.Port}}']`
})

It("podman search attempts HTTP if registry is in registries.insecure and force secure is false", func() {
SkipIfRemote("--tls-verify is not supportedon podman-remote search")
SkipIfRemote("--tls-verify is not supported on podman-remote search")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
Expand Down Expand Up @@ -278,7 +278,7 @@ registries = ['{{.Host}}:{{.Port}}']`
})

It("podman search doesn't attempt HTTP if force secure is true", func() {
SkipIfRemote("--tls-verify is not supportedon podman-remote search")
SkipIfRemote("--tls-verify is not supported on podman-remote search")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
Expand Down Expand Up @@ -317,7 +317,7 @@ registries = ['{{.Host}}:{{.Port}}']`
})

It("podman search doesn't attempt HTTP if registry is not listed as insecure", func() {
SkipIfRemote("--tls-verify is not supportedon podman-remote search")
SkipIfRemote("--tls-verify is not supported on podman-remote search")
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
Expand Down
2 changes: 1 addition & 1 deletion test/system/060-mount.bats
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ load helpers

# 'image mount', no args, tells us what's mounted
run_podman image mount
is "$output" "$IMAGE $mount_path" "podman image mount with no args"
is "$output" "$IMAGE *$mount_path" "podman image mount with no args"

# Clean up
run_podman image umount $IMAGE
Expand Down