mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Speed up field validation tests
This commit is contained in:
parent
a8c9dd6274
commit
8fa1c612fd
@ -28,10 +28,12 @@ import (
|
|||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apiserver/pkg/features"
|
"k8s.io/apiserver/pkg/features"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
@ -344,14 +346,66 @@ spec:
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestFieldValidationPost tests POST requests containing unknown fields with
|
func TestFieldValidation(t *testing.T) {
|
||||||
// strict and non-strict field validation.
|
|
||||||
func TestFieldValidationPost(t *testing.T) {
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
server, err := kubeapiservertesting.StartTestServer(t, kubeapiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
|
||||||
defer closeFn()
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
config := server.ClientConfig
|
||||||
|
defer server.TearDownFn()
|
||||||
|
|
||||||
|
schemaCRD := setupCRD(t, config, "schema.example.com", false)
|
||||||
|
schemaGVR := schema.GroupVersionResource{
|
||||||
|
Group: schemaCRD.Spec.Group,
|
||||||
|
Version: schemaCRD.Spec.Versions[0].Name,
|
||||||
|
Resource: schemaCRD.Spec.Names.Plural,
|
||||||
|
}
|
||||||
|
schemaGVK := schema.GroupVersionKind{
|
||||||
|
Group: schemaCRD.Spec.Group,
|
||||||
|
Version: schemaCRD.Spec.Versions[0].Name,
|
||||||
|
Kind: schemaCRD.Spec.Names.Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
schemalessCRD := setupCRD(t, config, "schemaless.example.com", true)
|
||||||
|
schemalessGVR := schema.GroupVersionResource{
|
||||||
|
Group: schemalessCRD.Spec.Group,
|
||||||
|
Version: schemalessCRD.Spec.Versions[0].Name,
|
||||||
|
Resource: schemalessCRD.Spec.Names.Plural,
|
||||||
|
}
|
||||||
|
schemalessGVK := schema.GroupVersionKind{
|
||||||
|
Group: schemalessCRD.Spec.Group,
|
||||||
|
Version: schemalessCRD.Spec.Versions[0].Name,
|
||||||
|
Kind: schemalessCRD.Spec.Names.Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
client := clientset.NewForConfigOrDie(config)
|
||||||
|
rest := client.Discovery().RESTClient()
|
||||||
|
|
||||||
|
t.Run("Post", func(t *testing.T) { testFieldValidationPost(t, client) })
|
||||||
|
t.Run("Put", func(t *testing.T) { testFieldValidationPut(t, client) })
|
||||||
|
t.Run("PatchTyped", func(t *testing.T) { testFieldValidationPatchTyped(t, client) })
|
||||||
|
t.Run("SMP", func(t *testing.T) { testFieldValidationSMP(t, client) })
|
||||||
|
t.Run("ApplyCreate", func(t *testing.T) { testFieldValidationApplyCreate(t, client) })
|
||||||
|
t.Run("ApplyUpdate", func(t *testing.T) { testFieldValidationApplyUpdate(t, client) })
|
||||||
|
|
||||||
|
t.Run("PostCRD", func(t *testing.T) { testFieldValidationPostCRD(t, rest, schemaGVK, schemaGVR) })
|
||||||
|
t.Run("PutCRD", func(t *testing.T) { testFieldValidationPutCRD(t, rest, schemaGVK, schemaGVR) })
|
||||||
|
t.Run("PatchCRD", func(t *testing.T) { testFieldValidationPatchCRD(t, rest, schemaGVK, schemaGVR) })
|
||||||
|
t.Run("ApplyCreateCRD", func(t *testing.T) { testFieldValidationApplyCreateCRD(t, rest, schemaGVK, schemaGVR) })
|
||||||
|
t.Run("ApplyUpdateCRD", func(t *testing.T) { testFieldValidationApplyUpdateCRD(t, rest, schemaGVK, schemaGVR) })
|
||||||
|
|
||||||
|
t.Run("PostCRDSchemaless", func(t *testing.T) { testFieldValidationPostCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) })
|
||||||
|
t.Run("PutCRDSchemaless", func(t *testing.T) { testFieldValidationPutCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) })
|
||||||
|
t.Run("PatchCRDSchemaless", func(t *testing.T) { testFieldValidationPatchCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) })
|
||||||
|
t.Run("ApplyCreateCRDSchemaless", func(t *testing.T) { testFieldValidationApplyCreateCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) })
|
||||||
|
t.Run("ApplyUpdateCRDSchemaless", func(t *testing.T) { testFieldValidationApplyUpdateCRDSchemaless(t, rest, schemalessGVK, schemalessGVR) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFieldValidationPost tests POST requests containing unknown fields with
|
||||||
|
// strict and non-strict field validation.
|
||||||
|
func testFieldValidationPost(t *testing.T, client clientset.Interface) {
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
bodyBase string
|
bodyBase string
|
||||||
@ -503,16 +557,11 @@ func TestFieldValidationPost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPut tests PUT requests
|
// testFieldValidationPut tests PUT requests
|
||||||
// that update existing objects with unknown fields
|
// that update existing objects with unknown fields
|
||||||
// for both strict and non-strict field validation.
|
// for both strict and non-strict field validation.
|
||||||
func TestFieldValidationPut(t *testing.T) {
|
func testFieldValidationPut(t *testing.T, client clientset.Interface) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
deployName := "test-deployment-put"
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
deployName := "test-deployment"
|
|
||||||
postBody := []byte(fmt.Sprintf(string(validBodyJSON), deployName))
|
postBody := []byte(fmt.Sprintf(string(validBodyJSON), deployName))
|
||||||
|
|
||||||
if _, err := client.CoreV1().RESTClient().Post().
|
if _, err := client.CoreV1().RESTClient().Post().
|
||||||
@ -676,15 +725,10 @@ func TestFieldValidationPut(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPatchTyped tests merge-patch and json-patch requests containing unknown fields with
|
// testFieldValidationPatchTyped tests merge-patch and json-patch requests containing unknown fields with
|
||||||
// strict and non-strict field validation for typed objects.
|
// strict and non-strict field validation for typed objects.
|
||||||
func TestFieldValidationPatchTyped(t *testing.T) {
|
func testFieldValidationPatchTyped(t *testing.T, client clientset.Interface) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
deployName := "test-deployment-patch-typed"
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
deployName := "test-deployment"
|
|
||||||
postBody := []byte(fmt.Sprintf(string(validBodyJSON), deployName))
|
postBody := []byte(fmt.Sprintf(string(validBodyJSON), deployName))
|
||||||
|
|
||||||
if _, err := client.CoreV1().RESTClient().Post().
|
if _, err := client.CoreV1().RESTClient().Post().
|
||||||
@ -929,7 +973,7 @@ func TestFieldValidationPatchTyped(t *testing.T) {
|
|||||||
AbsPath("/apis/apps/v1").
|
AbsPath("/apis/apps/v1").
|
||||||
Namespace("default").
|
Namespace("default").
|
||||||
Resource("deployments").
|
Resource("deployments").
|
||||||
Name("test-deployment").
|
Name(deployName).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
||||||
|
|
||||||
@ -955,16 +999,10 @@ func TestFieldValidationPatchTyped(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationSMP tests that attempting a strategic-merge-patch
|
// testFieldValidationSMP tests that attempting a strategic-merge-patch
|
||||||
// with unknown fields errors out when fieldValidation is strict,
|
// with unknown fields errors out when fieldValidation is strict,
|
||||||
// but succeeds when fieldValidation is ignored.
|
// but succeeds when fieldValidation is ignored.
|
||||||
func TestFieldValidationSMP(t *testing.T) {
|
func testFieldValidationSMP(t *testing.T, client clientset.Interface) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
smpBody := `
|
smpBody := `
|
||||||
{
|
{
|
||||||
"spec": {
|
"spec": {
|
||||||
@ -1172,15 +1210,9 @@ func TestFieldValidationSMP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyCreate tests apply patch requests containing unknown fields
|
// testFieldValidationApplyCreate tests apply patch requests containing unknown fields
|
||||||
// on newly created objects, with strict and non-strict field validation.
|
// on newly created objects, with strict and non-strict field validation.
|
||||||
func TestFieldValidationApplyCreate(t *testing.T) {
|
func testFieldValidationApplyCreate(t *testing.T, client clientset.Interface) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1262,15 +1294,9 @@ func TestFieldValidationApplyCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyUpdate tests apply patch requests containing unknown fields
|
// testFieldValidationApplyUpdate tests apply patch requests containing unknown fields
|
||||||
// on apply requests to existing objects, with strict and non-strict field validation.
|
// on apply requests to existing objects, with strict and non-strict field validation.
|
||||||
func TestFieldValidationApplyUpdate(t *testing.T) {
|
func testFieldValidationApplyUpdate(t *testing.T, client clientset.Interface) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
|
|
||||||
_, client, closeFn := setup(t)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1320,7 +1346,7 @@ func TestFieldValidationApplyUpdate(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
name := fmt.Sprintf("apply-create-deployment-%s", tc.name)
|
name := fmt.Sprintf("apply-update-deployment-%s", tc.name)
|
||||||
createBody := []byte(fmt.Sprintf(validBodyJSON, name))
|
createBody := []byte(fmt.Sprintf(validBodyJSON, name))
|
||||||
createReq := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
|
createReq := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis/apps/v1").
|
AbsPath("/apis/apps/v1").
|
||||||
@ -1363,14 +1389,9 @@ func TestFieldValidationApplyUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPostCRD tests that server-side schema validation
|
// testFieldValidationPostCRD tests that server-side schema validation
|
||||||
// works for CRD create requests for CRDs with schemas
|
// works for CRD create requests for CRDs with schemas
|
||||||
func TestFieldValidationPostCRD(t *testing.T) {
|
func testFieldValidationPostCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, false)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1484,13 +1505,13 @@ func TestFieldValidationPostCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
jsonBody := []byte(fmt.Sprintf(tc.body, apiVersion, kind, tc.name))
|
jsonBody := []byte(fmt.Sprintf(tc.body, apiVersion, kind, tc.name))
|
||||||
req := rest.Post().
|
req := rest.Post().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
SetHeader("Content-Type", tc.contentType).
|
SetHeader("Content-Type", tc.contentType).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body([]byte(jsonBody)).Do(context.TODO())
|
result := req.Body([]byte(jsonBody)).Do(context.TODO())
|
||||||
@ -1523,15 +1544,10 @@ func TestFieldValidationPostCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPostCRDSchemaless tests that server-side schema validation
|
// testFieldValidationPostCRDSchemaless tests that server-side schema validation
|
||||||
// works for CRD create requests for CRDs that have schemas
|
// works for CRD create requests for CRDs that have schemas
|
||||||
// with x-kubernetes-preserve-unknown-field set
|
// with x-kubernetes-preserve-unknown-field set
|
||||||
func TestFieldValidationPostCRDSchemaless(t *testing.T) {
|
func testFieldValidationPostCRDSchemaless(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, true)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1634,13 +1650,13 @@ func TestFieldValidationPostCRDSchemaless(t *testing.T) {
|
|||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
jsonBody := []byte(fmt.Sprintf(tc.body, apiVersion, kind, tc.name))
|
jsonBody := []byte(fmt.Sprintf(tc.body, apiVersion, kind, tc.name))
|
||||||
req := rest.Post().
|
req := rest.Post().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
SetHeader("Content-Type", tc.contentType).
|
SetHeader("Content-Type", tc.contentType).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body([]byte(jsonBody)).Do(context.TODO())
|
result := req.Body([]byte(jsonBody)).Do(context.TODO())
|
||||||
@ -1660,6 +1676,14 @@ func TestFieldValidationPostCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(result.Warnings()) != len(tc.strictDecodingWarnings) {
|
if len(result.Warnings()) != len(tc.strictDecodingWarnings) {
|
||||||
|
t.Logf("expected:")
|
||||||
|
for _, w := range tc.strictDecodingWarnings {
|
||||||
|
t.Logf("\t%v", w)
|
||||||
|
}
|
||||||
|
t.Logf("got:")
|
||||||
|
for _, w := range result.Warnings() {
|
||||||
|
t.Logf("\t%v", w.Text)
|
||||||
|
}
|
||||||
t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.strictDecodingWarnings), len(result.Warnings()))
|
t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.strictDecodingWarnings), len(result.Warnings()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1673,14 +1697,9 @@ func TestFieldValidationPostCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPutCRD tests that server-side schema validation
|
// testFieldValidationPutCRD tests that server-side schema validation
|
||||||
// works for CRD update requests for CRDs with schemas.
|
// works for CRD update requests for CRDs with schemas.
|
||||||
func TestFieldValidationPutCRD(t *testing.T) {
|
func testFieldValidationPutCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, false)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1794,13 +1813,13 @@ func TestFieldValidationPutCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
jsonPostBody := []byte(fmt.Sprintf(crdValidBody, apiVersion, kind, tc.name))
|
jsonPostBody := []byte(fmt.Sprintf(crdValidBody, apiVersion, kind, tc.name))
|
||||||
postReq := rest.Post().
|
postReq := rest.Post().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
postResult, err := postReq.Body([]byte(jsonPostBody)).Do(context.TODO()).Raw()
|
postResult, err := postReq.Body([]byte(jsonPostBody)).Do(context.TODO()).Raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1815,7 +1834,7 @@ func TestFieldValidationPutCRD(t *testing.T) {
|
|||||||
putBody := []byte(fmt.Sprintf(tc.putBody, apiVersion, kind, tc.name, postUnstructured.GetResourceVersion()))
|
putBody := []byte(fmt.Sprintf(tc.putBody, apiVersion, kind, tc.name, postUnstructured.GetResourceVersion()))
|
||||||
klog.Warningf("putBody: %s\n", string(putBody))
|
klog.Warningf("putBody: %s\n", string(putBody))
|
||||||
putReq := rest.Put().
|
putReq := rest.Put().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
SetHeader("Content-Type", tc.contentType).
|
SetHeader("Content-Type", tc.contentType).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
@ -1846,15 +1865,10 @@ func TestFieldValidationPutCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPutCRDSchemaless tests that server-side schema validation
|
// testFieldValidationPutCRDSchemaless tests that server-side schema validation
|
||||||
// works for CRD update requests for CRDs that have schemas
|
// works for CRD update requests for CRDs that have schemas
|
||||||
// with x-kubernetes-preserve-unknown-field set
|
// with x-kubernetes-preserve-unknown-field set
|
||||||
func TestFieldValidationPutCRDSchemaless(t *testing.T) {
|
func testFieldValidationPutCRDSchemaless(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, true)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -1956,13 +1970,13 @@ func TestFieldValidationPutCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
jsonPostBody := []byte(fmt.Sprintf(crdValidBody, apiVersion, kind, tc.name))
|
jsonPostBody := []byte(fmt.Sprintf(crdValidBody, apiVersion, kind, tc.name))
|
||||||
postReq := rest.Post().
|
postReq := rest.Post().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
postResult, err := postReq.Body([]byte(jsonPostBody)).Do(context.TODO()).Raw()
|
postResult, err := postReq.Body([]byte(jsonPostBody)).Do(context.TODO()).Raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1977,7 +1991,7 @@ func TestFieldValidationPutCRDSchemaless(t *testing.T) {
|
|||||||
putBody := []byte(fmt.Sprintf(tc.putBody, apiVersion, kind, tc.name, postUnstructured.GetResourceVersion()))
|
putBody := []byte(fmt.Sprintf(tc.putBody, apiVersion, kind, tc.name, postUnstructured.GetResourceVersion()))
|
||||||
klog.Warningf("putBody: %s\n", string(putBody))
|
klog.Warningf("putBody: %s\n", string(putBody))
|
||||||
putReq := rest.Put().
|
putReq := rest.Put().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
SetHeader("Content-Type", tc.contentType).
|
SetHeader("Content-Type", tc.contentType).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
@ -1995,6 +2009,14 @@ func TestFieldValidationPutCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(result.Warnings()) != len(tc.strictDecodingWarnings) {
|
if len(result.Warnings()) != len(tc.strictDecodingWarnings) {
|
||||||
|
t.Logf("expected:")
|
||||||
|
for _, w := range tc.strictDecodingWarnings {
|
||||||
|
t.Logf("\t%v", w)
|
||||||
|
}
|
||||||
|
t.Logf("got:")
|
||||||
|
for _, w := range result.Warnings() {
|
||||||
|
t.Logf("\t%v", w.Text)
|
||||||
|
}
|
||||||
t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.strictDecodingWarnings), len(result.Warnings()))
|
t.Fatalf("unexpected number of warnings, expected: %d, got: %d", len(tc.strictDecodingWarnings), len(result.Warnings()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2008,15 +2030,10 @@ func TestFieldValidationPutCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPatchCRD tests that server-side schema validation
|
// testFieldValidationPatchCRD tests that server-side schema validation
|
||||||
// works for jsonpatch and mergepatch requests
|
// works for jsonpatch and mergepatch requests
|
||||||
// for custom resources that have schemas.
|
// for custom resources that have schemas.
|
||||||
func TestFieldValidationPatchCRD(t *testing.T) {
|
func testFieldValidationPatchCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, false)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
patchYAMLBody := `
|
patchYAMLBody := `
|
||||||
apiVersion: %s
|
apiVersion: %s
|
||||||
kind: %s
|
kind: %s
|
||||||
@ -2198,12 +2215,12 @@ spec:
|
|||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
// create a CR
|
// create a CR
|
||||||
yamlBody := []byte(fmt.Sprintf(string(patchYAMLBody), apiVersion, kind, tc.name))
|
yamlBody := []byte(fmt.Sprintf(string(patchYAMLBody), apiVersion, kind, tc.name))
|
||||||
createResult, err := rest.Patch(types.ApplyPatchType).
|
createResult, err := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -2214,7 +2231,7 @@ spec:
|
|||||||
|
|
||||||
// patch the CR as specified by the test case
|
// patch the CR as specified by the test case
|
||||||
req := rest.Patch(tc.patchType).
|
req := rest.Patch(tc.patchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
||||||
@ -2246,16 +2263,11 @@ spec:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationPatchCRDSchemaless tests that server-side schema validation
|
// testFieldValidationPatchCRDSchemaless tests that server-side schema validation
|
||||||
// works for jsonpatch and mergepatch requests
|
// works for jsonpatch and mergepatch requests
|
||||||
// for custom resources that have schemas
|
// for custom resources that have schemas
|
||||||
// with x-kubernetes-preserve-unknown-field set
|
// with x-kubernetes-preserve-unknown-field set
|
||||||
func TestFieldValidationPatchCRDSchemaless(t *testing.T) {
|
func testFieldValidationPatchCRDSchemaless(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
// setup the testerver and install the CRD
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, true)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
mergePatchBody := `
|
mergePatchBody := `
|
||||||
{
|
{
|
||||||
"spec": {
|
"spec": {
|
||||||
@ -2408,12 +2420,12 @@ func TestFieldValidationPatchCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
// create a CR
|
// create a CR
|
||||||
yamlBody := []byte(fmt.Sprintf(string(patchYAMLBody), apiVersion, kind, tc.name))
|
yamlBody := []byte(fmt.Sprintf(string(patchYAMLBody), apiVersion, kind, tc.name))
|
||||||
createResult, err := rest.Patch(types.ApplyPatchType).
|
createResult, err := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -2424,7 +2436,7 @@ func TestFieldValidationPatchCRDSchemaless(t *testing.T) {
|
|||||||
|
|
||||||
// patch the CR as specified by the test case
|
// patch the CR as specified by the test case
|
||||||
req := rest.Patch(tc.patchType).
|
req := rest.Patch(tc.patchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(tc.name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
result := req.Body([]byte(tc.body)).Do(context.TODO())
|
||||||
@ -2456,16 +2468,11 @@ func TestFieldValidationPatchCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyCreateCRD tests apply patch requests containing duplicate fields
|
// testFieldValidationApplyCreateCRD tests apply patch requests containing duplicate fields
|
||||||
// on newly created objects, for CRDs that have schemas
|
// on newly created objects, for CRDs that have schemas
|
||||||
// Note that even prior to server-side validation, unknown fields were treated as
|
// Note that even prior to server-side validation, unknown fields were treated as
|
||||||
// errors in apply-patch and are not tested here.
|
// errors in apply-patch and are not tested here.
|
||||||
func TestFieldValidationApplyCreateCRD(t *testing.T) {
|
func testFieldValidationApplyCreateCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, false)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -2515,15 +2522,16 @@ func TestFieldValidationApplyCreateCRD(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
applyCreateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, tc.name))
|
name := fmt.Sprintf("apply-create-crd-%s", tc.name)
|
||||||
|
applyCreateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, name))
|
||||||
|
|
||||||
req := rest.Patch(types.ApplyPatchType).
|
req := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body(applyCreateBody).Do(context.TODO())
|
result := req.Body(applyCreateBody).Do(context.TODO())
|
||||||
if result.Error() != nil && len(tc.strictDecodingErrors) == 0 {
|
if result.Error() != nil && len(tc.strictDecodingErrors) == 0 {
|
||||||
@ -2551,17 +2559,12 @@ func TestFieldValidationApplyCreateCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyCreateCRDSchemaless tests apply patch requests containing duplicate fields
|
// testFieldValidationApplyCreateCRDSchemaless tests apply patch requests containing duplicate fields
|
||||||
// on newly created objects, for CRDs that have schemas
|
// on newly created objects, for CRDs that have schemas
|
||||||
// with x-kubernetes-preserve-unknown-field set
|
// with x-kubernetes-preserve-unknown-field set
|
||||||
// Note that even prior to server-side validation, unknown fields were treated as
|
// Note that even prior to server-side validation, unknown fields were treated as
|
||||||
// errors in apply-patch and are not tested here.
|
// errors in apply-patch and are not tested here.
|
||||||
func TestFieldValidationApplyCreateCRDSchemaless(t *testing.T) {
|
func testFieldValidationApplyCreateCRDSchemaless(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, true)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -2611,15 +2614,16 @@ func TestFieldValidationApplyCreateCRDSchemaless(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
applyCreateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, tc.name))
|
name := fmt.Sprintf("apply-create-crd-schemaless-%s", tc.name)
|
||||||
|
applyCreateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, name))
|
||||||
|
|
||||||
req := rest.Patch(types.ApplyPatchType).
|
req := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := req.Body(applyCreateBody).Do(context.TODO())
|
result := req.Body(applyCreateBody).Do(context.TODO())
|
||||||
if result.Error() != nil && len(tc.strictDecodingErrors) == 0 {
|
if result.Error() != nil && len(tc.strictDecodingErrors) == 0 {
|
||||||
@ -2647,16 +2651,11 @@ func TestFieldValidationApplyCreateCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyUpdateCRD tests apply patch requests containing duplicate fields
|
// testFieldValidationApplyUpdateCRD tests apply patch requests containing duplicate fields
|
||||||
// on existing objects, for CRDs with schemas
|
// on existing objects, for CRDs with schemas
|
||||||
// Note that even prior to server-side validation, unknown fields were treated as
|
// Note that even prior to server-side validation, unknown fields were treated as
|
||||||
// errors in apply-patch and are not tested here.
|
// errors in apply-patch and are not tested here.
|
||||||
func TestFieldValidationApplyUpdateCRD(t *testing.T) {
|
func testFieldValidationApplyUpdateCRD(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, false)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -2706,24 +2705,25 @@ func TestFieldValidationApplyUpdateCRD(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
applyCreateBody := []byte(fmt.Sprintf(crdApplyValidBody, apiVersion, kind, tc.name))
|
name := fmt.Sprintf("apply-update-crd-%s", tc.name)
|
||||||
|
applyCreateBody := []byte(fmt.Sprintf(crdApplyValidBody, apiVersion, kind, name))
|
||||||
createReq := rest.Patch(types.ApplyPatchType).
|
createReq := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
createResult := createReq.Body(applyCreateBody).Do(context.TODO())
|
createResult := createReq.Body(applyCreateBody).Do(context.TODO())
|
||||||
if createResult.Error() != nil {
|
if createResult.Error() != nil {
|
||||||
t.Fatalf("unexpected apply create err: %v", createResult.Error())
|
t.Fatalf("unexpected apply create err: %v", createResult.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
applyUpdateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, tc.name))
|
applyUpdateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, name))
|
||||||
updateReq := rest.Patch(types.ApplyPatchType).
|
updateReq := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := updateReq.Body(applyUpdateBody).Do(context.TODO())
|
result := updateReq.Body(applyUpdateBody).Do(context.TODO())
|
||||||
|
|
||||||
@ -2752,17 +2752,12 @@ func TestFieldValidationApplyUpdateCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFieldValidationApplyUpdateCRDSchemaless tests apply patch requests containing duplicate fields
|
// testFieldValidationApplyUpdateCRDSchemaless tests apply patch requests containing duplicate fields
|
||||||
// on existing objects, for CRDs with schemas
|
// on existing objects, for CRDs with schemas
|
||||||
// with x-kubernetes-preserve-unknown-field set
|
// with x-kubernetes-preserve-unknown-field set
|
||||||
// Note that even prior to server-side validation, unknown fields were treated as
|
// Note that even prior to server-side validation, unknown fields were treated as
|
||||||
// errors in apply-patch and are not tested here.
|
// errors in apply-patch and are not tested here.
|
||||||
func TestFieldValidationApplyUpdateCRDSchemaless(t *testing.T) {
|
func testFieldValidationApplyUpdateCRDSchemaless(t *testing.T, rest rest.Interface, gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideFieldValidation, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ServerSideApply, true)()
|
|
||||||
noxuDefinition, rest, closeFn := setupCRD(t, true)
|
|
||||||
defer closeFn()
|
|
||||||
|
|
||||||
var testcases = []struct {
|
var testcases = []struct {
|
||||||
name string
|
name string
|
||||||
opts metav1.PatchOptions
|
opts metav1.PatchOptions
|
||||||
@ -2812,24 +2807,25 @@ func TestFieldValidationApplyUpdateCRDSchemaless(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := gvk.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
apiVersion := gvk.Group + "/" + gvk.Version
|
||||||
|
|
||||||
// create the CR as specified by the test case
|
// create the CR as specified by the test case
|
||||||
applyCreateBody := []byte(fmt.Sprintf(crdApplyValidBody, apiVersion, kind, tc.name))
|
name := fmt.Sprintf("apply-update-crd-schemaless-%s", tc.name)
|
||||||
|
applyCreateBody := []byte(fmt.Sprintf(crdApplyValidBody, apiVersion, kind, name))
|
||||||
createReq := rest.Patch(types.ApplyPatchType).
|
createReq := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
createResult := createReq.Body(applyCreateBody).Do(context.TODO())
|
createResult := createReq.Body(applyCreateBody).Do(context.TODO())
|
||||||
if createResult.Error() != nil {
|
if createResult.Error() != nil {
|
||||||
t.Fatalf("unexpected apply create err: %v", createResult.Error())
|
t.Fatalf("unexpected apply create err: %v", createResult.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
applyUpdateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, tc.name))
|
applyUpdateBody := []byte(fmt.Sprintf(crdApplyInvalidBody, apiVersion, kind, name))
|
||||||
updateReq := rest.Patch(types.ApplyPatchType).
|
updateReq := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", gvr.Group, gvr.Version, gvr.Resource).
|
||||||
Name(tc.name).
|
Name(name).
|
||||||
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
VersionedParams(&tc.opts, metav1.ParameterCodec)
|
||||||
result := updateReq.Body(applyUpdateBody).Do(context.TODO())
|
result := updateReq.Body(applyUpdateBody).Do(context.TODO())
|
||||||
|
|
||||||
@ -2858,14 +2854,7 @@ func TestFieldValidationApplyUpdateCRDSchemaless(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupCRD(t *testing.T, schemaless bool) (*apiextensionsv1.CustomResourceDefinition, rest.Interface, kubeapiservertesting.TearDownFunc) {
|
func setupCRD(t *testing.T, config *rest.Config, apiGroup string, schemaless bool) *apiextensionsv1.CustomResourceDefinition {
|
||||||
|
|
||||||
server, err := kubeapiservertesting.StartTestServer(t, kubeapiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
config := server.ClientConfig
|
|
||||||
|
|
||||||
apiExtensionClient, err := apiextensionsclient.NewForConfig(config)
|
apiExtensionClient, err := apiextensionsclient.NewForConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -2882,22 +2871,26 @@ func setupCRD(t *testing.T, schemaless bool) (*apiextensionsv1.CustomResourceDef
|
|||||||
crdSchema := fmt.Sprintf(crdSchemaBase, preserveUnknownFields)
|
crdSchema := fmt.Sprintf(crdSchemaBase, preserveUnknownFields)
|
||||||
|
|
||||||
// create the CRD
|
// create the CRD
|
||||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
crd := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
|
|
||||||
|
// adjust the API group
|
||||||
|
crd.Name = crd.Spec.Names.Plural + "." + apiGroup
|
||||||
|
crd.Spec.Group = apiGroup
|
||||||
|
|
||||||
var c apiextensionsv1.CustomResourceValidation
|
var c apiextensionsv1.CustomResourceValidation
|
||||||
err = json.Unmarshal([]byte(crdSchema), &c)
|
err = json.Unmarshal([]byte(crdSchema), &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
//noxuDefinition.Spec.PreserveUnknownFields = false
|
//crd.Spec.PreserveUnknownFields = false
|
||||||
for i := range noxuDefinition.Spec.Versions {
|
for i := range crd.Spec.Versions {
|
||||||
noxuDefinition.Spec.Versions[i].Schema = &c
|
crd.Spec.Versions[i].Schema = &c
|
||||||
}
|
}
|
||||||
// install the CRD
|
// install the CRD
|
||||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
return crd
|
||||||
return noxuDefinition, rest, server.TearDownFn
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user