fieldmanager: Use unstructured rather than built-in types to remove dependency

This commit is contained in:
Antoine Pelisse 2023-01-19 10:48:46 -08:00
parent 577f3d8c9d
commit bc0962ad80
2 changed files with 94 additions and 72 deletions

View File

@ -17,13 +17,12 @@ limitations under the License.
package internal_test package internal_test
import ( import (
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"testing" "testing"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
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" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -100,91 +99,114 @@ spec:
func TestLargeLastApplied(t *testing.T) { func TestLargeLastApplied(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
oldObject *corev1.ConfigMap oldObject *unstructured.Unstructured
newObject *corev1.ConfigMap newObject *unstructured.Unstructured
}{ }{
{ {
name: "old object + new object last-applied annotation is too big", name: "old object + new object last-applied annotation is too big",
oldObject: &corev1.ConfigMap{ oldObject: func() *unstructured.Unstructured {
TypeMeta: metav1.TypeMeta{ u := &unstructured.Unstructured{}
APIVersion: "v1", err := json.Unmarshal([]byte(`
Kind: "ConfigMap", {
"metadata": {
"name": "large-update-test-cm",
"namespace": "default",
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "nonempty"
}
}, },
ObjectMeta: metav1.ObjectMeta{ "apiVersion": "v1",
Name: "large-update-test-cm", "kind": "ConfigMap",
Namespace: "default", "data": {
Annotations: map[string]string{ "k": "v"
internal.LastAppliedConfigAnnotation: "nonempty", }
}`), &u)
if err != nil {
panic(err)
}
return u
}(),
newObject: func() *unstructured.Unstructured {
u := &unstructured.Unstructured{}
err := json.Unmarshal([]byte(`
{
"metadata": {
"name": "large-update-test-cm",
"namespace": "default",
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "nonempty"
}
}, },
}, "apiVersion": "v1",
Data: map[string]string{"k": "v"}, "kind": "ConfigMap",
}, "data": {
newObject: func() *corev1.ConfigMap { "k": "v"
cfg := &corev1.ConfigMap{ }
TypeMeta: metav1.TypeMeta{ }`), &u)
APIVersion: "v1", if err != nil {
Kind: "ConfigMap", panic(err)
},
ObjectMeta: metav1.ObjectMeta{
Name: "large-update-test-cm",
Namespace: "default",
Annotations: map[string]string{
internal.LastAppliedConfigAnnotation: "nonempty",
},
},
Data: map[string]string{"k": "v"},
} }
for i := 0; i < 9999; i++ { for i := 0; i < 9999; i++ {
unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i) unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i)
cfg.Data[unique] = "A" unstructured.SetNestedField(u.Object, "A", "data", unique)
} }
return cfg return u
}(), }(),
}, },
{ {
name: "old object + new object annotations + new object last-applied annotation is too big", name: "old object + new object annotations + new object last-applied annotation is too big",
oldObject: func() *corev1.ConfigMap { oldObject: func() *unstructured.Unstructured {
cfg := &corev1.ConfigMap{ u := &unstructured.Unstructured{}
TypeMeta: metav1.TypeMeta{ err := json.Unmarshal([]byte(`
APIVersion: "v1", {
Kind: "ConfigMap", "metadata": {
"name": "large-update-test-cm",
"namespace": "default",
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "nonempty"
}
}, },
ObjectMeta: metav1.ObjectMeta{ "apiVersion": "v1",
Name: "large-update-test-cm", "kind": "ConfigMap",
Namespace: "default", "data": {
Annotations: map[string]string{ "k": "v"
internal.LastAppliedConfigAnnotation: "nonempty", }
}, }`), &u)
}, if err != nil {
Data: map[string]string{"k": "v"}, panic(err)
} }
for i := 0; i < 2000; i++ { for i := 0; i < 2000; i++ {
unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i) unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i)
cfg.Data[unique] = "A" unstructured.SetNestedField(u.Object, "A", "data", unique)
} }
return cfg return u
}(), }(),
newObject: func() *corev1.ConfigMap { newObject: func() *unstructured.Unstructured {
cfg := &corev1.ConfigMap{ u := &unstructured.Unstructured{}
TypeMeta: metav1.TypeMeta{ err := json.Unmarshal([]byte(`
APIVersion: "v1", {
Kind: "ConfigMap", "metadata": {
"name": "large-update-test-cm",
"namespace": "default",
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "nonempty"
}
}, },
ObjectMeta: metav1.ObjectMeta{ "apiVersion": "v1",
Name: "large-update-test-cm", "kind": "ConfigMap",
Namespace: "default", "data": {
Annotations: map[string]string{ "k": "v"
internal.LastAppliedConfigAnnotation: "nonempty", }
}, }`), &u)
}, if err != nil {
Data: map[string]string{"k": "v"}, panic(err)
} }
for i := 0; i < 2000; i++ { for i := 0; i < 2000; i++ {
unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i) unique := fmt.Sprintf("this-key-is-very-long-so-as-to-create-a-very-large-serialized-fieldset-%v", i)
cfg.Data[unique] = "A" unstructured.SetNestedField(u.Object, "A", "data", unique)
cfg.ObjectMeta.Annotations[unique] = "A" unstructured.SetNestedField(u.Object, "A", "metadata", "annotations", unique)
} }
return cfg return u
}(), }(),
}, },
} }

View File

@ -17,10 +17,10 @@ limitations under the License.
package internal_test package internal_test
import ( import (
"encoding/json"
"strings" "strings"
"testing" "testing"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"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/runtime/schema"
@ -78,10 +78,10 @@ func TestUpdateBeforeFirstApply(t *testing.T) {
) )
}) })
updatedObj := &corev1.Pod{} updatedObj := &unstructured.Unstructured{}
updatedObj.Kind = "Pod" if err := json.Unmarshal([]byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": {"labels": {"app": "my-nginx"}}}`), updatedObj); err != nil {
updatedObj.APIVersion = "v1" t.Fatalf("Failed to unmarshal object: %v", err)
updatedObj.ObjectMeta.Labels = map[string]string{"app": "my-nginx"} }
if err := f.Update(updatedObj, "fieldmanager_test_update"); err != nil { if err := f.Update(updatedObj, "fieldmanager_test_update"); err != nil {
t.Fatalf("failed to update object: %v", err) t.Fatalf("failed to update object: %v", err)