From f31afbbf8e93530afaa3d9521d948aaaad97caf4 Mon Sep 17 00:00:00 2001 From: Joe Betz Date: Fri, 7 Jun 2024 11:11:24 -0400 Subject: [PATCH] Add marker struct test case --- .../integration/apiserver/apply/apply_test.go | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/test/integration/apiserver/apply/apply_test.go b/test/integration/apiserver/apply/apply_test.go index 3872c97b779..ecd4060583b 100644 --- a/test/integration/apiserver/apply/apply_test.go +++ b/test/integration/apiserver/apply/apply_test.go @@ -356,6 +356,125 @@ func TestNoOpApplyWithEmptyMap(t *testing.T) { } } +// TestApplyEmptyMarkerStructDifferentFromNil +func TestApplyEmptyMarkerStructDifferentFromNil(t *testing.T) { + client, closeFn := setup(t) + defer closeFn() + + podName := "pod-with-empty-dir" + podsResource := "pods" + podBytesWithEmptyDir := []byte(`{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "` + podName + `" + }, + "spec": { + "containers": [{ + "name": "test-container-a", + "image": "test-image-one", + "volumeMounts": [{ + "mountPath": "/cache", + "name": "cache-volume" + }], + }], + "volumes": [{ + "name": "cache-volume", + "emptyDir": {} + }] + } + }`) + + _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType). + Namespace("default"). + Param("fieldManager", "apply_test"). + Resource(podsResource). + Name(podName). + Body(podBytesWithEmptyDir). + Do(context.TODO()). + Get() + if err != nil { + t.Fatalf("Failed to create object: %v", err) + } + + // This sleep is necessary to consistently produce different timestamps because the time field in managedFields has + // 1 second granularity and if both apply requests happen during the same second, this test would flake. + time.Sleep(1 * time.Second) + + createdObject, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource(podsResource).Name(podName).Do(context.TODO()).Get() + if err != nil { + t.Fatalf("Failed to retrieve created object: %v", err) + } + + createdAccessor, err := meta.Accessor(createdObject) + if err != nil { + t.Fatalf("Failed to get meta accessor for created object: %v", err) + } + + createdBytes, err := json.MarshalIndent(createdObject, "\t", "\t") + if err != nil { + t.Fatalf("Failed to marshal created object: %v", err) + } + + podBytesNoEmptyDir := []byte(`{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "` + podName + `" + }, + "spec": { + "containers": [{ + "name": "test-container-a", + "image": "test-image-one", + "volumeMounts": [{ + "mountPath": "/cache", + "name": "cache-volume" + }], + }], + "volumes": [{ + "name": "cache-volume" + }] + } + }`) + + // Test that an apply with no emptyDir is recognized as distinct from an empty marker struct emptyDir. + _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType). + Namespace("default"). + Param("fieldManager", "apply_test"). + Resource(podsResource). + Name(podName). + Body(podBytesNoEmptyDir). + Do(context.TODO()). + Get() + if err != nil { + t.Fatalf("Failed to create object: %v", err) + } + + updatedObject, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource(podsResource).Name(podName).Do(context.TODO()).Get() + if err != nil { + t.Fatalf("Failed to retrieve updated object: %v", err) + } + + updatedAccessor, err := meta.Accessor(updatedObject) + if err != nil { + t.Fatalf("Failed to get meta accessor for updated object: %v", err) + } + + updatedBytes, err := json.MarshalIndent(updatedObject, "\t", "\t") + if err != nil { + t.Fatalf("Failed to marshal updated object: %v", err) + } + + if createdAccessor.GetResourceVersion() == updatedAccessor.GetResourceVersion() { + t.Fatalf("Expected different resource version to be %v but got: %v\nold object:\n%v\nnew object:\n%v", + createdAccessor.GetResourceVersion(), + updatedAccessor.GetResourceVersion(), + string(createdBytes), + string(updatedBytes), + ) + } +} + func getRV(obj runtime.Object) (string, error) { acc, err := meta.Accessor(obj) if err != nil {