Get cmd uses print-column extn from Openapi schema

Get command now uses metadata x-kubernetes-print-columns, if present, in Openapi schema
to format output for a resource. This functionality is guarded by a boolean
flag 'use-openapi-print-columns'.
This commit is contained in:
Sunil Arora
2017-05-19 14:24:39 -07:00
parent 4a01f44b73
commit f768a63fb0
18 changed files with 309 additions and 89 deletions

View File

@@ -233,10 +233,12 @@ type BuilderFactory interface {
// 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, options printers.PrintOptions) (printers.ResourcePrinter, error)
PrinterForCommand(cmd *cobra.Command, outputOpts *printers.OutputOptions, 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).
PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error)
// 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, outputOpts *printers.OutputOptions, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error)
// PrintObject prints an api object given command line flags to modify the output format
PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error
// One stop shopping for a Builder

View File

@@ -48,7 +48,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
return f
}
func (f *ring2Factory) PrinterForCommand(cmd *cobra.Command, options printers.PrintOptions) (printers.ResourcePrinter, error) {
func (f *ring2Factory) PrinterForCommand(cmd *cobra.Command, outputOpts *printers.OutputOptions, options printers.PrintOptions) (printers.ResourcePrinter, error) {
mapper, typer, err := f.objectMappingFactory.UnstructuredObject()
if err != nil {
return nil, err
@@ -56,10 +56,10 @@ func (f *ring2Factory) PrinterForCommand(cmd *cobra.Command, options printers.Pr
// 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, mapper, typer, encoder, decoders, options)
return PrinterForCommand(cmd, outputOpts, mapper, typer, encoder, decoders, options)
}
func (f *ring2Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinter, error) {
func (f *ring2Factory) PrinterForMapping(cmd *cobra.Command, 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 {
@@ -76,7 +76,7 @@ func (f *ring2Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTM
ColumnLabels: columnLabel,
}
printer, err := f.PrinterForCommand(cmd, options)
printer, err := f.PrinterForCommand(cmd, outputOpts, options)
if err != nil {
return nil, err
}
@@ -132,7 +132,7 @@ func (f *ring2Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, o
return err
}
printer, err := f.PrinterForMapping(cmd, mapping, false)
printer, err := f.PrinterForMapping(cmd, nil, mapping, false)
if err != nil {
return err
}

View File

@@ -27,7 +27,7 @@ import (
"sync"
"time"
"github.com/emicklei/go-restful-swagger12"
swagger "github.com/emicklei/go-restful-swagger12"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@@ -417,6 +417,10 @@ func AddOpenAPIFlags(cmd *cobra.Command) {
cmd.MarkFlagFilename("schema-cache-dir")
}
func GetOpenAPICacheDir(cmd *cobra.Command) string {
return GetFlagString(cmd, "schema-cache-dir")
}
func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) {
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, "Filename, directory, or URL to files "+usage)
cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.")

View File

@@ -12,6 +12,7 @@ go_library(
name = "go_default_library",
srcs = [
"doc.go",
"extensions.go",
"openapi.go",
"openapi_cache.go",
"openapi_getter.go",

View File

@@ -0,0 +1,26 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package openapi
import "github.com/go-openapi/spec"
const PrintColumnsKey = "x-kubernetes-print-columns"
// GetPrintColumns looks for the open API extension for the display columns.
func GetPrintColumns(extensions spec.Extensions) (string, bool) {
return extensions.GetString(PrintColumnsKey)
}

View File

@@ -194,7 +194,7 @@ func (o *Resources) parseDefinition(name string, s spec.Schema) Kind {
Fields: map[string]Type{},
}
if err != nil {
glog.Warning(err)
glog.V(2).Info(err)
}
// Definition represents a primitive type - e.g.

View File

@@ -105,38 +105,18 @@ func ValidateOutputArgs(cmd *cobra.Command) error {
return nil
}
// PrinterForCommand returns the default printer for this command.
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
func PrinterForCommand(cmd *cobra.Command, mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options printers.PrintOptions) (printers.ResourcePrinter, error) {
outputFormat := GetFlagString(cmd, "output")
// PrinterForCommand 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) {
// 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
templateFile, _ := cmd.Flags().GetString("template")
if len(outputFormat) == 0 && len(templateFile) != 0 {
outputFormat = "template"
if outputOpts == nil {
outputOpts = extractOutputOptions(cmd)
}
templateFormat := []string{
"go-template=", "go-template-file=", "jsonpath=", "jsonpath-file=", "custom-columns=", "custom-columns-file=",
}
for _, format := range templateFormat {
if strings.HasPrefix(outputFormat, format) {
templateFile = outputFormat[len(format):]
outputFormat = format[:len(format)-1]
}
}
// 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 cmd.Flags().Lookup("allow-missing-template-keys") != nil {
allowMissingTemplateKeys = GetFlagBool(cmd, "allow-missing-template-keys")
}
printer, err := printers.GetStandardPrinter(
outputFormat, templateFile, GetFlagBool(cmd, "no-headers"), allowMissingTemplateKeys,
mapper, typer, encoder, decoders, options,
)
printer, err := printers.GetStandardPrinter(outputOpts,
GetFlagBool(cmd, "no-headers"), mapper, typer, encoder, decoders, options)
if err != nil {
return nil, err
}
@@ -149,12 +129,12 @@ func PrinterForCommand(cmd *cobra.Command, mapper meta.RESTMapper, typer runtime
// object passed is non-generic, it attempts to print the object using a HumanReadablePrinter.
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
func PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, f Factory, out io.Writer) error {
printer, err := f.PrinterForCommand(cmd, printers.PrintOptions{})
printer, err := f.PrinterForCommand(cmd, nil, printers.PrintOptions{})
if err != nil {
return err
}
if !printer.IsGeneric() {
printer, err = f.PrinterForMapping(cmd, nil, false)
printer, err = f.PrinterForMapping(cmd, nil, nil, false)
if err != nil {
return err
}
@@ -162,6 +142,50 @@ func PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, f Fact
return printer.PrintObj(info.Object, out)
}
// extractOutputOptions parses printer specific commandline args and returns
// printers.OutputsOptions object.
func extractOutputOptions(cmd *cobra.Command) *printers.OutputOptions {
flags := cmd.Flags()
var outputFormat string
if flags.Lookup("output") != nil {
outputFormat = GetFlagString(cmd, "output")
}
// 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
if flags.Lookup("template") != nil {
templateFile = GetFlagString(cmd, "template")
}
if len(outputFormat) == 0 && len(templateFile) != 0 {
outputFormat = "template"
}
templateFormats := []string{
"go-template=", "go-template-file=", "jsonpath=", "jsonpath-file=", "custom-columns=", "custom-columns-file=",
}
for _, format := range templateFormats {
if strings.HasPrefix(outputFormat, format) {
templateFile = outputFormat[len(format):]
outputFormat = format[:len(format)-1]
}
}
// 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")
}
return &printers.OutputOptions{
FmtType: outputFormat,
FmtArg: templateFile,
AllowMissingKeys: allowMissingTemplateKeys,
}
}
func maybeWrapSortingPrinter(cmd *cobra.Command, printer printers.ResourcePrinter) printers.ResourcePrinter {
sorting, err := cmd.Flags().GetString("sort-by")
if err != nil {