Skip to content

Support helm release upgrade on helm chart name change - #1447

Merged
matheuscscp merged 8 commits into
fluxcd:mainfrom
Nordix:issue-870
Jun 16, 2026
Merged

Support helm release upgrade on helm chart name change#1447
matheuscscp merged 8 commits into
fluxcd:mainfrom
Nordix:issue-870

Conversation

@MichaelMorrisEst

@MichaelMorrisEst MichaelMorrisEst commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #870

Proposes to add a new property in the 'upgrade' element of the HelmRelease CRD.

The new property shall have two allowed values: "InPlaceUpdate" and "Reinstall"

When the value "Reinstall" is specified, or when no value is specified, the current behaviour of uninstalling a Helm Release when the Helm chart name is changed shall remain unchanged. This results in a new Helm Release install.
When the value "InPlaceUpdate" is specified, the Helm Release will not be uninstalled when the Helm chart name is changed. This results in a Helm upgrade being performed. This was the behaviour before Flux 2.2.0

This re-introduces support that was lost going from Flux 2.1.x -> 2.2.x but controls the behaviour through the HelmRelease custom resource so either the previous (<2.2.x) behaviour or current behaviour can be achieved

Changes

  • Add chartNameChangeStrategy property to the 'Upgrade' struct in helmrelease_types.go and ensure the default "Reinstall" is used if no value is specified
  • In helmrelease_controller.go if the chart name has changed, only proceed to uninstall the HelmRelease if the new property is set to "Reinstall"
  • Change the visibility of action.targetChartName to enable it to be referenced in the HelmRelease controller
  • Tests added to verify new behaviour

Original proposal

The original proposal when the PR was submitted was to introduce a feature gate to control the behaviour. Following discussions in the comments below the implementation changed to use the custom resource instead. The above description has been updated to reflect the new implementation

@hiddeco hiddeco left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Feedback beyond the contents of the PR: I do wonder if there are not other changes (e.g., release name/namespace or storage namespace) where there could be a desire of control. Given this, I do wonder if what this PR attempts to do isn't too narrow.

Comment thread internal/features/features.go Outdated
// opt-in from v1.5.2
DefaultToRetryOnFailure: false,
// UninstallOnChartNameChange
// opt-in from v1.5.4

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The chance of this going into a patch release is unlikely, this should thus indicate 1.6.0.

Comment thread internal/action/verify.go
targetReleaseNamespace = "release namespace"
targetReleaseName = "release name"
targetChartName = "chart name"
TargetChartName = "chart name"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This list of constants was always meant to be a descriptive reason (factored out to a const for code readability), not an identifier. Additionally, only exposing one of them creates a weak contract. I would prefer a solution where:

  1. All identifiers are public
  2. Identifiers do not contain spaces

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@hiddeco

hiddeco commented Mar 19, 2026

Copy link
Copy Markdown
Member

Some additional thoughts:

  • For storage namespace changes, we could actually do the more intelligent thing and attempt to migrate instead of going through an uninstall cycle. This would open a surface for "Secret smuggling" however, and integrity would likely have to be verified as part of this.
  • In hindsight, the biggest design mistake I ever introduced in the helm-controller (and something that still bites me as an operator once in a while) is not having the storageNamespace field mirror the releaseNamespace unless explicitly overwritten. If we are rethinking how this all works, this might be worth addressing as well (behind a feature gate).
  • Some of these changes may actually require an uninstall (or juggling with Helm install options). As changing a release name would make the resources stay put, which could then cause the subsequent Helm install to fail.

@artem-nefedov

Copy link
Copy Markdown

How about having this setting on resource level rather than a global feature flag?
I feel like that's more correct approach, but don't know about the complexity involved to support that.

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

How about having this setting on resource level rather than a global feature flag? I feel like that's more correct approach, but don't know about the complexity involved to support that.

Hi @artem-nefedov Are you suggesting some on the CRD? e.g. maybe adding something to the 'Uninstall' element of 'HelmRelease'?

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @hiddeco
Thats for your feedback.

I dont think Helm itself supports changing the helm release name, namespace or storage namespace and, as you state yourself, this might require an uninstall anyway. The proposed scope of chart name changes only I believe is consistent with what Helm supports. I'd be concerned about the complexity of implementing this for other changes particularly if there isnt anybody looking for it. Having said that, I am happy to work on it if you feel its the way to go, but I would need your advice on how it should be implemented.

In relation to the default storageNamespace. If I understand you correctly, you are saying it would be better for it to default to targetNamespace and this change should be controlled by a feature gate? I am happy to implement such a change, but would it be better in a separate PR as its not directly related to this proposal?

@artem-nefedov

Copy link
Copy Markdown

Hi @artem-nefedov Are you suggesting some on the CRD? e.g. maybe adding something to the 'Uninstall' element of 'HelmRelease'?

Sorry for the delayed reply. Yes, I meant something like this, only rather than 'Uninstall', I think the better place is 'Upgrade'. For example:

spec:
  upgrade:
    chartNameChangePolicy: InPlaceUpdate # or "Reinstall" (default)

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @hiddeco
If you get a chance to look at my replay above and let me know how you would like to proceed that would be great, thanks

@hiddeco

hiddeco commented Apr 24, 2026

Copy link
Copy Markdown
Member

I would be okay with:

spec:
  upgrade:
    onChartNameChange: InPlaceUpdate # or "Reinstall" (default)

(or Upgrade and Reinstall).

@matheuscscp

Copy link
Copy Markdown
Member

I would be okay with:

spec:
  upgrade:
    onChartNameChange: InPlaceUpdate # or "Reinstall" (default)

I think we have a tendency to use somethingStrategy

@hiddeco

hiddeco commented Apr 24, 2026

Copy link
Copy Markdown
Member

That would also work for me. In any case, I am fine with allowing this to be defined at HelmRelease object level.

@MichaelMorrisEst
MichaelMorrisEst force-pushed the issue-870 branch 2 times, most recently from 14b2719 to cc70c6e Compare April 25, 2026 23:22
Reinstall: Reinstall the Helm release, uninstalling the existing Helm release.

InPlaceUpdate: Update the Helm release in place.
type: string

@artem-nefedov artem-nefedov Apr 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

should have enum with allowed values

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread api/v2/helmrelease_types.go
Comment thread api/v2/helmrelease_types.go Outdated
// Update the Helm release in place.
InPlaceUpdate ChartNameChangeStrategy = "InPlaceUpdate"
// Reinstall the Helm release, uninstalling the existing Helm release
Reinstall ChartNameChangeStrategy = "Reinstall"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

consider prefixing names with a type

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @artem-nefedov @hiddeco
Just checking if you have any further comments on this PR or if you happy with the updates

// previous release target first. If we did not do this, the installation would
// fail due to resources already existing.
if reason, changed := action.ReleaseTargetChanged(obj, loadedChart.Name()); changed {
if reason, changed := action.ReleaseTargetChanged(obj, loadedChart.Name()); changed && (reason != action.TargetChartName || obj.Spec.Upgrade.ChartNameChangeStrategy == v2.ChartNameChangeStrategyReinstall) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This condition explicitly checks for "Reinstall", but I don't understand where default value is supposed to be set as "Reinstall".
Is there a test to confirm the default behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My bad, the setting of the default value got lost when I switched from feature gate to resource level setting. Added back in now and test to validate

Comment thread internal/action/verify.go Outdated
TargetStorageNamespace = "storageNamespace"
TargetReleaseNamespace = "releaseNamespace"
TargetReleaseName = "releaseName"
TargetChartName = "chartName"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It looks like those are also used as a part of human-readable log message, so I don't know if it is correct to change the format.
The maintainers can decide.
I don't see any more obvious problems with the PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well pointed, I think we can just make the symbols public so the calling code can use them, but since they are used in a log I think we need to keep the literals as they are.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @hiddeco, @matheuscscp
If you can spare some time to review that would be great

@matheuscscp matheuscscp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread api/v2/helmrelease_types.go Outdated
Comment on lines +797 to +800
// Update the Helm release in place.
ChartNameChangeStrategyInPlaceUpdate ChartNameChangeStrategy = "InPlaceUpdate"
// Reinstall the Helm release, uninstalling the existing Helm release
ChartNameChangeStrategyReinstall ChartNameChangeStrategy = "Reinstall"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Go standard for comments on symbols is starting the comment with the symbol name and add full stop (.) at the end.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread internal/action/verify.go Outdated
TargetStorageNamespace = "storageNamespace"
TargetReleaseNamespace = "releaseNamespace"
TargetReleaseName = "releaseName"
TargetChartName = "chartName"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well pointed, I think we can just make the symbols public so the calling code can use them, but since they are used in a log I think we need to keep the literals as they are.

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

@MichaelMorrisEst Please add a few tests here: https://github.com/fluxcd/helm-controller/blob/main/.github/workflows/e2e.yaml

Hi @matheuscscp In order to add tests there I would need a renamed version of podinfo chart somewhere. Do you think it would be ok to add something to the pofinfo repo (or create a new repo?), or do you see some other approach?

@matheuscscp

Copy link
Copy Markdown
Member

@MichaelMorrisEst Please add a few tests here: https://github.com/fluxcd/helm-controller/blob/main/.github/workflows/e2e.yaml

Hi @matheuscscp In order to add tests there I would need a renamed version of podinfo chart somewhere. Do you think it would be ok to add something to the pofinfo repo (or create a new repo?), or do you see some other approach?

@MichaelMorrisEst You can do it like the CRD tests at the end, they run from a chart managed in this repo.

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @matheuscscp do you have any further comments?

@matheuscscp matheuscscp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! 🚀

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Thanks @matheuscscp for taking the time to review. Do you think it will be possible to get this merged in time to be included in the upcoming Flux 2.9 release?

@matheuscscp

Copy link
Copy Markdown
Member

Depends on another maintainer stamping the PR

@MichaelMorrisEst

Copy link
Copy Markdown
Contributor Author

Hi @stefanprodan @hiddeco if you could spare some time to review it would be much appreciated. It would be great to get this in Flux 2.9 if possible.

Comment thread api/v2/helmrelease_types.go
@stefanprodan

Copy link
Copy Markdown
Member

Please rebase with upstream main branch and force push.

This re-introduces support that was lost going from 2.1.x -> 2.2.x but controls the behaviour through a feature gate so either the previous or current behaviour (default) can be achieved

Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>
The newly added tests to e2e depend on local helm charts being installed, which is done in "Bootstrap Tests Using Local Helm Chart". However a condition exists on that step and on the already existing test cases that depend on it because that step cannot be run on a PR from a fork as the fork branch wont exist in the base repo.
Therefore the same condition needs to be placed on the newly added tests that also depend on that step.

Signed-off-by: MichaelMorris <michael.morris@est.tech>
Signed-off-by: MichaelMorris <michael.morris@est.tech>

@stefanprodan stefanprodan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Thanks @MichaelMorrisEst 🏅

@matheuscscp matheuscscp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! 🚀

@matheuscscp
matheuscscp merged commit a644069 into fluxcd:main Jun 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't change chart name without triggering uninstall (flux 2.2.x)

5 participants