Merge pull request #35810 from deads2k/client-18-decode-status

Automatic merge from submit-queue

always allow decoding of status when returned from the API

`unversioned.Status` should be able to come back from any API version and still be properly decoded.  This doesn't happen today by default.

@smarterclayton  Our projectrequest endpoint returns a `Status` object on a 200 return from list to indicate everything went well.  This (or something like it) is needed to make the API accepted by `kubectl`.  Alternatively, we change the API to return a different (still not a `Project`) value from list, which still feels wrong.
This commit is contained in:
Kubernetes Submit Queue 2016-11-03 11:18:23 -07:00 committed by GitHub
commit 7c391158e3
3 changed files with 45 additions and 7 deletions

View File

@ -173,9 +173,16 @@ func createSerializers(config ContentConfig) (*Serializers, error) {
info = mediaTypes[0] info = mediaTypes[0]
} }
internalGV := unversioned.GroupVersion{ internalGV := unversioned.GroupVersions{
{
Group: config.GroupVersion.Group, Group: config.GroupVersion.Group,
Version: runtime.APIVersionInternal, 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{ s := &Serializers{

View File

@ -47,6 +47,26 @@ type TestParam struct {
testBodyErrorIsNotNil bool 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) { func TestDoRequestSuccess(t *testing.T) {
testServer, fakeHandler, status := testServerEnv(t, 200) testServer, fakeHandler, status := testServerEnv(t, 200)
defer testServer.Close() defer testServer.Close()
@ -197,10 +217,11 @@ func TestBadRequest(t *testing.T) {
} }
func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utiltesting.FakeHandler) { func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utiltesting.FakeHandler) {
if testParam.expectingError { switch {
if testParam.actualError == nil { case testParam.expectingError && testParam.actualError == nil:
t.Errorf("Expected error") t.Errorf("Expected error")
} case !testParam.expectingError && testParam.actualError != nil:
t.Error(testParam.actualError)
} }
if !testParam.expCreated { if !testParam.expCreated {
if testParam.actualCreated { if testParam.actualCreated {

View File

@ -489,6 +489,7 @@ var (
clusterRoleColumns = []string{"NAME", "AGE"} clusterRoleColumns = []string{"NAME", "AGE"}
clusterRoleBindingColumns = []string{"NAME", "AGE"} clusterRoleBindingColumns = []string{"NAME", "AGE"}
storageClassColumns = []string{"NAME", "TYPE"} storageClassColumns = []string{"NAME", "TYPE"}
statusColumns = []string{"STATUS", "REASON", "MESSAGE"}
// TODO: consider having 'KIND' for third party resource data // TODO: consider having 'KIND' for third party resource data
thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"} thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"}
@ -591,6 +592,7 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(certificateSigningRequestColumns, printCertificateSigningRequestList) h.Handler(certificateSigningRequestColumns, printCertificateSigningRequestList)
h.Handler(storageClassColumns, printStorageClass) h.Handler(storageClassColumns, printStorageClass)
h.Handler(storageClassColumns, printStorageClassList) h.Handler(storageClassColumns, printStorageClassList)
h.Handler(statusColumns, printStatus)
} }
func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error { 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 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 { func AppendLabels(itemLabels map[string]string, columnLabels []string) string {
var buffer bytes.Buffer var buffer bytes.Buffer