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
import (
"encoding/json"
"fmt"
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
"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/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -100,91 +99,114 @@ spec:
func TestLargeLastApplied(t *testing.T) {
tests := []struct {
name string
oldObject *corev1.ConfigMap
newObject *corev1.ConfigMap
oldObject *unstructured.Unstructured
newObject *unstructured.Unstructured
}{
{
name: "old object + new object last-applied annotation is too big",
oldObject: &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
oldObject: 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"
}
},
ObjectMeta: metav1.ObjectMeta{
Name: "large-update-test-cm",
Namespace: "default",
Annotations: map[string]string{
internal.LastAppliedConfigAnnotation: "nonempty",
"apiVersion": "v1",
"kind": "ConfigMap",
"data": {
"k": "v"
}
}`), &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"
}
},
},
Data: map[string]string{"k": "v"},
},
newObject: func() *corev1.ConfigMap {
cfg := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: "large-update-test-cm",
Namespace: "default",
Annotations: map[string]string{
internal.LastAppliedConfigAnnotation: "nonempty",
},
},
Data: map[string]string{"k": "v"},
"apiVersion": "v1",
"kind": "ConfigMap",
"data": {
"k": "v"
}
}`), &u)
if err != nil {
panic(err)
}
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)
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",
oldObject: func() *corev1.ConfigMap {
cfg := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
oldObject: 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"
}
},
ObjectMeta: metav1.ObjectMeta{
Name: "large-update-test-cm",
Namespace: "default",
Annotations: map[string]string{
internal.LastAppliedConfigAnnotation: "nonempty",
},
},
Data: map[string]string{"k": "v"},
"apiVersion": "v1",
"kind": "ConfigMap",
"data": {
"k": "v"
}
}`), &u)
if err != nil {
panic(err)
}
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)
cfg.Data[unique] = "A"
unstructured.SetNestedField(u.Object, "A", "data", unique)
}
return cfg
return u
}(),
newObject: func() *corev1.ConfigMap {
cfg := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
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"
}
},
ObjectMeta: metav1.ObjectMeta{
Name: "large-update-test-cm",
Namespace: "default",
Annotations: map[string]string{
internal.LastAppliedConfigAnnotation: "nonempty",
},
},
Data: map[string]string{"k": "v"},
"apiVersion": "v1",
"kind": "ConfigMap",
"data": {
"k": "v"
}
}`), &u)
if err != nil {
panic(err)
}
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)
cfg.Data[unique] = "A"
cfg.ObjectMeta.Annotations[unique] = "A"
unstructured.SetNestedField(u.Object, "A", "data", unique)
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
import (
"encoding/json"
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -78,10 +78,10 @@ func TestUpdateBeforeFirstApply(t *testing.T) {
)
})
updatedObj := &corev1.Pod{}
updatedObj.Kind = "Pod"
updatedObj.APIVersion = "v1"
updatedObj.ObjectMeta.Labels = map[string]string{"app": "my-nginx"}
updatedObj := &unstructured.Unstructured{}
if err := json.Unmarshal([]byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": {"labels": {"app": "my-nginx"}}}`), updatedObj); err != nil {
t.Fatalf("Failed to unmarshal object: %v", err)
}
if err := f.Update(updatedObj, "fieldmanager_test_update"); err != nil {
t.Fatalf("failed to update object: %v", err)