Commit 77bfddac authored by Dr. Stefan Schimanski's avatar Dr. Stefan Schimanski

apiextensions: add pruning integration tests

parent 3f3ed794
...@@ -181,7 +181,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() { ...@@ -181,7 +181,7 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
defer testcrd.CleanUp() defer testcrd.CleanUp()
webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd) webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd)
defer webhookCleanup() defer webhookCleanup()
testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"]) testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], false)
}) })
ginkgo.It("Should deny crd creation", func() { ginkgo.It("Should deny crd creation", func() {
...@@ -202,6 +202,30 @@ var _ = SIGDescribe("AdmissionWebhook", func() { ...@@ -202,6 +202,30 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
testMultiVersionCustomResourceWebhook(f, testcrd) testMultiVersionCustomResourceWebhook(f, testcrd)
}) })
ginkgo.It("Should mutate custom resource with pruning", func() {
const prune = true
testcrd, err := createAdmissionWebhookMultiVersionTestCRDWithV1Storage(f, func(crd *apiextensionsv1beta1.CustomResourceDefinition) {
crd.Spec.PreserveUnknownFields = pointer.BoolPtr(false)
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
"mutation-start": {Type: "string"},
"mutation-stage-1": {Type: "string"},
// mutation-stage-2 is intentionally missing such that it is pruned
},
},
}
})
if err != nil {
return
}
defer testcrd.CleanUp()
webhookCleanup := registerMutatingWebhookForCustomResource(f, context, testcrd)
defer webhookCleanup()
testMutatingCustomResourceWebhook(f, testcrd.Crd, testcrd.DynamicClients["v1"], prune)
})
ginkgo.It("Should deny crd creation", func() { ginkgo.It("Should deny crd creation", func() {
crdWebhookCleanup := registerValidatingWebhookForCRD(f, context) crdWebhookCleanup := registerValidatingWebhookForCRD(f, context)
defer crdWebhookCleanup() defer crdWebhookCleanup()
...@@ -1329,7 +1353,7 @@ func testCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1 ...@@ -1329,7 +1353,7 @@ func testCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1
} }
} }
func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.ResourceInterface) { func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.ResourceInterface, prune bool) {
ginkgo.By("Creating a custom resource that should be mutated by the webhook") ginkgo.By("Creating a custom resource that should be mutated by the webhook")
crName := "cr-instance-1" crName := "cr-instance-1"
cr := &unstructured.Unstructured{ cr := &unstructured.Unstructured{
...@@ -1350,7 +1374,9 @@ func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextension ...@@ -1350,7 +1374,9 @@ func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextension
expectedCRData := map[string]interface{}{ expectedCRData := map[string]interface{}{
"mutation-start": "yes", "mutation-start": "yes",
"mutation-stage-1": "yes", "mutation-stage-1": "yes",
"mutation-stage-2": "yes", }
if !prune {
expectedCRData["mutation-stage-2"] = "yes"
} }
if !reflect.DeepEqual(expectedCRData, mutatedCR.Object["data"]) { if !reflect.DeepEqual(expectedCRData, mutatedCR.Object["data"]) {
framework.Failf("\nexpected %#v\n, got %#v\n", expectedCRData, mutatedCR.Object["data"]) framework.Failf("\nexpected %#v\n, got %#v\n", expectedCRData, mutatedCR.Object["data"])
...@@ -1571,9 +1597,9 @@ func testSlowWebhookTimeoutNoError(f *framework.Framework) { ...@@ -1571,9 +1597,9 @@ func testSlowWebhookTimeoutNoError(f *framework.Framework) {
// createAdmissionWebhookMultiVersionTestCRDWithV1Storage creates a new CRD specifically // createAdmissionWebhookMultiVersionTestCRDWithV1Storage creates a new CRD specifically
// for the admissin webhook calling test. // for the admissin webhook calling test.
func createAdmissionWebhookMultiVersionTestCRDWithV1Storage(f *framework.Framework) (*crd.TestCrd, error) { func createAdmissionWebhookMultiVersionTestCRDWithV1Storage(f *framework.Framework, opts ...crd.Option) (*crd.TestCrd, error) {
group := fmt.Sprintf("%s-multiversion-crd-test.k8s.io", f.BaseName) group := fmt.Sprintf("%s-multiversion-crd-test.k8s.io", f.BaseName)
return crd.CreateMultiVersionTestCRD(f, group, func(crd *apiextensionsv1beta1.CustomResourceDefinition) { return crd.CreateMultiVersionTestCRD(f, group, append([]crd.Option{func(crd *apiextensionsv1beta1.CustomResourceDefinition) {
crd.Spec.Versions = []apiextensionsv1beta1.CustomResourceDefinitionVersion{ crd.Spec.Versions = []apiextensionsv1beta1.CustomResourceDefinitionVersion{
{ {
Name: "v1", Name: "v1",
...@@ -1586,7 +1612,7 @@ func createAdmissionWebhookMultiVersionTestCRDWithV1Storage(f *framework.Framewo ...@@ -1586,7 +1612,7 @@ func createAdmissionWebhookMultiVersionTestCRDWithV1Storage(f *framework.Framewo
Storage: false, Storage: false,
}, },
} }
}) }}, opts...)...)
} }
// servedAPIVersions returns the API versions served by the CRD. // servedAPIVersions returns the API versions served by the CRD.
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/utils/pointer"
) )
// GetEtcdStorageData returns etcd data for all persisted objects. // GetEtcdStorageData returns etcd data for all persisted objects.
...@@ -485,6 +486,10 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes ...@@ -485,6 +486,10 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes
ExpectedEtcdPath: "/registry/awesome.bears.com/pandas/cr4panda", ExpectedEtcdPath: "/registry/awesome.bears.com/pandas/cr4panda",
ExpectedGVK: gvkP("awesome.bears.com", "v1", "Panda"), ExpectedGVK: gvkP("awesome.bears.com", "v1", "Panda"),
}, },
gvr("random.numbers.com", "v1", "integers"): {
Stub: `{"kind": "Integer", "apiVersion": "random.numbers.com/v1", "metadata": {"name": "fortytwo"}, "value": 42, "garbage": "oiujnasdf"}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
ExpectedEtcdPath: "/registry/random.numbers.com/integers/fortytwo",
},
// -- // --
// k8s.io/kubernetes/pkg/apis/auditregistration/v1alpha1 // k8s.io/kubernetes/pkg/apis/auditregistration/v1alpha1
...@@ -580,6 +585,32 @@ func GetCustomResourceDefinitionData() []*apiextensionsv1beta1.CustomResourceDef ...@@ -580,6 +585,32 @@ func GetCustomResourceDefinitionData() []*apiextensionsv1beta1.CustomResourceDef
}, },
}, },
}, },
// cluster scoped with legacy version field and pruning.
{
ObjectMeta: metav1.ObjectMeta{
Name: "integers.random.numbers.com",
},
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
Group: "random.numbers.com",
Version: "v1",
Scope: apiextensionsv1beta1.ClusterScoped,
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
Plural: "integers",
Kind: "Integer",
},
Validation: &apiextensionsv1beta1.CustomResourceValidation{
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
"value": {
Type: "number",
},
},
},
},
PreserveUnknownFields: pointer.BoolPtr(false),
},
},
// cluster scoped with versions field // cluster scoped with versions field
{ {
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment