From 235678d591f33f8195b90eb005c4e9710a89e4e5 Mon Sep 17 00:00:00 2001 From: deads2k Date: Fri, 28 Oct 2016 14:15:14 -0400 Subject: [PATCH] always allow decoding of status when returned from the API --- pkg/client/restclient/client.go | 13 ++++++++++--- pkg/client/restclient/client_test.go | 29 ++++++++++++++++++++++++---- pkg/kubectl/resource_printer.go | 10 ++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pkg/client/restclient/client.go b/pkg/client/restclient/client.go index 52bf13d936..69759f7a0f 100644 --- a/pkg/client/restclient/client.go +++ b/pkg/client/restclient/client.go @@ -173,9 +173,16 @@ func createSerializers(config ContentConfig) (*Serializers, error) { info = mediaTypes[0] } - internalGV := unversioned.GroupVersion{ - Group: config.GroupVersion.Group, - Version: runtime.APIVersionInternal, + internalGV := unversioned.GroupVersions{ + { + Group: config.GroupVersion.Group, + Version: runtime.APIVersionInternal, + }, + // always include the legacy group as a decoding target to handle non-error `Status` return types + { + Group: "", + Version: runtime.APIVersionInternal, + }, } s := &Serializers{ diff --git a/pkg/client/restclient/client_test.go b/pkg/client/restclient/client_test.go index 009a2febcc..8c91c4beac 100644 --- a/pkg/client/restclient/client_test.go +++ b/pkg/client/restclient/client_test.go @@ -47,6 +47,26 @@ type TestParam struct { testBodyErrorIsNotNil bool } +// TestSerializer makes sure that you're always able to decode an unversioned API object +func TestSerializer(t *testing.T) { + contentConfig := ContentConfig{ + ContentType: "application/json", + GroupVersion: &unversioned.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, + NegotiatedSerializer: api.Codecs, + } + + serializer, err := createSerializers(contentConfig) + if err != nil { + t.Fatal(err) + } + // bytes based on actual return from API server when encoding an "unversioned" object + obj, err := runtime.Decode(serializer.Decoder, []byte(`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Success"}`)) + t.Log(obj) + if err != nil { + t.Fatal(err) + } +} + func TestDoRequestSuccess(t *testing.T) { testServer, fakeHandler, status := testServerEnv(t, 200) defer testServer.Close() @@ -162,10 +182,11 @@ func TestBadRequest(t *testing.T) { } func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utiltesting.FakeHandler) { - if testParam.expectingError { - if testParam.actualError == nil { - t.Errorf("Expected error") - } + switch { + case testParam.expectingError && testParam.actualError == nil: + t.Errorf("Expected error") + case !testParam.expectingError && testParam.actualError != nil: + t.Error(testParam.actualError) } if !testParam.expCreated { if testParam.actualCreated { diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index e2736ba21f..4bd5749ecb 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -489,6 +489,7 @@ var ( clusterRoleColumns = []string{"NAME", "AGE"} clusterRoleBindingColumns = []string{"NAME", "AGE"} storageClassColumns = []string{"NAME", "TYPE"} + statusColumns = []string{"STATUS", "REASON", "MESSAGE"} // TODO: consider having 'KIND' for third party resource data thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"} @@ -591,6 +592,7 @@ func (h *HumanReadablePrinter) addDefaultHandlers() { h.Handler(certificateSigningRequestColumns, printCertificateSigningRequestList) h.Handler(storageClassColumns, printStorageClass) h.Handler(storageClassColumns, printStorageClassList) + h.Handler(statusColumns, printStatus) } func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error { @@ -2114,6 +2116,14 @@ func printStorageClassList(scList *storage.StorageClassList, w io.Writer, option return nil } +func printStatus(status *unversioned.Status, w io.Writer, options PrintOptions) error { + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", status.Status, status.Reason, status.Message); err != nil { + return err + } + + return nil +} + func AppendLabels(itemLabels map[string]string, columnLabels []string) string { var buffer bytes.Buffer