I am trying to update an object's Env field but I don't want to have to iterate through them to figure out which fields already exist and need to be updated instead of inserted if that isn't necessary. I'm using controller-runtime.
I tried patching using an ApplyPatchType, like so:r.Patch(ctx, myDeployment, client.Apply)
where client.Apply is here, and myDeployment
is an *appsv1.Deployment
that I found with List(...)
and then modified.
This failed with a 415 Unsupported Media Type
. I assume it has something to do with it needing to be encoded in YAML (since the type's value is "application/apply-patch+yaml"
I got it working by doing this (r has an embedded controller-runtime Client):
newDeploy := dep.DeepCopy()
original := dep.DeepCopy()
// ... (changing newDeploy)
rawObj, _ := apijson.Marshal(newDeploy)
r.Patch(ctx, original, client.ConstantPatch(types.StrategicMergePatchType, rawObj))
This feels inefficient though, with possibly unnecessary DeepCopies, and I feel like I'm unnecessarily Marshalling my object. I figured I could somehow use the Patch
command similar to how I use the Update
command, where I could just pass in the object in its already modified state and get the StrategicMergePatchType (or ApplyPatchType) behavior.
It seems to me like if I want to just pass in the modified object and have the client "figure out" what to patch, I want to use the client.Apply (ApplyPatchType) behavior, since I think that StrategicMergePatchType is just for diffs to apply (though providing the whole object can still be a valid diff I suppose). Any guidance is appreciated!
For now, I got the behavior I'm looking for without having to manually write the merging logic by using client.MergeFrom:
MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.
Relevant code:
r.Patch(ctx, newDeploy, client.MergeFrom(original))