Code change:
<ins> /* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fieldmanager_test import ( "reflect" "testing" "time" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/yaml" ) func TestNoManagedFieldsUpdateDoesntUpdateTime(t *testing.T) { f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"), false, nil) obj := &unstructured.Unstructured{Object: map[string]interface{}{}} if err := yaml.Unmarshal([]byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "pod", "labels": {"app": "nginx"} }, }`), &obj.Object); err != nil { t.Fatalf("error decoding YAML: %v", err) } if err := f.Update(obj, "fieldmanager_test"); err != nil { t.Fatalf("failed to update object: %v", err) } managed := f.ManagedFields() obj2 := &unstructured.Unstructured{Object: map[string]interface{}{}} if err := yaml.Unmarshal([]byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "pod", "labels": {"app": "nginx2"} }, }`), &obj2.Object); err != nil { t.Fatalf("error decoding YAML: %v", err) } time.Sleep(time.Second) if err := f.Update(obj2, "fieldmanager_test"); err != nil { t.Fatalf("failed to update object: %v", err) } if !reflect.DeepEqual(managed, f.ManagedFields()) { t.Errorf("ManagedFields changed:nBefore:n%vnAfter:n%v", managed, f.ManagedFields()) } } </ins>

Related discussion:
text: So the only actual issue is with the changing time field. Thanks for looking into that. Do let me know if there is anything I can do to help.
Can you show me the object before you run that diff? I'm curious what the first "fieldManager" is and why it's different from "kubectl-client-side-apply". Also, did you create the object using ?
I figured out what the problem is in that second message: the cpu goes from an to a : Note that I'm using a non-server-side capable apiserver version, but I think the problem is the same: we can't detect that this object has been changed because cpu goes from to , or from to and we consider this as a change. I have no clue how to solve that "bug".
Hi The test you made is comparing the local yaml against the version the apiserver currently has, correct? That would be similar to running the diff with the option to run server side, which I think yields a suspiciously similar result: I also suspect that it is for this reason that if I run the apply command with the dry-run flag, we always get incoming changes to apply: For comparison sake, the same test with the server-metrics manifest, that does not produce any diff changes, does not detect any incoming changes (notice all of the items are marked with unchanged): I also have no idea how to fix this properly, but perhaps running a yaml formatter on both sources (left and right) before comparison could produce better results? A canonical representation of both inputs might be better suited for comparison. Perhaps such a behavior could be controlled with a new enabling CLI flag. Again, thanks for looking into this. Having a more reliable diff behavior would go a long way for us to detect configuration mismatches against our configuration management system.
Sure thing! I spawned from this bug report to cover the "failed to create typed patch object" problem. I will try to test with the newly minted 1.19 release later today, to see if any previously observed behavior changes.
I recreated the cluster as version 1.19.0, and here are the results of the previous tests: Ran as expected Ran as expected Ran showing unexpected diff results
Thanks for all the details that's actually really useful for me to understand what's going on.
Some more context.