feat: add version-aware helm chart upgrade callbacks

Some helm chart upgrades require side-effects that a plain `helm upgrade` cannot perform, such as deleting deployments whose immutable selectors changed. Charts may now register pre and post upgrade hooks against a target version; applicable hooks fire in ascending semver order, each bracketed around an upgrade to its version, with a final upgrade to the chart's configured version when needed. The new `keda-add-ons-http` 0.12.2 hook deletes the chart-managed deployments before the upgrade so the new selectors take effect cleanly.
This commit is contained in:
Jose Diaz-Gonzalez
2026-04-27 07:57:38 -04:00
parent db1308a2ab
commit da13367ca8
5 changed files with 370 additions and 10 deletions

View File

@@ -1679,17 +1679,57 @@ func installHelmCharts(ctx context.Context, clientset KubernetesClient, shouldIn
return fmt.Errorf("Error parsing deploy timeout duration: %w", err)
}
err = helmAgent.InstallOrUpgradeChart(ctx, ChartInput{
ChartPath: chart.ChartPath,
Namespace: chart.Namespace,
ReleaseName: chart.ReleaseName,
RepoURL: chart.RepoURL,
Values: values,
Version: chart.Version,
Timeout: timeoutDuration,
Wait: true,
})
installedRevision, err := helmAgent.InstalledRevision(chart.ReleaseName)
if err != nil {
return fmt.Errorf("Error getting installed revision for %s: %w", chart.ReleaseName, err)
}
hooks, err := selectChartHooks(chart.ReleaseName, installedRevision.Version, chart.Version)
if err != nil {
return fmt.Errorf("Error selecting upgrade hooks for chart %s: %w", chart.ReleaseName, err)
}
buildChartInput := func(version string) ChartInput {
return ChartInput{
ChartPath: chart.ChartPath,
Namespace: chart.Namespace,
ReleaseName: chart.ReleaseName,
RepoURL: chart.RepoURL,
Values: values,
Version: version,
Timeout: timeoutDuration,
Wait: true,
}
}
lastUpgradedVersion := ""
for _, hook := range hooks {
if hook.PreUpgrade != nil {
common.LogVerbose(fmt.Sprintf("Running pre-upgrade hook %s@%s", chart.ReleaseName, hook.TargetVersion))
if err := hook.PreUpgrade(ctx, clientset, chart, installedRevision); err != nil {
return fmt.Errorf("Error running pre-upgrade hook for %s@%s: %w", chart.ReleaseName, hook.TargetVersion, err)
}
}
common.LogVerbose(fmt.Sprintf("Upgrading %s to intermediate version %s", chart.ReleaseName, hook.TargetVersion))
if err := helmAgent.InstallOrUpgradeChart(ctx, buildChartInput(hook.TargetVersion)); err != nil {
return fmt.Errorf("Error installing chart %s at version %s: %w", chart.ChartPath, hook.TargetVersion, err)
}
lastUpgradedVersion = hook.TargetVersion
if hook.PostUpgrade != nil {
common.LogVerbose(fmt.Sprintf("Running post-upgrade hook %s@%s", chart.ReleaseName, hook.TargetVersion))
if err := hook.PostUpgrade(ctx, clientset, chart, installedRevision); err != nil {
return fmt.Errorf("Error running post-upgrade hook for %s@%s: %w", chart.ReleaseName, hook.TargetVersion, err)
}
}
}
if lastUpgradedVersion == chart.Version {
continue
}
if err := helmAgent.InstallOrUpgradeChart(ctx, buildChartInput(chart.Version)); err != nil {
return fmt.Errorf("Error installing chart %s: %w", chart.ChartPath, err)
}
}