diff --git a/test/integration/apiserver/apply/apply_crd_test.go b/test/integration/apiserver/apply/apply_crd_test.go index 71a5e2fad46..6ecaa9febcb 100644 --- a/test/integration/apiserver/apply/apply_crd_test.go +++ b/test/integration/apiserver/apply/apply_crd_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" @@ -733,3 +735,108 @@ spec: t.Fatalf("Expecting to get one conflict when a different applier updates existing list item, got: %v", status.Status().Details.Causes) } } + +func TestNoOpApplyWithDefaultsSameResourceVersionCRD(t *testing.T) { + 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.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped) + err = json.Unmarshal([]byte(`{ + "openAPIV3Schema": { + "type": "object", + "properties": { + "spec": { + "type": "object", + "properties": { + "infrastructureRef": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string", + "default": "default-namespace" + } + }, + "x-kubernetes-map-type": "atomic" + } + } + } + } + } + }`), &noxuDefinition.Spec.Versions[0].Schema) + if err != nil { + t.Fatal(err) + } + noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient) + if err != nil { + t.Fatal(err) + } + + group := noxuDefinition.Spec.Group + kind := noxuDefinition.Spec.Names.Kind + resource := noxuDefinition.Spec.Names.Plural + version := noxuDefinition.Spec.Versions[0].Name + apiVersion := noxuDefinition.Spec.Group + "/" + version + gvr := schema.GroupVersionResource{Group: group, Version: version, Resource: resource} + name := "mytest" + + // fieldWithDefault will be defaulted + applyConfiguration := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": apiVersion, + "kind": kind, + "metadata": map[string]interface{}{ + "name": name, + }, + "spec": map[string]interface{}{"infrastructureRef": map[string]interface{}{"name": "infrastructure-machine-1\n"}}, + }, + } + + created, err := dynamicClient.Resource(gvr).Apply(context.TODO(), name, applyConfiguration, metav1.ApplyOptions{FieldManager: "apply_test"}) + + if err != nil { + t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, created) + } + + createdAccessor, err := meta.Accessor(created) + if err != nil { + t.Fatalf("Failed to get meta accessor for updated object: %v", err) + } + + // Sleep for one second to make sure that the times of each update operation is different. + time.Sleep(1 * time.Second) + + updated, err := dynamicClient.Resource(gvr).Apply(context.TODO(), name, applyConfiguration, metav1.ApplyOptions{FieldManager: "apply_test"}) + if err != nil { + t.Fatalf("failed to update custom resource with apply: %v:\n%v", err, updated) + } + + updatedAccessor, err := meta.Accessor(updated) + if err != nil { + t.Fatalf("Failed to get meta accessor for updated object: %v", err) + } + + if createdAccessor.GetResourceVersion() != updatedAccessor.GetResourceVersion() { + t.Fatalf("Expected same resource version to be %v but got: %v\nold object:\n%v\nnew object:\n%v", + createdAccessor.GetResourceVersion(), + updatedAccessor.GetResourceVersion(), + created, + updated, + ) + } +}