Skip to content

Commit 698d264

Browse files
authored
Merge pull request kubernetes#82661 from sttts/sttts-non-structural-crd-publishing-int-test
apiextensions: add integration test for not publishing non-structural CRDs
2 parents af88acc + da377c3 commit 698d264

File tree

1 file changed

+92
-28
lines changed

1 file changed

+92
-28
lines changed

test/integration/master/crd_test.go

Lines changed: 92 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package master
1919
import (
2020
"encoding/json"
2121
"fmt"
22+
"strings"
2223
"testing"
2324
"time"
2425

@@ -160,13 +161,36 @@ func TestCRDOpenAPI(t *testing.T) {
160161
if err != nil {
161162
t.Fatalf("Unexpected error: %v", err)
162163
}
163-
t.Logf("Trying to create a custom resource without conflict")
164-
crd := &apiextensionsv1beta1.CustomResourceDefinition{
164+
165+
t.Logf("Trying to create a CustomResourceDefinitions")
166+
nonStructuralCRD := &apiextensionsv1beta1.CustomResourceDefinition{
165167
ObjectMeta: metav1.ObjectMeta{
166-
Name: "foos.cr.bar.com",
168+
Name: "foos.nonstructural.cr.bar.com",
167169
},
168170
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
169-
Group: "cr.bar.com",
171+
Group: "nonstructural.cr.bar.com",
172+
Version: "v1",
173+
Scope: apiextensionsv1beta1.NamespaceScoped,
174+
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
175+
Plural: "foos",
176+
Kind: "Foo",
177+
},
178+
Validation: &apiextensionsv1beta1.CustomResourceValidation{
179+
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
180+
Type: "object",
181+
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
182+
"foo": {},
183+
},
184+
},
185+
},
186+
},
187+
}
188+
structuralCRD := &apiextensionsv1beta1.CustomResourceDefinition{
189+
ObjectMeta: metav1.ObjectMeta{
190+
Name: "foos.structural.cr.bar.com",
191+
},
192+
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
193+
Group: "structural.cr.bar.com",
170194
Version: "v1",
171195
Scope: apiextensionsv1beta1.NamespaceScoped,
172196
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
@@ -184,55 +208,95 @@ func TestCRDOpenAPI(t *testing.T) {
184208
},
185209
},
186210
}
187-
etcd.CreateTestCRDs(t, apiextensionsclient, false, crd)
188-
waitForSpec := func(expectedType string) {
211+
etcd.CreateTestCRDs(t, apiextensionsclient, false, nonStructuralCRD)
212+
etcd.CreateTestCRDs(t, apiextensionsclient, false, structuralCRD)
213+
214+
getPublishedSchema := func(defName string) (*spec.Schema, error) {
215+
bs, err := kubeclient.RESTClient().Get().AbsPath("openapi", "v2").DoRaw()
216+
if err != nil {
217+
return nil, err
218+
}
219+
spec := spec.Swagger{}
220+
if err := json.Unmarshal(bs, &spec); err != nil {
221+
return nil, err
222+
}
223+
if spec.SwaggerProps.Paths == nil {
224+
return nil, nil
225+
}
226+
d, ok := spec.SwaggerProps.Definitions[defName]
227+
if !ok {
228+
return nil, nil
229+
}
230+
return &d, nil
231+
}
232+
233+
waitForSpec := func(crd *apiextensionsv1beta1.CustomResourceDefinition, expectedType string) {
189234
t.Logf(`Waiting for {properties: {"foo": {"type":"%s"}}} to show up in schema`, expectedType)
190235
lastMsg := ""
191236
if err := wait.PollImmediate(500*time.Millisecond, 10*time.Second, func() (bool, error) {
192237
lastMsg = ""
193-
bs, err := kubeclient.RESTClient().Get().AbsPath("openapi", "v2").DoRaw()
238+
defName := crdDefinitionName(crd)
239+
schema, err := getPublishedSchema(defName)
194240
if err != nil {
195-
return false, err
196-
}
197-
spec := spec.Swagger{}
198-
if err := json.Unmarshal(bs, &spec); err != nil {
199-
return false, err
200-
}
201-
if spec.SwaggerProps.Paths == nil {
202-
lastMsg = "spec.SwaggerProps.Paths is nil"
241+
lastMsg = err.Error()
203242
return false, nil
204243
}
205-
d, ok := spec.SwaggerProps.Definitions["com.bar.cr.v1.Foo"]
206-
if !ok {
207-
lastMsg = `spec.SwaggerProps.Definitions["com.bar.cr.v1.Foo"] not found`
244+
if schema == nil {
245+
lastMsg = fmt.Sprintf("spec.SwaggerProps.Definitions[%q] not found", defName)
208246
return false, nil
209247
}
210-
p, ok := d.Properties["foo"]
248+
p, ok := schema.Properties["foo"]
211249
if !ok {
212-
lastMsg = `spec.SwaggerProps.Definitions["com.bar.cr.v1.Foo"].Properties["foo"] not found`
250+
lastMsg = fmt.Sprintf(`spec.SwaggerProps.Definitions[%q].Properties["foo"] not found`, defName)
213251
return false, nil
214252
}
215253
if !p.Type.Contains(expectedType) {
216-
lastMsg = fmt.Sprintf(`spec.SwaggerProps.Definitions["com.bar.cr.v1.Foo"].Properties["foo"].Type should be %q, but got: %q`, expectedType, p.Type)
254+
lastMsg = fmt.Sprintf(`spec.SwaggerProps.Definitions[%q].Properties["foo"].Type should be %q, but got: %q`, defName, expectedType, p.Type)
217255
return false, nil
218256
}
219257
return true, nil
220258
}); err != nil {
221-
t.Fatalf("Failed to see %s OpenAPI spec in discovery: %v, last message: %s", crd.Name, err, lastMsg)
259+
t.Fatalf("Failed to see %s OpenAPI spec in discovery: %v, last message: %s", structuralCRD.Name, err, lastMsg)
222260
}
223261
}
224-
waitForSpec("string")
225-
crd, err = apiextensionsclient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{})
262+
263+
t.Logf("Check that structural schema is published")
264+
waitForSpec(structuralCRD, "string")
265+
structuralCRD, err = apiextensionsclient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(structuralCRD.Name, metav1.GetOptions{})
226266
if err != nil {
227267
t.Fatal(err)
228268
}
229-
prop := crd.Spec.Validation.OpenAPIV3Schema.Properties["foo"]
269+
prop := structuralCRD.Spec.Validation.OpenAPIV3Schema.Properties["foo"]
230270
prop.Type = "boolean"
231-
crd.Spec.Validation.OpenAPIV3Schema.Properties["foo"] = prop
232-
if _, err = apiextensionsclient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(crd); err != nil {
271+
structuralCRD.Spec.Validation.OpenAPIV3Schema.Properties["foo"] = prop
272+
if _, err = apiextensionsclient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(structuralCRD); err != nil {
233273
t.Fatal(err)
234274
}
235-
waitForSpec("boolean")
275+
waitForSpec(structuralCRD, "boolean")
276+
277+
t.Logf("Check that non-structural schema is not published")
278+
schema, err := getPublishedSchema(crdDefinitionName(nonStructuralCRD))
279+
if err != nil {
280+
t.Fatal(err)
281+
}
282+
if schema == nil {
283+
t.Fatal("expected a non-nil schema")
284+
}
285+
if foo, ok := schema.Properties["foo"]; ok {
286+
t.Fatalf("unexpected published 'foo' property: %#v", foo)
287+
}
288+
}
289+
290+
func crdDefinitionName(crd *apiextensionsv1beta1.CustomResourceDefinition) string {
291+
sgmts := strings.Split(crd.Spec.Group, ".")
292+
reverse(sgmts)
293+
return strings.Join(append(sgmts, crd.Spec.Version, crd.Spec.Names.Kind), ".")
294+
}
295+
296+
func reverse(s []string) {
297+
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
298+
s[i], s[j] = s[j], s[i]
299+
}
236300
}
237301

238302
type Foo struct {

0 commit comments

Comments
 (0)