Skip to content

Commit 21c7628

Browse files
authored
Merge pull request #1700 from gianlucam76/helm-chart-v3
Add support for Helm chart API version v3
2 parents 3381607 + 43c63c7 commit 21c7628

2 files changed

Lines changed: 60 additions & 38 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ deploy-projectsveltos: $(KUSTOMIZE) $(ENVSUBST) $(KUBECTL)
426426

427427
@echo 'Install libsveltos CRDs'
428428
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_debuggingconfigurations.lib.projectsveltos.io.yaml
429+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifiers.lib.projectsveltos.io.yaml
429430
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_resourcesummaries.lib.projectsveltos.io.yaml
430431
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_sveltosclusters.lib.projectsveltos.io.yaml
431432
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_clustersets.lib.projectsveltos.io.yaml

controllers/handlers_helm.go

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ import (
5151
"helm.sh/helm/v4/pkg/action"
5252
chartbase "helm.sh/helm/v4/pkg/chart"
5353
"helm.sh/helm/v4/pkg/chart/common"
54+
chartloader "helm.sh/helm/v4/pkg/chart/loader"
5455
chart "helm.sh/helm/v4/pkg/chart/v2"
55-
"helm.sh/helm/v4/pkg/chart/v2/loader"
5656
"helm.sh/helm/v4/pkg/cli"
5757
"helm.sh/helm/v4/pkg/downloader"
5858
"helm.sh/helm/v4/pkg/getter"
@@ -99,6 +99,7 @@ const (
9999
notInstalledMessage = "Not installed yet and action is uninstall"
100100
defaultMaxHistory = 2
101101
defaultDeletionPropagation = "background"
102+
defaultChartVersion = "0.1.0"
102103
)
103104

104105
type registryClientOptions struct {
@@ -1606,9 +1607,15 @@ func repoAddOrUpdate(settings *cli.EnvSettings, name, repoURL string, registryOp
16061607
return nil
16071608
}
16081609

1609-
func getChartVersion(requestedChart *configv1beta1.HelmChart, chartRequested *chart.Chart) string {
1610+
func getChartVersion(requestedChart *configv1beta1.HelmChart, chartRequested chartbase.Charter) string {
16101611
if requestedChart.ChartVersion == "" && isReferencingFluxSource(requestedChart) {
1611-
return chartRequested.AppVersion()
1612+
if ac, err := chartbase.NewAccessor(chartRequested); err == nil {
1613+
if meta := ac.MetadataAsMap(); meta != nil {
1614+
if appVersion, ok := meta["AppVersion"].(string); ok {
1615+
return appVersion
1616+
}
1617+
}
1618+
}
16121619
}
16131620

16141621
return requestedChart.ChartVersion
@@ -1716,15 +1723,15 @@ func locateChartWithCacheRetry(
17161723

17171724
func locateLoadAndValidateChart(chartName string, settings *cli.EnvSettings, requestedChart *configv1beta1.HelmChart,
17181725
registryOptions *registryClientOptions, installClient *action.Install, logger logr.Logger,
1719-
) (*chart.Chart, error) {
1726+
) (chartbase.Charter, error) {
17201727

17211728
cp, err := locateChartWithCacheRetry(installClient.LocateChart, chartName, settings,
17221729
requestedChart, registryOptions, logger)
17231730
if err != nil {
17241731
return nil, err
17251732
}
17261733

1727-
chartRequested, err := loader.Load(cp)
1734+
chartRequested, err := chartloader.Load(cp)
17281735
if err != nil {
17291736
logger.V(logs.LogDebug).Info("Load failed")
17301737
return nil, err
@@ -1744,20 +1751,20 @@ func locateLoadAndValidateChart(chartName string, settings *cli.EnvSettings, req
17441751
}
17451752

17461753
// Reload the chart with the updated Chart.lock file.
1747-
if chartRequested, err = loader.Load(cp); err != nil {
1754+
if chartRequested, err = chartloader.Load(cp); err != nil {
17481755
return nil, fmt.Errorf("%w: failed reloading chart after repo update", err)
17491756
}
17501757

17511758
return chartRequested, nil
17521759
}
17531760

1754-
func checkDependencies(chartRequested *chart.Chart, installClient *action.Install, cp string, settings *cli.EnvSettings) error {
1755-
if req := chartRequested.Metadata.Dependencies; req != nil {
1756-
deps := make([]chartbase.Dependency, len(req))
1757-
for i, d := range req {
1758-
deps[i] = d
1759-
}
1760-
err := action.CheckDependencies(chartRequested, deps)
1761+
func checkDependencies(chartRequested chartbase.Charter, installClient *action.Install, cp string, settings *cli.EnvSettings) error {
1762+
ac, err := chartbase.NewAccessor(chartRequested)
1763+
if err != nil {
1764+
return err
1765+
}
1766+
if req := ac.MetaDependencies(); len(req) > 0 {
1767+
err := action.CheckDependencies(chartRequested, req)
17611768
if err != nil {
17621769
if installClient.DependencyUpdate {
17631770
man := &downloader.Manager{
@@ -1899,7 +1906,7 @@ func upgradeRelease(ctx context.Context, clusterSummary *configv1beta1.ClusterSu
18991906
return nil, err
19001907
}
19011908

1902-
chartRequested, err := loader.Load(cp)
1909+
chartRequested, err := chartloader.Load(cp)
19031910
if err != nil {
19041911
return nil, err
19051912
}
@@ -1967,16 +1974,21 @@ func handleUpgradeError(ctx context.Context, err error, clusterSummary *configv1
19671974

19681975
// prepareChartAndDependencies ensures chart dependencies are present and metadata is valid.
19691976
func prepareChartAndDependencies(
1970-
chartRequested *chart.Chart,
1977+
chartRequested chartbase.Charter,
19711978
requestedChart *configv1beta1.HelmChart,
19721979
chartPath string,
19731980
settings *cli.EnvSettings,
19741981
registryOptions *registryClientOptions,
19751982
logger logr.Logger,
1976-
) (*chart.Chart, error) {
1983+
) (chartbase.Charter, error) {
19771984

1978-
req := chartRequested.Metadata.Dependencies
1979-
if req == nil {
1985+
ac, err := chartbase.NewAccessor(chartRequested)
1986+
if err != nil {
1987+
return nil, err
1988+
}
1989+
1990+
req := ac.MetaDependencies()
1991+
if len(req) == 0 {
19801992
return chartRequested, nil
19811993
}
19821994

@@ -1986,11 +1998,7 @@ func prepareChartAndDependencies(
19861998
return nil, fmt.Errorf("failed to get registry client: %w", err)
19871999
}
19882000

1989-
deps := make([]chartbase.Dependency, len(req))
1990-
for i, d := range req {
1991-
deps[i] = d
1992-
}
1993-
if err := action.CheckDependencies(chartRequested, deps); err != nil {
2001+
if err := action.CheckDependencies(chartRequested, req); err != nil {
19942002
logger.V(logs.LogInfo).Info("Dependencies missing or out of date, attempting to fetch")
19952003

19962004
man := &downloader.Manager{
@@ -2007,23 +2015,33 @@ func prepareChartAndDependencies(
20072015
return nil, fmt.Errorf("failed to update dependencies: %w", err)
20082016
}
20092017

2010-
chartRequested, err = loader.Load(chartPath)
2018+
chartRequested, err = chartloader.Load(chartPath)
20112019
if err != nil {
20122020
logger.V(logs.LogDebug).Info("standard loader failed, trying LoadDir", "err", err)
2013-
chartRequested, err = loader.LoadDir(chartPath)
2021+
chartRequested, err = chartloader.LoadDir(chartPath)
20142022
if err != nil {
20152023
return nil, fmt.Errorf("failed to reload chart: %w", err)
20162024
}
20172025
}
2026+
2027+
// Refresh accessor after reload.
2028+
ac, err = chartbase.NewAccessor(chartRequested)
2029+
if err != nil {
2030+
return nil, err
2031+
}
20182032
}
20192033

2020-
if chartRequested.Metadata.Version == "" || !isValidSemver(chartRequested.Metadata.Version) {
2021-
logger.V(logs.LogInfo).Info("fixing invalid or empty chart version", "oldVersion",
2022-
chartRequested.Metadata.Version)
2023-
chartRequested.Metadata.Version = "0.1.0"
2034+
version, _ := ac.MetadataAsMap()["Version"].(string)
2035+
if version == "" || !isValidSemver(version) {
2036+
logger.V(logs.LogInfo).Info("fixing invalid or empty chart version", "oldVersion", version)
2037+
// For v2 charts, mutate version in-place so the release uses the corrected value.
2038+
if v2ch, ok := chartRequested.(*chart.Chart); ok {
2039+
v2ch.Metadata.Version = defaultChartVersion
2040+
}
2041+
version = defaultChartVersion
20242042
}
20252043

2026-
requestedChart.ChartVersion = chartRequested.Metadata.Version
2044+
requestedChart.ChartVersion = version
20272045

20282046
return chartRequested, nil
20292047
}
@@ -2220,13 +2238,12 @@ func actionConfigInit(namespace, kubeconfig string, registryOptions *registryCli
22202238
return actionConfig, nil
22212239
}
22222240

2223-
func isChartInstallable(ch *chart.Chart) bool {
2224-
switch ch.Metadata.Type {
2225-
case "", "application":
2226-
return true
2241+
func isChartInstallable(ch chartbase.Charter) bool {
2242+
ac, err := chartbase.NewAccessor(ch)
2243+
if err != nil {
2244+
return false
22272245
}
2228-
2229-
return false
2246+
return !ac.IsLibraryChart()
22302247
}
22312248

22322249
func getCurrentRelease(releaseName, releaseNamespace, kubeconfig string, registryOptions *registryClientOptions,
@@ -5128,9 +5145,13 @@ func isValidSemver(v string) bool {
51285145
return err == nil
51295146
}
51305147

5131-
func getCRDObjects(ch *chart.Chart) []chart.CRD {
5148+
func getCRDObjects(ch chartbase.Charter) []chart.CRD {
5149+
ac, err := chartbase.NewAccessor(ch)
5150+
if err != nil {
5151+
return nil
5152+
}
51325153
var crds []chart.CRD
5133-
for _, f := range ch.Files {
5154+
for _, f := range ac.Files() {
51345155
// Helm expects CRDs to be in the "crds/" directory
51355156
if strings.HasPrefix(f.Name, "crds/") {
51365157
crds = append(crds, chart.CRD{

0 commit comments

Comments
 (0)