kubectl resource printing: actually do versioned print

This commit is contained in:
Daniel Smith 2014-11-11 15:29:01 -08:00
parent f1b0b64a75
commit 6fa6d3ee3e
2 changed files with 62 additions and 21 deletions

View File

@ -37,6 +37,7 @@ import (
// GetPrinter returns a resource printer and a bool indicating whether the object must be // GetPrinter returns a resource printer and a bool indicating whether the object must be
// versioned for the given format. // 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) { func GetPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (ResourcePrinter, bool, error) {
versioned := true versioned := true
var printer ResourcePrinter 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. // 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 { 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 { if err != nil {
return err 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 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. // YAMLPrinter is an implementation of ResourcePrinter which parsess JSON, and re-formats as YAML.
type YAMLPrinter struct{} type YAMLPrinter struct{}
// PrintObj prints the data as YAML. // PrintObj prints the data as YAML.
func (y *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { 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 { if err != nil {
return err return err
} }
@ -328,12 +350,7 @@ func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
// PrintObj formats the obj with the Go Template. // PrintObj formats the obj with the Go Template.
func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
data, err := latest.Codec.Encode(obj) outObj, err := toVersionedMap(obj)
if err != nil {
return err
}
outObj := map[string]interface{}{}
err = json.Unmarshal(data, &outObj)
if err != nil { if err != nil {
return err return err
} }

View File

@ -25,10 +25,15 @@ import (
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"gopkg.in/v1/yaml" "gopkg.in/v1/yaml"
) )
type testStruct struct { type testStruct struct {
api.TypeMeta `yaml:",inline" json:",inline"`
api.ObjectMeta `yaml:"metadata,omitempty" json:"metadata,omitempty"`
Key string `yaml:"Key" json:"Key"` Key string `yaml:"Key" json:"Key"`
Map map[string]int `yaml:"Map" json:"Map"` Map map[string]int `yaml:"Map" json:"Map"`
StringList []string `yaml:"StringList" json:"StringList"` StringList []string `yaml:"StringList" json:"StringList"`
@ -37,11 +42,16 @@ type testStruct struct {
func (ts *testStruct) IsAnAPIObject() {} func (ts *testStruct) IsAnAPIObject() {}
func init() {
api.Scheme.AddKnownTypes("", &testStruct{})
api.Scheme.AddKnownTypes(latest.Version, &testStruct{})
}
var testData = testStruct{ var testData = testStruct{
"testValue", Key: "testValue",
map[string]int{"TestSubkey": 1}, Map: map[string]int{"TestSubkey": 1},
[]string{"a", "b", "c"}, StringList: []string{"a", "b", "c"},
[]int{1, 2, 3}, IntList: []int{1, 2, 3},
} }
func TestYAMLPrinter(t *testing.T) { func TestYAMLPrinter(t *testing.T) {
@ -128,12 +138,19 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data
t.Fatal(err) t.Fatal(err)
} }
var poutput testStruct 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(testData, poutput) { 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{ obj := &api.Pod{
@ -142,12 +159,19 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data
buf.Reset() buf.Reset()
printer.PrintObj(obj, buf) printer.PrintObj(obj, buf)
var objOut api.Pod 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 { if err != nil {
t.Errorf("Unexpeted error: %#v", err) 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) { 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))
} }
} }