使用控制器运行时修补对象的正确方法是什么?

What is the proper way to Patch an object with controller-runtime?

我正在尝试更新对象的 Env 字段,但我不想遍历它们以找出哪些字段已经存在并且需要更新而不是插入(如果不需要的话)。我正在使用控制器运行时。

我尝试使用 ApplyPatchType 进行修补,如下所示:
r.Patch(ctx, myDeployment, client.Apply)
其中 client.Apply 是 here,而 myDeployment 是我用 List(...) 找到然后修改的 *appsv1.Deployment

这失败了 415 Unsupported Media Type。我认为它与需要在 YAML 中编码有关(因为类型的值为 "application/apply-patch+yaml"

我通过这样做让它工作(r 有一个嵌入式控制器运行时客户端):

newDeploy := dep.DeepCopy()
original := dep.DeepCopy()
// ... (changing newDeploy)
rawObj, _ := apijson.Marshal(newDeploy)
r.Patch(ctx, original, client.ConstantPatch(types.StrategicMergePatchType, rawObj))

这感觉效率低下,可能有不必要的 DeepCopies,而且我觉得我不必要地编组我的对象。我想我可以以某种方式使用 Patch 命令,类似于我使用 Update 命令的方式,我可以在其中传入已修改状态的对象并获得 StrategicMergePatchType(或 ApplyPatchType)行为。

在我看来,如果我只想传递修改后的对象并让客户端 "figure out" 修补什么,我想使用 client.Apply (ApplyPatchType) 行为,因为我认为 StrategicMergePatchType 只是为了应用差异(尽管我认为提供整个对象仍然是一个有效的差异)。任何指导表示赞赏!

现在,我得到了我正在寻找的行为,而无需使用 client.MergeFrom:

手动编写合并逻辑

MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.

相关代码:

r.Patch(ctx, newDeploy, client.MergeFrom(original))