change Apply signature and move decoding into handlers
This commit is contained in:
		| @@ -70,6 +70,7 @@ go_library( | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/validation:go_default_library", | ||||
| @@ -104,6 +105,7 @@ go_library( | ||||
|         "//vendor/golang.org/x/net/websocket:go_default_library", | ||||
|         "//vendor/k8s.io/klog:go_default_library", | ||||
|         "//vendor/k8s.io/utils/trace:go_default_library", | ||||
|         "//vendor/sigs.k8s.io/yaml:go_default_library", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -17,7 +17,6 @@ go_library( | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", | ||||
|         "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", | ||||
|         "//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal:go_default_library", | ||||
| @@ -25,7 +24,6 @@ go_library( | ||||
|         "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", | ||||
|         "//vendor/sigs.k8s.io/structured-merge-diff/fieldpath:go_default_library", | ||||
|         "//vendor/sigs.k8s.io/structured-merge-diff/merge:go_default_library", | ||||
|         "//vendor/sigs.k8s.io/yaml:go_default_library", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -51,12 +51,12 @@ func (f *buildManagerInfoManager) Update(liveObj, newObj runtime.Object, managed | ||||
| } | ||||
|  | ||||
| // Apply implements Manager. | ||||
| func (f *buildManagerInfoManager) Apply(liveObj runtime.Object, patch []byte, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| func (f *buildManagerInfoManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	manager, err := f.buildManagerInfo(manager, metav1.ManagedFieldsOperationApply) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, fmt.Errorf("failed to build manager identifier: %v", err) | ||||
| 	} | ||||
| 	return f.fieldManager.Apply(liveObj, patch, managed, manager, force) | ||||
| 	return f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force) | ||||
| } | ||||
|  | ||||
| func (f *buildManagerInfoManager) buildManagerInfo(prefix string, operation metav1.ManagedFieldsOperationType) (string, error) { | ||||
|   | ||||
| @@ -58,8 +58,8 @@ func (f *capManagersManager) Update(liveObj, newObj runtime.Object, managed Mana | ||||
| } | ||||
|  | ||||
| // Apply implements Manager. | ||||
| func (f *capManagersManager) Apply(liveObj runtime.Object, patch []byte, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	return f.fieldManager.Apply(liveObj, patch, managed, fieldManager, force) | ||||
| func (f *capManagersManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	return f.fieldManager.Apply(liveObj, appliedObj, managed, fieldManager, force) | ||||
| } | ||||
|  | ||||
| // capUpdateManagers merges a number of the oldest update entries into versioned buckets, | ||||
|   | ||||
| @@ -41,7 +41,7 @@ func (*fakeManager) Update(_, newObj runtime.Object, managed fieldmanager.Manage | ||||
| 	return newObj, managed, nil | ||||
| } | ||||
|  | ||||
| func (*fakeManager) Apply(_ runtime.Object, _ []byte, _ fieldmanager.Managed, _ string, force bool) (runtime.Object, fieldmanager.Managed, error) { | ||||
| func (*fakeManager) Apply(_, _ runtime.Object, _ fieldmanager.Managed, _ string, force bool) (runtime.Object, fieldmanager.Managed, error) { | ||||
| 	panic("not implemented") | ||||
| 	return nil, nil, nil | ||||
| } | ||||
|   | ||||
| @@ -51,7 +51,7 @@ type Manager interface { | ||||
|  | ||||
| 	// Apply is used when server-side apply is called, as it merges the | ||||
| 	// object and updates the managed fields. | ||||
| 	Apply(liveObj runtime.Object, patch []byte, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) | ||||
| 	Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) | ||||
| } | ||||
|  | ||||
| // FieldManager updates the managed fields and merge applied | ||||
| @@ -135,7 +135,7 @@ func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (o | ||||
|  | ||||
| // Apply is used when server-side apply is called, as it merges the | ||||
| // object and updates the managed fields. | ||||
| func (f *FieldManager) Apply(liveObj runtime.Object, patch []byte, manager string, force bool) (object runtime.Object, err error) { | ||||
| func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, force bool) (object runtime.Object, err error) { | ||||
| 	// If the object doesn't have metadata, apply isn't allowed. | ||||
| 	if _, err = meta.Accessor(liveObj); err != nil { | ||||
| 		return nil, fmt.Errorf("couldn't get accessor: %v", err) | ||||
| @@ -149,7 +149,7 @@ func (f *FieldManager) Apply(liveObj runtime.Object, patch []byte, manager strin | ||||
|  | ||||
| 	internal.RemoveObjectManagedFields(liveObj) | ||||
|  | ||||
| 	if object, managed, err = f.fieldManager.Apply(liveObj, patch, managed, manager, force); err != nil { | ||||
| 	if object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -106,7 +106,7 @@ func (f *TestFieldManager) Reset() { | ||||
| 	f.liveObj = f.emptyObj.DeepCopyObject() | ||||
| } | ||||
|  | ||||
| func (f *TestFieldManager) Apply(obj []byte, manager string, force bool) error { | ||||
| func (f *TestFieldManager) Apply(obj runtime.Object, manager string, force bool) error { | ||||
| 	out, err := fieldmanager.NewFieldManager(f.fieldManager).Apply(f.liveObj, obj, manager, force) | ||||
| 	if err == nil { | ||||
| 		f.liveObj = out | ||||
| @@ -174,7 +174,8 @@ func TestUpdateApplyConflict(t *testing.T) { | ||||
| 		t.Fatalf("failed to apply object: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "apps/v1", | ||||
| 		"kind": "Deployment", | ||||
| 		"metadata": { | ||||
| @@ -183,7 +184,11 @@ func TestUpdateApplyConflict(t *testing.T) { | ||||
| 		"spec": { | ||||
| 			"replicas": 101, | ||||
| 		} | ||||
| 	}`), "fieldmanager_conflict", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_conflict", false) | ||||
| 	if err == nil || !apierrors.IsConflict(err) { | ||||
| 		t.Fatalf("Expecting to get conflicts but got %v", err) | ||||
| 	} | ||||
| @@ -225,20 +230,68 @@ func TestApplyStripsFields(t *testing.T) { | ||||
| func TestVersionCheck(t *testing.T) { | ||||
| 	f := NewTestFieldManager(schema.FromAPIVersionAndKind("apps/v1", "Deployment")) | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v1' and live version is apps/v1 -> no errors | ||||
| 	err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "apps/v1", | ||||
| 		"kind": "Deployment", | ||||
| 	}`), "fieldmanager_test", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v1' and live version is apps/v1 -> no errors | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to apply object: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v2' but live version is apps/v1 -> error | ||||
| 	err = f.Apply([]byte(`{ | ||||
| 	appliedObj = &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "apps/v1beta1", | ||||
| 		"kind": "Deployment", | ||||
| 	}`), "fieldmanager_test", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v2' but live version is apps/v1 -> error | ||||
| 	err = f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("expected an error from mismatched patch and live versions") | ||||
| 	} | ||||
| 	switch typ := err.(type) { | ||||
| 	default: | ||||
| 		t.Fatalf("expected error to be of type %T was %T", apierrors.StatusError{}, typ) | ||||
| 	case apierrors.APIStatus: | ||||
| 		if typ.Status().Code != http.StatusBadRequest { | ||||
| 			t.Fatalf("expected status code to be %d but was %d", | ||||
| 				http.StatusBadRequest, typ.Status().Code) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| func TestVersionCheckDoesNotPanic(t *testing.T) { | ||||
| 	f := NewTestFieldManager(schema.FromAPIVersionAndKind("apps/v1", "Deployment")) | ||||
|  | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "apps/v1", | ||||
| 		"kind": "Deployment", | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v1' and live version is apps/v1 -> no errors | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to apply object: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	appliedObj = &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// patch has 'apiVersion: apps/v2' but live version is apps/v1 -> error | ||||
| 	err = f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("expected an error from mismatched patch and live versions") | ||||
| 	} | ||||
| @@ -256,7 +309,8 @@ func TestVersionCheck(t *testing.T) { | ||||
| func TestApplyDoesNotStripLabels(t *testing.T) { | ||||
| 	f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod")) | ||||
|  | ||||
| 	err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "v1", | ||||
| 		"kind": "Pod", | ||||
| 		"metadata": { | ||||
| @@ -264,7 +318,11 @@ func TestApplyDoesNotStripLabels(t *testing.T) { | ||||
| 				"a": "b" | ||||
| 			}, | ||||
| 		} | ||||
| 	}`), "fieldmanager_test", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to apply object: %v", err) | ||||
| 	} | ||||
| @@ -305,7 +363,12 @@ func TestApplyNewObject(t *testing.T) { | ||||
| 		t.Run(test.gvk.String(), func(t *testing.T) { | ||||
| 			f := NewTestFieldManager(test.gvk) | ||||
|  | ||||
| 			if err := f.Apply(test.obj, "fieldmanager_test", false); err != nil { | ||||
| 			appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 			if err := yaml.Unmarshal(test.obj, &appliedObj.Object); err != nil { | ||||
| 				t.Fatalf("error decoding YAML: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			if err := f.Apply(appliedObj, "fieldmanager_test", false); err != nil { | ||||
| 				t.Fatal(err) | ||||
| 			} | ||||
| 		}) | ||||
| @@ -362,7 +425,11 @@ func BenchmarkNewObject(b *testing.B) { | ||||
| 				b.ReportAllocs() | ||||
| 				b.ResetTimer() | ||||
| 				for n := 0; n < b.N; n++ { | ||||
| 					err := f.Apply(test.obj, "fieldmanager_test", false) | ||||
| 					appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 					if err := yaml.Unmarshal(test.obj, &appliedObj.Object); err != nil { | ||||
| 						b.Fatalf("error decoding YAML: %v", err) | ||||
| 					} | ||||
| 					err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
| 					if err != nil { | ||||
| 						b.Fatal(err) | ||||
| 					} | ||||
| @@ -387,7 +454,12 @@ func BenchmarkRepeatedUpdate(b *testing.B) { | ||||
| 	obj.Spec.Containers[0].Image = "nginx:4.3" | ||||
| 	objs = append(objs, obj) | ||||
|  | ||||
| 	err := f.Apply(podBytes, "fieldmanager_apply", false) | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal(podBytes, &appliedObj.Object); err != nil { | ||||
| 		b.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_apply", false) | ||||
| 	if err != nil { | ||||
| 		b.Fatal(err) | ||||
| 	} | ||||
| @@ -410,7 +482,8 @@ func BenchmarkRepeatedUpdate(b *testing.B) { | ||||
| func TestApplyFailsWithManagedFields(t *testing.T) { | ||||
| 	f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod")) | ||||
|  | ||||
| 	err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "v1", | ||||
| 		"kind": "Pod", | ||||
| 		"metadata": { | ||||
| @@ -420,7 +493,11 @@ func TestApplyFailsWithManagedFields(t *testing.T) { | ||||
| 				} | ||||
| 			] | ||||
| 		} | ||||
| 	}`), "fieldmanager_test", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
|  | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("successfully applied with set managed fields") | ||||
| @@ -430,7 +507,8 @@ func TestApplyFailsWithManagedFields(t *testing.T) { | ||||
| func TestApplySuccessWithNoManagedFields(t *testing.T) { | ||||
| 	f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod")) | ||||
|  | ||||
| 	err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "v1", | ||||
| 		"kind": "Pod", | ||||
| 		"metadata": { | ||||
| @@ -438,7 +516,10 @@ func TestApplySuccessWithNoManagedFields(t *testing.T) { | ||||
| 				"a": "b" | ||||
| 			}, | ||||
| 		} | ||||
| 	}`), "fieldmanager_test", false) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test", false) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to apply object: %v", err) | ||||
|   | ||||
| @@ -51,7 +51,7 @@ func (f *skipNonAppliedManager) Update(liveObj, newObj runtime.Object, managed M | ||||
| } | ||||
|  | ||||
| // Apply implements Manager. | ||||
| func (f *skipNonAppliedManager) Apply(liveObj runtime.Object, patch []byte, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) { | ||||
| func (f *skipNonAppliedManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, fieldManager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	if len(managed.Fields()) == 0 { | ||||
| 		emptyObj, err := f.objectCreater.New(f.gvk) | ||||
| 		if err != nil { | ||||
| @@ -62,5 +62,5 @@ func (f *skipNonAppliedManager) Apply(liveObj runtime.Object, patch []byte, mana | ||||
| 			return nil, nil, fmt.Errorf("failed to create manager for existing fields: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	return f.fieldManager.Apply(liveObj, patch, managed, fieldManager, force) | ||||
| 	return f.fieldManager.Apply(liveObj, appliedObj, managed, fieldManager, force) | ||||
| } | ||||
|   | ||||
| @@ -26,6 +26,7 @@ import ( | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager" | ||||
| 	"sigs.k8s.io/yaml" | ||||
| ) | ||||
|  | ||||
| type fakeObjectCreater struct { | ||||
| @@ -49,7 +50,8 @@ func TestNoUpdateBeforeFirstApply(t *testing.T) { | ||||
| 		schema.GroupVersionKind{}, | ||||
| 	) | ||||
|  | ||||
| 	if err := f.Apply([]byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "v1", | ||||
| 		"kind": "Pod", | ||||
| 		"metadata": { | ||||
| @@ -62,7 +64,11 @@ func TestNoUpdateBeforeFirstApply(t *testing.T) { | ||||
| 				"image": "nginx:latest" | ||||
| 			}] | ||||
|         } | ||||
| 	}`), "fieldmanager_test_apply", false); err != nil { | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := f.Apply(appliedObj, "fieldmanager_test_apply", false); err != nil { | ||||
| 		t.Fatalf("failed to update object: %v", err) | ||||
| 	} | ||||
|  | ||||
| @@ -96,7 +102,8 @@ func TestUpdateBeforeFirstApply(t *testing.T) { | ||||
| 		t.Fatalf("managedFields were tracked on update only: %v", m) | ||||
| 	} | ||||
|  | ||||
| 	appliedBytes := []byte(`{ | ||||
| 	appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal([]byte(`{ | ||||
| 		"apiVersion": "v1", | ||||
| 		"kind": "Pod", | ||||
| 		"metadata": { | ||||
| @@ -109,9 +116,11 @@ func TestUpdateBeforeFirstApply(t *testing.T) { | ||||
| 				"image": "nginx:latest" | ||||
| 			}] | ||||
|         } | ||||
| 	}`) | ||||
| 	}`), &appliedObj.Object); err != nil { | ||||
| 		t.Fatalf("error decoding YAML: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	err := f.Apply(appliedBytes, "fieldmanager_test_apply", false) | ||||
| 	err := f.Apply(appliedObj, "fieldmanager_test_apply", false) | ||||
| 	apiStatus, _ := err.(apierrors.APIStatus) | ||||
| 	if err == nil || !apierrors.IsConflict(err) || len(apiStatus.Status().Details.Causes) != 1 { | ||||
| 		t.Fatalf("Expecting to get one conflict but got %v", err) | ||||
| @@ -125,7 +134,7 @@ func TestUpdateBeforeFirstApply(t *testing.T) { | ||||
| 		t.Fatalf("Expecting conflict message to contain %q but got %q: %v", e, a, err) | ||||
| 	} | ||||
|  | ||||
| 	if err := f.Apply(appliedBytes, "fieldmanager_test_apply", true); err != nil { | ||||
| 	if err := f.Apply(appliedObj, "fieldmanager_test_apply", true); err != nil { | ||||
| 		t.Fatalf("failed to update object: %v", err) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -64,13 +64,13 @@ func (f *stripMetaManager) Update(liveObj, newObj runtime.Object, managed Manage | ||||
| } | ||||
|  | ||||
| // Apply implements Manager. | ||||
| func (f *stripMetaManager) Apply(liveObj runtime.Object, patch []byte, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	newObj, managed, err := f.fieldManager.Apply(liveObj, patch, managed, manager, force) | ||||
| func (f *stripMetaManager) Apply(liveObj, appliedObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	appliedObj, managed, err := f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	f.stripFields(managed.Fields(), manager) | ||||
| 	return newObj, managed, nil | ||||
| 	return appliedObj, managed, nil | ||||
| } | ||||
|  | ||||
| // stripFields removes a predefined set of paths found in typed from managed | ||||
|   | ||||
| @@ -21,8 +21,8 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	"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" | ||||
| 	"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal" | ||||
| @@ -30,7 +30,6 @@ import ( | ||||
| 	openapiproto "k8s.io/kube-openapi/pkg/util/proto" | ||||
| 	"sigs.k8s.io/structured-merge-diff/fieldpath" | ||||
| 	"sigs.k8s.io/structured-merge-diff/merge" | ||||
| 	"sigs.k8s.io/yaml" | ||||
| ) | ||||
|  | ||||
| type structuredMergeManager struct { | ||||
| @@ -136,22 +135,18 @@ func (f *structuredMergeManager) Update(liveObj, newObj runtime.Object, managed | ||||
| } | ||||
|  | ||||
| // Apply implements Manager. | ||||
| func (f *structuredMergeManager) Apply(liveObj runtime.Object, patch []byte, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	patchObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal(patch, &patchObj.Object); err != nil { | ||||
| 		return nil, nil, errors.NewBadRequest(fmt.Sprintf("error decoding YAML: %v", err)) | ||||
| 	} | ||||
|  | ||||
| func (f *structuredMergeManager) Apply(liveObj, patchObj runtime.Object, managed Managed, manager string, force bool) (runtime.Object, Managed, error) { | ||||
| 	// Check that the patch object has the same version as the live object | ||||
| 	if patchObj.GetAPIVersion() != f.groupVersion.String() { | ||||
| 	if patchObj.GetObjectKind().GroupVersionKind().GroupVersion() != f.groupVersion { | ||||
| 		return nil, nil, | ||||
| 			errors.NewBadRequest( | ||||
| 				fmt.Sprintf("Incorrect version specified in apply patch. "+ | ||||
| 					"Specified patch version: %s, expected: %s", | ||||
| 					patchObj.GetAPIVersion(), f.groupVersion.String())) | ||||
| 					patchObj.GetObjectKind().GroupVersionKind().GroupVersion(), f.groupVersion)) | ||||
| 	} | ||||
|  | ||||
| 	if patchObj.GetManagedFields() != nil { | ||||
| 	patchObjMeta, err := meta.Accessor(patchObj) | ||||
| 	if patchObjMeta.GetManagedFields() != nil { | ||||
| 		return nil, nil, errors.NewBadRequest(fmt.Sprintf("metadata.managedFields must be nil")) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import ( | ||||
| 	"k8s.io/apimachinery/pkg/api/meta" | ||||
| 	metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/validation" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| @@ -48,6 +49,7 @@ import ( | ||||
| 	"k8s.io/apiserver/pkg/util/dryrun" | ||||
| 	utilfeature "k8s.io/apiserver/pkg/util/feature" | ||||
| 	utiltrace "k8s.io/utils/trace" | ||||
| 	"sigs.k8s.io/yaml" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| @@ -433,7 +435,13 @@ func (p *applyPatcher) applyPatchToCurrentObject(obj runtime.Object) (runtime.Ob | ||||
| 	if p.fieldManager == nil { | ||||
| 		panic("FieldManager must be installed to run apply") | ||||
| 	} | ||||
| 	return p.fieldManager.Apply(obj, p.patch, p.options.FieldManager, force) | ||||
|  | ||||
| 	patchObj := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||||
| 	if err := yaml.Unmarshal(p.patch, &patchObj.Object); err != nil { | ||||
| 		return nil, errors.NewBadRequest(fmt.Sprintf("error decoding YAML: %v", err)) | ||||
| 	} | ||||
|  | ||||
| 	return p.fieldManager.Apply(obj, patchObj, p.options.FieldManager, force) | ||||
| } | ||||
|  | ||||
| func (p *applyPatcher) createNewObject() (runtime.Object, error) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kevin Wiesmüller
					Kevin Wiesmüller