mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00
Merge pull request #8077 from jwhonce/wip/report
Refactor podman to use c/common/pkg/report
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
package report
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,9 +1,9 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/common"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
@ -54,10 +54,10 @@ func diff(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(diffOpts.Format):
|
||||
return report.ChangesToJSON(results)
|
||||
case report.IsJSON(diffOpts.Format):
|
||||
return common.ChangesToJSON(results)
|
||||
case diffOpts.Format == "":
|
||||
return report.ChangesToTable(results)
|
||||
return common.ChangesToTable(results)
|
||||
default:
|
||||
return errors.New("only supported value for '--format' is 'json'")
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
@ -97,7 +97,7 @@ func mount(_ *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(mountOpts.Format):
|
||||
case report.IsJSON(mountOpts.Format):
|
||||
return printJSON(reports)
|
||||
case mountOpts.Format == "":
|
||||
break // print defaults
|
||||
|
@ -11,9 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
@ -92,7 +91,7 @@ func checkFlags(c *cobra.Command) error {
|
||||
if listOpts.Size || listOpts.Namespace {
|
||||
return errors.Errorf("quiet conflicts with size and namespace")
|
||||
}
|
||||
if c.Flag("format").Changed && !parse.MatchesJSONFormat(listOpts.Format) {
|
||||
if c.Flag("format").Changed && !report.IsJSON(listOpts.Format) {
|
||||
// Quiet is overridden by Go template output.
|
||||
listOpts.Quiet = false
|
||||
}
|
||||
@ -179,7 +178,7 @@ func ps(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(listOpts.Format):
|
||||
case report.IsJSON(listOpts.Format):
|
||||
return jsonOut(listContainers)
|
||||
case listOpts.Quiet:
|
||||
return quietOut(listContainers)
|
||||
|
@ -7,9 +7,8 @@ import (
|
||||
"text/template"
|
||||
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/libpod/define"
|
||||
"github.com/containers/podman/v2/pkg/cgroups"
|
||||
@ -157,7 +156,7 @@ func outputStats(reports []define.ContainerStats) error {
|
||||
for _, r := range reports {
|
||||
stats = append(stats, containerStats{r})
|
||||
}
|
||||
if parse.MatchesJSONFormat(statsOptions.Format) {
|
||||
if report.IsJSON(statsOptions.Format) {
|
||||
return outputJSON(stats)
|
||||
}
|
||||
format := defaultStatsRow
|
||||
@ -240,9 +239,9 @@ func combineHumanValues(a, b uint64) string {
|
||||
|
||||
func outputJSON(stats []containerStats) error {
|
||||
type jstat struct {
|
||||
Id string `json:"id"` //nolint
|
||||
Id string `json:"id"` // nolint
|
||||
Name string `json:"name"`
|
||||
CpuPercent string `json:"cpu_percent"` //nolint
|
||||
CpuPercent string `json:"cpu_percent"` // nolint
|
||||
MemUsage string `json:"mem_usage"`
|
||||
MemPerc string `json:"mem_percent"`
|
||||
NetIO string `json:"net_io"`
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
@ -63,7 +63,7 @@ func systemd(cmd *cobra.Command, args []string) error {
|
||||
logrus.Warnln("The generated units should be placed on your remote system")
|
||||
}
|
||||
|
||||
report, err := registry.ContainerEngine().GenerateSystemd(registry.GetContext(), args[0], systemdOptions)
|
||||
reports, err := registry.ContainerEngine().GenerateSystemd(registry.GetContext(), args[0], systemdOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -73,7 +73,7 @@ func systemd(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting current working directory")
|
||||
}
|
||||
for name, content := range report.Units {
|
||||
for name, content := range reports.Units {
|
||||
path := filepath.Join(cwd, fmt.Sprintf("%s.service", name))
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
@ -94,15 +94,15 @@ func systemd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
// modify in place so we can print the
|
||||
// paths when --files is set
|
||||
report.Units[name] = path
|
||||
reports.Units[name] = path
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(format):
|
||||
return printJSON(report.Units)
|
||||
case report.IsJSON(format):
|
||||
return printJSON(reports.Units)
|
||||
case format == "":
|
||||
return printDefault(report.Units)
|
||||
return printDefault(reports.Units)
|
||||
default:
|
||||
return errors.Errorf("unknown --format argument: %s", format)
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/common"
|
||||
"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/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -51,10 +51,10 @@ func diff(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(diffOpts.Format):
|
||||
return report.ChangesToJSON(results)
|
||||
case report.IsJSON(diffOpts.Format):
|
||||
return common.ChangesToJSON(results)
|
||||
case diffOpts.Format == "":
|
||||
return report.ChangesToTable(results)
|
||||
return common.ChangesToTable(results)
|
||||
default:
|
||||
return errors.New("only supported value for '--format' is 'json'")
|
||||
}
|
||||
|
@ -10,9 +10,8 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"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"
|
||||
@ -81,7 +80,7 @@ func history(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if parse.MatchesJSONFormat(opts.format) {
|
||||
if report.IsJSON(opts.format) {
|
||||
var err error
|
||||
if len(results.Layers) == 0 {
|
||||
_, err = fmt.Fprintf(os.Stdout, "[]\n")
|
||||
|
@ -10,10 +10,9 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"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"
|
||||
@ -108,7 +107,7 @@ func images(cmd *cobra.Command, args []string) error {
|
||||
switch {
|
||||
case listFlag.quiet:
|
||||
return writeID(imgs)
|
||||
case parse.MatchesJSONFormat(listFlag.format):
|
||||
case report.IsJSON(listFlag.format):
|
||||
return writeJSON(imgs)
|
||||
default:
|
||||
if cmd.Flag("format").Changed {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
@ -80,7 +80,7 @@ func mount(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(mountOpts.Format):
|
||||
case report.IsJSON(mountOpts.Format):
|
||||
return printJSON(reports)
|
||||
case mountOpts.Format == "":
|
||||
break // default format
|
||||
|
@ -6,9 +6,9 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/common/pkg/auth"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"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/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -9,9 +9,8 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
@ -143,7 +142,7 @@ func (i *inspector) inspect(namesOrIDs []string) error {
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(i.options.Format) || i.options.Format == "":
|
||||
case report.IsJSON(i.options.Format) || i.options.Format == "":
|
||||
err = printJSON(data)
|
||||
default:
|
||||
row := inspectNormalize(i.options.Format)
|
||||
|
@ -34,9 +34,9 @@ func networkCreateFlags(flags *pflag.FlagSet) {
|
||||
flags.IPNetVar(&networkCreateOptions.Range, "ip-range", net.IPNet{}, "allocate container IP from range")
|
||||
flags.StringVar(&networkCreateOptions.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device")
|
||||
// TODO not supported yet
|
||||
//flags.StringVar(&networkCreateOptions.IPamDriver, "ipam-driver", "", "IP Address Management Driver")
|
||||
// flags.StringVar(&networkCreateOptions.IPamDriver, "ipam-driver", "", "IP Address Management Driver")
|
||||
// TODO enable when IPv6 is working
|
||||
//flags.BoolVar(&networkCreateOptions.IPV6, "IPv6", false, "enable IPv6 networking")
|
||||
// flags.BoolVar(&networkCreateOptions.IPV6, "IPv6", false, "enable IPv6 networking")
|
||||
flags.IPNetVar(&networkCreateOptions.Subnet, "subnet", net.IPNet{}, "subnet in CIDR format")
|
||||
flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"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/spf13/cobra"
|
||||
)
|
||||
@ -47,7 +46,7 @@ func networkInspect(_ *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(networkInspectOptions.Format) || networkInspectOptions.Format == "":
|
||||
case report.IsJSON(networkInspectOptions.Format) || networkInspectOptions.Format == "":
|
||||
b, err := json.MarshalIndent(responses, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -36,7 +36,7 @@ var (
|
||||
|
||||
func networkListFlags(flags *pflag.FlagSet) {
|
||||
// TODO enable filters based on something
|
||||
//flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
|
||||
// flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
|
||||
flags.StringVarP(&networkListOptions.Format, "format", "f", "", "Pretty-print networks to JSON or using a Go template")
|
||||
flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
|
||||
flags.StringVarP(&networkListOptions.Filter, "filter", "", "", "Provide filter values (e.g. 'name=podman')")
|
||||
|
@ -7,9 +7,8 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
@ -62,7 +61,7 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if parse.MatchesJSONFormat(inspectOptions.Format) {
|
||||
if report.IsJSON(inspectOptions.Format) {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(responses)
|
||||
|
@ -10,9 +10,8 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/docker/go-units"
|
||||
@ -85,7 +84,7 @@ func pods(cmd *cobra.Command, _ []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(psInput.Format):
|
||||
case report.IsJSON(psInput.Format):
|
||||
b, err := json.MarshalIndent(responses, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,9 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/buger/goterm"
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/spf13/cobra"
|
||||
@ -66,7 +65,7 @@ func stats(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
row := report.NormalizeFormat(statsOptions.Format)
|
||||
doJSON := parse.MatchesJSONFormat(row)
|
||||
doJSON := report.IsJSON(row)
|
||||
|
||||
headers := report.Headers(entities.PodStatsReport{}, map[string]string{
|
||||
"CPU": "CPU %",
|
||||
|
@ -1,68 +0,0 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// tableReplacer will remove 'table ' prefix and clean up tabs
|
||||
var tableReplacer = strings.NewReplacer(
|
||||
"table ", "",
|
||||
`\t`, "\t",
|
||||
`\n`, "\n",
|
||||
" ", "\t",
|
||||
)
|
||||
|
||||
// escapedReplacer will clean up escaped characters from CLI
|
||||
var escapedReplacer = strings.NewReplacer(
|
||||
`\t`, "\t",
|
||||
`\n`, "\n",
|
||||
)
|
||||
|
||||
// NormalizeFormat reads given go template format provided by CLI and munges it into what we need
|
||||
func NormalizeFormat(format string) string {
|
||||
f := format
|
||||
// two replacers used so we only remove the prefix keyword `table`
|
||||
if strings.HasPrefix(f, "table ") {
|
||||
f = tableReplacer.Replace(f)
|
||||
} else {
|
||||
f = escapedReplacer.Replace(format)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(f, "\n") {
|
||||
f += "\n"
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Headers queries the interface for field names
|
||||
func Headers(object interface{}, overrides map[string]string) []map[string]string {
|
||||
value := reflect.ValueOf(object)
|
||||
if value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
|
||||
// Column header will be field name upper-cased.
|
||||
headers := make(map[string]string, value.NumField())
|
||||
for i := 0; i < value.Type().NumField(); i++ {
|
||||
field := value.Type().Field(i)
|
||||
// Recurse to find field names from promoted structs
|
||||
if field.Type.Kind() == reflect.Struct && field.Anonymous {
|
||||
h := Headers(reflect.New(field.Type).Interface(), nil)
|
||||
for k, v := range h[0] {
|
||||
headers[k] = v
|
||||
}
|
||||
continue
|
||||
}
|
||||
headers[field.Name] = strings.ToUpper(field.Name)
|
||||
}
|
||||
|
||||
if len(overrides) > 0 {
|
||||
// Override column header as provided
|
||||
for k, v := range overrides {
|
||||
headers[k] = strings.ToUpper(v)
|
||||
}
|
||||
}
|
||||
return []map[string]string{headers}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNormalizeFormat(t *testing.T) {
|
||||
cases := []struct {
|
||||
format string
|
||||
expected string
|
||||
}{
|
||||
{"table {{.ID}}", "{{.ID}}\n"},
|
||||
{"table {{.ID}} {{.C}}", "{{.ID}}\t{{.C}}\n"},
|
||||
{"{{.ID}}", "{{.ID}}\n"},
|
||||
{"{{.ID}}\n", "{{.ID}}\n"},
|
||||
{"{{.ID}} {{.C}}", "{{.ID}} {{.C}}\n"},
|
||||
{"\t{{.ID}}", "\t{{.ID}}\n"},
|
||||
{`\t` + "{{.ID}}", "\t{{.ID}}\n"},
|
||||
{"table {{.ID}}\t{{.C}}", "{{.ID}}\t{{.C}}\n"},
|
||||
{"{{.ID}} table {{.C}}", "{{.ID}} table {{.C}}\n"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
label := strings.ReplaceAll(tc.format, " ", "<sp>")
|
||||
t.Run("NormalizeFormat/"+label, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
actual := NormalizeFormat(tc.format)
|
||||
if actual != tc.expected {
|
||||
t.Errorf("Expected %q, actual %q", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package report
|
||||
|
||||
import "github.com/containers/podman/v2/cmd/podman/registry"
|
||||
|
||||
// Pull in configured json library
|
||||
var json = registry.JSONLibrary()
|
@ -8,8 +8,8 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/docker/go-units"
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/libpod/events"
|
||||
@ -65,7 +65,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
|
||||
)
|
||||
|
||||
if cmd.Flags().Changed("format") {
|
||||
doJSON = parse.MatchesJSONFormat(eventFormat)
|
||||
doJSON = report.IsJSON(eventFormat)
|
||||
if !doJSON {
|
||||
var err error
|
||||
tmpl, err = template.New("events").Parse(eventFormat)
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
@ -70,7 +70,7 @@ func info(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(inFormat):
|
||||
case report.IsJSON(inFormat):
|
||||
b, err := json.MarshalIndent(info, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -8,9 +8,8 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/libpod/define"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
@ -42,7 +41,7 @@ func version(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if parse.MatchesJSONFormat(versionFormat) {
|
||||
if report.IsJSON(versionFormat) {
|
||||
s, err := json.MarshalToString(versions)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -5,9 +5,8 @@ import (
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"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/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -55,7 +54,7 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(inspectFormat), inspectFormat == "":
|
||||
case report.IsJSON(inspectFormat), inspectFormat == "":
|
||||
jsonOut, err := json.MarshalIndent(responses, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error marshalling inspect JSON")
|
||||
|
@ -8,9 +8,8 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/podman/v2/cmd/podman/parse"
|
||||
"github.com/containers/common/pkg/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||
"github.com/containers/podman/v2/cmd/podman/report"
|
||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
@ -75,7 +74,7 @@ func list(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
switch {
|
||||
case parse.MatchesJSONFormat(cliOpts.Format):
|
||||
case report.IsJSON(cliOpts.Format):
|
||||
return outputJSON(responses)
|
||||
case len(responses) < 1:
|
||||
return nil
|
||||
|
20
vendor/github.com/containers/common/pkg/report/camelcase/LICENSE.md
generated
vendored
Normal file
20
vendor/github.com/containers/common/pkg/report/camelcase/LICENSE.md
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Fatih Arslan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
58
vendor/github.com/containers/common/pkg/report/camelcase/README.md
generated
vendored
Normal file
58
vendor/github.com/containers/common/pkg/report/camelcase/README.md
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
# CamelCase [](http://godoc.org/github.com/fatih/camelcase) [](https://travis-ci.org/fatih/camelcase)
|
||||
|
||||
CamelCase is a Golang (Go) package to split the words of a camelcase type
|
||||
string into a slice of words. It can be used to convert a camelcase word (lower
|
||||
or upper case) into any type of word.
|
||||
|
||||
## Splitting rules:
|
||||
|
||||
1. If string is not valid UTF-8, return it without splitting as
|
||||
single item array.
|
||||
2. Assign all unicode characters into one of 4 sets: lower case
|
||||
letters, upper case letters, numbers, and all other characters.
|
||||
3. Iterate through characters of string, introducing splits
|
||||
between adjacent characters that belong to different sets.
|
||||
4. Iterate through array of split strings, and if a given string
|
||||
is upper case:
|
||||
* if subsequent string is lower case:
|
||||
* move last character of upper case string to beginning of
|
||||
lower case string
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
go get github.com/fatih/camelcase
|
||||
```
|
||||
|
||||
## Usage and examples
|
||||
|
||||
```go
|
||||
splitted := camelcase.Split("GolangPackage")
|
||||
|
||||
fmt.Println(splitted[0], splitted[1]) // prints: "Golang", "Package"
|
||||
```
|
||||
|
||||
Both lower camel case and upper camel case are supported. For more info please
|
||||
check: [http://en.wikipedia.org/wiki/CamelCase](http://en.wikipedia.org/wiki/CamelCase)
|
||||
|
||||
Below are some example cases:
|
||||
|
||||
```
|
||||
"" => []
|
||||
"lowercase" => ["lowercase"]
|
||||
"Class" => ["Class"]
|
||||
"MyClass" => ["My", "Class"]
|
||||
"MyC" => ["My", "C"]
|
||||
"HTML" => ["HTML"]
|
||||
"PDFLoader" => ["PDF", "Loader"]
|
||||
"AString" => ["A", "String"]
|
||||
"SimpleXMLParser" => ["Simple", "XML", "Parser"]
|
||||
"vimRPCPlugin" => ["vim", "RPC", "Plugin"]
|
||||
"GL11Version" => ["GL", "11", "Version"]
|
||||
"99Bottles" => ["99", "Bottles"]
|
||||
"May5" => ["May", "5"]
|
||||
"BFG9000" => ["BFG", "9000"]
|
||||
"BöseÜberraschung" => ["Böse", "Überraschung"]
|
||||
"Two spaces" => ["Two", " ", "spaces"]
|
||||
"BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"]
|
||||
```
|
91
vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go
generated
vendored
Normal file
91
vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// Package camelcase is a micro package to split the words of a camelcase type
|
||||
// string into a slice of words.
|
||||
package camelcase
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Split splits the camelcase word and returns a list of words. It also
|
||||
// supports digits. Both lower camel case and upper camel case are supported.
|
||||
// For more info please check: http://en.wikipedia.org/wiki/CamelCase
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// "" => [""]
|
||||
// "lowercase" => ["lowercase"]
|
||||
// "Class" => ["Class"]
|
||||
// "MyClass" => ["My", "Class"]
|
||||
// "MyC" => ["My", "C"]
|
||||
// "HTML" => ["HTML"]
|
||||
// "PDFLoader" => ["PDF", "Loader"]
|
||||
// "AString" => ["A", "String"]
|
||||
// "SimpleXMLParser" => ["Simple", "XML", "Parser"]
|
||||
// "vimRPCPlugin" => ["vim", "RPC", "Plugin"]
|
||||
// "GL11Version" => ["GL", "11", "Version"]
|
||||
// "99Bottles" => ["99", "Bottles"]
|
||||
// "May5" => ["May", "5"]
|
||||
// "BFG9000" => ["BFG", "9000"]
|
||||
// "BöseÜberraschung" => ["Böse", "Überraschung"]
|
||||
// "Two spaces" => ["Two", " ", "spaces"]
|
||||
// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"]
|
||||
//
|
||||
// Splitting rules
|
||||
//
|
||||
// 1) If string is not valid UTF-8, return it without splitting as
|
||||
// single item array.
|
||||
// 2) Assign all unicode characters into one of 4 sets: lower case
|
||||
// letters, upper case letters, numbers, and all other characters.
|
||||
// 3) Iterate through characters of string, introducing splits
|
||||
// between adjacent characters that belong to different sets.
|
||||
// 4) Iterate through array of split strings, and if a given string
|
||||
// is upper case:
|
||||
// if subsequent string is lower case:
|
||||
// move last character of upper case string to beginning of
|
||||
// lower case string
|
||||
func Split(src string) (entries []string) {
|
||||
// don't split invalid utf8
|
||||
if !utf8.ValidString(src) {
|
||||
return []string{src}
|
||||
}
|
||||
entries = []string{}
|
||||
var runes [][]rune
|
||||
lastClass := 0
|
||||
class := 0
|
||||
// split into fields based on class of unicode character
|
||||
for _, r := range src {
|
||||
switch {
|
||||
case unicode.IsLower(r):
|
||||
class = 1
|
||||
case unicode.IsUpper(r):
|
||||
class = 2
|
||||
case unicode.IsDigit(r):
|
||||
class = 3
|
||||
default:
|
||||
class = 4
|
||||
}
|
||||
if class == lastClass {
|
||||
runes[len(runes)-1] = append(runes[len(runes)-1], r)
|
||||
} else {
|
||||
runes = append(runes, []rune{r})
|
||||
}
|
||||
lastClass = class
|
||||
}
|
||||
// handle upper case -> lower case sequences, e.g.
|
||||
// "PDFL", "oader" -> "PDF", "Loader"
|
||||
for i := 0; i < len(runes)-1; i++ {
|
||||
if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) {
|
||||
runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
|
||||
runes[i] = runes[i][:len(runes[i])-1]
|
||||
}
|
||||
}
|
||||
// construct []string from results
|
||||
for _, s := range runes {
|
||||
if len(s) > 0 {
|
||||
entries = append(entries, string(s))
|
||||
}
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
46
vendor/github.com/containers/common/pkg/report/doc.go
generated
vendored
Normal file
46
vendor/github.com/containers/common/pkg/report/doc.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Package report provides helper structs/methods/funcs for formatting output
|
||||
|
||||
To format output for an array of structs:
|
||||
|
||||
w := report.NewWriterDefault(os.Stdout)
|
||||
defer w.Flush()
|
||||
|
||||
headers := report.Headers(struct {
|
||||
ID string
|
||||
}{}, nil)
|
||||
t, _ := report.NewTemplate("command name").Parse("{{range .}}{{.ID}}{{end}}")
|
||||
t.Execute(t, headers)
|
||||
t.Execute(t, map[string]string{
|
||||
"ID":"fa85da03b40141899f3af3de6d27852b",
|
||||
})
|
||||
// t.IsTable() == false
|
||||
|
||||
or
|
||||
|
||||
w := report.NewWriterDefault(os.Stdout)
|
||||
defer w.Flush()
|
||||
|
||||
headers := report.Headers(struct {
|
||||
CID string
|
||||
}{}, map[string]string{
|
||||
"CID":"ID"})
|
||||
t, _ := report.NewTemplate("command name").Parse("table {{.CID}}")
|
||||
t.Execute(t, headers)
|
||||
t.Execute(t,map[string]string{
|
||||
"CID":"fa85da03b40141899f3af3de6d27852b",
|
||||
})
|
||||
// t.IsTable() == true
|
||||
|
||||
Helpers:
|
||||
|
||||
if report.IsJSON(cmd.Flag("format").Value.String()) {
|
||||
... process JSON and output
|
||||
}
|
||||
|
||||
and
|
||||
|
||||
|
||||
Note: Your code should not ignore errors
|
||||
*/
|
||||
package report
|
114
vendor/github.com/containers/common/pkg/report/template.go
generated
vendored
Normal file
114
vendor/github.com/containers/common/pkg/report/template.go
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/containers/common/pkg/report/camelcase"
|
||||
)
|
||||
|
||||
// Template embeds template.Template to add functionality to methods
|
||||
type Template struct {
|
||||
*template.Template
|
||||
isTable bool
|
||||
}
|
||||
|
||||
// FuncMap is aliased from template.FuncMap
|
||||
type FuncMap template.FuncMap
|
||||
|
||||
// tableReplacer will remove 'table ' prefix and clean up tabs
|
||||
var tableReplacer = strings.NewReplacer(
|
||||
"table ", "",
|
||||
`\t`, "\t",
|
||||
`\n`, "\n",
|
||||
" ", "\t",
|
||||
)
|
||||
|
||||
// escapedReplacer will clean up escaped characters from CLI
|
||||
var escapedReplacer = strings.NewReplacer(
|
||||
`\t`, "\t",
|
||||
`\n`, "\n",
|
||||
)
|
||||
|
||||
// NormalizeFormat reads given go template format provided by CLI and munges it into what we need
|
||||
func NormalizeFormat(format string) string {
|
||||
var f string
|
||||
// two replacers used so we only remove the prefix keyword `table`
|
||||
if strings.HasPrefix(format, "table ") {
|
||||
f = tableReplacer.Replace(format)
|
||||
} else {
|
||||
f = escapedReplacer.Replace(format)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(f, "\n") {
|
||||
f += "\n"
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Headers queries the interface for field names.
|
||||
// Array of map is returned to support range templates
|
||||
// Note: unexported fields can be supported by adding field to overrides
|
||||
// Note: It is left to the developer to write out said headers
|
||||
// Podman commands use the general rules of:
|
||||
// 1) unchanged --format includes headers
|
||||
// 2) --format '{{.ID}" # no headers
|
||||
// 3) --format 'table {{.ID}}' # includes headers
|
||||
func Headers(object interface{}, overrides map[string]string) []map[string]string {
|
||||
value := reflect.ValueOf(object)
|
||||
if value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
}
|
||||
|
||||
// Column header will be field name upper-cased.
|
||||
headers := make(map[string]string, value.NumField())
|
||||
for i := 0; i < value.Type().NumField(); i++ {
|
||||
field := value.Type().Field(i)
|
||||
// Recurse to find field names from promoted structs
|
||||
if field.Type.Kind() == reflect.Struct && field.Anonymous {
|
||||
h := Headers(reflect.New(field.Type).Interface(), nil)
|
||||
for k, v := range h[0] {
|
||||
headers[k] = v
|
||||
}
|
||||
continue
|
||||
}
|
||||
name := strings.Join(camelcase.Split(field.Name), " ")
|
||||
headers[field.Name] = strings.ToUpper(name)
|
||||
}
|
||||
|
||||
if len(overrides) > 0 {
|
||||
// Override column header as provided
|
||||
for k, v := range overrides {
|
||||
headers[k] = strings.ToUpper(v)
|
||||
}
|
||||
}
|
||||
return []map[string]string{headers}
|
||||
}
|
||||
|
||||
// NewTemplate creates a new template object
|
||||
func NewTemplate(name string) *Template {
|
||||
return &Template{template.New(name), false}
|
||||
}
|
||||
|
||||
// Parse parses text as a template body for t
|
||||
func (t *Template) Parse(text string) (*Template, error) {
|
||||
if strings.HasPrefix(text, "table ") {
|
||||
t.isTable = true
|
||||
text = "{{range .}}" + NormalizeFormat(text) + "{{end}}"
|
||||
}
|
||||
|
||||
tt, err := t.Template.Parse(text)
|
||||
return &Template{tt, t.isTable}, err
|
||||
}
|
||||
|
||||
// Funcs adds the elements of the argument map to the template's function map
|
||||
func (t *Template) Funcs(funcMap FuncMap) *Template {
|
||||
return &Template{t.Template.Funcs(template.FuncMap(funcMap)), t.isTable}
|
||||
}
|
||||
|
||||
// IsTable returns true if format string defines a "table"
|
||||
func (t *Template) IsTable() bool {
|
||||
return t.isTable
|
||||
}
|
13
vendor/github.com/containers/common/pkg/report/validate.go
generated
vendored
Normal file
13
vendor/github.com/containers/common/pkg/report/validate.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package report
|
||||
|
||||
import "regexp"
|
||||
|
||||
var jsonRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`)
|
||||
|
||||
// JSONFormat test CLI --format string to be a JSON request
|
||||
// if report.IsJSON(cmd.Flag("format").Value.String()) {
|
||||
// ... process JSON and output
|
||||
// }
|
||||
func IsJSON(s string) bool {
|
||||
return jsonRegex.MatchString(s)
|
||||
}
|
27
vendor/github.com/containers/common/pkg/report/writer.go
generated
vendored
Normal file
27
vendor/github.com/containers/common/pkg/report/writer.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"io"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
// Writer aliases tabwriter.Writer to provide Podman defaults
|
||||
type Writer struct {
|
||||
*tabwriter.Writer
|
||||
}
|
||||
|
||||
// NewWriter initializes a new report.Writer with given values
|
||||
func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) (*Writer, error) {
|
||||
t := tabwriter.NewWriter(output, minwidth, tabwidth, padding, padchar, flags)
|
||||
return &Writer{t}, nil
|
||||
}
|
||||
|
||||
// NewWriterDefault initializes a new report.Writer with Podman defaults
|
||||
func NewWriterDefault(output io.Writer) (*Writer, error) {
|
||||
return NewWriter(output, 12, 2, 2, ' ', 0)
|
||||
}
|
||||
|
||||
// Flush any output left in buffers
|
||||
func (w *Writer) Flush() error {
|
||||
return w.Writer.Flush()
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -94,6 +94,8 @@ github.com/containers/common/pkg/capabilities
|
||||
github.com/containers/common/pkg/cgroupv2
|
||||
github.com/containers/common/pkg/completion
|
||||
github.com/containers/common/pkg/config
|
||||
github.com/containers/common/pkg/report
|
||||
github.com/containers/common/pkg/report/camelcase
|
||||
github.com/containers/common/pkg/retry
|
||||
github.com/containers/common/pkg/seccomp
|
||||
github.com/containers/common/pkg/sysinfo
|
||||
|
Reference in New Issue
Block a user