Skip to content

Fix --take-ownership for custom resources - closes #30622#30697

Merged
scottrigby merged 4 commits intohelm:mainfrom
p-se:fix-take-ownership
Apr 17, 2025
Merged

Fix --take-ownership for custom resources - closes #30622#30697
scottrigby merged 4 commits intohelm:mainfrom
p-se:fix-take-ownership

Conversation

@p-se
Copy link
Copy Markdown
Contributor

@p-se p-se commented Mar 21, 2025

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:

  • this PR contains user facing changes (the docs needed label 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.
  • this PR contains unit tests
  • this PR has been tested for backwards compatibility
    The changes in this PR are meant to not change any existing behavior, except for how helm behaves when called with --take-ownership.

@pull-request-size pull-request-size bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Mar 21, 2025
@p-se p-se changed the title Fix --take-ownership Fix --take-ownership for custom resources Mar 21, 2025
@p-se
Copy link
Copy Markdown
Contributor Author

p-se commented Mar 21, 2025

The YAML after a successful --take-ownership with the changes of this PR:

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 p-se marked this pull request as ready for review March 21, 2025 12:51
@banjoh
Copy link
Copy Markdown
Contributor

banjoh commented Mar 21, 2025

@p-se the PR needs to be merged to main first, then another PR cherry picking commits into dev-v3 needs to be created. Please have the PR point to main branch

Copy link
Copy Markdown
Contributor

@banjoh banjoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested a happy path test using the example in #30622 and it works. Testing a real use case would be needed.

// 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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are targeting to fix this in v3, this API change will break backward compatibility

Copy link
Copy Markdown
Contributor Author

@p-se p-se Mar 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Notes: https://docs.google.com/document/d/1d-6xJEx0C78csIYSPKJzRPeWaHG_8W1Hjl72OJggwdc/edit?tab=t.0#heading=h.cafxi2yfgqg1

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p-se remember to add // TODO Helm 4: Remove this... in the new interface, similar to the other extensions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
}

@p-se p-se force-pushed the fix-take-ownership branch from 0e4042d to c551686 Compare March 21, 2025 19:57
@p-se p-se changed the base branch from release-3.17 to main March 21, 2025 19:58
Copy link
Copy Markdown
Member

@robertsirc robertsirc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thank you for your PR could you please update and ensure you have test.

@p-se p-se changed the title Fix --take-ownership for custom resources Fix --take-ownership for custom resources - closes #30622 Mar 23, 2025
_, isCRD := versionedObject.(*apiextv1beta1.CustomResourceDefinition)

if isUnstructured || isCRD {
if threeWayMergeForUnstructured {
Copy link
Copy Markdown
Contributor

@banjoh banjoh Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Member

@scottrigby scottrigby Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

@banjoh banjoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

} 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 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@p-se p-se force-pushed the fix-take-ownership branch 3 times, most recently from 01b94b6 to d360800 Compare April 7, 2025 07:29
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>
@p-se p-se force-pushed the fix-take-ownership branch from d360800 to e55707b Compare April 7, 2025 11:55
scottrigby
scottrigby previously approved these changes Apr 7, 2025
Copy link
Copy Markdown
Member

@scottrigby scottrigby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

@scottrigby scottrigby added the Has One Approval This PR has one approval. It still needs a second approval to be merged. label Apr 7, 2025
@scottrigby
Copy link
Copy Markdown
Member

Needs to remove the empty test commit (will also fix missing DCO) 250c69b and now needs to resolve conflicts in upstream pkg/kube/client.go.

@ivelichkovich
Copy link
Copy Markdown

Thanks for adding this, lgtm

@banjoh banjoh force-pushed the fix-take-ownership branch 3 times, most recently from 9dc6fab to f52e42d Compare April 15, 2025 09:33
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
@banjoh banjoh force-pushed the fix-take-ownership branch from b3a8b60 to 7c37a10 Compare April 15, 2025 10:24
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
robertsirc
robertsirc previously approved these changes Apr 16, 2025
Copy link
Copy Markdown
Member

@robertsirc robertsirc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@robertsirc robertsirc added approved Indicates a PR has been approved by the required number of approvers and removed Has One Approval This PR has one approval. It still needs a second approval to be merged. labels Apr 16, 2025
Signed-off-by: Evans Mungai <mbuevans@gmail.com>
Copy link
Copy Markdown
Member

@scottrigby scottrigby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work. Approving again to allow merge

@scottrigby scottrigby added the Needs v3 backport Label PRs for v4/main, which are still applicable to v3 so need a separate backport PR label Apr 17, 2025
@scottrigby scottrigby merged commit 599fad1 into helm:main Apr 17, 2025
5 checks passed
@scottrigby scottrigby removed the Needs v3 backport Label PRs for v4/main, which are still applicable to v3 so need a separate backport PR label Apr 21, 2025
@scottrigby scottrigby added v3 port complete For completed v2->v3 ports and removed approved Indicates a PR has been approved by the required number of approvers labels Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Categorizes issue or PR as related to a bug. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. v3 port complete For completed v2->v3 ports

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--take-ownership does not adopt custom resources

5 participants