Skip to content

Commit 6825daa

Browse files
Check CRD protobuf negotiation in integration tests
Add a few more tests to verify CRDs don't regress as client changes are made.
1 parent d29afda commit 6825daa

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

test/integration/apiserver/apiserver_test.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,150 @@ func TestNameInFieldSelector(t *testing.T) {
340340
}
341341
}
342342

343+
func TestAPICRDProtobuf(t *testing.T) {
344+
tearDown, config, _, err := fixtures.StartDefaultServer(t)
345+
if err != nil {
346+
t.Fatal(err)
347+
}
348+
defer tearDown()
349+
350+
s, _, closeFn := setup(t)
351+
defer closeFn()
352+
353+
apiExtensionClient, err := apiextensionsclient.NewForConfig(config)
354+
if err != nil {
355+
t.Fatal(err)
356+
}
357+
358+
dynamicClient, err := dynamic.NewForConfig(config)
359+
if err != nil {
360+
t.Fatal(err)
361+
}
362+
363+
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
364+
ObjectMeta: metav1.ObjectMeta{
365+
Name: "foos.cr.bar.com",
366+
},
367+
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
368+
Group: "cr.bar.com",
369+
Version: "v1",
370+
Scope: apiextensionsv1beta1.NamespaceScoped,
371+
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
372+
Plural: "foos",
373+
Kind: "Foo",
374+
},
375+
},
376+
}
377+
fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
378+
if err != nil {
379+
t.Fatal(err)
380+
}
381+
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"}
382+
crclient := dynamicClient.Resource(crdGVR).Namespace("default")
383+
384+
testcases := []struct {
385+
name string
386+
accept string
387+
object func(*testing.T) (metav1.Object, string, string)
388+
wantErr func(*testing.T, error)
389+
wantBody func(*testing.T, io.Reader)
390+
}{
391+
{
392+
name: "server returns 406 when asking for protobuf for CRDs",
393+
accept: "application/vnd.kubernetes.protobuf",
394+
object: func(t *testing.T) (metav1.Object, string, string) {
395+
cr, err := crclient.Create(&unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "cr.bar.com/v1", "kind": "Foo", "metadata": map[string]interface{}{"name": "test-1"}}}, metav1.CreateOptions{})
396+
if err != nil {
397+
t.Fatalf("unable to create cr: %v", err)
398+
}
399+
if _, err := crclient.Patch("test-1", types.MergePatchType, []byte(`{"metadata":{"annotations":{"test":"1"}}}`), metav1.PatchOptions{}); err != nil {
400+
t.Fatalf("unable to patch cr: %v", err)
401+
}
402+
return cr, crdGVR.Group, "foos"
403+
},
404+
wantErr: func(t *testing.T, err error) {
405+
if !apierrors.IsNotAcceptable(err) {
406+
t.Fatal(err)
407+
}
408+
// TODO: this should be a more specific error
409+
if err.Error() != "only the following media types are accepted: application/json, application/yaml" {
410+
t.Fatal(err)
411+
}
412+
},
413+
},
414+
{
415+
name: "server returns JSON when asking for protobuf and json for CRDs",
416+
accept: "application/vnd.kubernetes.protobuf,application/json",
417+
object: func(t *testing.T) (metav1.Object, string, string) {
418+
cr, err := crclient.Create(&unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "cr.bar.com/v1", "kind": "Foo", "spec": map[string]interface{}{"field": 1}, "metadata": map[string]interface{}{"name": "test-2"}}}, metav1.CreateOptions{})
419+
if err != nil {
420+
t.Fatalf("unable to create cr: %v", err)
421+
}
422+
if _, err := crclient.Patch("test-2", types.MergePatchType, []byte(`{"metadata":{"annotations":{"test":"1"}}}`), metav1.PatchOptions{}); err != nil {
423+
t.Fatalf("unable to patch cr: %v", err)
424+
}
425+
return cr, crdGVR.Group, "foos"
426+
},
427+
wantBody: func(t *testing.T, w io.Reader) {
428+
obj := &unstructured.Unstructured{}
429+
if err := json.NewDecoder(w).Decode(obj); err != nil {
430+
t.Fatal(err)
431+
}
432+
v, ok, err := unstructured.NestedInt64(obj.UnstructuredContent(), "spec", "field")
433+
if !ok || err != nil {
434+
data, _ := json.MarshalIndent(obj.UnstructuredContent(), "", " ")
435+
t.Fatalf("err=%v ok=%t json=%s", err, ok, string(data))
436+
}
437+
if v != 1 {
438+
t.Fatalf("unexpected body: %#v", obj.UnstructuredContent())
439+
}
440+
},
441+
},
442+
}
443+
444+
for i := range testcases {
445+
tc := testcases[i]
446+
t.Run(tc.name, func(t *testing.T) {
447+
obj, group, resource := tc.object(t)
448+
449+
cfg := dynamic.ConfigFor(config)
450+
if len(group) == 0 {
451+
cfg = dynamic.ConfigFor(&restclient.Config{Host: s.URL})
452+
cfg.APIPath = "/api"
453+
} else {
454+
cfg.APIPath = "/apis"
455+
}
456+
cfg.GroupVersion = &schema.GroupVersion{Group: group, Version: "v1"}
457+
client, err := restclient.RESTClientFor(cfg)
458+
if err != nil {
459+
t.Fatal(err)
460+
}
461+
462+
rv, _ := strconv.Atoi(obj.GetResourceVersion())
463+
if rv < 1 {
464+
rv = 1
465+
}
466+
467+
w, err := client.Get().
468+
Resource(resource).NamespaceIfScoped(obj.GetNamespace(), len(obj.GetNamespace()) > 0).Name(obj.GetName()).
469+
SetHeader("Accept", tc.accept).
470+
Stream()
471+
if (tc.wantErr != nil) != (err != nil) {
472+
t.Fatalf("unexpected error: %v", err)
473+
}
474+
if tc.wantErr != nil {
475+
tc.wantErr(t, err)
476+
return
477+
}
478+
if err != nil {
479+
t.Fatal(err)
480+
}
481+
defer w.Close()
482+
tc.wantBody(t, w)
483+
})
484+
}
485+
}
486+
343487
func TestTransformOnWatch(t *testing.T) {
344488
tearDown, config, _, err := fixtures.StartDefaultServer(t)
345489
if err != nil {

0 commit comments

Comments
 (0)