mirror of https://github.com/containers/podman.git
Refactor podman to use c/common/pkg/report
All formatting for containers stack moved into one package The does not correct issue with headers when using custom tables Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
parent
f96dbd0896
commit
bab3cda0e8
|
@ -1,4 +1,4 @@
|
||||||
package report
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,9 +1,9 @@
|
||||||
package containers
|
package containers
|
||||||
|
|
||||||
import (
|
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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -54,10 +54,10 @@ func diff(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(diffOpts.Format):
|
case report.IsJSON(diffOpts.Format):
|
||||||
return report.ChangesToJSON(results)
|
return common.ChangesToJSON(results)
|
||||||
case diffOpts.Format == "":
|
case diffOpts.Format == "":
|
||||||
return report.ChangesToTable(results)
|
return common.ChangesToTable(results)
|
||||||
default:
|
default:
|
||||||
return errors.New("only supported value for '--format' is 'json'")
|
return errors.New("only supported value for '--format' is 'json'")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
|
@ -97,7 +97,7 @@ func mount(_ *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(mountOpts.Format):
|
case report.IsJSON(mountOpts.Format):
|
||||||
return printJSON(reports)
|
return printJSON(reports)
|
||||||
case mountOpts.Format == "":
|
case mountOpts.Format == "":
|
||||||
break // print defaults
|
break // print defaults
|
||||||
|
|
|
@ -11,9 +11,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
tm "github.com/buger/goterm"
|
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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
|
@ -92,7 +91,7 @@ func checkFlags(c *cobra.Command) error {
|
||||||
if listOpts.Size || listOpts.Namespace {
|
if listOpts.Size || listOpts.Namespace {
|
||||||
return errors.Errorf("quiet conflicts with size and 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.
|
// Quiet is overridden by Go template output.
|
||||||
listOpts.Quiet = false
|
listOpts.Quiet = false
|
||||||
}
|
}
|
||||||
|
@ -179,7 +178,7 @@ func ps(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(listOpts.Format):
|
case report.IsJSON(listOpts.Format):
|
||||||
return jsonOut(listContainers)
|
return jsonOut(listContainers)
|
||||||
case listOpts.Quiet:
|
case listOpts.Quiet:
|
||||||
return quietOut(listContainers)
|
return quietOut(listContainers)
|
||||||
|
|
|
@ -7,9 +7,8 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
tm "github.com/buger/goterm"
|
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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/libpod/define"
|
"github.com/containers/podman/v2/libpod/define"
|
||||||
"github.com/containers/podman/v2/pkg/cgroups"
|
"github.com/containers/podman/v2/pkg/cgroups"
|
||||||
|
@ -157,7 +156,7 @@ func outputStats(reports []define.ContainerStats) error {
|
||||||
for _, r := range reports {
|
for _, r := range reports {
|
||||||
stats = append(stats, containerStats{r})
|
stats = append(stats, containerStats{r})
|
||||||
}
|
}
|
||||||
if parse.MatchesJSONFormat(statsOptions.Format) {
|
if report.IsJSON(statsOptions.Format) {
|
||||||
return outputJSON(stats)
|
return outputJSON(stats)
|
||||||
}
|
}
|
||||||
format := defaultStatsRow
|
format := defaultStatsRow
|
||||||
|
@ -240,9 +239,9 @@ func combineHumanValues(a, b uint64) string {
|
||||||
|
|
||||||
func outputJSON(stats []containerStats) error {
|
func outputJSON(stats []containerStats) error {
|
||||||
type jstat struct {
|
type jstat struct {
|
||||||
Id string `json:"id"` //nolint
|
Id string `json:"id"` // nolint
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CpuPercent string `json:"cpu_percent"` //nolint
|
CpuPercent string `json:"cpu_percent"` // nolint
|
||||||
MemUsage string `json:"mem_usage"`
|
MemUsage string `json:"mem_usage"`
|
||||||
MemPerc string `json:"mem_percent"`
|
MemPerc string `json:"mem_percent"`
|
||||||
NetIO string `json:"net_io"`
|
NetIO string `json:"net_io"`
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"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")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func systemd(cmd *cobra.Command, args []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error getting current working directory")
|
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))
|
path := filepath.Join(cwd, fmt.Sprintf("%s.service", name))
|
||||||
f, err := os.Create(path)
|
f, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -94,15 +94,15 @@ func systemd(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
// modify in place so we can print the
|
// modify in place so we can print the
|
||||||
// paths when --files is set
|
// paths when --files is set
|
||||||
report.Units[name] = path
|
reports.Units[name] = path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(format):
|
case report.IsJSON(format):
|
||||||
return printJSON(report.Units)
|
return printJSON(reports.Units)
|
||||||
case format == "":
|
case format == "":
|
||||||
return printDefault(report.Units)
|
return printDefault(reports.Units)
|
||||||
default:
|
default:
|
||||||
return errors.Errorf("unknown --format argument: %s", format)
|
return errors.Errorf("unknown --format argument: %s", format)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package images
|
package images
|
||||||
|
|
||||||
import (
|
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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -51,10 +51,10 @@ func diff(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(diffOpts.Format):
|
case report.IsJSON(diffOpts.Format):
|
||||||
return report.ChangesToJSON(results)
|
return common.ChangesToJSON(results)
|
||||||
case diffOpts.Format == "":
|
case diffOpts.Format == "":
|
||||||
return report.ChangesToTable(results)
|
return common.ChangesToTable(results)
|
||||||
default:
|
default:
|
||||||
return errors.New("only supported value for '--format' is 'json'")
|
return errors.New("only supported value for '--format' is 'json'")
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -81,7 +80,7 @@ func history(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parse.MatchesJSONFormat(opts.format) {
|
if report.IsJSON(opts.format) {
|
||||||
var err error
|
var err error
|
||||||
if len(results.Layers) == 0 {
|
if len(results.Layers) == 0 {
|
||||||
_, err = fmt.Fprintf(os.Stdout, "[]\n")
|
_, err = fmt.Fprintf(os.Stdout, "[]\n")
|
||||||
|
|
|
@ -10,10 +10,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/image/v5/docker/reference"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -108,7 +107,7 @@ func images(cmd *cobra.Command, args []string) error {
|
||||||
switch {
|
switch {
|
||||||
case listFlag.quiet:
|
case listFlag.quiet:
|
||||||
return writeID(imgs)
|
return writeID(imgs)
|
||||||
case parse.MatchesJSONFormat(listFlag.format):
|
case report.IsJSON(listFlag.format):
|
||||||
return writeJSON(imgs)
|
return writeJSON(imgs)
|
||||||
default:
|
default:
|
||||||
if cmd.Flag("format").Changed {
|
if cmd.Flag("format").Changed {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
|
@ -80,7 +80,7 @@ func mount(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(mountOpts.Format):
|
case report.IsJSON(mountOpts.Format):
|
||||||
return printJSON(reports)
|
return printJSON(reports)
|
||||||
case mountOpts.Format == "":
|
case mountOpts.Format == "":
|
||||||
break // default format
|
break // default format
|
||||||
|
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/auth"
|
"github.com/containers/common/pkg/auth"
|
||||||
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/image/v5/types"
|
"github.com/containers/image/v5/types"
|
||||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
"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/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
|
@ -9,9 +9,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -143,7 +142,7 @@ func (i *inspector) inspect(namesOrIDs []string) error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(i.options.Format) || i.options.Format == "":
|
case report.IsJSON(i.options.Format) || i.options.Format == "":
|
||||||
err = printJSON(data)
|
err = printJSON(data)
|
||||||
default:
|
default:
|
||||||
row := inspectNormalize(i.options.Format)
|
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.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")
|
flags.StringVar(&networkCreateOptions.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device")
|
||||||
// TODO not supported yet
|
// 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
|
// 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.IPNetVar(&networkCreateOptions.Subnet, "subnet", net.IPNet{}, "subnet in CIDR format")
|
||||||
flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")
|
flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -47,7 +46,7 @@ func networkInspect(_ *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(networkInspectOptions.Format) || networkInspectOptions.Format == "":
|
case report.IsJSON(networkInspectOptions.Format) || networkInspectOptions.Format == "":
|
||||||
b, err := json.MarshalIndent(responses, "", " ")
|
b, err := json.MarshalIndent(responses, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -36,7 +36,7 @@ var (
|
||||||
|
|
||||||
func networkListFlags(flags *pflag.FlagSet) {
|
func networkListFlags(flags *pflag.FlagSet) {
|
||||||
// TODO enable filters based on something
|
// 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.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.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
|
||||||
flags.StringVarP(&networkListOptions.Filter, "filter", "", "", "Provide filter values (e.g. 'name=podman')")
|
flags.StringVarP(&networkListOptions.Filter, "filter", "", "", "Provide filter values (e.g. 'name=podman')")
|
||||||
|
|
|
@ -7,9 +7,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -62,7 +61,7 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parse.MatchesJSONFormat(inspectOptions.Format) {
|
if report.IsJSON(inspectOptions.Format) {
|
||||||
enc := json.NewEncoder(os.Stdout)
|
enc := json.NewEncoder(os.Stdout)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
return enc.Encode(responses)
|
return enc.Encode(responses)
|
||||||
|
|
|
@ -10,9 +10,8 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
|
@ -85,7 +84,7 @@ func pods(cmd *cobra.Command, _ []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(psInput.Format):
|
case report.IsJSON(psInput.Format):
|
||||||
b, err := json.MarshalIndent(responses, "", " ")
|
b, err := json.MarshalIndent(responses, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -9,9 +9,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/buger/goterm"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -66,7 +65,7 @@ func stats(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
row := report.NormalizeFormat(statsOptions.Format)
|
row := report.NormalizeFormat(statsOptions.Format)
|
||||||
doJSON := parse.MatchesJSONFormat(row)
|
doJSON := report.IsJSON(row)
|
||||||
|
|
||||||
headers := report.Headers(entities.PodStatsReport{}, map[string]string{
|
headers := report.Headers(entities.PodStatsReport{}, map[string]string{
|
||||||
"CPU": "CPU %",
|
"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"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/report"
|
||||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
"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/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/libpod/events"
|
"github.com/containers/podman/v2/libpod/events"
|
||||||
|
@ -65,7 +65,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
if cmd.Flags().Changed("format") {
|
if cmd.Flags().Changed("format") {
|
||||||
doJSON = parse.MatchesJSONFormat(eventFormat)
|
doJSON = report.IsJSON(eventFormat)
|
||||||
if !doJSON {
|
if !doJSON {
|
||||||
var err error
|
var err error
|
||||||
tmpl, err = template.New("events").Parse(eventFormat)
|
tmpl, err = template.New("events").Parse(eventFormat)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
|
@ -70,7 +70,7 @@ func info(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(inFormat):
|
case report.IsJSON(inFormat):
|
||||||
b, err := json.MarshalIndent(info, "", " ")
|
b, err := json.MarshalIndent(info, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -8,9 +8,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/libpod/define"
|
"github.com/containers/podman/v2/libpod/define"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
|
@ -42,7 +41,7 @@ func version(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parse.MatchesJSONFormat(versionFormat) {
|
if report.IsJSON(versionFormat) {
|
||||||
s, err := json.MarshalToString(versions)
|
s, err := json.MarshalToString(versions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -5,9 +5,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -55,7 +54,7 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(inspectFormat), inspectFormat == "":
|
case report.IsJSON(inspectFormat), inspectFormat == "":
|
||||||
jsonOut, err := json.MarshalIndent(responses, "", " ")
|
jsonOut, err := json.MarshalIndent(responses, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error marshalling inspect JSON")
|
return errors.Wrapf(err, "error marshalling inspect JSON")
|
||||||
|
|
|
@ -8,9 +8,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/report"
|
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -75,7 +74,7 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case parse.MatchesJSONFormat(cliOpts.Format):
|
case report.IsJSON(cliOpts.Format):
|
||||||
return outputJSON(responses)
|
return outputJSON(responses)
|
||||||
case len(responses) < 1:
|
case len(responses) < 1:
|
||||||
return nil
|
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
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
|
@ -94,6 +94,8 @@ github.com/containers/common/pkg/capabilities
|
||||||
github.com/containers/common/pkg/cgroupv2
|
github.com/containers/common/pkg/cgroupv2
|
||||||
github.com/containers/common/pkg/completion
|
github.com/containers/common/pkg/completion
|
||||||
github.com/containers/common/pkg/config
|
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/retry
|
||||||
github.com/containers/common/pkg/seccomp
|
github.com/containers/common/pkg/seccomp
|
||||||
github.com/containers/common/pkg/sysinfo
|
github.com/containers/common/pkg/sysinfo
|
||||||
|
|
Loading…
Reference in New Issue