API server should offer metav1 Table/Partial transforms
Now that internal types are equivalent, allow the apiserver to serve metav1 and metav1beta1 depending on the client. Test that in the apiserver integration test and ensure we get the appropriate responses. Register the metav1 type in the appropriate external locations. Kubernetes-commit: 33a3e325f754d179b25558dee116fca1c67d353a
This commit is contained in:
parent
d498040504
commit
1394d8d85c
|
|
@ -1749,14 +1749,14 @@ func TestGetPretty(t *testing.T) {
|
||||||
pretty bool
|
pretty bool
|
||||||
}{
|
}{
|
||||||
{accept: runtime.ContentTypeJSON},
|
{accept: runtime.ContentTypeJSON},
|
||||||
{accept: runtime.ContentTypeJSON + ";pretty=0"},
|
{accept: "application/json;pretty=0"},
|
||||||
{accept: runtime.ContentTypeJSON, userAgent: "kubectl"},
|
{accept: runtime.ContentTypeJSON, userAgent: "kubectl"},
|
||||||
{accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"0"}}},
|
{accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"0"}}},
|
||||||
|
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "curl"},
|
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "curl"},
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "Mozilla/5.0"},
|
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "Mozilla/5.0"},
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "Wget"},
|
{pretty: true, accept: runtime.ContentTypeJSON, userAgent: "Wget"},
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON + ";pretty=1"},
|
{pretty: true, accept: "application/json;pretty=1"},
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"1"}}},
|
{pretty: true, accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"1"}}},
|
||||||
{pretty: true, accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"true"}}},
|
{pretty: true, accept: runtime.ContentTypeJSON, params: url.Values{"pretty": {"true"}}},
|
||||||
}
|
}
|
||||||
|
|
@ -1818,14 +1818,28 @@ func TestGetTable(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
partial := meta.AsPartialObjectMetadata(m)
|
var encodedV1Beta1Body []byte
|
||||||
partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
{
|
||||||
encodedBody, err := runtime.Encode(metainternalversion.Codecs.LegacyCodec(metav1beta1.SchemeGroupVersion), partial)
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
if err != nil {
|
partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
||||||
t.Fatal(err)
|
encodedBody, err := runtime.Encode(metainternalversion.Codecs.LegacyCodec(metav1beta1.SchemeGroupVersion), partial)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// the codec includes a trailing newline that is not present during decode
|
||||||
|
encodedV1Beta1Body = bytes.TrimSpace(encodedBody)
|
||||||
|
}
|
||||||
|
var encodedV1Body []byte
|
||||||
|
{
|
||||||
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
|
partial.GetObjectKind().SetGroupVersionKind(metav1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
||||||
|
encodedBody, err := runtime.Encode(metainternalversion.Codecs.LegacyCodec(metav1.SchemeGroupVersion), partial)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// the codec includes a trailing newline that is not present during decode
|
||||||
|
encodedV1Body = bytes.TrimSpace(encodedBody)
|
||||||
}
|
}
|
||||||
// the codec includes a trailing newline that is not present during decode
|
|
||||||
encodedBody = bytes.TrimSpace(encodedBody)
|
|
||||||
|
|
||||||
metaDoc := metav1.ObjectMeta{}.SwaggerDoc()
|
metaDoc := metav1.ObjectMeta{}.SwaggerDoc()
|
||||||
|
|
||||||
|
|
@ -1838,16 +1852,36 @@ func TestGetTable(t *testing.T) {
|
||||||
item bool
|
item bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1alpha1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accept: runtime.ContentTypeProtobuf + ";as=Table;v=v1;g=meta.k8s.io",
|
||||||
|
statusCode: http.StatusNotAcceptable,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
item: true,
|
item: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1;g=meta.k8s.io",
|
||||||
|
expected: &metav1.Table{
|
||||||
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1"},
|
||||||
|
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
|
||||||
|
ColumnDefinitions: []metav1.TableColumnDefinition{
|
||||||
|
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
|
||||||
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
|
},
|
||||||
|
Rows: []metav1.TableRow{
|
||||||
|
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Body}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
item: true,
|
||||||
|
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
expected: &metav1beta1.Table{
|
expected: &metav1beta1.Table{
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
||||||
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
|
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
|
||||||
|
|
@ -1856,7 +1890,7 @@ func TestGetTable(t *testing.T) {
|
||||||
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
},
|
},
|
||||||
Rows: []metav1beta1.TableRow{
|
Rows: []metav1beta1.TableRow{
|
||||||
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
|
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1864,7 +1898,7 @@ func TestGetTable(t *testing.T) {
|
||||||
item: true,
|
item: true,
|
||||||
accept: strings.Join([]string{
|
accept: strings.Join([]string{
|
||||||
runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
"application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
}, ","),
|
}, ","),
|
||||||
expected: &metav1beta1.Table{
|
expected: &metav1beta1.Table{
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
||||||
|
|
@ -1874,13 +1908,13 @@ func TestGetTable(t *testing.T) {
|
||||||
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
},
|
},
|
||||||
Rows: []metav1beta1.TableRow{
|
Rows: []metav1beta1.TableRow{
|
||||||
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
|
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: true,
|
item: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
params: url.Values{"includeObject": []string{"Metadata"}},
|
params: url.Values{"includeObject": []string{"Metadata"}},
|
||||||
expected: &metav1beta1.Table{
|
expected: &metav1beta1.Table{
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
||||||
|
|
@ -1890,12 +1924,12 @@ func TestGetTable(t *testing.T) {
|
||||||
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
},
|
},
|
||||||
Rows: []metav1beta1.TableRow{
|
Rows: []metav1beta1.TableRow{
|
||||||
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
|
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
params: url.Values{"includeObject": []string{"Metadata"}},
|
params: url.Values{"includeObject": []string{"Metadata"}},
|
||||||
expected: &metav1beta1.Table{
|
expected: &metav1beta1.Table{
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
|
||||||
|
|
@ -1905,7 +1939,7 @@ func TestGetTable(t *testing.T) {
|
||||||
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
},
|
},
|
||||||
Rows: []metav1beta1.TableRow{
|
Rows: []metav1beta1.TableRow{
|
||||||
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
|
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1996,6 +2030,13 @@ func TestWatchTable(t *testing.T) {
|
||||||
// the codec includes a trailing newline that is not present during decode
|
// the codec includes a trailing newline that is not present during decode
|
||||||
encodedBody = bytes.TrimSpace(encodedBody)
|
encodedBody = bytes.TrimSpace(encodedBody)
|
||||||
|
|
||||||
|
encodedBodyV1, err := runtime.Encode(metainternalversion.Codecs.LegacyCodec(metav1.SchemeGroupVersion), partial)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// the codec includes a trailing newline that is not present during decode
|
||||||
|
encodedBodyV1 = bytes.TrimSpace(encodedBodyV1)
|
||||||
|
|
||||||
metaDoc := metav1.ObjectMeta{}.SwaggerDoc()
|
metaDoc := metav1.ObjectMeta{}.SwaggerDoc()
|
||||||
|
|
||||||
s := metainternalversion.Codecs.SupportedMediaTypes()[0].Serializer
|
s := metainternalversion.Codecs.SupportedMediaTypes()[0].Serializer
|
||||||
|
|
@ -2011,11 +2052,11 @@ func TestWatchTable(t *testing.T) {
|
||||||
item bool
|
item bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1alpha1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
send: func(w *watch.FakeWatcher) {
|
send: func(w *watch.FakeWatcher) {
|
||||||
w.Add(&obj)
|
w.Add(&obj)
|
||||||
},
|
},
|
||||||
|
|
@ -2039,7 +2080,7 @@ func TestWatchTable(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=Table;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
|
||||||
send: func(w *watch.FakeWatcher) {
|
send: func(w *watch.FakeWatcher) {
|
||||||
w.Add(&obj)
|
w.Add(&obj)
|
||||||
w.Modify(&obj)
|
w.Modify(&obj)
|
||||||
|
|
@ -2075,6 +2116,43 @@ func TestWatchTable(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accept: "application/json;as=Table;v=v1;g=meta.k8s.io",
|
||||||
|
send: func(w *watch.FakeWatcher) {
|
||||||
|
w.Add(&obj)
|
||||||
|
w.Modify(&obj)
|
||||||
|
},
|
||||||
|
expected: []*metav1.WatchEvent{
|
||||||
|
{
|
||||||
|
Type: "ADDED",
|
||||||
|
Object: runtime.RawExtension{
|
||||||
|
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
|
||||||
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1"},
|
||||||
|
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
|
||||||
|
ColumnDefinitions: []metav1beta1.TableColumnDefinition{
|
||||||
|
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
|
||||||
|
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
|
||||||
|
},
|
||||||
|
Rows: []metav1.TableRow{
|
||||||
|
{Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBodyV1}},
|
||||||
|
},
|
||||||
|
}))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "MODIFIED",
|
||||||
|
Object: runtime.RawExtension{
|
||||||
|
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
|
||||||
|
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1"},
|
||||||
|
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
|
||||||
|
Rows: []metav1.TableRow{
|
||||||
|
{Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBodyV1}},
|
||||||
|
},
|
||||||
|
}))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||||
|
|
@ -2122,6 +2200,7 @@ func TestWatchTable(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
if test.statusCode != 0 {
|
if test.statusCode != 0 {
|
||||||
if resp.StatusCode != test.statusCode {
|
if resp.StatusCode != test.statusCode {
|
||||||
t.Fatalf("%d: unexpected response: %#v", i, resp)
|
t.Fatalf("%d: unexpected response: %#v", i, resp)
|
||||||
|
|
@ -2228,46 +2307,72 @@ func TestGetPartialObjectMetadata(t *testing.T) {
|
||||||
statusCode int
|
statusCode int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1;g=meta.k8s.io",
|
accept: "application/json;as=PartialObjectMetadata;v=v1alpha1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1;g=meta.k8s.io, application/json",
|
accept: "application/json;as=PartialObjectMetadata;v=v1alpha1;g=meta.k8s.io, application/json",
|
||||||
expectKind: schema.GroupVersionKind{Kind: "Simple", Group: testGroupVersion.Group, Version: testGroupVersion.Version},
|
expectKind: schema.GroupVersionKind{Kind: "Simple", Group: testGroupVersion.Group, Version: testGroupVersion.Version},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io, application/json",
|
accept: "application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io, application/json",
|
||||||
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
list: true,
|
list: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// verify preferred version overrides supported version
|
||||||
|
{
|
||||||
|
accept: "application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io, application/json;as=PartialObjectMetadata;v=v1;g=meta.k8s.io, application/json",
|
||||||
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accept: "application/json;as=PartialObjectMetadata;v=v1;g=meta.k8s.io, application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io, application/json",
|
||||||
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accept: "application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io, application/json;as=PartialObjectMetadata;v=v1;g=meta.k8s.io",
|
||||||
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accept: "application/json;as=PartialObjectMetadata;v=v1;g=meta.k8s.io, application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io",
|
||||||
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1"},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
list: true,
|
list: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1;g=meta.k8s.io, application/json",
|
accept: "application/json;as=PartialObjectMetadata;v=v1alpha1;g=meta.k8s.io, application/json",
|
||||||
expectKind: schema.GroupVersionKind{Kind: "SimpleList", Group: testGroupVersion.Group, Version: testGroupVersion.Version},
|
expectKind: schema.GroupVersionKind{Kind: "SimpleList", Group: testGroupVersion.Group, Version: testGroupVersion.Version},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
list: true,
|
list: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io, application/json",
|
accept: "application/json;as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io, application/json",
|
||||||
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadataList", Group: "meta.k8s.io", Version: "v1beta1"},
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadataList", Group: "meta.k8s.io", Version: "v1beta1"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io",
|
||||||
statusCode: http.StatusNotAcceptable,
|
statusCode: http.StatusNotAcceptable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=PartialObjectMetadata;v=v1beta1;g=meta.k8s.io",
|
||||||
expected: &metav1beta1.PartialObjectMetadata{
|
expected: &metav1beta1.PartialObjectMetadata{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "foo1", Namespace: "ns1", CreationTimestamp: now, UID: types.UID("abcdef0123")},
|
ObjectMeta: metav1.ObjectMeta{Name: "foo1", Namespace: "ns1", CreationTimestamp: now, UID: types.UID("abcdef0123")},
|
||||||
},
|
},
|
||||||
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1beta1"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accept: "application/json;as=PartialObjectMetadata;v=v1;g=meta.k8s.io",
|
||||||
|
expected: &metav1.PartialObjectMetadata{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "foo1", Namespace: "ns1", CreationTimestamp: now, UID: types.UID("abcdef0123")},
|
||||||
|
},
|
||||||
|
expectKind: schema.GroupVersionKind{Kind: "PartialObjectMetadata", Group: "meta.k8s.io", Version: "v1"},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
list: true,
|
list: true,
|
||||||
accept: runtime.ContentTypeJSON + ";as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io",
|
accept: "application/json;as=PartialObjectMetadataList;v=v1beta1;g=meta.k8s.io",
|
||||||
expected: &metav1beta1.PartialObjectMetadataList{
|
expected: &metav1beta1.PartialObjectMetadataList{
|
||||||
ListMeta: metav1.ListMeta{
|
ListMeta: metav1.ListMeta{
|
||||||
ResourceVersion: "10",
|
ResourceVersion: "10",
|
||||||
|
|
|
||||||
|
|
@ -49,18 +49,18 @@ func transformObject(ctx context.Context, obj runtime.Object, opts interface{},
|
||||||
case target == nil:
|
case target == nil:
|
||||||
return obj, nil
|
return obj, nil
|
||||||
|
|
||||||
case target.Kind == "PartialObjectMetadata" && target.GroupVersion() == metav1beta1.SchemeGroupVersion:
|
case target.Kind == "PartialObjectMetadata":
|
||||||
return asV1Beta1PartialObjectMetadata(obj)
|
return asPartialObjectMetadata(obj, target.GroupVersion())
|
||||||
|
|
||||||
case target.Kind == "PartialObjectMetadataList" && target.GroupVersion() == metav1beta1.SchemeGroupVersion:
|
case target.Kind == "PartialObjectMetadataList":
|
||||||
return asV1Beta1PartialObjectMetadataList(obj)
|
return asPartialObjectMetadataList(obj, target.GroupVersion())
|
||||||
|
|
||||||
case target.Kind == "Table" && target.GroupVersion() == metav1beta1.SchemeGroupVersion:
|
case target.Kind == "Table":
|
||||||
options, ok := opts.(*metav1beta1.TableOptions)
|
options, ok := opts.(*metav1beta1.TableOptions)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected TableOptions, got %T", opts)
|
return nil, fmt.Errorf("unexpected TableOptions, got %T", opts)
|
||||||
}
|
}
|
||||||
return asV1Beta1Table(ctx, obj, options, scope)
|
return asTable(ctx, obj, options, scope, target.GroupVersion())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
accepted, _ := negotiation.MediaTypesForSerializer(metainternalversion.Codecs)
|
accepted, _ := negotiation.MediaTypesForSerializer(metainternalversion.Codecs)
|
||||||
|
|
@ -74,7 +74,7 @@ func transformObject(ctx context.Context, obj runtime.Object, opts interface{},
|
||||||
func optionsForTransform(mediaType negotiation.MediaTypeOptions, req *http.Request) (interface{}, error) {
|
func optionsForTransform(mediaType negotiation.MediaTypeOptions, req *http.Request) (interface{}, error) {
|
||||||
switch target := mediaType.Convert; {
|
switch target := mediaType.Convert; {
|
||||||
case target == nil:
|
case target == nil:
|
||||||
case target.Kind == "Table" && target.GroupVersion() == metav1beta1.SchemeGroupVersion:
|
case target.Kind == "Table" && (target.GroupVersion() == metav1beta1.SchemeGroupVersion || target.GroupVersion() == metav1.SchemeGroupVersion):
|
||||||
opts := &metav1beta1.TableOptions{}
|
opts := &metav1beta1.TableOptions{}
|
||||||
if err := metav1beta1.ParameterCodec.DecodeParameters(req.URL.Query(), metav1beta1.SchemeGroupVersion, opts); err != nil {
|
if err := metav1beta1.ParameterCodec.DecodeParameters(req.URL.Query(), metav1beta1.SchemeGroupVersion, opts); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -95,9 +95,8 @@ func optionsForTransform(mediaType negotiation.MediaTypeOptions, req *http.Reque
|
||||||
func targetEncodingForTransform(scope *RequestScope, mediaType negotiation.MediaTypeOptions, req *http.Request) (schema.GroupVersionKind, runtime.NegotiatedSerializer, bool) {
|
func targetEncodingForTransform(scope *RequestScope, mediaType negotiation.MediaTypeOptions, req *http.Request) (schema.GroupVersionKind, runtime.NegotiatedSerializer, bool) {
|
||||||
switch target := mediaType.Convert; {
|
switch target := mediaType.Convert; {
|
||||||
case target == nil:
|
case target == nil:
|
||||||
case target.Kind == "PartialObjectMetadata" && target.GroupVersion() == metav1beta1.SchemeGroupVersion,
|
case (target.Kind == "PartialObjectMetadata" || target.Kind == "PartialObjectMetadataList" || target.Kind == "Table") &&
|
||||||
target.Kind == "PartialObjectMetadataList" && target.GroupVersion() == metav1beta1.SchemeGroupVersion,
|
(target.GroupVersion() == metav1beta1.SchemeGroupVersion || target.GroupVersion() == metav1.SchemeGroupVersion):
|
||||||
target.Kind == "Table" && target.GroupVersion() == metav1beta1.SchemeGroupVersion:
|
|
||||||
return *target, metainternalversion.Codecs, true
|
return *target, metainternalversion.Codecs, true
|
||||||
}
|
}
|
||||||
return scope.Kind, scope.Serializer, false
|
return scope.Kind, scope.Serializer, false
|
||||||
|
|
@ -142,31 +141,39 @@ func (e errNotAcceptable) Status() metav1.Status {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func asV1Beta1Table(ctx context.Context, result runtime.Object, opts *metav1beta1.TableOptions, scope *RequestScope) (runtime.Object, error) {
|
func asTable(ctx context.Context, result runtime.Object, opts *metav1beta1.TableOptions, scope *RequestScope, groupVersion schema.GroupVersion) (runtime.Object, error) {
|
||||||
table, err := scope.TableConvertor.ConvertToTable(ctx, result, opts)
|
switch groupVersion {
|
||||||
|
case metav1beta1.SchemeGroupVersion, metav1.SchemeGroupVersion:
|
||||||
|
default:
|
||||||
|
return nil, newNotAcceptableError(fmt.Sprintf("no Table exists in group version %s", groupVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := scope.TableConvertor.ConvertToTable(ctx, result, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table := (*metav1.Table)(obj)
|
||||||
|
|
||||||
for i := range table.Rows {
|
for i := range table.Rows {
|
||||||
item := &table.Rows[i]
|
item := &table.Rows[i]
|
||||||
switch opts.IncludeObject {
|
switch opts.IncludeObject {
|
||||||
case metav1beta1.IncludeObject:
|
case metav1.IncludeObject:
|
||||||
item.Object.Object, err = scope.Convertor.ConvertToVersion(item.Object.Object, scope.Kind.GroupVersion())
|
item.Object.Object, err = scope.Convertor.ConvertToVersion(item.Object.Object, scope.Kind.GroupVersion())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO: rely on defaulting for the value here?
|
// TODO: rely on defaulting for the value here?
|
||||||
case metav1beta1.IncludeMetadata, "":
|
case metav1.IncludeMetadata, "":
|
||||||
m, err := meta.Accessor(item.Object.Object)
|
m, err := meta.Accessor(item.Object.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO: turn this into an internal type and do conversion in order to get object kind automatically set?
|
// TODO: turn this into an internal type and do conversion in order to get object kind automatically set?
|
||||||
partial := meta.AsPartialObjectMetadata(m)
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
partial.GetObjectKind().SetGroupVersionKind(groupVersion.WithKind("PartialObjectMetadata"))
|
||||||
item.Object.Object = partial
|
item.Object.Object = partial
|
||||||
case metav1beta1.IncludeNone:
|
case metav1.IncludeNone:
|
||||||
item.Object.Object = nil
|
item.Object.Object = nil
|
||||||
default:
|
default:
|
||||||
err = errors.NewBadRequest(fmt.Sprintf("unrecognized includeObject value: %q", opts.IncludeObject))
|
err = errors.NewBadRequest(fmt.Sprintf("unrecognized includeObject value: %q", opts.IncludeObject))
|
||||||
|
|
@ -177,42 +184,74 @@ func asV1Beta1Table(ctx context.Context, result runtime.Object, opts *metav1beta
|
||||||
return table, nil
|
return table, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func asV1Beta1PartialObjectMetadata(result runtime.Object) (runtime.Object, error) {
|
func asPartialObjectMetadata(result runtime.Object, groupVersion schema.GroupVersion) (runtime.Object, error) {
|
||||||
if meta.IsListType(result) {
|
if meta.IsListType(result) {
|
||||||
err := newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadata, but the requested object is a list (%T)", result))
|
err := newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadata, but the requested object is a list (%T)", result))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
switch groupVersion {
|
||||||
|
case metav1beta1.SchemeGroupVersion, metav1.SchemeGroupVersion:
|
||||||
|
default:
|
||||||
|
return nil, newNotAcceptableError(fmt.Sprintf("no PartialObjectMetadataList exists in group version %s", groupVersion))
|
||||||
|
}
|
||||||
m, err := meta.Accessor(result)
|
m, err := meta.Accessor(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
partial := meta.AsPartialObjectMetadata(m)
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
partial.GetObjectKind().SetGroupVersionKind(groupVersion.WithKind("PartialObjectMetadata"))
|
||||||
return partial, nil
|
return partial, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func asV1Beta1PartialObjectMetadataList(result runtime.Object) (runtime.Object, error) {
|
func asPartialObjectMetadataList(result runtime.Object, groupVersion schema.GroupVersion) (runtime.Object, error) {
|
||||||
if !meta.IsListType(result) {
|
li, ok := result.(metav1.ListInterface)
|
||||||
|
if !ok {
|
||||||
return nil, newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadataList, but the requested object is not a list (%T)", result))
|
return nil, newNotAcceptableError(fmt.Sprintf("you requested PartialObjectMetadataList, but the requested object is not a list (%T)", result))
|
||||||
}
|
}
|
||||||
list := &metav1beta1.PartialObjectMetadataList{}
|
|
||||||
if li, ok := result.(metav1.ListInterface); ok {
|
gvk := groupVersion.WithKind("PartialObjectMetadata")
|
||||||
|
switch {
|
||||||
|
case groupVersion == metav1beta1.SchemeGroupVersion:
|
||||||
|
list := &metav1beta1.PartialObjectMetadataList{}
|
||||||
|
err := meta.EachListItem(result, func(obj runtime.Object) error {
|
||||||
|
m, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
|
partial.GetObjectKind().SetGroupVersionKind(gvk)
|
||||||
|
list.Items = append(list.Items, partial)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
list.SelfLink = li.GetSelfLink()
|
list.SelfLink = li.GetSelfLink()
|
||||||
list.ResourceVersion = li.GetResourceVersion()
|
list.ResourceVersion = li.GetResourceVersion()
|
||||||
list.Continue = li.GetContinue()
|
list.Continue = li.GetContinue()
|
||||||
}
|
return list, nil
|
||||||
err := meta.EachListItem(result, func(obj runtime.Object) error {
|
|
||||||
m, err := meta.Accessor(obj)
|
case groupVersion == metav1.SchemeGroupVersion:
|
||||||
|
list := &metav1.PartialObjectMetadataList{}
|
||||||
|
err := meta.EachListItem(result, func(obj runtime.Object) error {
|
||||||
|
m, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
partial := meta.AsPartialObjectMetadata(m)
|
||||||
|
partial.GetObjectKind().SetGroupVersionKind(gvk)
|
||||||
|
list.Items = append(list.Items, partial)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
partial := meta.AsPartialObjectMetadata(m)
|
list.SelfLink = li.GetSelfLink()
|
||||||
partial.GetObjectKind().SetGroupVersionKind(metav1beta1.SchemeGroupVersion.WithKind("PartialObjectMetadata"))
|
list.ResourceVersion = li.GetResourceVersion()
|
||||||
list.Items = append(list.Items, partial)
|
list.Continue = li.GetContinue()
|
||||||
return nil
|
return list, nil
|
||||||
})
|
|
||||||
if err != nil {
|
default:
|
||||||
return nil, err
|
return nil, newNotAcceptableError(fmt.Sprintf("no PartialObjectMetadataList exists in group version %s", groupVersion))
|
||||||
}
|
}
|
||||||
return list, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func (scope *RequestScope) err(err error, w http.ResponseWriter, req *http.Reque
|
||||||
|
|
||||||
func (scope *RequestScope) AllowsConversion(gvk schema.GroupVersionKind, mimeType, mimeSubType string) bool {
|
func (scope *RequestScope) AllowsConversion(gvk schema.GroupVersionKind, mimeType, mimeSubType string) bool {
|
||||||
// TODO: this is temporary, replace with an abstraction calculated at endpoint installation time
|
// TODO: this is temporary, replace with an abstraction calculated at endpoint installation time
|
||||||
if gvk.GroupVersion() == metav1beta1.SchemeGroupVersion {
|
if gvk.GroupVersion() == metav1beta1.SchemeGroupVersion || gvk.GroupVersion() == metav1.SchemeGroupVersion {
|
||||||
switch gvk.Kind {
|
switch gvk.Kind {
|
||||||
case "Table":
|
case "Table":
|
||||||
return scope.TableConvertor != nil &&
|
return scope.TableConvertor != nil &&
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue