k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/integration/apiserver/openapi/openapi_crd_test.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package openapi 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 25 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 26 "k8s.io/apiextensions-apiserver/test/integration/fixtures" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/util/wait" 29 "k8s.io/client-go/dynamic" 30 kubernetes "k8s.io/client-go/kubernetes" 31 apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" 32 "k8s.io/kubernetes/test/integration/framework" 33 34 "k8s.io/kube-openapi/pkg/validation/spec" 35 ) 36 37 func TestOpenAPICRDGenerationNumber(t *testing.T) { 38 server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd()) 39 if err != nil { 40 t.Fatal(err) 41 } 42 defer server.TearDownFn() 43 config := server.ClientConfig 44 45 apiExtensionClient, err := clientset.NewForConfig(config) 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 clientset, err := kubernetes.NewForConfig(config) 51 if err != nil { 52 t.Fatal(err) 53 } 54 dynamicClient, err := dynamic.NewForConfig(config) 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 // Create a new CRD with group mygroup.example.com 60 crd := fixtures.NewRandomNameV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped) 61 _, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient) 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 defer func() { 67 apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}) 68 }() 69 70 crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{}) 71 if err != nil { 72 t.Fatal(err) 73 } 74 75 // Update OpenAPI schema and ensure it's reflected in the publishing 76 crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{ 77 OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ 78 Type: "object", 79 Properties: map[string]apiextensionsv1.JSONSchemaProps{"num": {Type: "integer", Description: "description"}}, 80 }, 81 } 82 83 updatedCRD, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}) 84 if err != nil { 85 t.Fatal(err) 86 } 87 if updatedCRD.Generation <= crd.Generation { 88 t.Fatalf("Expected updated CRD to increment Generation counter. got preupdate: %d, postupdate %d", crd.Generation, updatedCRD.Generation) 89 } 90 91 err = wait.Poll(time.Second*1, wait.ForeverTestTimeout, func() (bool, error) { 92 body, err := clientset.RESTClient().Get().AbsPath("/openapi/v2").Do(context.TODO()).Raw() 93 if err != nil { 94 t.Fatal(err) 95 } 96 swagger := &spec.Swagger{} 97 if err := swagger.UnmarshalJSON(body); err != nil { 98 t.Error(err) 99 } 100 101 // Ensure that OpenAPI schema updated is reflected 102 if description := swagger.Definitions["com.example.mygroup.v1beta1."+crd.Spec.Names.Kind].Properties["num"].Description; description == "description" { 103 return true, nil 104 } 105 return false, nil 106 }) 107 108 if err != nil { 109 t.Errorf("Expected description to be updated, err: %s", err) 110 } 111 112 }