mirror of https://github.com/k3s-io/k3s
consolidate printer OutputOpts w PrintOpts
This patch removes the use of printers.OutputOptions in favor of only having a single struct for setting / passing printer options set by user flags.pull/6/head
parent
40e7101844
commit
d3773b4b06
|
@ -548,7 +548,7 @@ func Example_printPodHideTerminated() {
|
|||
podList := newAllPhasePodList()
|
||||
// filter pods
|
||||
filterFuncs := f.DefaultResourceFilterFunc()
|
||||
filterOpts := f.DefaultResourceFilterOptions(cmd, false)
|
||||
filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, false)
|
||||
_, filteredPodList, errs := cmdutil.FilterResourceList(podList, filterFuncs, filterOpts)
|
||||
if errs != nil {
|
||||
fmt.Printf("Unexpected filter error: %v\n", errs)
|
||||
|
|
|
@ -81,7 +81,8 @@ func NewCmdConfigView(out, errOut io.Writer, ConfigAccess clientcmd.ConfigAccess
|
|||
cmd.Flags().Set("output", defaultOutputFormat)
|
||||
}
|
||||
|
||||
printer, err := cmdutil.PrinterForCommand(cmd, nil, meta.NewDefaultRESTMapper(nil, nil), latest.Scheme, nil, []runtime.Decoder{latest.Codec}, printers.PrintOptions{})
|
||||
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false)
|
||||
printer, err := cmdutil.PrinterForOptions(meta.NewDefaultRESTMapper(nil, nil), latest.Scheme, nil, []runtime.Decoder{latest.Codec}, *printOpts)
|
||||
cmdutil.CheckErr(err)
|
||||
printer = printers.NewVersionedPrinter(printer, latest.Scheme, latest.ExternalVersion)
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C
|
|||
cmd.Flags().Set("output", outputFormat)
|
||||
}
|
||||
o.encoder = f.JSONEncoder()
|
||||
o.printer, err = f.PrinterForCommand(cmd, o.local, nil, printers.PrintOptions{})
|
||||
o.printer, err = f.PrinterForOptions(printers.PrintOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -254,12 +254,13 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
|
|||
return err
|
||||
}
|
||||
|
||||
printer, err := f.PrinterForCommand(cmd, false, nil, printers.PrintOptions{})
|
||||
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
|
||||
printer, err := f.PrinterForOptions(*printOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filterOpts := f.DefaultResourceFilterOptions(cmd, options.AllNamespaces)
|
||||
filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
|
||||
filterFuncs := f.DefaultResourceFilterFunc()
|
||||
if r.TargetsSingleItems() {
|
||||
filterFuncs = nil
|
||||
|
@ -330,14 +331,14 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
|
|||
printWithNamespace = false
|
||||
}
|
||||
|
||||
var outputOpts *printers.OutputOptions
|
||||
printOpts := *cmdutil.ExtractCmdPrintOptions(cmd, printWithNamespace)
|
||||
// if cmd does not specify output format and useOpenAPIPrintColumnFlagLabel flag is true,
|
||||
// then get the default output options for this mapping from OpenAPI schema.
|
||||
if !cmdSpecifiesOutputFmt(cmd) && useOpenAPIPrintColumns {
|
||||
outputOpts, _ = outputOptsForMappingFromOpenAPI(f, mapping)
|
||||
outputOptsForMappingFromOpenAPI(f, mapping, &printOpts)
|
||||
}
|
||||
|
||||
printer, err = f.PrinterForMapping(cmd, false, outputOpts, mapping, printWithNamespace)
|
||||
printer, err = f.PrinterForMapping(printOpts, mapping)
|
||||
if err != nil {
|
||||
if !errs.Has(err.Error()) {
|
||||
errs.Insert(err.Error())
|
||||
|
@ -470,7 +471,7 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
|
|||
return i18n.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", len(infos))
|
||||
}
|
||||
|
||||
filterOpts := f.DefaultResourceFilterOptions(cmd, options.AllNamespaces)
|
||||
filterOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
|
||||
filterFuncs := f.DefaultResourceFilterFunc()
|
||||
if r.TargetsSingleItems() {
|
||||
filterFuncs = nil
|
||||
|
@ -478,7 +479,8 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
|
|||
|
||||
info := infos[0]
|
||||
mapping := info.ResourceMapping()
|
||||
printer, err := f.PrinterForMapping(cmd, false, nil, mapping, options.AllNamespaces)
|
||||
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
|
||||
printer, err := f.PrinterForMapping(*printOpts, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -662,43 +664,44 @@ func cmdSpecifiesOutputFmt(cmd *cobra.Command) bool {
|
|||
|
||||
// outputOptsForMappingFromOpenAPI looks for the output format metatadata in the
|
||||
// openapi schema and returns the output options for the mapping if found.
|
||||
func outputOptsForMappingFromOpenAPI(f cmdutil.Factory, mapping *meta.RESTMapping) (*printers.OutputOptions, bool) {
|
||||
func outputOptsForMappingFromOpenAPI(f cmdutil.Factory, mapping *meta.RESTMapping, printOpts *printers.PrintOptions) bool {
|
||||
|
||||
// user has not specified any output format, check if OpenAPI has
|
||||
// default specification to print this resource type
|
||||
api, err := f.OpenAPISchema()
|
||||
if err != nil {
|
||||
// Error getting schema
|
||||
return nil, false
|
||||
return false
|
||||
}
|
||||
// Found openapi metadata for this resource
|
||||
schema := api.LookupResource(mapping.GroupVersionKind)
|
||||
if schema == nil {
|
||||
// Schema not found, return empty columns
|
||||
return nil, false
|
||||
return false
|
||||
}
|
||||
|
||||
columns, found := openapi.GetPrintColumns(schema.GetExtensions())
|
||||
if !found {
|
||||
// Extension not found, return empty columns
|
||||
return nil, false
|
||||
return false
|
||||
}
|
||||
|
||||
return outputOptsFromStr(columns)
|
||||
return outputOptsFromStr(columns, printOpts)
|
||||
}
|
||||
|
||||
// outputOptsFromStr parses the print-column metadata and generates printer.OutputOptions object.
|
||||
func outputOptsFromStr(columnStr string) (*printers.OutputOptions, bool) {
|
||||
func outputOptsFromStr(columnStr string, printOpts *printers.PrintOptions) bool {
|
||||
if columnStr == "" {
|
||||
return nil, false
|
||||
return false
|
||||
}
|
||||
parts := strings.SplitN(columnStr, "=", 2)
|
||||
if len(parts) < 2 {
|
||||
return nil, false
|
||||
return false
|
||||
}
|
||||
return &printers.OutputOptions{
|
||||
FmtType: parts[0],
|
||||
FmtArg: parts[1],
|
||||
AllowMissingKeys: true,
|
||||
}, true
|
||||
|
||||
printOpts.OutputFormatType = parts[0]
|
||||
printOpts.OutputFormatArgument = parts[1]
|
||||
printOpts.AllowMissingKeys = true
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -352,17 +352,17 @@ func (f *FakeFactory) Describer(*meta.RESTMapping) (printers.Describer, error) {
|
|||
return f.tf.Describer, f.tf.Err
|
||||
}
|
||||
|
||||
func (f *FakeFactory) PrinterForCommand(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
func (f *FakeFactory) PrinterForOptions(options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
return f.tf.Printer, f.tf.Err
|
||||
}
|
||||
|
||||
func (f *FakeFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, out io.Writer) error {
|
||||
printer, err := f.PrinterForCommand(cmd, false, nil, printers.PrintOptions{})
|
||||
printer, err := f.PrinterForOptions(printers.PrintOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !printer.IsGeneric() {
|
||||
printer, err = f.PrinterForMapping(cmd, false, nil, nil, false)
|
||||
printer, err = f.PrinterForMapping(printers.PrintOptions{}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ func (f *FakeFactory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeFactory) PrinterForMapping(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error) {
|
||||
func (f *FakeFactory) PrinterForMapping(printOpts printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) {
|
||||
return f.tf.Printer, f.tf.Err
|
||||
}
|
||||
|
||||
|
@ -744,17 +744,17 @@ func (f *fakeAPIFactory) UnstructuredClientForMapping(m *meta.RESTMapping) (reso
|
|||
return f.tf.UnstructuredClient, f.tf.Err
|
||||
}
|
||||
|
||||
func (f *fakeAPIFactory) PrinterForCommand(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
func (f *fakeAPIFactory) PrinterForOptions(options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
return f.tf.Printer, f.tf.Err
|
||||
}
|
||||
|
||||
func (f *fakeAPIFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, out io.Writer) error {
|
||||
printer, err := f.PrinterForCommand(cmd, false, nil, printers.PrintOptions{})
|
||||
printer, err := f.PrinterForOptions(printers.PrintOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !printer.IsGeneric() {
|
||||
printer, err = f.PrinterForMapping(cmd, false, nil, nil, false)
|
||||
printer, err = f.PrinterForMapping(printers.PrintOptions{}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -851,14 +851,14 @@ func (f *fakeAPIFactory) PrintObject(cmd *cobra.Command, isLocal bool, mapper me
|
|||
return err
|
||||
}
|
||||
|
||||
printer, err := f.PrinterForMapping(cmd, isLocal, nil, mapping, false)
|
||||
printer, err := f.PrinterForMapping(printers.PrintOptions{}, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
|
||||
func (f *fakeAPIFactory) PrinterForMapping(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error) {
|
||||
func (f *fakeAPIFactory) PrinterForMapping(outputOpts printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) {
|
||||
return f.tf.Printer, f.tf.Err
|
||||
}
|
||||
|
||||
|
|
|
@ -140,8 +140,6 @@ type ClientAccessFactory interface {
|
|||
// BindExternalFlags adds any flags defined by external projects (not part of pflags)
|
||||
BindExternalFlags(flags *pflag.FlagSet)
|
||||
|
||||
// TODO: Break the dependency on cmd here.
|
||||
DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace bool) *printers.PrintOptions
|
||||
// DefaultResourceFilterFunc returns a collection of FilterFuncs suitable for filtering specific resource types.
|
||||
DefaultResourceFilterFunc() kubectl.Filters
|
||||
|
||||
|
@ -232,13 +230,12 @@ type BuilderFactory interface {
|
|||
// PrinterForCommand returns the default printer for the command. It requires that certain options
|
||||
// are declared on the command (see AddPrinterFlags). Returns a printer, or an error if a printer
|
||||
// could not be found.
|
||||
// TODO: Break the dependency on cmd here.
|
||||
PrinterForCommand(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, options printers.PrintOptions) (printers.ResourcePrinter, error)
|
||||
PrinterForOptions(options printers.PrintOptions) (printers.ResourcePrinter, error)
|
||||
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
|
||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
|
||||
// Returns a printer, true if the printer is generic (is not internal), or
|
||||
// an error if a printer could not be found.
|
||||
PrinterForMapping(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error)
|
||||
PrinterForMapping(options printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error)
|
||||
// PrintObject prints an api object given command line flags to modify the output format
|
||||
PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error
|
||||
// PrintResourceInfoForCommand receives a *cobra.Command and a *resource.Info and
|
||||
|
|
|
@ -47,7 +47,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
|
|||
return f
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForCommand(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
func (f *ring2Factory) PrinterForOptions(options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
var mapper meta.RESTMapper
|
||||
var typer runtime.ObjectTyper
|
||||
|
||||
|
@ -56,27 +56,11 @@ func (f *ring2Factory) PrinterForCommand(cmd *cobra.Command, isLocal bool, outpu
|
|||
// TODO: used by the custom column implementation and the name implementation, break this dependency
|
||||
decoders := []runtime.Decoder{f.clientAccessFactory.Decoder(true), unstructured.UnstructuredJSONScheme}
|
||||
encoder := f.clientAccessFactory.JSONEncoder()
|
||||
return PrinterForCommand(cmd, outputOpts, mapper, typer, encoder, decoders, options)
|
||||
return PrinterForOptions(mapper, typer, encoder, decoders, options)
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForMapping(cmd *cobra.Command, isLocal bool, outputOpts *printers.OutputOptions, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error) {
|
||||
// Some callers do not have "label-columns" so we can't use the GetFlagStringSlice() helper
|
||||
columnLabel, err := cmd.Flags().GetStringSlice("label-columns")
|
||||
if err != nil {
|
||||
columnLabel = []string{}
|
||||
}
|
||||
|
||||
options := printers.PrintOptions{
|
||||
NoHeaders: GetFlagBool(cmd, "no-headers"),
|
||||
WithNamespace: withNamespace,
|
||||
Wide: GetWideFlag(cmd),
|
||||
ShowAll: GetFlagBool(cmd, "show-all"),
|
||||
ShowLabels: GetFlagBool(cmd, "show-labels"),
|
||||
AbsoluteTimestamps: isWatch(cmd),
|
||||
ColumnLabels: columnLabel,
|
||||
}
|
||||
|
||||
printer, err := f.PrinterForCommand(cmd, isLocal, outputOpts, options)
|
||||
func (f *ring2Factory) PrinterForMapping(options printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) {
|
||||
printer, err := f.PrinterForOptions(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -140,7 +124,7 @@ func (f *ring2Factory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta
|
|||
return err
|
||||
}
|
||||
|
||||
printer, err := f.PrinterForMapping(cmd, isLocal, nil, mapping, false)
|
||||
printer, err := f.PrinterForMapping(printers.PrintOptions{}, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -148,12 +132,12 @@ func (f *ring2Factory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta
|
|||
}
|
||||
|
||||
func (f *ring2Factory) PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, out io.Writer) error {
|
||||
printer, err := f.PrinterForCommand(cmd, false, nil, printers.PrintOptions{})
|
||||
printer, err := f.PrinterForOptions(printers.PrintOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !printer.IsGeneric() {
|
||||
printer, err = f.PrinterForMapping(cmd, false, nil, nil, false)
|
||||
printer, err = f.PrinterForMapping(printers.PrintOptions{}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -411,24 +411,6 @@ func (f *ring0Factory) BindExternalFlags(flags *pflag.FlagSet) {
|
|||
flags.AddGoFlagSet(flag.CommandLine)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace bool) *printers.PrintOptions {
|
||||
columnLabel, err := cmd.Flags().GetStringSlice("label-columns")
|
||||
if err != nil {
|
||||
columnLabel = []string{}
|
||||
}
|
||||
opts := &printers.PrintOptions{
|
||||
NoHeaders: GetFlagBool(cmd, "no-headers"),
|
||||
WithNamespace: withNamespace,
|
||||
Wide: GetWideFlag(cmd),
|
||||
ShowAll: GetFlagBool(cmd, "show-all"),
|
||||
ShowLabels: GetFlagBool(cmd, "show-labels"),
|
||||
AbsoluteTimestamps: isWatch(cmd),
|
||||
ColumnLabels: columnLabel,
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (f *ring0Factory) DefaultResourceFilterFunc() kubectl.Filters {
|
||||
return kubectl.NewResourceFilter()
|
||||
}
|
||||
|
|
|
@ -81,23 +81,11 @@ func ValidateOutputArgs(cmd *cobra.Command) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PrinterForCommand returns the printer for the outputOptions (if given) or
|
||||
// printerForOptions returns the printer for the outputOptions (if given) or
|
||||
// returns the default printer for the command. Requires that printer flags have
|
||||
// been added to cmd (see AddPrinterFlags).
|
||||
// TODO: remove the dependency on cmd object
|
||||
func PrinterForCommand(cmd *cobra.Command, outputOpts *printers.OutputOptions, mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
|
||||
if outputOpts == nil {
|
||||
outputOpts = extractOutputOptions(cmd)
|
||||
}
|
||||
|
||||
// this function may be invoked by a command that did not call AddPrinterFlags first, so we need
|
||||
// to be safe about how we access the no-headers flag
|
||||
noHeaders := false
|
||||
if cmd.Flags().Lookup("no-headers") != nil {
|
||||
noHeaders = GetFlagBool(cmd, "no-headers")
|
||||
}
|
||||
printer, err := printers.GetStandardPrinter(outputOpts, noHeaders, mapper, typer, encoder, decoders, options)
|
||||
func PrinterForOptions(mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
printer, err := printers.GetStandardPrinter(mapper, typer, encoder, decoders, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -109,19 +97,39 @@ func PrinterForCommand(cmd *cobra.Command, outputOpts *printers.OutputOptions, m
|
|||
printersinternal.AddHandlers(humanReadablePrinter)
|
||||
}
|
||||
|
||||
return maybeWrapSortingPrinter(cmd, printer), nil
|
||||
return maybeWrapSortingPrinter(printer, options), nil
|
||||
}
|
||||
|
||||
// extractOutputOptions parses printer specific commandline args and returns
|
||||
// printers.OutputsOptions object.
|
||||
func extractOutputOptions(cmd *cobra.Command) *printers.OutputOptions {
|
||||
// ExtractCmdPrintOptions parses printer specific commandline args and
|
||||
// returns a PrintOptions object.
|
||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags)
|
||||
func ExtractCmdPrintOptions(cmd *cobra.Command, withNamespace bool) *printers.PrintOptions {
|
||||
flags := cmd.Flags()
|
||||
|
||||
columnLabel, err := flags.GetStringSlice("label-columns")
|
||||
if err != nil {
|
||||
columnLabel = []string{}
|
||||
}
|
||||
|
||||
options := &printers.PrintOptions{
|
||||
NoHeaders: GetFlagBool(cmd, "no-headers"),
|
||||
Wide: GetWideFlag(cmd),
|
||||
ShowAll: GetFlagBool(cmd, "show-all"),
|
||||
ShowLabels: GetFlagBool(cmd, "show-labels"),
|
||||
AbsoluteTimestamps: isWatch(cmd),
|
||||
ColumnLabels: columnLabel,
|
||||
WithNamespace: withNamespace,
|
||||
}
|
||||
|
||||
var outputFormat string
|
||||
if flags.Lookup("output") != nil {
|
||||
outputFormat = GetFlagString(cmd, "output")
|
||||
}
|
||||
|
||||
if flags.Lookup("sort-by") != nil {
|
||||
options.SortBy = GetFlagString(cmd, "sort-by")
|
||||
}
|
||||
|
||||
// templates are logically optional for specifying a format.
|
||||
// TODO once https://github.com/kubernetes/kubernetes/issues/12668 is fixed, this should fall back to GetFlagString
|
||||
var templateFile string
|
||||
|
@ -146,29 +154,21 @@ func extractOutputOptions(cmd *cobra.Command) *printers.OutputOptions {
|
|||
|
||||
// this function may be invoked by a command that did not call AddPrinterFlags first, so we need
|
||||
// to be safe about how we access the allow-missing-template-keys flag
|
||||
allowMissingTemplateKeys := false
|
||||
if flags.Lookup("allow-missing-template-keys") != nil {
|
||||
allowMissingTemplateKeys = GetFlagBool(cmd, "allow-missing-template-keys")
|
||||
options.AllowMissingKeys = GetFlagBool(cmd, "allow-missing-template-keys")
|
||||
}
|
||||
|
||||
return &printers.OutputOptions{
|
||||
FmtType: outputFormat,
|
||||
FmtArg: templateFile,
|
||||
AllowMissingKeys: allowMissingTemplateKeys,
|
||||
}
|
||||
options.OutputFormatType = outputFormat
|
||||
options.OutputFormatArgument = templateFile
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
func maybeWrapSortingPrinter(cmd *cobra.Command, printer printers.ResourcePrinter) printers.ResourcePrinter {
|
||||
sorting, err := cmd.Flags().GetString("sort-by")
|
||||
if err != nil {
|
||||
// error can happen on missing flag or bad flag type. In either case, this command didn't intent to sort
|
||||
return printer
|
||||
}
|
||||
|
||||
if len(sorting) != 0 {
|
||||
func maybeWrapSortingPrinter(printer printers.ResourcePrinter, printOpts printers.PrintOptions) printers.ResourcePrinter {
|
||||
if len(printOpts.SortBy) != 0 {
|
||||
return &kubectl.SortingPrinter{
|
||||
Delegate: printer,
|
||||
SortField: fmt.Sprintf("{%s}", sorting),
|
||||
SortField: fmt.Sprintf("{%s}", printOpts.SortBy),
|
||||
}
|
||||
}
|
||||
return printer
|
||||
|
|
|
@ -57,6 +57,10 @@ func (fn ResourcePrinterFunc) IsGeneric() bool {
|
|||
}
|
||||
|
||||
type PrintOptions struct {
|
||||
// supported Format types can be found in pkg/printers/printers.go
|
||||
OutputFormatType string
|
||||
OutputFormatArgument string
|
||||
|
||||
NoHeaders bool
|
||||
WithNamespace bool
|
||||
WithKind bool
|
||||
|
@ -66,6 +70,11 @@ type PrintOptions struct {
|
|||
AbsoluteTimestamps bool
|
||||
Kind string
|
||||
ColumnLabels []string
|
||||
|
||||
SortBy string
|
||||
|
||||
// indicates if it is OK to ignore missing keys for rendering an output template.
|
||||
AllowMissingKeys bool
|
||||
}
|
||||
|
||||
// Describer generates output for the named resource or an error
|
||||
|
@ -100,13 +109,3 @@ type ErrNoDescriber struct {
|
|||
func (e ErrNoDescriber) Error() string {
|
||||
return fmt.Sprintf("no describer has been defined for %v", e.Types)
|
||||
}
|
||||
|
||||
// OutputOptions represents resource output options which is used to generate a resource printer.
|
||||
type OutputOptions struct {
|
||||
// supported Format types can be found in pkg/printers/printers.go
|
||||
FmtType string
|
||||
FmtArg string
|
||||
|
||||
// indicates if it is OK to ignore missing keys for rendering an output template.
|
||||
AllowMissingKeys bool
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ func TestPrintDefault(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range printerTests {
|
||||
printer, err := printers.GetStandardPrinter(&printers.OutputOptions{AllowMissingKeys: false}, false, nil, nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{})
|
||||
printer, err := printers.GetStandardPrinter(nil, nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
|
@ -254,24 +254,24 @@ func TestPrinter(t *testing.T) {
|
|||
|
||||
printerTests := []struct {
|
||||
Name string
|
||||
OutputOpts *printers.OutputOptions
|
||||
PrintOpts *printers.PrintOptions
|
||||
Input runtime.Object
|
||||
OutputVersions []schema.GroupVersion
|
||||
Expect string
|
||||
}{
|
||||
{"test json", &printers.OutputOptions{FmtType: "json", AllowMissingKeys: true}, simpleTest, nil, "{\n \"Data\": \"foo\"\n}\n"},
|
||||
{"test yaml", &printers.OutputOptions{FmtType: "yaml", AllowMissingKeys: true}, simpleTest, nil, "Data: foo\n"},
|
||||
{"test template", &printers.OutputOptions{FmtType: "template", FmtArg: "{{if .id}}{{.id}}{{end}}{{if .metadata.name}}{{.metadata.name}}{{end}}", AllowMissingKeys: true},
|
||||
{"test json", &printers.PrintOptions{OutputFormatType: "json", AllowMissingKeys: true}, simpleTest, nil, "{\n \"Data\": \"foo\"\n}\n"},
|
||||
{"test yaml", &printers.PrintOptions{OutputFormatType: "yaml", AllowMissingKeys: true}, simpleTest, nil, "Data: foo\n"},
|
||||
{"test template", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{if .id}}{{.id}}{{end}}{{if .metadata.name}}{{.metadata.name}}{{end}}", AllowMissingKeys: true},
|
||||
podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"},
|
||||
{"test jsonpath", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.metadata.name}", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"},
|
||||
{"test jsonpath list", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.items[*].metadata.name}", AllowMissingKeys: true}, podListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo bar"},
|
||||
{"test jsonpath empty list", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.items[*].metadata.name}", AllowMissingKeys: true}, emptyListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, ""},
|
||||
{"test name", &printers.OutputOptions{FmtType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pods/foo\n"},
|
||||
{"emits versioned objects", &printers.OutputOptions{FmtType: "template", FmtArg: "{{.kind}}", AllowMissingKeys: true}, testapi, []schema.GroupVersion{v1.SchemeGroupVersion}, "Pod"},
|
||||
{"test jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.metadata.name}", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"},
|
||||
{"test jsonpath list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, podListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo bar"},
|
||||
{"test jsonpath empty list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, emptyListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, ""},
|
||||
{"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pods/foo\n"},
|
||||
{"emits versioned objects", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.kind}}", AllowMissingKeys: true}, testapi, []schema.GroupVersion{v1.SchemeGroupVersion}, "Pod"},
|
||||
}
|
||||
for _, test := range printerTests {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
printer, err := printers.GetStandardPrinter(test.OutputOpts, false, legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{})
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
|
@ -290,18 +290,18 @@ func TestPrinter(t *testing.T) {
|
|||
|
||||
func TestBadPrinter(t *testing.T) {
|
||||
badPrinterTests := []struct {
|
||||
Name string
|
||||
OutputOpts *printers.OutputOptions
|
||||
Error error
|
||||
Name string
|
||||
PrintOpts *printers.PrintOptions
|
||||
Error error
|
||||
}{
|
||||
{"empty template", &printers.OutputOptions{FmtType: "template", AllowMissingKeys: false}, fmt.Errorf("template format specified but no template given")},
|
||||
{"bad template", &printers.OutputOptions{FmtType: "template", FmtArg: "{{ .Name", AllowMissingKeys: false}, fmt.Errorf("error parsing template {{ .Name, template: output:1: unclosed action\n")},
|
||||
{"bad templatefile", &printers.OutputOptions{FmtType: "templatefile", AllowMissingKeys: false}, fmt.Errorf("templatefile format specified but no template file given")},
|
||||
{"bad jsonpath", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.Name", AllowMissingKeys: false}, fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")},
|
||||
{"unknown format", &printers.OutputOptions{FmtType: "anUnknownFormat", FmtArg: "", AllowMissingKeys: false}, fmt.Errorf("output format \"anUnknownFormat\" not recognized")},
|
||||
{"empty template", &printers.PrintOptions{OutputFormatType: "template", AllowMissingKeys: false}, fmt.Errorf("template format specified but no template given")},
|
||||
{"bad template", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{ .Name", AllowMissingKeys: false}, fmt.Errorf("error parsing template {{ .Name, template: output:1: unclosed action\n")},
|
||||
{"bad templatefile", &printers.PrintOptions{OutputFormatType: "templatefile", AllowMissingKeys: false}, fmt.Errorf("templatefile format specified but no template file given")},
|
||||
{"bad jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.Name", AllowMissingKeys: false}, fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")},
|
||||
{"unknown format", &printers.PrintOptions{OutputFormatType: "anUnknownFormat", OutputFormatArgument: "", AllowMissingKeys: false}, fmt.Errorf("output format \"anUnknownFormat\" not recognized")},
|
||||
}
|
||||
for _, test := range badPrinterTests {
|
||||
_, err := printers.GetStandardPrinter(test.OutputOpts, false, legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{})
|
||||
_, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err == nil || err.Error() != test.Error.Error() {
|
||||
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
|
||||
}
|
||||
|
@ -494,8 +494,8 @@ func TestNamePrinter(t *testing.T) {
|
|||
},
|
||||
"pods/foo\npods/bar\n"},
|
||||
}
|
||||
outputOpts := &printers.OutputOptions{FmtType: "name", AllowMissingKeys: false}
|
||||
printer, _ := printers.GetStandardPrinter(outputOpts, false, legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{})
|
||||
printOpts := &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: false}
|
||||
printer, _ := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts)
|
||||
for name, item := range tests {
|
||||
buff := &bytes.Buffer{}
|
||||
err := printer.PrintObj(item.obj, buff)
|
||||
|
@ -2793,20 +2793,20 @@ func TestPrintPodDisruptionBudget(t *testing.T) {
|
|||
|
||||
func TestAllowMissingKeys(t *testing.T) {
|
||||
tests := []struct {
|
||||
Name string
|
||||
OutputOpts *printers.OutputOptions
|
||||
Input runtime.Object
|
||||
Expect string
|
||||
Error string
|
||||
Name string
|
||||
PrintOpts *printers.PrintOptions
|
||||
Input runtime.Object
|
||||
Expect string
|
||||
Error string
|
||||
}{
|
||||
{"test template, allow missing keys", &printers.OutputOptions{FmtType: "template", FmtArg: "{{.blarg}}", AllowMissingKeys: true}, &api.Pod{}, "<no value>", ""},
|
||||
{"test template, strict", &printers.OutputOptions{FmtType: "template", FmtArg: "{{.blarg}}", AllowMissingKeys: false}, &api.Pod{}, "", `error executing template "{{.blarg}}": template: output:1:2: executing "output" at <.blarg>: map has no entry for key "blarg"`},
|
||||
{"test jsonpath, allow missing keys", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.blarg}", AllowMissingKeys: true}, &api.Pod{}, "", ""},
|
||||
{"test jsonpath, strict", &printers.OutputOptions{FmtType: "jsonpath", FmtArg: "{.blarg}", AllowMissingKeys: false}, &api.Pod{}, "", "error executing jsonpath \"{.blarg}\": blarg is not found\n"},
|
||||
{"test template, allow missing keys", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.blarg}}", AllowMissingKeys: true}, &api.Pod{}, "<no value>", ""},
|
||||
{"test template, strict", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.blarg}}", AllowMissingKeys: false}, &api.Pod{}, "", `error executing template "{{.blarg}}": template: output:1:2: executing "output" at <.blarg>: map has no entry for key "blarg"`},
|
||||
{"test jsonpath, allow missing keys", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.blarg}", AllowMissingKeys: true}, &api.Pod{}, "", ""},
|
||||
{"test jsonpath, strict", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.blarg}", AllowMissingKeys: false}, &api.Pod{}, "", "error executing jsonpath \"{.blarg}\": blarg is not found\n"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
printer, err := printers.GetStandardPrinter(test.OutputOpts, false, legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{})
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
|
|
|
@ -29,12 +29,8 @@ import (
|
|||
// a printer or an error. The printer is agnostic to schema versions, so you must
|
||||
// send arguments to PrintObj in the version you wish them to be shown using a
|
||||
// VersionedPrinter (typically when generic is true).
|
||||
func GetStandardPrinter(outputOpts *OutputOptions, noHeaders bool, mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options PrintOptions) (ResourcePrinter, error) {
|
||||
if outputOpts == nil {
|
||||
return nil, fmt.Errorf("no output options specified")
|
||||
}
|
||||
|
||||
format, formatArgument, allowMissingTemplateKeys := outputOpts.FmtType, outputOpts.FmtArg, outputOpts.AllowMissingKeys
|
||||
func GetStandardPrinter(mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options PrintOptions) (ResourcePrinter, error) {
|
||||
format, formatArgument, allowMissingTemplateKeys := options.OutputFormatType, options.OutputFormatArgument, options.AllowMissingKeys
|
||||
|
||||
var printer ResourcePrinter
|
||||
switch format {
|
||||
|
@ -106,7 +102,7 @@ func GetStandardPrinter(outputOpts *OutputOptions, noHeaders bool, mapper meta.R
|
|||
|
||||
case "custom-columns":
|
||||
var err error
|
||||
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, decoders[0], noHeaders); err != nil {
|
||||
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, decoders[0], options.NoHeaders); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue