diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/apiapproval_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/apiapproval_test.go index 003e507c5d0..a1f8132a618 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/apiapproval_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/apiapproval_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/test/integration/fixtures" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" @@ -34,43 +34,50 @@ func TestAPIApproval(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1beta1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil { + if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil { t.Fatal(noxuAPIApproved) } - newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1beta1.KubeAPIApprovedAnnotation: approvalAnnotation}}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "sigs.k8s.io", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: approvalAnnotation}}, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "sigs.k8s.io", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + Schema: fixtures.AllowAllSchema(), + }, + }, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: resource, Singular: resource + "singular", Kind: resource + "Kind", ListKind: resource + "List", }, - Scope: apiextensionsv1beta1.NamespaceScoped, + Scope: apiextensionsv1.NamespaceScoped, }, } } // the unit tests cover all variations. We just need to be sure that we see the code being called approvedKubeAPI := newSigKubeAPIFn("approved", "https://github.com/kubernetes/kubernetes/pull/79724") - approvedKubeAPI, err = fixtures.CreateNewCustomResourceDefinition(approvedKubeAPI, apiExtensionClient, dynamicClient) + approvedKubeAPI, err = fixtures.CreateNewV1CustomResourceDefinition(approvedKubeAPI, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) { - approvedKubeAPI, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), approvedKubeAPI.Name, metav1.GetOptions{}) + approvedKubeAPI, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), approvedKubeAPI.Name, metav1.GetOptions{}) if err != nil { return false, err } - if approvedKubeAPIApproved := findCRDCondition(approvedKubeAPI, apiextensionsv1beta1.KubernetesAPIApprovalPolicyConformant); approvedKubeAPIApproved == nil || approvedKubeAPIApproved.Status != apiextensionsv1beta1.ConditionTrue { + if approvedKubeAPIApproved := findCRDCondition(approvedKubeAPI, apiextensionsv1.KubernetesAPIApprovalPolicyConformant); approvedKubeAPIApproved == nil || approvedKubeAPIApproved.Status != apiextensionsv1.ConditionTrue { t.Log(approvedKubeAPIApproved) return false, nil } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/apply_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/apply_test.go index 727844c772c..ea481fa6e2c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/apply_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/apply_test.go @@ -21,7 +21,7 @@ import ( "fmt" "testing" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apimachinery/pkg/api/errors" @@ -50,14 +50,14 @@ func TestApplyBasic(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name rest := apiExtensionClient.Discovery().RESTClient() yamlBody := []byte(fmt.Sprintf(` @@ -70,7 +70,7 @@ values: boolVal: true stringVal: "1"`, apiVersion, kind)) result, err := rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name("mytest"). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -80,7 +80,7 @@ values: } result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name("mytest"). Body([]byte(`{"values":{"numVal": 5}}`)). DoRaw(context.TODO()) @@ -90,7 +90,7 @@ values: // Re-apply the same object, we should get conflicts now. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name("mytest"). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -108,7 +108,7 @@ values: // Re-apply with force, should work fine. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name("mytest"). Param("force", "true"). Param("fieldManager", "apply_test"). diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go index a370c9d8a7a..66fca6a47a8 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/basic_test.go @@ -25,7 +25,7 @@ import ( "testing" "time" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -56,8 +56,8 @@ func TestNamespaceScopedCRUD(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -75,8 +75,8 @@ func TestClusterScopedCRUD(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -86,7 +86,7 @@ func TestClusterScopedCRUD(t *testing.T) { testFieldSelector(t, ns, noxuDefinition, dynamicClient) } -func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { +func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition, dynamicClient dynamic.Interface) { noxuResourceClients := map[string]dynamic.ResourceInterface{} noxuWatchs := map[string]watch.Interface{} disabledVersions := map[string]bool{} @@ -321,8 +321,8 @@ func TestInvalidCRUD(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -373,7 +373,7 @@ func TestInvalidCRUD(t *testing.T) { } } -func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) { +func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition, dynamicClient dynamic.Interface) { noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) initialList, err := noxuResourceClient.List(context.TODO(), metav1.ListOptions{}) if err != nil { @@ -527,9 +527,9 @@ func TestDiscovery(t *testing.T) { } defer tearDown() - scope := apiextensionsv1beta1.NamespaceScoped - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(scope) - if _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil { + scope := apiextensionsv1.NamespaceScoped + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(scope) + if _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil { t.Fatal(err) } @@ -574,8 +574,8 @@ func TestNoNamespaceReject(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -593,7 +593,7 @@ func TestNoNamespaceReject(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, initialListTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a { @@ -613,8 +613,8 @@ func TestSameNameDiffNamespace(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -636,8 +636,8 @@ func TestSelfLink(t *testing.T) { defer tearDown() // namespace scoped - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -656,8 +656,8 @@ func TestSelfLink(t *testing.T) { } // cluster scoped - curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) + curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -682,8 +682,8 @@ func TestPreserveInt(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -724,8 +724,8 @@ func TestPatch(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -802,8 +802,8 @@ func TestCrossNamespaceListWatch(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -881,7 +881,7 @@ func TestCrossNamespaceListWatch(t *testing.T) { if err != nil { t.Fatal(err) } - if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a { + if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, createdTypeMeta.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a { @@ -901,7 +901,7 @@ func TestCrossNamespaceListWatch(t *testing.T) { checkNamespacesWatchHelper(t, ns2, noxuNamespacesWatch2) } -func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.ResourceInterface, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) *unstructured.Unstructured { +func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.ResourceInterface, noxuDefinition *apiextensionsv1.CustomResourceDefinition) *unstructured.Unstructured { createdInstance, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, name), noxuNamespacedResourceClient, noxuDefinition) if err != nil { t.Fatalf("unable to create noxu Instance:%v", err) @@ -944,27 +944,27 @@ func TestNameConflict(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{}) + noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } // A NameConflict occurs err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{}) + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } for _, condition := range crd.Status.Conditions { - if condition.Type == apiextensionsv1beta1.NamesAccepted && condition.Status == apiextensionsv1beta1.ConditionFalse { + if condition.Type == apiextensionsv1.NamesAccepted && condition.Status == apiextensionsv1.ConditionFalse { return true, nil } } @@ -974,20 +974,20 @@ func TestNameConflict(t *testing.T) { t.Fatal(err) } - err = fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient) + err = fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient) if err != nil { t.Fatal(err) } // Names are now accepted err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{}) + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{}) if err != nil { return false, err } for _, condition := range crd.Status.Conditions { - if condition.Type == apiextensionsv1beta1.NamesAccepted && condition.Status == apiextensionsv1beta1.ConditionTrue { + if condition.Type == apiextensionsv1.NamesAccepted && condition.Status == apiextensionsv1.ConditionTrue { return true, nil } } @@ -1005,15 +1005,15 @@ func TestStatusGetAndPatch(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } // make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource - result := &apiextensionsv1beta1.CustomResourceDefinition{} - err = apiExtensionClient.ApiextensionsV1beta1().RESTClient().Get(). + result := &apiextensionsv1.CustomResourceDefinition{} + err = apiExtensionClient.ApiextensionsV1().RESTClient().Get(). Resource("customresourcedefinitions"). Name(noxuDefinition.Name). SubResource("status"). @@ -1024,7 +1024,7 @@ func TestStatusGetAndPatch(t *testing.T) { } // make sure we don't get 405 Method Not Allowed from Patching CRD/status subresource - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions(). + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions(). Patch(context.TODO(), noxuDefinition.Name, types.StrategicMergePatchType, []byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), metav1.PatchOptions{}, "status") diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/change_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/change_test.go index 8c11b550ea9..b0ddb00da21 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/change_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/change_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -50,8 +50,8 @@ func TestChangeCRD(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -76,7 +76,7 @@ func TestChangeCRD(t *testing.T) { time.Sleep(10 * time.Millisecond) - noxuDefinitionToUpdate, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) + noxuDefinitionToUpdate, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) if err != nil { t.Error(err) continue @@ -90,7 +90,7 @@ func TestChangeCRD(t *testing.T) { } else { noxuDefinitionToUpdate.Spec.Versions = noxuDefinitionToUpdate.Spec.Versions[0:1] } - if _, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), noxuDefinitionToUpdate, metav1.UpdateOptions{}); err != nil && !apierrors.IsConflict(err) { + if _, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), noxuDefinitionToUpdate, metav1.UpdateOptions{}); err != nil && !apierrors.IsConflict(err) { t.Error(err) continue } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/conversion_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/conversion_test.go index 971d4f6f3f2..73a479b8865 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/conversion_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/conversion_test.go @@ -335,10 +335,8 @@ func validateNonTrivialConverted(t *testing.T, ctc *conversionTestContext) { client := ctc.versionedClient(ns, createVersion.Name) fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name) - if !*ctc.crd.Spec.PreserveUnknownFields { - if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil { - t.Fatal(err) - } + if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil { + t.Fatal(err) } if _, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{}); err != nil { t.Fatal(err) @@ -393,10 +391,8 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) { name := "converted-" + createVersion.Name client := ctc.versionedClient(ns, createVersion.Name) fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name) - if !*ctc.crd.Spec.PreserveUnknownFields { - if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil { - t.Fatal(err) - } + if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil { + t.Fatal(err) } _, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{}) if err != nil { @@ -428,10 +424,6 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) { } func validateStoragePruning(t *testing.T, ctc *conversionTestContext) { - if *ctc.crd.Spec.PreserveUnknownFields { - return - } - ns := ctc.namespace for _, createVersion := range ctc.crd.Spec.Versions { @@ -905,13 +897,13 @@ func newConversionTestContext(t *testing.T, apiExtensionsClient clientset.Interf if err != nil { t.Fatal(err) } - crd, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), v1CRD.Name, metav1.GetOptions{}) + crd, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), v1CRD.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } tearDown := func() { - if err := fixtures.DeleteCustomResourceDefinition(crd, apiExtensionsClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionsClient); err != nil { t.Fatal(err) } } @@ -923,13 +915,13 @@ type conversionTestContext struct { namespace string apiExtensionsClient clientset.Interface dynamicClient dynamic.Interface - crd *apiextensionsv1beta1.CustomResourceDefinition + crd *apiextensionsv1.CustomResourceDefinition etcdObjectReader *storage.EtcdObjectReader } func (c *conversionTestContext) versionedClient(ns string, version string) dynamic.ResourceInterface { gvr := schema.GroupVersionResource{Group: c.crd.Spec.Group, Version: version, Resource: c.crd.Spec.Names.Plural} - if c.crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + if c.crd.Spec.Scope != apiextensionsv1.ClusterScoped { return c.dynamicClient.Resource(gvr).Namespace(ns) } return c.dynamicClient.Resource(gvr) @@ -943,17 +935,19 @@ func (c *conversionTestContext) versionedClients(ns string) map[string]dynamic.R return ret } -func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1beta1.WebhookClientConfig, reviewVersions []string) { - crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) +func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1.WebhookClientConfig, reviewVersions []string) { + crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } - crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{ - Strategy: apiextensionsv1beta1.WebhookConverter, - WebhookClientConfig: webhookClientConfig, - ConversionReviewVersions: reviewVersions, + crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{ + Strategy: apiextensionsv1.WebhookConverter, + Webhook: &apiextensionsv1.WebhookConversion{ + ClientConfig: webhookClientConfig, + ConversionReviewVersions: reviewVersions, + }, } - crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err != nil { t.Fatal(err) } @@ -962,15 +956,15 @@ func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClient } func (c *conversionTestContext) removeConversionWebhook(t *testing.T) { - crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) + crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } - crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{ - Strategy: apiextensionsv1beta1.NoneConverter, + crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{ + Strategy: apiextensionsv1.NoneConverter, } - crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err != nil { t.Fatal(err) } @@ -998,14 +992,14 @@ func (c *conversionTestContext) setAndWaitStorageVersion(t *testing.T, version s } func (c *conversionTestContext) setStorageVersion(t *testing.T, version string) { - crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) + crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } for i, v := range crd.Spec.Versions { crd.Spec.Versions[i].Storage = v.Name == version } - crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err != nil { t.Fatal(err) } @@ -1027,7 +1021,7 @@ func (c *conversionTestContext) waitForStorageVersion(t *testing.T, version stri } func (c *conversionTestContext) setServed(t *testing.T, version string, served bool) { - crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) + crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } @@ -1036,7 +1030,7 @@ func (c *conversionTestContext) setServed(t *testing.T, version string, served b crd.Spec.Versions[i].Served = served } } - crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/webhook.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/webhook.go index 41adf59ab25..0f2faeff550 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/webhook.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/conversion/webhook.go @@ -38,7 +38,7 @@ import ( // StartConversionWebhookServer starts an http server with the provided handler and returns the WebhookClientConfig // needed to configure a CRD to use this conversion webhook as its converter. -func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1beta1.WebhookClientConfig, error) { +func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1.WebhookClientConfig, error) { roots := x509.NewCertPool() if !roots.AppendCertsFromPEM(localhostCert) { return nil, nil, fmt.Errorf("failed to append Cert from PEM") @@ -57,7 +57,7 @@ func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv } webhookServer.StartTLS() endpoint := webhookServer.URL + "/convert" - webhookConfig := &apiextensionsv1beta1.WebhookClientConfig{ + webhookConfig := &apiextensionsv1.WebhookClientConfig{ CABundle: localhostCert, URL: &endpoint, } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go index c04df0bc055..045d7bb06b6 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go @@ -23,8 +23,7 @@ import ( "github.com/stretchr/testify/require" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,8 +35,8 @@ func TestFinalization(t *testing.T) { require.NoError(t, err) defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) require.NoError(t, err) ns := "not-the-default" @@ -100,8 +99,8 @@ func TestFinalizationAndDeletion(t *testing.T) { defer tearDown() // Create a CRD. - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) require.NoError(t, err) // Create a CR with a finalizer. @@ -129,7 +128,7 @@ func TestFinalizationAndDeletion(t *testing.T) { require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp()) // Delete the CRD. - fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient) + fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient) // Check is CR still there after the CRD deletion. gottenNoxuInstance, err = noxuResourceClient.Get(context.TODO(), name, metav1.GetOptions{}) @@ -157,7 +156,7 @@ func TestFinalizationAndDeletion(t *testing.T) { } err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) return errors.IsNotFound(err), err }) if !errors.IsNotFound(err) { diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/resources.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/resources.go index 9e723ad1eb5..1fa21135ea6 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/resources.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/resources.go @@ -44,6 +44,16 @@ const ( noxuInstanceNum int64 = 9223372036854775807 ) +// AllowAllSchema doesn't enforce any schema restrictions +func AllowAllSchema() *apiextensionsv1.CustomResourceValidation { + return &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + XPreserveUnknownFields: pointer.BoolPtr(true), + Type: "object", + }, + } +} + // NewRandomNameV1CustomResourceDefinition generates a CRD with random name to avoid name conflict in e2e tests func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition { // ensure the singular doesn't end in an s for now @@ -57,12 +67,7 @@ func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope Name: "v1beta1", Served: true, Storage: true, - Schema: &apiextensionsv1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ - XPreserveUnknownFields: pointer.BoolPtr(true), - Type: "object", - }, - }, + Schema: AllowAllSchema(), }, }, Names: apiextensionsv1.CustomResourceDefinitionNames{ @@ -76,46 +81,6 @@ func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope } } -// NewRandomNameCustomResourceDefinition generates a CRD with random name to avoid name conflict in e2e tests -func NewRandomNameCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { - // ensure the singular doesn't end in an s for now - gName := names.SimpleNameGenerator.GenerateName("foo") + "a" - return &apiextensionsv1beta1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{Name: gName + "s.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ - Plural: gName + "s", - Singular: gName, - Kind: gName, - ListKind: gName + "List", - }, - Scope: scope, - }, - } -} - -// NewNoxuCustomResourceDefinition returns a WishIHadChosenNoxu CRD. -func NewNoxuCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ - Plural: "noxus", - Singular: "nonenglishnoxu", - Kind: "WishIHadChosenNoxu", - ShortNames: []string{"foo", "bar", "abc", "def"}, - ListKind: "NoxuItemList", - Categories: []string{"all"}, - }, - Scope: scope, - }, - } -} - // NewNoxuV1CustomResourceDefinition returns a WishIHadChosenNoxu CRD. func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition { return &apiextensionsv1.CustomResourceDefinition{ @@ -126,12 +91,7 @@ func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *api Name: "v1beta1", Served: true, Storage: true, - Schema: &apiextensionsv1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ - XPreserveUnknownFields: pointer.BoolPtr(true), - Type: "object", - }, - }, + Schema: AllowAllSchema(), }}, Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "noxus", @@ -173,13 +133,12 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured { } // NewMultipleVersionNoxuCRD returns a WishIHadChosenNoxu with multiple versions. -func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ +func NewMultipleVersionNoxuCRD(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "noxus", Singular: "nonenglishnoxu", Kind: "WishIHadChosenNoxu", @@ -188,38 +147,52 @@ func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiext Categories: []string{"all"}, }, Scope: scope, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: false, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + }, + Schema: AllowAllSchema(), }, { Name: "v1beta2", Served: true, Storage: true, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + }, + Schema: AllowAllSchema(), }, { Name: "v0", Served: false, Storage: false, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + }, + Schema: AllowAllSchema(), }, }, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - }, }, } } // NewNoxu2CustomResourceDefinition returns a WishIHadChosenNoxu2 CRD. -func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ +func NewNoxu2CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1alpha1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{ + Name: "v1alpha1", + Served: true, + Storage: true, + Schema: AllowAllSchema(), + }}, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "noxus2", Singular: "nonenglishnoxu2", Kind: "WishIHadChosenNoxu2", @@ -231,14 +204,21 @@ func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) } } -// NewCurletCustomResourceDefinition returns a Curlet CRD. -func NewCurletCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ +// NewCurletV1CustomResourceDefinition returns a Curlet CRD. +func NewCurletV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "curlets.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + Schema: AllowAllSchema(), + }, + }, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "curlets", Singular: "curlet", Kind: "Curlet", @@ -506,23 +486,6 @@ func isWatchCachePrimed(crd *apiextensionsv1.CustomResourceDefinition, dynamicCl return true, nil } -// DeleteCustomResourceDefinition deletes a CRD and waits until it disappears from discovery. -func DeleteCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error { - if err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}); err != nil { - return err - } - for _, version := range servedVersions(crd) { - err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) { - exists, err := existsInDiscovery(crd, apiExtensionsClient, version) - return !exists, err - }) - if err != nil { - return err - } - } - return nil -} - // DeleteV1CustomResourceDefinition deletes a CRD and waits until it disappears from discovery. func DeleteV1CustomResourceDefinition(crd *apiextensionsv1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error { if err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}); err != nil { @@ -564,7 +527,7 @@ func DeleteV1CustomResourceDefinitions(deleteListOpts metav1.ListOptions, apiExt } // CreateNewVersionedScaleClient returns a scale client. -func CreateNewVersionedScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, config *rest.Config, version string) (scale.ScalesGetter, error) { +func CreateNewVersionedScaleClient(crd *apiextensionsv1.CustomResourceDefinition, config *rest.Config, version string) (scale.ScalesGetter, error) { discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) if err != nil { return nil, err diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/server.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/server.go index 63eaa80cc0f..93dbea1697a 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/server.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/fixtures/server.go @@ -20,9 +20,15 @@ import ( "io/ioutil" "os" "strings" + "time" "github.com/google/uuid" + "go.etcd.io/etcd/clientv3" + "go.etcd.io/etcd/pkg/transport" + "google.golang.org/grpc" "k8s.io/apiextensions-apiserver/pkg/cmd/server/options" + serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" servertesting "k8s.io/apiextensions-apiserver/pkg/cmd/server/testing" @@ -103,6 +109,55 @@ func StartDefaultServerWithClients(t servertesting.Logger, extraFlags ...string) return tearDown, apiExtensionsClient, dynamicClient, nil } +// StartDefaultServerWithClientsAndEtcd starts a test server and returns clients for it. +func StartDefaultServerWithClientsAndEtcd(t servertesting.Logger, extraFlags ...string) (func(), clientset.Interface, dynamic.Interface, *clientv3.Client, string, error) { + tearDown, config, options, err := StartDefaultServer(t, extraFlags...) + if err != nil { + return nil, nil, nil, nil, "", err + } + + apiExtensionsClient, err := clientset.NewForConfig(config) + if err != nil { + tearDown() + return nil, nil, nil, nil, "", err + } + + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + tearDown() + return nil, nil, nil, nil, "", err + } + + RESTOptionsGetter := serveroptions.NewCRDRESTOptionsGetter(*options.RecommendedOptions.Etcd) + restOptions, err := RESTOptionsGetter.GetRESTOptions(schema.GroupResource{Group: "hopefully-ignored-group", Resource: "hopefully-ignored-resources"}) + if err != nil { + return nil, nil, nil, nil, "", err + } + tlsInfo := transport.TLSInfo{ + CertFile: restOptions.StorageConfig.Transport.CertFile, + KeyFile: restOptions.StorageConfig.Transport.KeyFile, + TrustedCAFile: restOptions.StorageConfig.Transport.TrustedCAFile, + } + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + return nil, nil, nil, nil, "", err + } + etcdConfig := clientv3.Config{ + Endpoints: restOptions.StorageConfig.Transport.ServerList, + DialTimeout: 20 * time.Second, + DialOptions: []grpc.DialOption{ + grpc.WithBlock(), // block until the underlying connection is up + }, + TLS: tlsConfig, + } + etcdclient, err := clientv3.New(etcdConfig) + if err != nil { + return nil, nil, nil, nil, "", err + } + + return tearDown, apiExtensionsClient, dynamicClient, etcdclient, restOptions.StorageConfig.Prefix, nil +} + // IntegrationEtcdServers returns etcd server URLs. func IntegrationEtcdServers() []string { if etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL"); ok { diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go index c53a8669cbb..59134f7768c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/helpers.go @@ -22,7 +22,6 @@ import ( "testing" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -34,11 +33,11 @@ import ( var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() -func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) { +func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1.CustomResourceDefinition) (*unstructured.Unstructured, error) { return instantiateVersionedCustomResource(t, instanceToCreate, client, definition, definition.Spec.Versions[0].Name) } -func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) { +func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) { createdInstance, err := client.Create(context.TODO(), instanceToCreate, metav1.CreateOptions{}) if err != nil { t.Logf("%#v", createdInstance) @@ -65,28 +64,28 @@ func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstruct return createdInstance, nil } -func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition, version string) dynamic.ResourceInterface { +func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1.CustomResourceDefinition, version string) dynamic.ResourceInterface { gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural} - if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped { + if crd.Spec.Scope != apiextensionsv1.ClusterScoped { return client.Resource(gvr).Namespace(ns) } return client.Resource(gvr) } -func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface { +func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1.CustomResourceDefinition) dynamic.ResourceInterface { return newNamespacedCustomResourceVersionedClient(ns, client, crd, crd.Spec.Versions[0].Name) } // UpdateCustomResourceDefinitionWithRetry updates a CRD, retrying up to 5 times on version conflict errors. -func UpdateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1beta1.CustomResourceDefinition)) (*apiextensionsv1beta1.CustomResourceDefinition, error) { +func UpdateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1.CustomResourceDefinition)) (*apiextensionsv1.CustomResourceDefinition, error) { for i := 0; i < 5; i++ { - crd, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) + crd, err := client.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err) } update(crd) - crd, err = client.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd, err = client.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err == nil { return crd, nil } @@ -117,13 +116,7 @@ func UpdateV1CustomResourceDefinitionWithRetry(client clientset.Interface, name } // getSchemaForVersion returns the validation schema for given version in given CRD. -func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.CustomResourceValidation, error) { - if !hasPerVersionSchema(crd.Spec.Versions) { - return crd.Spec.Validation, nil - } - if crd.Spec.Validation != nil { - return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version schemas must be mutual exclusive", crd.Name, version) - } +func getSchemaForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceValidation, error) { for _, v := range crd.Spec.Versions { if version == v.Name { return v.Schema, nil @@ -133,13 +126,7 @@ func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, ver } // getSubresourcesForVersion returns the subresources for given version in given CRD. -func getSubresourcesForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.CustomResourceSubresources, error) { - if !hasPerVersionSubresources(crd.Spec.Versions) { - return crd.Spec.Subresources, nil - } - if crd.Spec.Subresources != nil { - return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version subresources must be mutual exclusive", crd.Name, version) - } +func getSubresourcesForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceSubresources, error) { for _, v := range crd.Spec.Versions { if version == v.Name { return v.Subresources, nil @@ -152,13 +139,7 @@ func getSubresourcesForVersion(crd *apiextensionsv1beta1.CustomResourceDefinitio // NOTE: the newly logically-defaulted columns is not pointing to the original CRD object. // One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through // the original CRD object instead. -func getColumnsForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) ([]apiextensionsv1beta1.CustomResourceColumnDefinition, error) { - if !hasPerVersionColumns(crd.Spec.Versions) { - return serveDefaultColumnsIfEmpty(crd.Spec.AdditionalPrinterColumns), nil - } - if len(crd.Spec.AdditionalPrinterColumns) > 0 { - return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version additionalPrinterColumns must be mutual exclusive", crd.Name, version) - } +func getColumnsForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) ([]apiextensionsv1.CustomResourceColumnDefinition, error) { for _, v := range crd.Spec.Versions { if version == v.Name { return serveDefaultColumnsIfEmpty(v.AdditionalPrinterColumns), nil @@ -171,41 +152,11 @@ func getColumnsForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, ve // NOTE: in this way, the newly logically-defaulted columns is not pointing to the original CRD object. // One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through // the original CRD object instead. -func serveDefaultColumnsIfEmpty(columns []apiextensionsv1beta1.CustomResourceColumnDefinition) []apiextensionsv1beta1.CustomResourceColumnDefinition { +func serveDefaultColumnsIfEmpty(columns []apiextensionsv1.CustomResourceColumnDefinition) []apiextensionsv1.CustomResourceColumnDefinition { if len(columns) > 0 { return columns } - return []apiextensionsv1beta1.CustomResourceColumnDefinition{ + return []apiextensionsv1.CustomResourceColumnDefinition{ {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, } } - -// hasPerVersionSchema returns true if a CRD uses per-version schema. -func hasPerVersionSchema(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool { - for _, v := range versions { - if v.Schema != nil { - return true - } - } - return false -} - -// hasPerVersionSubresources returns true if a CRD uses per-version subresources. -func hasPerVersionSubresources(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool { - for _, v := range versions { - if v.Subresources != nil { - return true - } - } - return false -} - -// hasPerVersionColumns returns true if a CRD uses per-version columns. -func hasPerVersionColumns(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool { - for _, v := range versions { - if len(v.AdditionalPrinterColumns) > 0 { - return true - } - } - return false -} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/limit_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/limit_test.go index 77dd0773fde..456d06a2077 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/limit_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/limit_test.go @@ -22,13 +22,12 @@ import ( "strings" "testing" - "k8s.io/client-go/dynamic" - - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" ) func TestLimits(t *testing.T) { @@ -47,14 +46,14 @@ func TestLimits(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name rest := apiExtensionClient.Discovery().RESTClient() @@ -70,7 +69,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(yamlBody). DoRaw(context.TODO()) if !apierrors.IsRequestEntityTooLargeError(err) { @@ -93,7 +92,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(yamlBody). DoRaw(context.TODO()) if !apierrors.IsBadRequest(err) { @@ -116,7 +115,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(yamlBody). DoRaw(context.TODO()) if !apierrors.IsBadRequest(err) { @@ -137,7 +136,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(jsonBody). DoRaw(context.TODO()) if !apierrors.IsRequestEntityTooLargeError(err) { @@ -161,7 +160,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(jsonBody). DoRaw(context.TODO()) if !apierrors.IsBadRequest(err) { @@ -185,7 +184,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) _, err := rest.Post(). SetHeader("Accept", "application/json"). SetHeader("Content-Type", "application/json"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(jsonBody). DoRaw(context.TODO()) if !apierrors.IsBadRequest(err) { @@ -196,7 +195,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) // Create instance to allow patching { jsonBody := []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": "test"}}`, apiVersion, kind)) - _, err := rest.Post().AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).Body(jsonBody).DoRaw(context.TODO()) + _, err := rest.Post().AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).Body(jsonBody).DoRaw(context.TODO()) if err != nil { t.Fatalf("error creating object: %v", err) } @@ -207,7 +206,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) t.Skip("skipping expensive test") } patchBody := []byte(`[{"op":"add","path":"/foo","value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}]`) - err = rest.Patch(types.JSONPatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test"). + err = rest.Patch(types.JSONPatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test"). Body(patchBody).Do(context.TODO()).Error() if !apierrors.IsBadRequest(err) { t.Errorf("expected success or bad request err, got %v", err) @@ -218,7 +217,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) t.Skip("skipping expensive test") } patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`) - err = rest.Patch(types.MergePatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test"). + err = rest.Patch(types.MergePatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test"). Body(patchBody).Do(context.TODO()).Error() if !apierrors.IsBadRequest(err) { t.Errorf("expected success or bad request err, got %v", err) @@ -229,7 +228,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind)) t.Skip("skipping expensive test") } patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`) - err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test"). + err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test"). Body(patchBody).Do(context.TODO()).Error() if !apierrors.IsBadRequest(err) { t.Errorf("expected bad request err, got %#v", err) diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/listtype_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/listtype_test.go index 97bc4d48028..aafc42da166 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/listtype_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/listtype_test.go @@ -22,37 +22,36 @@ import ( "testing" "time" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/util/retry" - "sigs.k8s.io/yaml" - - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/test/integration/fixtures" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/yaml" ) -var listTypeResourceFixture = &apiextensionsv1beta1.CustomResourceDefinition{ +var listTypeResourceFixture = &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ Group: "tests.example.com", - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Storage: true, Served: true, + Schema: fixtures.AllowAllSchema(), }, }, - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "foos", Singular: "foo", Kind: "Foo", ListKind: "FooList", }, - Scope: apiextensionsv1beta1.ClusterScoped, - Validation: &apiextensionsv1beta1.CustomResourceValidation{}, + Scope: apiextensionsv1.ClusterScoped, }, } @@ -128,11 +127,11 @@ func TestListTypes(t *testing.T) { defer tearDownFn() crd := listTypeResourceFixture.DeepCopy() - if err := yaml.Unmarshal([]byte(listTypeResourceSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + if err := yaml.Unmarshal([]byte(listTypeResourceSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -195,14 +194,14 @@ func TestListTypes(t *testing.T) { t.Logf("Remove \"b\" from the keys in the schema which renders the valid instance invalid") err = retry.RetryOnConflict(retry.DefaultBackoff, func() error { - crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { return err } - s := crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"] + s := crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"] s.XListMapKeys = []string{"a"} - crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"] = s - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"] = s + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) return err }) if err != nil { diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go index 7cd71d2ab98..34adaad989d 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go @@ -30,7 +30,6 @@ import ( "sigs.k8s.io/yaml" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options" "k8s.io/apiextensions-apiserver/test/integration/fixtures" @@ -52,8 +51,8 @@ func TestPostInvalidObjectMeta(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -114,11 +113,11 @@ func TestInvalidObjectMetaInStorage(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{ + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ Type: "object", - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "embedded": { Type: "object", XEmbeddedResource: true, @@ -127,7 +126,7 @@ func TestInvalidObjectMetaInStorage(t *testing.T) { }, }, } - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/pruning_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/pruning_test.go index dfca944824a..baccc222472 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/pruning_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/pruning_test.go @@ -24,6 +24,8 @@ import ( "testing" "time" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "go.etcd.io/etcd/clientv3" "go.etcd.io/etcd/pkg/transport" "google.golang.org/grpc" @@ -39,29 +41,37 @@ import ( "k8s.io/apimachinery/pkg/util/json" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/client-go/dynamic" - "k8s.io/utils/pointer" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" ) -var pruningFixture = &apiextensionsv1beta1.CustomResourceDefinition{ +var pruningFixture = &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "tests.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "tests.example.com", + Scope: apiextensionsv1.ClusterScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + }, + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + }, + }, + }, + }, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "foos", Singular: "foo", Kind: "Foo", ListKind: "FooList", }, - Scope: apiextensionsv1beta1.ClusterScoped, - PreserveUnknownFields: pointer.BoolPtr(false), - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - }, }, } @@ -189,18 +199,18 @@ func TestPruningCreate(t *testing.T) { defer tearDownFn() crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } t.Logf("Creating CR and expect 'unspecified' fields to be pruned") - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil { t.Fatal(err) @@ -241,18 +251,18 @@ func TestPruningStatus(t *testing.T) { defer tearDownFn() crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } t.Logf("Creating CR and expect 'unspecified' fields to be pruned") - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil { t.Fatal(err) @@ -310,12 +320,12 @@ func TestPruningFromStorage(t *testing.T) { } crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -368,7 +378,7 @@ func TestPruningFromStorage(t *testing.T) { } t.Logf("Checking that CustomResource is pruned from unknown fields") - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo, err := fooClient.Get(context.TODO(), "foo", metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -400,16 +410,16 @@ func TestPruningPatch(t *testing.T) { defer tearDownFn() crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil { t.Fatal(err) @@ -451,18 +461,18 @@ func TestPruningCreatePreservingUnknownFields(t *testing.T) { defer tearDownFn() crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } t.Logf("Creating CR and expect 'unspecified' field to be pruned") - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil { t.Fatal(err) @@ -536,18 +546,18 @@ func TestPruningEmbeddedResources(t *testing.T) { defer tearDownFn() crd := pruningFixture.DeepCopy() - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{} - if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Validation.OpenAPIV3Schema); err != nil { + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{} + if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil { t.Fatal(err) } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } t.Logf("Creating CR and expect 'unspecified' field to be pruned") - fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural}) + fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural}) foo := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResourceInstance), &foo.Object); err != nil { t.Fatal(err) diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go index 620748cfdfa..bd402616ace 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/registration_test.go @@ -28,7 +28,7 @@ import ( "go.etcd.io/etcd/clientv3" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apimachinery/pkg/api/errors" @@ -47,8 +47,8 @@ func TestMultipleResourceInstances(t *testing.T) { defer tearDown() ns := "not-the-default" - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -172,8 +172,8 @@ func TestMultipleRegistration(t *testing.T) { ns := "not-the-default" sameInstanceName := "foo" - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -191,8 +191,8 @@ func TestMultipleRegistration(t *testing.T) { t.Errorf("expected %v, got %v", e, a) } - curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) + curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -225,11 +225,11 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { t.Fatal(err) } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) ns := "not-the-default" sameInstanceName := "foo" func() { - noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -237,10 +237,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { if _, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil { t.Fatal(err) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } - if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } if _, err = noxuNamespacedResourceClient.List(context.TODO(), metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) { @@ -252,10 +252,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) { }() func() { - if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { + if _, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) { t.Fatalf("expected a NotFound error, got:%v", err) } - noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -327,8 +327,8 @@ func TestEtcdStorage(t *testing.T) { etcdPrefix := s.RecommendedOptions.Etcd.StorageConfig.Prefix ns1 := "another-default-is-possible" - curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) + curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -338,8 +338,8 @@ func TestEtcdStorage(t *testing.T) { } ns2 := "the-cruel-default" - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/scope_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/scope_test.go index 70fbb0f7d71..e2ca979c837 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/scope_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/scope_test.go @@ -23,15 +23,14 @@ import ( "github.com/stretchr/testify/assert" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apiextensions-apiserver/test/integration/fixtures" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/dynamic" - - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apiextensions-apiserver/test/integration/fixtures" ) func TestHandlerScope(t *testing.T) { @@ -41,15 +40,32 @@ func TestHandlerScope(t *testing.T) { } defer tearDown() - for _, scope := range []apiextensionsv1beta1.ResourceScope{apiextensionsv1beta1.ClusterScoped, apiextensionsv1beta1.NamespaceScoped} { + for _, scope := range []apiextensionsv1.ResourceScope{apiextensionsv1.ClusterScoped, apiextensionsv1.NamespaceScoped} { t.Run(string(scope), func(t *testing.T) { - crd := &apiextensionsv1beta1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "test.apiextensions-apiserver.k8s.io", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + crd := &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io", + Annotations: map[string]string{"api-approved.kubernetes.io": "unapproved, test-only"}, + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "test.apiextensions-apiserver.k8s.io", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + Scale: &apiextensionsv1.CustomResourceSubresourceScale{ + SpecReplicasPath: ".spec.replicas", + StatusReplicasPath: ".status.replicas", + }, + }, + Schema: fixtures.AllowAllSchema(), + }, + }, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: strings.ToLower(string(scope)) + "s", Singular: strings.ToLower(string(scope)), Kind: string(scope), @@ -58,14 +74,7 @@ func TestHandlerScope(t *testing.T) { Scope: scope, }, } - crd.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{ - SpecReplicasPath: ".spec.replicas", - StatusReplicasPath: ".status.replicas", - }, - } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -75,7 +84,7 @@ func TestHandlerScope(t *testing.T) { ns := "test" var client dynamic.ResourceInterface = dynamicClient.Resource(gvr) var otherScopeClient dynamic.ResourceInterface = dynamicClient.Resource(gvr).Namespace(ns) - if crd.Spec.Scope == apiextensionsv1beta1.NamespaceScoped { + if crd.Spec.Scope == apiextensionsv1.NamespaceScoped { client, otherScopeClient = otherScopeClient, client } @@ -141,7 +150,7 @@ func TestHandlerScope(t *testing.T) { err = otherScopeClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{}) assert.True(t, apierrors.IsNotFound(err)) - if scope == apiextensionsv1beta1.ClusterScoped { + if scope == apiextensionsv1.ClusterScoped { _, err = otherScopeClient.List(context.TODO(), metav1.ListOptions{}) assert.True(t, apierrors.IsNotFound(err)) diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go index d6e227e0b2c..9df139f1595 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/subresources_test.go @@ -35,7 +35,7 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/dynamic" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" ) @@ -43,51 +43,14 @@ import ( var labelSelectorPath = ".status.labelSelector" var anotherLabelSelectorPath = ".status.anotherLabelSelector" -func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition { - return []*apiextensionsv1beta1.CustomResourceDefinition{ - // CRD that uses top-level subresources - { - ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ - Plural: "noxus", - Singular: "nonenglishnoxu", - Kind: "WishIHadChosenNoxu", - ShortNames: []string{"foo", "bar", "abc", "def"}, - ListKind: "NoxuItemList", - }, - Scope: scope, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1beta1", - Served: true, - Storage: true, - }, - { - Name: "v1", - Served: true, - Storage: false, - }, - }, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{ - SpecReplicasPath: ".spec.replicas", - StatusReplicasPath: ".status.replicas", - LabelSelectorPath: &labelSelectorPath, - }, - }, - }, - }, +func NewNoxuSubresourcesCRDs(scope apiextensionsv1.ResourceScope) []*apiextensionsv1.CustomResourceDefinition { + return []*apiextensionsv1.CustomResourceDefinition{ // CRD that uses per-version subresources { ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "noxus", Singular: "nonenglishnoxu", Kind: "WishIHadChosenNoxu", @@ -95,32 +58,34 @@ func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiext ListKind: "NoxuItemList", }, Scope: scope, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: true, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{ + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + Scale: &apiextensionsv1.CustomResourceSubresourceScale{ SpecReplicasPath: ".spec.replicas", StatusReplicasPath: ".status.replicas", LabelSelectorPath: &labelSelectorPath, }, }, + Schema: fixtures.AllowAllSchema(), }, { Name: "v1", Served: true, Storage: false, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{ + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + Scale: &apiextensionsv1.CustomResourceSubresourceScale{ SpecReplicasPath: ".spec.replicas", StatusReplicasPath: ".status.replicas", LabelSelectorPath: &anotherLabelSelectorPath, }, }, + Schema: fixtures.AllowAllSchema(), }, }, }, @@ -155,9 +120,9 @@ func TestStatusSubresource(t *testing.T) { } defer tearDown() - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -254,7 +219,7 @@ func TestStatusSubresource(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -281,7 +246,7 @@ func TestScaleSubresource(t *testing.T) { t.Fatal(err) } - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) for _, noxuDefinition := range noxuDefinitions { for _, v := range noxuDefinition.Spec.Versions { // Start with a new CRD, so that the object doesn't have resourceVersion @@ -293,13 +258,13 @@ func TestScaleSubresource(t *testing.T) { } // set invalid json path for specReplicasPath subresources.Scale.SpecReplicasPath = "foo,bar" - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec") } subresources.Scale.SpecReplicasPath = ".spec.replicas" - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -400,7 +365,7 @@ func TestScaleSubresource(t *testing.T) { t.Fatalf("unexpected non-error: .spec.replicas should be less than 2147483647") } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -423,22 +388,16 @@ func TestValidationSchemaWithStatus(t *testing.T) { t.Fatal(err) } - // fields other than properties in root schema are not allowed - noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[0] - noxuDefinition.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, - } - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) - if err == nil { - t.Fatalf(`unexpected non-error, expected: must not have "additionalProperties" at the root of the schema if the status subresource is enabled`) - } + noxuDefinition := newNoxuValidationCRDs()[0] // make sure we are not restricting fields to properties even in subschemas - noxuDefinition.Spec.Validation.OpenAPIV3Schema = &apiextensionsv1beta1.JSONSchemaProps{ - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + noxuDefinition.Spec.Versions[0].Schema.OpenAPIV3Schema = &apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "spec": { + Type: "object", Description: "Validation for spec", - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "replicas": { Type: "integer", }, @@ -448,7 +407,9 @@ func TestValidationSchemaWithStatus(t *testing.T) { Required: []string{"spec"}, Description: "This is a description at the root of the schema", } - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition.Spec.Versions[1].Schema.OpenAPIV3Schema = noxuDefinition.Spec.Versions[0].Schema.OpenAPIV3Schema + + _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err) } @@ -468,10 +429,12 @@ func TestValidateOnlyStatus(t *testing.T) { // 4. update the spec of the cr with .spec.num = 15 (spec is invalid), expect error // max value of spec.num = 10 and status.num = 10 - schema := &apiextensionsv1beta1.JSONSchemaProps{ - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + schema := &apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "spec": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "num": { Type: "integer", Maximum: float64Ptr(10), @@ -479,7 +442,8 @@ func TestValidateOnlyStatus(t *testing.T) { }, }, "status": { - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "num": { Type: "integer", Maximum: float64Ptr(10), @@ -489,24 +453,16 @@ func TestValidateOnlyStatus(t *testing.T) { }, } - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) - for i, noxuDefinition := range noxuDefinitions { - if i == 0 { - noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: schema, - } - } else { - noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: schema, - } - schemaWithDescription := schema.DeepCopy() - schemaWithDescription.Description = "test" - noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: schemaWithDescription, - } + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) + for _, noxuDefinition := range noxuDefinitions { + noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: schema.DeepCopy(), + } + noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: schema.DeepCopy(), } - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -554,7 +510,7 @@ func TestValidateOnlyStatus(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -576,9 +532,9 @@ func TestSubresourcesDiscovery(t *testing.T) { t.Fatal(err) } - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -645,7 +601,7 @@ func TestSubresourcesDiscovery(t *testing.T) { t.Fatalf("incorrect scale via discovery: expected: %v, got: %v", expectedVerbs, scale.Verbs) } } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -658,9 +614,9 @@ func TestGeneration(t *testing.T) { } defer tearDown() - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -718,7 +674,7 @@ func TestGeneration(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -745,9 +701,9 @@ func TestSubresourcePatch(t *testing.T) { t.Fatal(err) } - noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped) for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -882,7 +838,7 @@ func TestSubresourcePatch(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go index f6db46b8e0e..9e9f7cd67a0 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/table_test.go @@ -32,42 +32,42 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" ) -func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition { - return &apiextensionsv1beta1.CustomResourceDefinition{ +func newTableCRD() *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "tables", Singular: "table", Kind: "Table", ListKind: "TablemList", }, - Scope: apiextensionsv1beta1.ClusterScoped, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + Scope: apiextensionsv1.ClusterScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: false, - AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ + AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{ {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, {Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"}, {Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"}, {Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"}, {Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"}, }, + Schema: fixtures.AllowAllSchema(), }, { Name: "v1", Served: true, Storage: true, - AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{ + AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{ {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"}, {Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"}, {Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"}, @@ -75,6 +75,7 @@ func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition { {Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"}, {Name: "Zeta", Type: "integer", Description: "the zeta field", Format: "int64", Priority: 42, JSONPath: ".spec.zeta"}, }, + Schema: fixtures.AllowAllSchema(), }, }, }, @@ -119,12 +120,12 @@ func TestTableGet(t *testing.T) { } crd := newTableCRD() - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } @@ -377,8 +378,8 @@ func TestColumnsPatch(t *testing.T) { } // CRD with no top-level and per-version columns should be created successfully - crd := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0] - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0] + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -386,14 +387,50 @@ func TestColumnsPatch(t *testing.T) { // One should be able to patch the CRD to use per-version columns. The top-level columns // should not be defaulted during creation, and apiserver should not return validation // error about top-level and per-version columns being mutual exclusive. - patch := []byte(`{"spec":{"versions":[{"name":"v1beta1","served":true,"storage":true,"additionalPrinterColumns":[{"name":"Age","type":"date","JSONPath":".metadata.creationTimestamp"}]},{"name":"v1","served":true,"storage":false,"additionalPrinterColumns":[{"name":"Age2","type":"date","JSONPath":".metadata.creationTimestamp"}]}]}}`) + patch := []byte(`{ + "spec": { + "versions": [ + { + "name": "v1beta1", + "served": true, + "storage": true, + "additionalPrinterColumns": [ + { + "name": "Age", + "type": "date", + "jsonPath": ".metadata.creationTimestamp" + } + ], + "schema": { + "openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"} + } + }, + { + "name": "v1", + "served": true, + "storage": false, + "additionalPrinterColumns": [ + { + "name": "Age2", + "type": "date", + "jsonPath": ".metadata.creationTimestamp" + } + ], + "schema": { + "openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"} + } + } + ] + } +} +`) - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{}) + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{}) if err != nil { t.Fatal(err) } - crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } @@ -420,11 +457,11 @@ func TestPatchCleanTopLevelColumns(t *testing.T) { t.Fatal(err) } - crd := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0] - crd.Spec.AdditionalPrinterColumns = []apiextensionsv1beta1.CustomResourceColumnDefinition{ + crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0] + crd.Spec.Versions[0].AdditionalPrinterColumns = []apiextensionsv1.CustomResourceColumnDefinition{ {Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"}, } - crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient) + crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -432,14 +469,51 @@ func TestPatchCleanTopLevelColumns(t *testing.T) { // One should be able to patch the CRD to use per-version columns by cleaning // the top-level columns. - patch := []byte(`{"spec":{"additionalPrinterColumns":null,"versions":[{"name":"v1beta1","served":true,"storage":true,"additionalPrinterColumns":[{"name":"Age","type":"date","JSONPath":".metadata.creationTimestamp"}]},{"name":"v1","served":true,"storage":false,"additionalPrinterColumns":[{"name":"Age2","type":"date","JSONPath":".metadata.creationTimestamp"}]}]}}`) + patch := []byte(`{ + "spec": { + "additionalPrinterColumns": null, + "versions": [ + { + "name": "v1beta1", + "served": true, + "storage": true, + "additionalPrinterColumns": [ + { + "name": "Age", + "type": "date", + "jsonPath": ".metadata.creationTimestamp" + } + ], + "schema": { + "openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"} + } + }, + { + "name": "v1", + "served": true, + "storage": false, + "additionalPrinterColumns": [ + { + "name": "Age2", + "type": "date", + "jsonPath": ".metadata.creationTimestamp" + } + ], + "schema": { + "openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"} + } + } + ] + } +} +`) - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{}) + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{}) if err != nil { t.Fatal(err) } - crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go index 38b41ffb6db..05bf41a186c 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/validation_test.go @@ -19,6 +19,7 @@ package integration import ( "context" "fmt" + "path" "strings" "testing" "time" @@ -27,9 +28,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/yaml" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -44,8 +46,8 @@ func TestForProperValidationErrors(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -91,13 +93,11 @@ func TestForProperValidationErrors(t *testing.T) { } } -func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition { - validationSchema := &apiextensionsv1beta1.JSONSchemaProps{ +func newNoxuValidationCRDs() []*apiextensionsv1.CustomResourceDefinition { + validationSchema := &apiextensionsv1.JSONSchemaProps{ + Type: "object", Required: []string{"alpha", "beta"}, - AdditionalProperties: &apiextensionsv1beta1.JSONSchemaPropsOrBool{ - Allows: true, - }, - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ + Properties: map[string]apiextensionsv1.JSONSchemaProps{ "alpha": { Description: "Alpha is an alphanumeric string with underscores", Type: "string", @@ -111,7 +111,7 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten "gamma": { Description: "Gamma is restricted to foo, bar and baz", Type: "string", - Enum: []apiextensionsv1beta1.JSON{ + Enum: []apiextensionsv1.JSON{ { Raw: []byte(`"foo"`), }, @@ -123,73 +123,29 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten }, }, }, - "delta": { - Description: "Delta is a string with a maximum length of 5 or a number with a minimum value of 0", - AnyOf: []apiextensionsv1beta1.JSONSchemaProps{ - { - Type: "string", - MaxLength: int64Ptr(5), - }, - { - Type: "number", - Minimum: float64Ptr(0), - }, - }, - }, }, } validationSchemaWithDescription := validationSchema.DeepCopy() validationSchemaWithDescription.Description = "test" - return []*apiextensionsv1beta1.CustomResourceDefinition{ + return []*apiextensionsv1.CustomResourceDefinition{ { ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "noxus", Singular: "nonenglishnoxu", Kind: "WishIHadChosenNoxu", ShortNames: []string{"foo", "bar", "abc", "def"}, ListKind: "NoxuItemList", }, - Scope: apiextensionsv1beta1.NamespaceScoped, - Validation: &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: validationSchema, - }, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + Scope: apiextensionsv1.NamespaceScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: true, - }, - { - Name: "v1", - Served: true, - Storage: false, - }, - }, - }, - }, - { - ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "mygroup.example.com", - Version: "v1beta1", - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ - Plural: "noxus", - Singular: "nonenglishnoxu", - Kind: "WishIHadChosenNoxu", - ShortNames: []string{"foo", "bar", "abc", "def"}, - ListKind: "NoxuItemList", - }, - Scope: apiextensionsv1beta1.NamespaceScoped, - Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1beta1", - Served: true, - Storage: true, - Schema: &apiextensionsv1beta1.CustomResourceValidation{ + Schema: &apiextensionsv1.CustomResourceValidation{ OpenAPIV3Schema: validationSchema, }, }, @@ -197,7 +153,39 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten Name: "v1", Served: true, Storage: false, - Schema: &apiextensionsv1beta1.CustomResourceValidation{ + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: validationSchema, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "noxus", + Singular: "nonenglishnoxu", + Kind: "WishIHadChosenNoxu", + ShortNames: []string{"foo", "bar", "abc", "def"}, + ListKind: "NoxuItemList", + }, + Scope: apiextensionsv1.NamespaceScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: true, + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: validationSchema, + }, + }, + { + Name: "v1", + Served: true, + Storage: false, + Schema: &apiextensionsv1.CustomResourceValidation{ OpenAPIV3Schema: validationSchemaWithDescription, }, }, @@ -231,9 +219,9 @@ func TestCustomResourceValidation(t *testing.T) { } defer tearDown() - noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := newNoxuValidationCRDs() for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -249,7 +237,7 @@ func TestCustomResourceValidation(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -436,9 +424,9 @@ func TestCustomResourceUpdateValidation(t *testing.T) { } defer tearDown() - noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := newNoxuValidationCRDs() for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -476,7 +464,7 @@ func TestCustomResourceUpdateValidation(t *testing.T) { } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -489,9 +477,9 @@ func TestCustomResourceValidationErrors(t *testing.T) { } defer tearDown() - noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := newNoxuValidationCRDs() for _, noxuDefinition := range noxuDefinitions { - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -530,18 +518,6 @@ func TestCustomResourceValidationErrors(t *testing.T) { }, expectedErrors: []string{`gamma: Unsupported value: "qux": supported values: "foo", "bar", "baz"`}, }, - { - name: "bad delta", - instanceFn: func() *unstructured.Unstructured { - instance := newNoxuValidationInstance(ns, "foo") - instance.Object["delta"] = "foobarbaz" - return instance - }, - expectedErrors: []string{ - "must validate at least one schema (anyOf)", - "delta in body should be at most 5 chars long", - }, - }, { name: "absent alpha and beta", instanceFn: func() *unstructured.Unstructured { @@ -580,7 +556,7 @@ func TestCustomResourceValidationErrors(t *testing.T) { } } } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -593,26 +569,27 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { } defer tearDown() - noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := newNoxuValidationCRDs() for i, noxuDefinition := range noxuDefinitions { for _, v := range noxuDefinition.Spec.Versions { // Re-define the CRD to make sure we start with a clean CRD - noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[i] + noxuDefinition := newNoxuValidationCRDs()[i] validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name) if err != nil { t.Fatal(err) } // set stricter schema - validationSchema.OpenAPIV3Schema.Required = []string{"alpha", "beta", "epsilon"} + validationSchema.OpenAPIV3Schema.Required = []string{"alpha", "beta", "gamma"} - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } ns := "not-the-default" noxuResourceClient := newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name) instanceToCreate := newNoxuValidationInstance(ns, "foo") + unstructured.RemoveNestedField(instanceToCreate.Object, "gamma") instanceToCreate.Object["apiVersion"] = fmt.Sprintf("%s/%s", noxuDefinition.Spec.Group, v.Name) // CR is rejected @@ -622,7 +599,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { } // update the CRD to a less stricter schema - _, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1beta1.CustomResourceDefinition) { + _, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1.CustomResourceDefinition) { validationSchema, err := getSchemaForVersion(crd, v.Name) if err != nil { t.Fatal(err) @@ -650,7 +627,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) { t.Fatal(err) } noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{}) - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -664,51 +641,59 @@ func TestForbiddenFieldsInSchema(t *testing.T) { } defer tearDown() - noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped) + noxuDefinitions := newNoxuValidationCRDs() for i, noxuDefinition := range noxuDefinitions { for _, v := range noxuDefinition.Spec.Versions { // Re-define the CRD to make sure we start with a clean CRD - noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[i] + noxuDefinition := newNoxuValidationCRDs()[i] validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name) if err != nil { t.Fatal(err) } - validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = false - - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + existingProperties := validationSchema.OpenAPIV3Schema.Properties + validationSchema.OpenAPIV3Schema.Properties = nil + validationSchema.OpenAPIV3Schema.AdditionalProperties = &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false} + _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: additionalProperties cannot be set to false") } + // reset + validationSchema.OpenAPIV3Schema.Properties = existingProperties + validationSchema.OpenAPIV3Schema.AdditionalProperties = nil - validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1beta1.JSONSchemaProps{ + validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1.JSONSchemaProps{ Type: "array", UniqueItems: true, + AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{ + Allows: true, + }, } - validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = true - - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatalf("unexpected non-error: uniqueItems cannot be set to true") } validationSchema.OpenAPIV3Schema.Ref = strPtr("#/definition/zeta") - validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1beta1.JSONSchemaProps{ + validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1.JSONSchemaProps{ Type: "array", UniqueItems: false, + Items: &apiextensionsv1.JSONSchemaPropsOrArray{ + Schema: &apiextensionsv1.JSONSchemaProps{Type: "object"}, + }, } - _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err == nil { t.Fatal("unexpected non-error: $ref cannot be non-empty string") } validationSchema.OpenAPIV3Schema.Ref = nil - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { + if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil { t.Fatal(err) } } @@ -716,7 +701,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) { } func TestNonStructuralSchemaConditionUpdate(t *testing.T) { - tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t) + tearDown, apiExtensionClient, _, etcdclient, etcdStoragePrefix, err := fixtures.StartDefaultServerWithClientsAndEtcd(t) if err != nil { t.Fatal(err) } @@ -752,27 +737,37 @@ spec: if err != nil { t.Fatalf("failed decoding of: %v\n\n%s", err, manifest) } - crd := obj.(*apiextensionsv1beta1.CustomResourceDefinition) - name := crd.Name + betaCRD := obj.(*apiextensionsv1beta1.CustomResourceDefinition) + name := betaCRD.Name // save schema for later - origSchema := crd.Spec.Validation.OpenAPIV3Schema + origSchema := &apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ + "a": { + Type: "object", + }, + }, + } - // create CRDs - t.Logf("Creating CRD %s", crd.Name) - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), crd, metav1.CreateOptions{}); err != nil { - t.Fatalf("unexpected create error: %v", err) + // create CRDs. We cannot create these in v1, but they can exist in upgraded clusters + t.Logf("Creating CRD %s", betaCRD.Name) + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) + key := path.Join("/", etcdStoragePrefix, "apiextensions.k8s.io", "customresourcedefinitions/foos.tests.example.com") + val, _ := json.Marshal(betaCRD) + if _, err := etcdclient.Put(ctx, key, string(val)); err != nil { + t.Fatalf("unexpected error: %v", err) } // wait for condition with violations t.Log("Waiting for NonStructuralSchema condition") - var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition + var cond *apiextensionsv1.CustomResourceDefinitionCondition err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) { - obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) + obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { return false, err } - cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema) + cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema) return cond != nil, nil }) if err != nil { @@ -785,34 +780,32 @@ spec: t.Fatalf("expected violation %q, but got: %v", v, cond.Message) } - // remove schema - t.Log("Remove schema") + t.Log("fix schema") for retry := 0; retry < 5; retry++ { - // This patch fixes two fields to resolve - // 1. property type validation error - // 2. preserveUnknownFields validation error - patch := []byte("[{\"op\":\"add\",\"path\":\"/spec/validation/openAPIV3Schema/properties/a/type\",\"value\":\"int\"}," + - "{\"op\":\"replace\",\"path\":\"/spec/preserveUnknownFields\",\"value\":false}]") - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), name, types.JSONPatchType, patch, metav1.PatchOptions{}); apierrors.IsConflict(err) { + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + crd.Spec.Versions[0].Schema = fixtures.AllowAllSchema() + crd.Spec.PreserveUnknownFields = false + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + if apierrors.IsConflict(err) { continue } if err != nil { - t.Fatalf("unexpected update error: %v", err) + t.Fatal(err) } break } - if err != nil { - t.Fatalf("unexpected update error: %v", err) - } // wait for condition to go away t.Log("Wait for condition to disappear") err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) { - obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) + obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { return false, err } - cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema) + cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema) return cond == nil, nil }) if err != nil { @@ -822,43 +815,23 @@ spec: // re-add schema t.Log("Re-add schema") for retry := 0; retry < 5; retry++ { - crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { t.Fatalf("unexpected get error: %v", err) } - crd.Spec.PreserveUnknownFields = nil - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{OpenAPIV3Schema: origSchema} - if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) { + crd.Spec.PreserveUnknownFields = true + crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{OpenAPIV3Schema: origSchema} + if _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) { continue } - if err != nil { - t.Fatalf("unexpected update error: %v", err) + if err == nil { + t.Fatalf("missing error") + } + if !strings.Contains(err.Error(), "spec.preserveUnknownFields") { + t.Fatal(err) } break } - if err != nil { - t.Fatalf("unexpected update error: %v", err) - } - - // wait for condition with violations - t.Log("Wait for condition to reappear") - err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) { - obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{}) - if err != nil { - return false, err - } - cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema) - return cond != nil, nil - }) - if err != nil { - t.Fatalf("unexpected error waiting for NonStructuralSchema condition: %v", cond) - } - if v := "spec.versions[0].schema.openAPIV3Schema.properties[a].type: Required value: must not be empty for specified object fields"; !strings.Contains(cond.Message, v) { - t.Fatalf("expected violation %q, but got: %v", v, cond.Message) - } - if v := "spec.preserveUnknownFields: Invalid value: true: must be false"; !strings.Contains(cond.Message, v) { - t.Fatalf("expected violation %q, but got: %v", v, cond.Message) - } } func TestNonStructuralSchemaCondition(t *testing.T) { @@ -1657,13 +1630,13 @@ properties: if len(tst.expectedViolations) == 0 { // wait for condition to not appear - var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition + var cond *apiextensionsv1.CustomResourceDefinitionCondition err := wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) { - obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { return false, err } - cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema) + cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema) if cond == nil { return false, nil } @@ -1676,13 +1649,13 @@ properties: } // wait for condition to appear with the given violations - var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition + var cond *apiextensionsv1.CustomResourceDefinitionCondition err = wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) + obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) if err != nil { return false, err } - cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema) + cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema) if cond != nil { return true, nil } @@ -1696,7 +1669,7 @@ properties: if cond.Reason != "Violations" { t.Errorf("expected reason Violations, got: %v", cond.Reason) } - if cond.Status != apiextensionsv1beta1.ConditionTrue { + if cond.Status != apiextensionsv1.ConditionTrue { t.Errorf("expected reason True, got: %v", cond.Status) } @@ -1717,7 +1690,7 @@ properties: } // findCRDCondition returns the condition you're looking for or nil. -func findCRDCondition(crd *apiextensionsv1beta1.CustomResourceDefinition, conditionType apiextensionsv1beta1.CustomResourceDefinitionConditionType) *apiextensionsv1beta1.CustomResourceDefinitionCondition { +func findCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) *apiextensionsv1.CustomResourceDefinitionCondition { for i := range crd.Status.Conditions { if crd.Status.Conditions[i].Type == conditionType { return &crd.Status.Conditions[i] @@ -1742,10 +1715,6 @@ func float64Ptr(f float64) *float64 { return &f } -func int64Ptr(f int64) *int64 { - return &f -} - func strPtr(str string) *string { return &str } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go index 2d9b6c4b112..d9abdf5c67b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/versioning_test.go @@ -25,7 +25,7 @@ import ( "time" "github.com/stretchr/testify/assert" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/test/integration/fixtures" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -40,13 +40,13 @@ func TestInternalVersionIsHandlerVersion(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped) assert.Equal(t, "v1beta1", noxuDefinition.Spec.Versions[0].Name) assert.Equal(t, "v1beta2", noxuDefinition.Spec.Versions[1].Name) assert.True(t, noxuDefinition.Spec.Versions[1].Storage) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -64,16 +64,20 @@ func TestInternalVersionIsHandlerVersion(t *testing.T) { // update validation via update because the cache priming in CreateNewCustomResourceDefinition will fail otherwise t.Logf("Updating CRD to validate apiVersion") - noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1beta1.CustomResourceDefinition) { - crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{ - Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{ - "apiVersion": { - Pattern: "^mygroup.example.com/v1beta1$", // this means we can only patch via the v1beta1 handler version + noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1.CustomResourceDefinition) { + for i := range crd.Spec.Versions { + crd.Spec.Versions[i].Schema = &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ + "apiVersion": { + Pattern: "^mygroup.example.com/v1beta1$", // this means we can only patch via the v1beta1 handler version + Type: "string", + }, }, + Required: []string{"apiVersion"}, }, - Required: []string{"apiVersion"}, - }, + } } }) assert.NoError(t, err) @@ -134,8 +138,8 @@ func TestVersionedNamespacedScopedCRD(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -151,8 +155,8 @@ func TestVersionedClusterScopedCRD(t *testing.T) { } defer tearDown() - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } @@ -162,40 +166,44 @@ func TestVersionedClusterScopedCRD(t *testing.T) { } func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) { - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped) ns := "not-the-default" testStoragedVersionInCRDStatus(t, ns, noxuDefinition) } func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) { - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped) ns := "" testStoragedVersionInCRDStatus(t, ns, noxuDefinition) } -func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) { - versionsV1Beta1Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ +func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition) { + versionsV1Beta1Storage := []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: true, + Schema: fixtures.AllowAllSchema(), }, { Name: "v1beta2", Served: true, Storage: false, + Schema: fixtures.AllowAllSchema(), }, } - versionsV1Beta2Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + versionsV1Beta2Storage := []apiextensionsv1.CustomResourceDefinitionVersion{ { Name: "v1beta1", Served: true, Storage: false, + Schema: fixtures.AllowAllSchema(), }, { Name: "v1beta2", Served: true, Storage: true, + Schema: fixtures.AllowAllSchema(), }, } tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t) @@ -205,13 +213,13 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api defer tearDown() noxuDefinition.Spec.Versions = versionsV1Beta1Storage - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } // The storage version list should be initilized to storage version - crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) + crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } @@ -221,11 +229,11 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api // Changing CRD storage version should be reflected immediately crd.Spec.Versions = versionsV1Beta2Storage - _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) + _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) if err != nil { t.Fatal(err) } - crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) + crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } @@ -233,7 +241,7 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api t.Errorf("expected %v, got %v", e, a) } - err = fixtures.DeleteCustomResourceDefinition(crd, apiExtensionClient) + err = fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionClient) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go index 3f17af6f7a7..313ddd0fbc3 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/yaml_test.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/dynamic" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" ) @@ -51,15 +51,15 @@ func TestYAML(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind listKind := noxuDefinition.Spec.Names.ListKind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name rest := apiExtensionClient.Discovery().RESTClient() @@ -67,7 +67,7 @@ func TestYAML(t *testing.T) { { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name). DoRaw(context.TODO()) if err != nil { t.Fatal(err, string(result)) @@ -88,7 +88,7 @@ func TestYAML(t *testing.T) { { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "missingname"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "missingname"). DoRaw(context.TODO()) if !errors.IsNotFound(err) { t.Fatalf("expected not found, got %v", err) @@ -123,7 +123,7 @@ values: result, err := rest.Post(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(yamlBody). DoRaw(context.TODO()) if err != nil { @@ -159,7 +159,7 @@ values: { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest"). DoRaw(context.TODO()) if err != nil { t.Fatal(err) @@ -192,7 +192,7 @@ values: { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). DoRaw(context.TODO()) if err != nil { t.Fatal(err, string(result)) @@ -236,7 +236,7 @@ values: { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Param("watch", "true"). DoRaw(context.TODO()) if !errors.IsNotAcceptable(err) { @@ -273,7 +273,7 @@ values: result, err := rest.Put(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest"). Body(yamlBody). DoRaw(context.TODO()) if err != nil { @@ -314,7 +314,7 @@ values: result, err := rest.Patch(types.MergePatchType). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest"). Body(yamlBody). DoRaw(context.TODO()) if !errors.IsUnsupportedMediaType(err) { @@ -336,7 +336,7 @@ values: { result, err := rest.Delete(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest"). DoRaw(context.TODO()) if err != nil { t.Fatal(err, string(result)) @@ -370,14 +370,14 @@ func TestYAMLSubresource(t *testing.T) { t.Fatal(err) } - noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.ClusterScoped)[0] - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1.ClusterScoped)[0] + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name rest := apiExtensionClient.Discovery().RESTClient() @@ -397,7 +397,7 @@ spec: result, err := rest.Post(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Body(yamlBody). DoRaw(context.TODO()) if err != nil { @@ -427,7 +427,7 @@ spec: { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "status"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "status"). DoRaw(context.TODO()) if err != nil { t.Fatal(err) @@ -466,7 +466,7 @@ status: result, err := rest.Put(). SetHeader("Accept", "application/yaml"). SetHeader("Content-Type", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "status"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "status"). Body(yamlBody). DoRaw(context.TODO()) if err != nil { @@ -500,7 +500,7 @@ status: { result, err := rest.Get(). SetHeader("Accept", "application/yaml"). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "scale"). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "scale"). DoRaw(context.TODO()) if err != nil { t.Fatal(err) diff --git a/test/integration/apiserver/apiserver_test.go b/test/integration/apiserver/apiserver_test.go index 267e8bb0ef6..559616edae6 100644 --- a/test/integration/apiserver/apiserver_test.go +++ b/test/integration/apiserver/apiserver_test.go @@ -34,7 +34,7 @@ import ( apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apiextensions-apiserver/test/integration/fixtures" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -798,28 +798,35 @@ func TestMetadataClient(t *testing.T) { t.Fatal(err) } - fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{ + fooCRD := &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ Name: "foos.cr.bar.com", }, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "cr.bar.com", - Version: "v1", - Scope: apiextensionsv1beta1.NamespaceScoped, - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "cr.bar.com", + Scope: apiextensionsv1.NamespaceScoped, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "foos", Kind: "Foo", }, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ - Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: fixtures.AllowAllSchema(), + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + }, + }, }, }, } - fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) + fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"} + crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"} testcases := []struct { name string @@ -1119,26 +1126,33 @@ func TestAPICRDProtobuf(t *testing.T) { t.Fatal(err) } - fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{ + fooCRD := &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ Name: "foos.cr.bar.com", }, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "cr.bar.com", - Version: "v1", - Scope: apiextensionsv1beta1.NamespaceScoped, - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "cr.bar.com", + Scope: apiextensionsv1.NamespaceScoped, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "foos", Kind: "Foo", }, - Subresources: &apiextensionsv1beta1.CustomResourceSubresources{Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}}, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: fixtures.AllowAllSchema(), + Subresources: &apiextensionsv1.CustomResourceSubresources{Status: &apiextensionsv1.CustomResourceSubresourceStatus{}}, + }, + }, }, } - fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) + fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"} + crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"} crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace) testcases := []struct { @@ -1331,25 +1345,32 @@ func TestTransform(t *testing.T) { t.Fatal(err) } - fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{ + fooCRD := &apiextensionsv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ Name: "foos.cr.bar.com", }, - Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ - Group: "cr.bar.com", - Version: "v1", - Scope: apiextensionsv1beta1.NamespaceScoped, - Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "cr.bar.com", + Scope: apiextensionsv1.NamespaceScoped, + Names: apiextensionsv1.CustomResourceDefinitionNames{ Plural: "foos", Kind: "Foo", }, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: fixtures.AllowAllSchema(), + }, + }, }, } - fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) + fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } - crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"} + crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"} crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace) testcases := []struct { diff --git a/test/integration/apiserver/apply/apply_crd_beta_test.go b/test/integration/apiserver/apply/apply_crd_beta_test.go new file mode 100644 index 00000000000..eef869e8282 --- /dev/null +++ b/test/integration/apiserver/apply/apply_crd_beta_test.go @@ -0,0 +1,234 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apiserver + +import ( + "context" + "fmt" + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apiextensions-apiserver/test/integration/fixtures" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + genericfeatures "k8s.io/apiserver/pkg/features" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/dynamic" + featuregatetesting "k8s.io/component-base/featuregate/testing" + apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" + "k8s.io/kubernetes/test/integration/framework" +) + +// TestApplyCRDNoSchema tests that CRDs and CRs can both be applied to with a PATCH request with the apply content type +// when there is no validation field provided. +func TestApplyCRDNoSchema(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)() + + server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd()) + if err != nil { + t.Fatal(err) + } + defer server.TearDownFn() + config := server.ClientConfig + + apiExtensionClient, err := clientset.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + t.Fatal(err) + } + + noxuDefinition := nearlyRemovedBetaMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + + noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + kind := noxuDefinition.Spec.Names.Kind + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + name := "mytest" + + rest := apiExtensionClient.Discovery().RESTClient() + yamlBody := []byte(fmt.Sprintf(` +apiVersion: %s +kind: %s +metadata: + name: %s +spec: + replicas: 1`, apiVersion, kind, name)) + result, err := rest.Patch(types.ApplyPatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + Name(name). + Param("fieldManager", "apply_test"). + Body(yamlBody). + DoRaw(context.TODO()) + if err != nil { + t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, string(result)) + } + verifyReplicas(t, result, 1) + + // Patch object to change the number of replicas + result, err = rest.Patch(types.MergePatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + Name(name). + Body([]byte(`{"spec":{"replicas": 5}}`)). + DoRaw(context.TODO()) + if err != nil { + t.Fatalf("failed to update number of replicas with merge patch: %v:\n%v", err, string(result)) + } + verifyReplicas(t, result, 5) + + // Re-apply, we should get conflicts now, since the number of replicas was changed. + result, err = rest.Patch(types.ApplyPatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + Name(name). + Param("fieldManager", "apply_test"). + Body(yamlBody). + DoRaw(context.TODO()) + if err == nil { + t.Fatalf("Expecting to get conflicts when applying object after updating replicas, got no error: %s", result) + } + status, ok := err.(*apierrors.StatusError) + if !ok { + t.Fatalf("Expecting to get conflicts as API error") + } + if len(status.Status().Details.Causes) != 1 { + t.Fatalf("Expecting to get one conflict when applying object after updating replicas, got: %v", status.Status().Details.Causes) + } + + // Re-apply with force, should work fine. + result, err = rest.Patch(types.ApplyPatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + Name(name). + Param("force", "true"). + Param("fieldManager", "apply_test"). + Body(yamlBody). + DoRaw(context.TODO()) + if err != nil { + t.Fatalf("failed to apply object with force after updating replicas: %v:\n%v", err, string(result)) + } + verifyReplicas(t, result, 1) + + // Try to set managed fields using a subresource and verify that it has no effect + existingManagedFields, err := getManagedFields(result) + if err != nil { + t.Fatalf("failed to get managedFields from response: %v", err) + } + updateBytes := []byte(`{ + "metadata": { + "managedFields": [{ + "manager":"testing", + "operation":"Update", + "apiVersion":"v1", + "fieldsType":"FieldsV1", + "fieldsV1":{ + "f:spec":{ + "f:containers":{ + "k:{\"name\":\"testing\"}":{ + ".":{}, + "f:image":{}, + "f:name":{} + } + } + } + } + }] + } + }`) + result, err = rest.Patch(types.MergePatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + SubResource("status"). + Name(name). + Param("fieldManager", "subresource_test"). + Body(updateBytes). + DoRaw(context.TODO()) + if err != nil { + t.Fatalf("Error updating subresource: %v ", err) + } + newManagedFields, err := getManagedFields(result) + if err != nil { + t.Fatalf("failed to get managedFields from response: %v", err) + } + if !reflect.DeepEqual(existingManagedFields, newManagedFields) { + t.Fatalf("Expected managed fields to not have changed when trying manually settting them via subresoures.\n\nExpected: %#v\n\nGot: %#v", existingManagedFields, newManagedFields) + } + + // However, it is possible to modify managed fields using the main resource + result, err = rest.Patch(types.MergePatchType). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + Name(name). + Param("fieldManager", "subresource_test"). + Body([]byte(`{"metadata":{"managedFields":[{}]}}`)). + DoRaw(context.TODO()) + if err != nil { + t.Fatalf("Error updating managed fields of the main resource: %v ", err) + } + newManagedFields, err = getManagedFields(result) + if err != nil { + t.Fatalf("failed to get managedFields from response: %v", err) + } + + if len(newManagedFields) != 0 { + t.Fatalf("Expected managed fields to have been reset, but got: %v", newManagedFields) + } +} + +func nearlyRemovedBetaMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition { + return &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Version: "v1beta1", + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "noxus", + Singular: "nonenglishnoxu", + Kind: "WishIHadChosenNoxu", + ShortNames: []string{"foo", "bar", "abc", "def"}, + ListKind: "NoxuItemList", + Categories: []string{"all"}, + }, + Scope: scope, + Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ + { + Name: "v1beta1", + Served: true, + Storage: false, + }, + { + Name: "v1beta2", + Served: true, + Storage: true, + }, + { + Name: "v0", + Served: false, + Storage: false, + }, + }, + Subresources: &apiextensionsv1beta1.CustomResourceSubresources{ + Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}, + }, + }, + } +} diff --git a/test/integration/apiserver/apply/apply_crd_test.go b/test/integration/apiserver/apply/apply_crd_test.go index 342a638cd8a..ef313bbd346 100644 --- a/test/integration/apiserver/apply/apply_crd_test.go +++ b/test/integration/apiserver/apply/apply_crd_test.go @@ -20,8 +20,18 @@ import ( "context" "encoding/json" "fmt" + "path" "reflect" "testing" + "time" + + "k8s.io/apimachinery/pkg/util/wait" + + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + + "go.etcd.io/etcd/clientv3" + "go.etcd.io/etcd/pkg/transport" + "google.golang.org/grpc" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -39,163 +49,6 @@ import ( "k8s.io/kubernetes/test/integration/framework" ) -// TestApplyCRDNoSchema tests that CRDs and CRs can both be applied to with a PATCH request with the apply content type -// when there is no validation field provided. -func TestApplyCRDNoSchema(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)() - - server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd()) - if err != nil { - t.Fatal(err) - } - defer server.TearDownFn() - config := server.ClientConfig - - apiExtensionClient, err := clientset.NewForConfig(config) - if err != nil { - t.Fatal(err) - } - dynamicClient, err := dynamic.NewForConfig(config) - if err != nil { - t.Fatal(err) - } - - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) - - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) - if err != nil { - t.Fatal(err) - } - - kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version - name := "mytest" - - rest := apiExtensionClient.Discovery().RESTClient() - yamlBody := []byte(fmt.Sprintf(` -apiVersion: %s -kind: %s -metadata: - name: %s -spec: - replicas: 1`, apiVersion, kind, name)) - result, err := rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - Name(name). - Param("fieldManager", "apply_test"). - Body(yamlBody). - DoRaw(context.TODO()) - if err != nil { - t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, string(result)) - } - verifyReplicas(t, result, 1) - - // Patch object to change the number of replicas - result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - Name(name). - Body([]byte(`{"spec":{"replicas": 5}}`)). - DoRaw(context.TODO()) - if err != nil { - t.Fatalf("failed to update number of replicas with merge patch: %v:\n%v", err, string(result)) - } - verifyReplicas(t, result, 5) - - // Re-apply, we should get conflicts now, since the number of replicas was changed. - result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - Name(name). - Param("fieldManager", "apply_test"). - Body(yamlBody). - DoRaw(context.TODO()) - if err == nil { - t.Fatalf("Expecting to get conflicts when applying object after updating replicas, got no error: %s", result) - } - status, ok := err.(*apierrors.StatusError) - if !ok { - t.Fatalf("Expecting to get conflicts as API error") - } - if len(status.Status().Details.Causes) != 1 { - t.Fatalf("Expecting to get one conflict when applying object after updating replicas, got: %v", status.Status().Details.Causes) - } - - // Re-apply with force, should work fine. - result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - Name(name). - Param("force", "true"). - Param("fieldManager", "apply_test"). - Body(yamlBody). - DoRaw(context.TODO()) - if err != nil { - t.Fatalf("failed to apply object with force after updating replicas: %v:\n%v", err, string(result)) - } - verifyReplicas(t, result, 1) - - // Try to set managed fields using a subresource and verify that it has no effect - existingManagedFields, err := getManagedFields(result) - if err != nil { - t.Fatalf("failed to get managedFields from response: %v", err) - } - updateBytes := []byte(`{ - "metadata": { - "managedFields": [{ - "manager":"testing", - "operation":"Update", - "apiVersion":"v1", - "fieldsType":"FieldsV1", - "fieldsV1":{ - "f:spec":{ - "f:containers":{ - "k:{\"name\":\"testing\"}":{ - ".":{}, - "f:image":{}, - "f:name":{} - } - } - } - } - }] - } - }`) - result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - SubResource("status"). - Name(name). - Param("fieldManager", "subresource_test"). - Body(updateBytes). - DoRaw(context.TODO()) - if err != nil { - t.Fatalf("Error updating subresource: %v ", err) - } - newManagedFields, err := getManagedFields(result) - if err != nil { - t.Fatalf("failed to get managedFields from response: %v", err) - } - if !reflect.DeepEqual(existingManagedFields, newManagedFields) { - t.Fatalf("Expected managed fields to not have changed when trying manually settting them via subresoures.\n\nExpected: %#v\n\nGot: %#v", existingManagedFields, newManagedFields) - } - - // However, it is possible to modify managed fields using the main resource - result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). - Name(name). - Param("fieldManager", "subresource_test"). - Body([]byte(`{"metadata":{"managedFields":[{}]}}`)). - DoRaw(context.TODO()) - if err != nil { - t.Fatalf("Error updating managed fields of the main resource: %v ", err) - } - newManagedFields, err = getManagedFields(result) - if err != nil { - t.Fatalf("failed to get managedFields from response: %v", err) - } - - if len(newManagedFields) != 0 { - t.Fatalf("Expected managed fields to have been reset, but got: %v", newManagedFields) - } -} - // TestApplyCRDStructuralSchema tests that when a CRD has a structural schema in its validation field, // it will be used to construct the CR schema used by apply. func TestApplyCRDStructuralSchema(t *testing.T) { @@ -217,9 +70,9 @@ func TestApplyCRDStructuralSchema(t *testing.T) { t.Fatal(err) } - noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped) + noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped) - var c apiextensionsv1beta1.CustomResourceValidation + var c apiextensionsv1.CustomResourceValidation err = json.Unmarshal([]byte(`{ "openAPIV3Schema": { "type": "object", @@ -274,17 +127,17 @@ func TestApplyCRDStructuralSchema(t *testing.T) { if err != nil { t.Fatal(err) } - noxuDefinition.Spec.Validation = &c - falseBool := false - noxuDefinition.Spec.PreserveUnknownFields = &falseBool + for i := range noxuDefinition.Spec.Versions { + noxuDefinition.Spec.Versions[i].Schema = &c + } - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name name := "mytest" rest := apiExtensionClient.Discovery().RESTClient() @@ -303,7 +156,7 @@ spec: containerPort: 80 protocol: TCP`, apiVersion, kind, name)) result, err := rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -318,7 +171,7 @@ spec: // Patch object to add another finalizer to the finalizers list result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Body([]byte(`{"metadata":{"finalizers":["test-finalizer","another-one"]}}`)). DoRaw(context.TODO()) @@ -331,7 +184,7 @@ spec: // Re-apply the same config, should work fine, since finalizers should have the list-type extension 'set'. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test"). SetHeader("Accept", "application/json"). @@ -346,7 +199,7 @@ spec: // Patch object to change the number of replicas result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Body([]byte(`{"spec":{"replicas": 5}}`)). DoRaw(context.TODO()) @@ -357,7 +210,7 @@ spec: // Re-apply, we should get conflicts now, since the number of replicas was changed. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -375,7 +228,7 @@ spec: // Re-apply with force, should work fine. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("force", "true"). Param("fieldManager", "apply_test"). @@ -388,7 +241,7 @@ spec: // New applier tries to edit an existing list item, we should get conflicts. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test_2"). Body([]byte(fmt.Sprintf(` @@ -415,7 +268,7 @@ spec: // New applier tries to add a new list item, should work fine. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test_2"). Body([]byte(fmt.Sprintf(` @@ -459,7 +312,7 @@ spec: "protocol": "TCP" }`, apiVersion, kind, "should-not-exist")) _, err = rest.Put(). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name("should-not-exist"). Param("fieldManager", "apply_test"). Body(notExistingYAMLBody). @@ -552,12 +405,45 @@ func verifyNumPorts(t *testing.T, b []byte, n int) { } } +func findCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) *apiextensionsv1.CustomResourceDefinitionCondition { + for i := range crd.Status.Conditions { + if crd.Status.Conditions[i].Type == conditionType { + return &crd.Status.Conditions[i] + } + } + + return nil +} + // TestApplyCRDUnhandledSchema tests that when a CRD has a schema that kube-openapi ToProtoModels cannot handle correctly, // apply falls back to non-schema behavior func TestApplyCRDUnhandledSchema(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)() - server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd()) + storageConfig := framework.SharedEtcd() + tlsInfo := transport.TLSInfo{ + CertFile: storageConfig.Transport.CertFile, + KeyFile: storageConfig.Transport.KeyFile, + TrustedCAFile: storageConfig.Transport.TrustedCAFile, + } + tlsConfig, err := tlsInfo.ClientConfig() + if err != nil { + t.Fatal(err) + } + etcdConfig := clientv3.Config{ + Endpoints: storageConfig.Transport.ServerList, + DialTimeout: 20 * time.Second, + DialOptions: []grpc.DialOption{ + grpc.WithBlock(), // block until the underlying connection is up + }, + TLS: tlsConfig, + } + etcdclient, err := clientv3.New(etcdConfig) + if err != nil { + t.Fatal(err) + } + + server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, storageConfig) if err != nil { t.Fatal(err) } @@ -568,12 +454,33 @@ func TestApplyCRDUnhandledSchema(t *testing.T) { if err != nil { t.Fatal(err) } - dynamicClient, err := dynamic.NewForConfig(config) - if err != nil { - t.Fatal(err) - } - noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped) + // this has to be v1beta1, so we can have an item with validation that does not match. v1 validation prevents this. + + noxuBetaDefinition := &apiextensionsv1beta1.CustomResourceDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: "CustomResourceDefinition", + APIVersion: "apiextensions.k8s.io/v1beta1", + }, + ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"}, + Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{ + Group: "mygroup.example.com", + Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{{ + Name: "v1beta1", + Served: true, + Storage: true, + }}, + Names: apiextensionsv1beta1.CustomResourceDefinitionNames{ + Plural: "noxus", + Singular: "nonenglishnoxu", + Kind: "WishIHadChosenNoxu", + ShortNames: []string{"foo", "bar", "abc", "def"}, + ListKind: "NoxuItemList", + Categories: []string{"all"}, + }, + Scope: apiextensionsv1beta1.ClusterScoped, + }, + } // This is a schema that kube-openapi ToProtoModels does not handle correctly. // https://github.com/kubernetes/kubernetes/blob/38752f7f99869ed65fb44378360a517649dc2f83/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go#L184 @@ -590,15 +497,44 @@ func TestApplyCRDUnhandledSchema(t *testing.T) { if err != nil { t.Fatal(err) } - noxuDefinition.Spec.Validation = &c + noxuBetaDefinition.Spec.Validation = &c - noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + betaBytes, err := json.Marshal(noxuBetaDefinition) + if err != nil { + t.Fatal(err) + } + t.Log(string(betaBytes)) + ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) + key := path.Join("/", storageConfig.Prefix, "apiextensions.k8s.io", "customresourcedefinitions", noxuBetaDefinition.Name) + if _, err := etcdclient.Put(ctx, key, string(betaBytes)); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + noxuDefinition, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuBetaDefinition.Name, metav1.GetOptions{}) + if err != nil { + t.Fatal(err) + } + // wait until the CRD is established + err = wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) { + localCrd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuBetaDefinition.Name, metav1.GetOptions{}) + if err != nil { + return false, err + } + condition := findCRDCondition(localCrd, apiextensionsv1.Established) + if condition == nil { + return false, nil + } + if condition.Status == apiextensionsv1.ConditionTrue { + return true, nil + } + return false, nil + }) if err != nil { t.Fatal(err) } kind := noxuDefinition.Spec.Names.Kind - apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version + apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name name := "mytest" rest := apiExtensionClient.Discovery().RESTClient() @@ -610,7 +546,7 @@ metadata: spec: replicas: 1`, apiVersion, kind, name)) result, err := rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -622,7 +558,7 @@ spec: // Patch object to change the number of replicas result, err = rest.Patch(types.MergePatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Body([]byte(`{"spec":{"replicas": 5}}`)). DoRaw(context.TODO()) @@ -633,7 +569,7 @@ spec: // Re-apply, we should get conflicts now, since the number of replicas was changed. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("fieldManager", "apply_test"). Body(yamlBody). @@ -651,7 +587,7 @@ spec: // Re-apply with force, should work fine. result, err = rest.Patch(types.ApplyPatchType). - AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural). + AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural). Name(name). Param("force", "true"). Param("fieldManager", "apply_test"). diff --git a/test/integration/garbagecollector/garbage_collector_test.go b/test/integration/garbagecollector/garbage_collector_test.go index 63e85f7d7dd..e4100c24287 100644 --- a/test/integration/garbagecollector/garbage_collector_test.go +++ b/test/integration/garbagecollector/garbage_collector_test.go @@ -26,7 +26,7 @@ import ( "time" v1 "k8s.io/api/core/v1" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apiextensionstestserver "k8s.io/apiextensions-apiserver/test/integration/fixtures" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -136,11 +136,11 @@ func newOwnerRC(name, namespace string) *v1.ReplicationController { } } -func newCRDInstance(definition *apiextensionsv1beta1.CustomResourceDefinition, namespace, name string) *unstructured.Unstructured { +func newCRDInstance(definition *apiextensionsv1.CustomResourceDefinition, namespace, name string) *unstructured.Unstructured { return &unstructured.Unstructured{ Object: map[string]interface{}{ "kind": definition.Spec.Names.Kind, - "apiVersion": definition.Spec.Group + "/" + definition.Spec.Version, + "apiVersion": definition.Spec.Group + "/" + definition.Spec.Versions[0].Name, "metadata": map[string]interface{}{ "name": name, "namespace": namespace, @@ -180,18 +180,18 @@ func createRandomCustomResourceDefinition( t *testing.T, apiExtensionClient apiextensionsclientset.Interface, dynamicClient dynamic.Interface, namespace string, -) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.ResourceInterface) { +) (*apiextensionsv1.CustomResourceDefinition, dynamic.ResourceInterface) { // Create a random custom resource definition and ensure it's available for // use. - definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped) + definition := apiextensionstestserver.NewRandomNameV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) - definition, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient) + definition, err := apiextensionstestserver.CreateNewV1CustomResourceDefinition(definition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("failed to create CustomResourceDefinition: %v", err) } // Get a client for the custom resource. - gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural} + gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Versions[0].Name, Resource: definition.Spec.Names.Plural} resourceClient := dynamicClient.Resource(gvr).Namespace(namespace) @@ -1230,14 +1230,14 @@ func TestCRDDeletionCascading(t *testing.T) { t.Logf("Second pass CRD cascading deletion") accessor := meta.NewAccessor() accessor.SetResourceVersion(definition, "") - _, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient) + _, err := apiextensionstestserver.CreateNewV1CustomResourceDefinition(definition, apiExtensionClient, dynamicClient) if err != nil { t.Fatalf("failed to create CustomResourceDefinition: %v", err) } testCRDDeletion(t, ctx, ns, definition, resourceClient) } -func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definition *apiextensionsv1beta1.CustomResourceDefinition, resourceClient dynamic.ResourceInterface) { +func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definition *apiextensionsv1.CustomResourceDefinition, resourceClient dynamic.ResourceInterface) { clientSet, apiExtensionClient := ctx.clientSet, ctx.apiExtensionClient configMapClient := clientSet.CoreV1().ConfigMaps(ns.Name) @@ -1261,7 +1261,7 @@ func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definitio time.Sleep(ctx.syncPeriod + 5*time.Second) // Delete the definition, which should cascade to the owner and ultimately its dependents. - if err := apiextensionstestserver.DeleteCustomResourceDefinition(definition, apiExtensionClient); err != nil { + if err := apiextensionstestserver.DeleteV1CustomResourceDefinition(definition, apiExtensionClient); err != nil { t.Fatalf("failed to delete %q: %v", definition.Name, err) } diff --git a/test/utils/crd/crd_util.go b/test/utils/crd/crd_util.go index 445c9852c26..e51df2d696f 100644 --- a/test/utils/crd/crd_util.go +++ b/test/utils/crd/crd_util.go @@ -89,12 +89,7 @@ func CreateMultiVersionTestCRD(f *framework.Framework, group string, opts ...Opt Served: true, Storage: true, Name: "v1", - Schema: &apiextensionsv1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ - XPreserveUnknownFields: pointer.BoolPtr(true), - Type: "object", - }, - }, + Schema: fixtures.AllowAllSchema(), }} }