} } <ins> func testFinalizerValidationApplyCreateAndUpdateCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) { var testcases = []struct { name                 string finalizer            []string updatedFinalizer     []string opts                 metav1.PatchOptions expectUpdateWarnings []string expectCreateWarnings []string }{ { name:      "create-crd-with-invalid-finalizer", finalizer: []string{"invalid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, { name:      "create-crd-with-valid-finalizer", finalizer: []string{"kubernetes.io/valid-finalizer"}, }, { name:             "update-crd-with-invalid-finalizer", finalizer:        []string{"invalid-finalizer"}, updatedFinalizer: []string{"another-invalid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, expectUpdateWarnings: []string{ `metadata.finalizers: "another-invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, { name:             "update-crd-with-valid-finalizer", finalizer:        []string{"kubernetes.io/valid-finalizer"}, updatedFinalizer: []string{"kubernetes.io/another-valid-finalizer"}, }, { name:             "update-crd-with-valid-finalizer-leaving-an-existing-invalid-finalizer", finalizer:        []string{"invalid-finalizer"}, updatedFinalizer: []string{"kubernetes.io/another-valid-finalizer"}, expectCreateWarnings: []string{ `metadata.finalizers: "invalid-finalizer": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers`, }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { kind := gvk.Kind apiVersion := gvk.Group + "/" + gvk.Version // create the CR as specified by the test case name := fmt.Sprintf("apply-create-crd-%s", tc.name) finalizerVal, _ := json.Marshal(tc.finalizer) applyCreateBody := []byte(fmt.Sprintf(crdApplyFinalizerBody, apiVersion, kind, name, finalizerVal)) req := rest.Patch(types.ApplyPatchType). AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource). Name(name). Param("fieldManager", "apply_test"). VersionedParams(&tc.opts, metav1.ParameterCodec) result := req.Body(applyCreateBody).Do(context.TODO()) if result.Error() != nil { t.Fatalf("unexpected error: %v", result.Error()) } if len(result.Warnings()) != len(tc.expectCreateWarnings) { for _, r := range result.Warnings() { t.Logf("received warning: %v", r) } t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.expectCreateWarnings), len(result.Warnings())) } for i, expectedWarning := range tc.expectCreateWarnings { if expectedWarning != result.Warnings()[i].Text { t.Fatalf("expected warning: %s, got warning: %s", expectedWarning, result.Warnings()[i].Text) } } if len(tc.updatedFinalizer) != 0 { finalizerVal, _ := json.Marshal(tc.updatedFinalizer) applyUpdateBody := []byte(fmt.Sprintf(crdApplyFinalizerBody, apiVersion, kind, name, finalizerVal)) updateReq := rest.Patch(types.ApplyPatchType). AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource). Name(name). Param("fieldManager", "apply_test"). VersionedParams(&tc.opts, metav1.ParameterCodec) result = updateReq.Body(applyUpdateBody).Do(context.TODO()) if result.Error() != nil { t.Fatalf("unexpected error: %v", result.Error()) } if len(result.Warnings()) != len(tc.expectUpdateWarnings) { t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.expectUpdateWarnings), len(result.Warnings())) } for i, expectedWarning := range tc.expectUpdateWarnings { if expectedWarning != result.Warnings()[i].Text { t.Fatalf("expected warning: %s, got warning: %s", expectedWarning, result.Warnings()[i].Text) } } } }) } } </ins> func setupCRD(t testing.TB, config *rest.Config, apiGroup string, schemaless bool) *apiextensionsv1.CustomResourceDefinition { apiExtensionClient, err := apiextensionsclient.NewForConfig(config) if err != nil {