Fix --take-ownership for custom resources - closes #30622#30697
Fix --take-ownership for custom resources - closes #30622#30697scottrigby merged 4 commits intohelm:mainfrom
Conversation
|
The YAML after a successful apiVersion: crd.com/v1
kind: Data
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"crd.com/v1","kind":"Data","metadata":{"annotations":{},"labels":{"test":"adopt"},"name":"crd-test","namespace":"kube-system"},"spec":{"color":"blue","size":"large"}}
meta.helm.sh/release-name: foo
meta.helm.sh/release-namespace: default
creationTimestamp: "2025-03-21T12:37:34Z"
generation: 2
labels:
app.kubernetes.io/managed-by: Helm
test: adopt
name: crd-test
namespace: kube-system
resourceVersion: "374259"
uid: 4e87ddf2-2012-4ee7-a804-a8a7406c72b7
spec:
color: blue
size: large
weight: heavy |
|
@p-se the PR needs to be merged to |
pkg/kube/interface.go
Outdated
| // Update updates one or more resources or creates the resource | ||
| // if it doesn't exist. | ||
| Update(original, target ResourceList, force bool) (*Result, error) | ||
| Update(original, target ResourceList, force bool, threeWayMergeForUnstructured bool) (*Result, error) |
There was a problem hiding this comment.
Since we are targeting to fix this in v3, this API change will break backward compatibility
There was a problem hiding this comment.
Would you like me to add a method to the interface and use that new method instead of adapting the existing method to preserve backward compatibility?
There was a problem hiding this comment.
I'll bring this PR up in the developer call tomorrow. Depending on the outcome, you might not need to make any change to this function.
If we can default to 3-way merging, the additional threeWayMergeForUnstructured parameter may not be needed. If we need the parameter, the way to extend the API is to create a new interface which kube Client implements. Take a look at here and here. In golang, extending an interface is a breaking change because any type implementing that interface will break
There was a problem hiding this comment.
@p-se remember to add // TODO Helm 4: Remove this... in the new interface, similar to the other extensions
There was a problem hiding this comment.
@p-se from today's developer call, it was agreed not to have to 3-way merging for CRDs and unstructured resources as the default behaviour so as not to surprise users with a change in behaviour.
We will keep the threeWayMergeForUnstructured boolean that will be true whenever --take-ownership flag is set.
There was a problem hiding this comment.
Please create a new interface like below (or similar) that kube.Client implements, then revert the previous change you made. Once that's done this PR should be good to go
// TODO Helm 4: Remove InterfaceThreeWayMerge and integrate its method(s) into the Interface.
type InterfaceThreeWayMerge interface {
UpdateThreeWayMerge(original, target ResourceList, force bool, threeWayMergeForUnstructured bool) (*Result, error)
}0e4042d to
c551686
Compare
robertsirc
left a comment
There was a problem hiding this comment.
Hello, thank you for your PR could you please update and ensure you have test.
| _, isCRD := versionedObject.(*apiextv1beta1.CustomResourceDefinition) | ||
|
|
||
| if isUnstructured || isCRD { | ||
| if threeWayMergeForUnstructured { |
There was a problem hiding this comment.
@mattfarina in light of #13411 (review), is there any objection defaulting to 3-way merge for CRDs and unstructured resources in Helm v3, or should we have a CLI flag to opt into the merge strategy? I do not see any backward compatibility risk, but I might be missing something
For v4 I'm leaning towards having 3-way merge as default.
There was a problem hiding this comment.
The result of the conversation in last Helm dev meeting is that it's ok to use 3-way merge for the CR during --take-ownership (given that it fixes the bug, which didn't work previously). But we should NOT change the behavior for CRs everywhere apart from take-ownership in Helm v3.
Perhaps we may want to do that in Helm v4 if we don't implement Server Side Apply before then, but let's hold off on that in this PR.
pkg/action/install.go
Outdated
| } else if len(resources) > 0 { | ||
| _, err = i.cfg.KubeClient.Update(toBeAdopted, resources, i.Force) | ||
| if i.TakeOwnership { | ||
| if kubeClient, ok := i.cfg.KubeClient.(kube.InterfaceThreeWayMerge); ok { |
There was a problem hiding this comment.
nit: You could remove this check since there is var _ InterfaceThreeWayMerge = (*Client)(nil) check that ensures the client implements this API. If you want to keep this check, then return an error in an else block
01b94b6 to
d360800
Compare
If a resource exists in the cluster and is to be adopted by helm install --take-ownership, it is left unchanged while helm reports the installation to have succeeded. This is due to CRs and CRDs being merged without three-way-merge, which results in an empty patch. By using a three-way-merge transparently when --take-ownership is used, the helm behaves as expected without breaking previous behavior. Fixes helm#30622 Signed-off-by: Patrick Seidensal <pseidensal@suse.com>
scottrigby
left a comment
There was a problem hiding this comment.
@p-se nice work 👍 LGTM
Re @robertsirc #30697 (comment) about tests. I agree we need to add tests to PRs whenever possible. Currently this PR fixes a glaring bug for a feature that did not have tests for the feature, but as @banjoh noted there are several open PRs for that already: #30697 (comment). However, this PR does add tests for code that is changed—specifically the merge strategies—which I think is important and covers what we need for this PR.
|
Needs to remove the empty test commit (will also fix missing DCO) 250c69b and now needs to resolve conflicts in upstream |
|
Thanks for adding this, lgtm |
9dc6fab to
f52e42d
Compare
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
b3a8b60 to
7c37a10
Compare
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
If a resource exists in the cluster and is to be adopted by helm install --take-ownership, it is left unchanged while helm reports the installation to have succeeded.
This is due to CRs and CRDs being merged without three-way-merge, which results in an empty patch.
By using a three-way-merge transparently when --take-ownership is used, helm behaves as expected without breaking previous behavior.
Fixes #30622
What this PR does / why we need it:
Special notes for your reviewer:
If applicable:
docs neededlabel should be applied if so)--take-ownership does not appear to be documented at all, so perhaps yes from that perspective, but no from the perspective of this PR.
The changes in this PR are meant to not change any existing behavior, except for how helm behaves when called with
--take-ownership.