diff --git a/pkg/printers/BUILD b/pkg/printers/BUILD index cafea756599..89fb01796a4 100644 --- a/pkg/printers/BUILD +++ b/pkg/printers/BUILD @@ -13,6 +13,7 @@ go_library( "humanreadable.go", "interface.go", "json.go", + "json_yaml_flags.go", "jsonpath.go", "name.go", "printers.go", @@ -24,6 +25,7 @@ go_library( deps = [ "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", @@ -39,7 +41,10 @@ go_library( go_test( name = "go_default_xtest", - srcs = ["customcolumn_test.go"], + srcs = [ + "customcolumn_test.go", + "json_yaml_flags_test.go", + ], deps = [ ":go_default_library", "//pkg/api/legacyscheme:go_default_library", diff --git a/pkg/printers/json_yaml_flags.go b/pkg/printers/json_yaml_flags.go new file mode 100644 index 00000000000..6ef587b6491 --- /dev/null +++ b/pkg/printers/json_yaml_flags.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 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 printers + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" +) + +// JSONYamlPrintFlags provides default flags necessary for json/yaml printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type JSONYamlPrintFlags struct{} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling --output=(yaml|json) printing. +// Returns false if the specified outputFormat does not match a supported format. +// Supported Format types can be found in pkg/printers/printers.go +func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool, error) { + outputFormat = strings.ToLower(outputFormat) + switch outputFormat { + case "json": + return &JSONPrinter{}, true, nil + case "yaml": + return &YAMLPrinter{}, true, nil + case "": + return nil, false, fmt.Errorf("missing output format") + default: + return nil, false, nil + } +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to JSON or Yaml printing to it +func (f *JSONYamlPrintFlags) AddFlags(c *cobra.Command) {} + +// NewJSONYamlPrintFlags returns flags associated with +// yaml or json printing, with default values set. +func NewJSONYamlPrintFlags() *JSONYamlPrintFlags { + return &JSONYamlPrintFlags{} +} diff --git a/pkg/printers/json_yaml_flags_test.go b/pkg/printers/json_yaml_flags_test.go new file mode 100644 index 00000000000..bd56bf3d0cb --- /dev/null +++ b/pkg/printers/json_yaml_flags_test.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 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 printers_test + +import ( + "bytes" + "strings" + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/printers" +) + +func TestPrinterSupportsExpectedJSONYamlFormats(t *testing.T) { + testObject := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + + testCases := []struct { + name string + outputFormat string + expectedOutput string + expectNoMatch bool + }{ + { + name: "json output format matches a json printer", + outputFormat: "json", + expectedOutput: "\"name\": \"foo\"", + }, + { + name: "yaml output format matches a yaml printer", + outputFormat: "yaml", + expectedOutput: "name: foo", + }, + { + name: "output format for another printer does not match a json/yaml printer", + outputFormat: "jsonpath", + expectNoMatch: true, + }, + { + name: "invalid output format results in no match", + outputFormat: "invalid", + expectNoMatch: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + printFlags := printers.JSONYamlPrintFlags{} + + p, matched, err := printFlags.ToPrinter(tc.outputFormat) + if tc.expectNoMatch { + if matched { + t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) + } + return + } + if !matched { + t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + out := bytes.NewBuffer([]byte{}) + err = p.PrintObj(testObject, out) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if !strings.Contains(out.String(), tc.expectedOutput) { + t.Errorf("unexpected output: expecting %q, got %q", tc.expectedOutput, out.String()) + } + }) + } +} diff --git a/pkg/printers/printers.go b/pkg/printers/printers.go index 357faf498a4..d0df738f9d8 100644 --- a/pkg/printers/printers.go +++ b/pkg/printers/printers.go @@ -34,11 +34,17 @@ func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, deco var printer ResourcePrinter switch format { - case "json": - printer = &JSONPrinter{} + case "json", "yaml": + jsonYamlFlags := NewJSONYamlPrintFlags() + p, matched, err := jsonYamlFlags.ToPrinter(format) + if !matched { + return nil, fmt.Errorf("unable to match a printer to handle current print options") + } + if err != nil { + return nil, err + } - case "yaml": - printer = &YAMLPrinter{} + printer = p case "name": printer = &NamePrinter{