From 6fa6d3ee3e30ef6f19f059a0f45ae3835f2cd1cd Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Tue, 11 Nov 2014 15:29:01 -0800 Subject: [PATCH] kubectl resource printing: actually do versioned print --- pkg/kubectl/resource_printer.go | 35 ++++++++++++++------ pkg/kubectl/resource_printer_test.go | 48 +++++++++++++++++++++------- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 1fa60a51dd2..ec2f1978338 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -37,6 +37,7 @@ import ( // GetPrinter returns a resource printer and a bool indicating whether the object must be // versioned for the given format. +// TODO: remove the 'versioned' return value, replace with method on ResourcePrinter. func GetPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (ResourcePrinter, bool, error) { versioned := true var printer ResourcePrinter @@ -86,20 +87,41 @@ type JSONPrinter struct{} // PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer. func (i *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - output, err := json.MarshalIndent(obj, "", " ") + data, err := latest.Codec.Encode(obj) if err != nil { return err } - _, err = fmt.Fprint(w, string(output)+"\n") + dst := bytes.Buffer{} + err = json.Indent(&dst, data, "", " ") + dst.WriteByte('\n') + _, err = w.Write(dst.Bytes()) return err } +func toVersionedMap(obj runtime.Object) (map[string]interface{}, error) { + data, err := latest.Codec.Encode(obj) + if err != nil { + return nil, err + } + outObj := map[string]interface{}{} + err = json.Unmarshal(data, &outObj) + if err != nil { + return nil, err + } + return outObj, nil +} + // YAMLPrinter is an implementation of ResourcePrinter which parsess JSON, and re-formats as YAML. type YAMLPrinter struct{} // PrintObj prints the data as YAML. func (y *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - output, err := yaml.Marshal(obj) + outObj, err := toVersionedMap(obj) + if err != nil { + return err + } + + output, err := yaml.Marshal(outObj) if err != nil { return err } @@ -328,12 +350,7 @@ func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) { // PrintObj formats the obj with the Go Template. func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { - data, err := latest.Codec.Encode(obj) - if err != nil { - return err - } - outObj := map[string]interface{}{} - err = json.Unmarshal(data, &outObj) + outObj, err := toVersionedMap(obj) if err != nil { return err } diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index fc7c6b6bd8d..b52580976a4 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -25,23 +25,33 @@ import ( "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "gopkg.in/v1/yaml" ) type testStruct struct { - Key string `yaml:"Key" json:"Key"` - Map map[string]int `yaml:"Map" json:"Map"` - StringList []string `yaml:"StringList" json:"StringList"` - IntList []int `yaml:"IntList" json:"IntList"` + api.TypeMeta `yaml:",inline" json:",inline"` + api.ObjectMeta `yaml:"metadata,omitempty" json:"metadata,omitempty"` + Key string `yaml:"Key" json:"Key"` + Map map[string]int `yaml:"Map" json:"Map"` + StringList []string `yaml:"StringList" json:"StringList"` + IntList []int `yaml:"IntList" json:"IntList"` } func (ts *testStruct) IsAnAPIObject() {} +func init() { + api.Scheme.AddKnownTypes("", &testStruct{}) + api.Scheme.AddKnownTypes(latest.Version, &testStruct{}) +} + var testData = testStruct{ - "testValue", - map[string]int{"TestSubkey": 1}, - []string{"a", "b", "c"}, - []int{1, 2, 3}, + Key: "testValue", + Map: map[string]int{"TestSubkey": 1}, + StringList: []string{"a", "b", "c"}, + IntList: []int{1, 2, 3}, } func TestYAMLPrinter(t *testing.T) { @@ -128,12 +138,19 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data t.Fatal(err) } var poutput testStruct - err = yaml.Unmarshal(buf.Bytes(), &poutput) + // Verify that given function runs without error. + err = unmarshalFunc(buf.Bytes(), &poutput) + if err != nil { + t.Fatal(err) + } + // Use real decode function to undo the versioning process. + poutput = testStruct{} + err = latest.Codec.DecodeInto(buf.Bytes(), &poutput) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(testData, poutput) { - t.Errorf("Test data and unmarshaled data are not equal: %#v vs %#v", poutput, testData) + t.Errorf("Test data and unmarshaled data are not equal: %v", util.ObjectDiff(poutput, testData)) } obj := &api.Pod{ @@ -142,12 +159,19 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data buf.Reset() printer.PrintObj(obj, buf) var objOut api.Pod - err = yaml.Unmarshal([]byte(buf.String()), &objOut) + // Verify that given function runs without error. + err = unmarshalFunc(buf.Bytes(), &objOut) if err != nil { t.Errorf("Unexpeted error: %#v", err) } + // Use real decode function to undo the versioning process. + objOut = api.Pod{} + err = latest.Codec.DecodeInto(buf.Bytes(), &objOut) + if err != nil { + t.Fatal(err) + } if !reflect.DeepEqual(obj, &objOut) { - t.Errorf("Unexpected inequality:\n%#v \nvs\n%#v", obj, &objOut) + t.Errorf("Unexpected inequality:\n%v", util.ObjectDiff(obj, &objOut)) } }