Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions pkg/helm/client/client.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package client

import (
"helm.sh/helm/v3/pkg/chart"

"github.com/flant/addon-operator/pkg/utils"
)

type HelmClient interface {
LastReleaseStatus(releaseName string) (string, string, error)
UpgradeRelease(releaseName string, chart string, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string) error
Render(releaseName string, chart string, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string, debug bool) (string, error)
UpgradeRelease(releaseName string, chart *chart.Chart, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string) error
Render(releaseName string, chart *chart.Chart, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string, debug bool) (string, error)
GetReleaseValues(releaseName string) (utils.Values, error)
GetReleaseChecksum(releaseName string) (string, error)
GetReleaseLabels(releaseName, labelName string) (string, error)
Expand Down
30 changes: 10 additions & 20 deletions pkg/helm/helm3lib/helm3lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/deckhouse/deckhouse/pkg/log"
logContext "github.com/deckhouse/deckhouse/pkg/log/context"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
Expand Down Expand Up @@ -164,15 +164,15 @@ func (h *LibClient) LastReleaseStatus(releaseName string) (string /*revision*/,
return strconv.FormatInt(int64(lastRelease.Version), 10), lastRelease.Info.Status.String(), nil
}

func (h *LibClient) UpgradeRelease(releaseName string, chartName string, valuesPaths []string, setValues []string, labels map[string]string, namespace string) error {
err := h.upgradeRelease(releaseName, chartName, valuesPaths, setValues, labels, namespace)
func (h *LibClient) UpgradeRelease(releaseName string, chart *chart.Chart, valuesPaths []string, setValues []string, labels map[string]string, namespace string) error {
err := h.upgradeRelease(releaseName, chart, valuesPaths, setValues, labels, namespace)
if err != nil {
// helm validation can fail because FeatureGate was enabled for example
// handling this case we can reinitialize kubeClient and repeat one more time by backoff
if err := actionConfigInit(h.Logger); err != nil {
return err
}
return h.upgradeRelease(releaseName, chartName, valuesPaths, setValues, labels, namespace)
return h.upgradeRelease(releaseName, chart, valuesPaths, setValues, labels, namespace)
}
h.Logger.Debug("helm release upgraded", slog.String("version", releaseName))
return nil
Expand All @@ -182,7 +182,7 @@ func (h *LibClient) hasLabelsToApply() bool {
return len(h.labels) > 0
}

func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesPaths []string, setValues []string, labels map[string]string, namespace string) error {
func (h *LibClient) upgradeRelease(releaseName string, chart *chart.Chart, valuesPaths []string, setValues []string, labels map[string]string, namespace string) error {
upg := action.NewUpgrade(actionConfig)
if namespace != "" {
upg.Namespace = namespace
Expand All @@ -197,11 +197,6 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
upg.Timeout = options.Timeout
upg.Labels = labels

chart, err := loader.Load(chartName)
if err != nil {
return err
}

var resultValues chartutil.Values

for _, vp := range valuesPaths {
Expand All @@ -226,7 +221,7 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP

h.Logger.Info("Running helm upgrade for release",
slog.String("release", releaseName),
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace))
histClient := action.NewHistory(actionConfig)
// Max is not working!!! Sort the final of releases by your own
Expand Down Expand Up @@ -312,7 +307,7 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
}
h.Logger.Info("Helm upgrade successful",
slog.String("release", releaseName),
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace))

return nil
Expand Down Expand Up @@ -451,12 +446,7 @@ func (h *LibClient) ListReleasesNames() ([]string, error) {
return releases, nil
}

func (h *LibClient) Render(releaseName, chartName string, valuesPaths, setValues []string, _ map[string]string, namespace string, debug bool) (string, error) {
chart, err := loader.Load(chartName)
if err != nil {
return "", err
}

func (h *LibClient) Render(releaseName string, chart *chart.Chart, valuesPaths, setValues []string, _ map[string]string, namespace string, debug bool) (string, error) {
var resultValues chartutil.Values

for _, vp := range valuesPaths {
Expand All @@ -480,7 +470,7 @@ func (h *LibClient) Render(releaseName, chartName string, valuesPaths, setValues
}

h.Logger.Debug("Render helm templates for chart ...",
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace))

inst := h.newDryRunInstAction(namespace, releaseName)
Expand All @@ -506,7 +496,7 @@ func (h *LibClient) Render(releaseName, chartName string, valuesPaths, setValues
rs.Manifest += fmt.Sprintf("\n\n\n%v", err)
}

h.Logger.Info("Render helm templates for chart was successful", slog.String("chart", chartName))
h.Logger.Info("Render helm templates for chart was successful", slog.String("chart", chart.Metadata.Name))

return rs.Manifest, nil
}
Expand Down
21 changes: 17 additions & 4 deletions pkg/helm/helm3lib/helm3lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/deckhouse/deckhouse/pkg/log"
. "github.com/onsi/gomega"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
kubefake "helm.sh/helm/v3/pkg/kube/fake"
Expand Down Expand Up @@ -47,7 +48,10 @@ func TestHelm3LibUpgradeDelete(t *testing.T) {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(releases).To(BeEmpty(), "should get empty list of releases")

err = cl.UpgradeRelease("test-release", "testdata/chart", nil, nil, map[string]string{"key": "value"}, cl.Namespace)
chart, err := loader.Load("testdata/chart")
g.Expect(err).ShouldNot(HaveOccurred())

err = cl.UpgradeRelease("test-release", chart, nil, nil, map[string]string{"key": "value"}, cl.Namespace)
g.Expect(err).ShouldNot(HaveOccurred())

releasesNames, err := cl.ListReleasesNames()
Expand Down Expand Up @@ -91,7 +95,10 @@ func TestReleaseExistsReturnsTrueForExistingRelease(t *testing.T) {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(releases).To(BeEmpty(), "should get empty list of releases")

err = cl.UpgradeRelease("existing-release", "testdata/chart", nil, nil, nil, cl.Namespace)
chart, err := loader.Load("testdata/chart")
g.Expect(err).ShouldNot(HaveOccurred())

err = cl.UpgradeRelease("existing-release", chart, nil, nil, nil, cl.Namespace)
g.Expect(err).ShouldNot(HaveOccurred())

releases, err = cl.ListReleases()
Expand Down Expand Up @@ -129,7 +136,10 @@ func TestDeleteReleaseRemovesExistingRelease(t *testing.T) {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(releases).To(BeEmpty(), "should get empty list of releases")

err = cl.UpgradeRelease("release-to-delete", "testdata/chart", nil, nil, nil, cl.Namespace)
chart, err := loader.Load("testdata/chart")
g.Expect(err).ShouldNot(HaveOccurred())

err = cl.UpgradeRelease("release-to-delete", chart, nil, nil, nil, cl.Namespace)
g.Expect(err).ShouldNot(HaveOccurred())

releases, err = cl.ListReleases()
Expand Down Expand Up @@ -157,7 +167,10 @@ func TestLastReleaseStatusReturnsCorrectStatusForExistingRelease(t *testing.T) {
g := NewWithT(t)
cl := initHelmClient(t)

err := cl.UpgradeRelease("status-release", "testdata/chart", nil, nil, nil, cl.Namespace)
chart, err := loader.Load("testdata/chart")
g.Expect(err).ShouldNot(HaveOccurred())

err = cl.UpgradeRelease("status-release", chart, nil, nil, nil, cl.Namespace)
g.Expect(err).ShouldNot(HaveOccurred())

revision, status, err := cl.LastReleaseStatus("status-release")
Expand Down
6 changes: 5 additions & 1 deletion pkg/helm/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/deckhouse/deckhouse/pkg/log"
. "github.com/onsi/gomega"
"helm.sh/helm/v3/pkg/chart/loader"

"github.com/flant/addon-operator/pkg/helm/helm3lib"
"github.com/flant/addon-operator/pkg/helm/nelm"
Expand Down Expand Up @@ -51,7 +52,10 @@ func TestHelmFactory(t *testing.T) {
g.Expect(err).ShouldNot(HaveOccurred())
g.Expect(isExists).Should(BeFalse(), "should not found release in the empty cluster")

err = helmCl.UpgradeRelease("test-release", "helm3lib/testdata/chart", nil, nil, nil, namespace)
chart, err := loader.Load("helm3lib/testdata/chart")
g.Expect(err).ShouldNot(HaveOccurred())

err = helmCl.UpgradeRelease("test-release", chart, nil, nil, nil, namespace)
g.Expect(err).ShouldNot(HaveOccurred())

releasesAfterUpgrade, err := helmCl.ListReleasesNames()
Expand Down
87 changes: 50 additions & 37 deletions pkg/helm/nelm/nelm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/deckhouse/deckhouse/pkg/log"
"github.com/werf/nelm/pkg/action"
nelmLog "github.com/werf/nelm/pkg/log"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -181,10 +182,10 @@ func (c *NelmClient) LastReleaseStatus(releaseName string) (string, string, erro
return strconv.FormatInt(int64(releaseGetResult.Release.Revision), 10), releaseGetResult.Release.Status.String(), nil
}

func (c *NelmClient) UpgradeRelease(releaseName, chartName string, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string) error {
func (c *NelmClient) UpgradeRelease(releaseName string, chart *chart.Chart, valuesPaths []string, setValues []string, releaseLabels map[string]string, namespace string) error {
logger := c.logger.With(
slog.String("release_name", releaseName),
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace),
)

Expand Down Expand Up @@ -219,27 +220,33 @@ func (c *NelmClient) UpgradeRelease(releaseName, chartName string, valuesPaths [
}
}

if err := c.actions.ReleaseInstall(context.TODO(), releaseName, namespace, action.ReleaseInstallOptions{
Chart: chartName,
ExtraLabels: c.labels,
ExtraAnnotations: extraAnnotations,
KubeContext: c.opts.KubeContext,
NoInstallCRDs: true,
ReleaseHistoryLimit: int(c.opts.HistoryMax),
ReleaseLabels: releaseLabels,
ReleaseStorageDriver: c.opts.HelmDriver,
Timeout: c.opts.Timeout,
ValuesFilesPaths: valuesPaths,
ValuesSets: setValues,
ForceAdoption: true,
NoPodLogs: true,
}); err != nil {
// Prepare chart options based on whether this is a virtual chart
opts := action.ReleaseInstallOptions{
Chart: chart.ChartPath(),
DefaultChartVersion: chart.Metadata.Version,
DefaultChartName: chart.Metadata.Name,
DefaultChartAPIVersion: chart.Metadata.APIVersion,
ExtraLabels: c.labels,
ExtraAnnotations: extraAnnotations,
KubeContext: c.opts.KubeContext,
NoInstallCRDs: true,
ReleaseHistoryLimit: int(c.opts.HistoryMax),
ReleaseLabels: releaseLabels,
ReleaseStorageDriver: c.opts.HelmDriver,
Timeout: c.opts.Timeout,
ValuesFilesPaths: valuesPaths,
ValuesSets: setValues,
ForceAdoption: true,
NoPodLogs: true,
}

if err = c.actions.ReleaseInstall(context.TODO(), releaseName, namespace, opts); err != nil {
return fmt.Errorf("install nelm release %q: %w", releaseName, err)
}

logger.Info("Nelm upgrade successful",
slog.String("release", releaseName),
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace))

return nil
Expand Down Expand Up @@ -360,9 +367,9 @@ func (c *NelmClient) ListReleasesNames() ([]string, error) {
return releaseNames, nil
}

func (c *NelmClient) Render(releaseName, chartName string, valuesPaths, setValues []string, releaseLabels map[string]string, namespace string, debug bool) (string, error) {
func (c *NelmClient) Render(releaseName string, chart *chart.Chart, valuesPaths, setValues []string, releaseLabels map[string]string, namespace string, debug bool) (string, error) {
c.logger.Debug("Render nelm templates for chart ...",
slog.String("chart", chartName),
slog.String("chart", chart.Metadata.Name),
slog.String("namespace", namespace))

// Add client annotations
Expand All @@ -377,28 +384,34 @@ func (c *NelmClient) Render(releaseName, chartName string, valuesPaths, setValue
extraAnnotations["maintenance.deckhouse.io/no-resource-reconciliation"] = ""
}

chartRenderResult, err := c.actions.ChartRender(context.TODO(), action.ChartRenderOptions{
OutputFilePath: "/dev/null", // No output file, we want to return the manifest as a string
Chart: chartName,
ExtraLabels: c.labels,
ExtraAnnotations: extraAnnotations,
KubeContext: c.opts.KubeContext,
ReleaseName: releaseName,
ReleaseNamespace: namespace,
ReleaseStorageDriver: c.opts.HelmDriver,
Remote: true,
ValuesFilesPaths: valuesPaths,
ValuesSets: setValues,
ForceAdoption: true,
})
// Prepare chart render options based on whether this is a virtual chart
renderOpts := action.ChartRenderOptions{
Chart: chart.ChartPath(),
DefaultChartAPIVersion: chart.Metadata.APIVersion,
DefaultChartName: chart.Metadata.Name,
DefaultChartVersion: chart.Metadata.Version,
OutputFilePath: "/dev/null", // No output file, we want to return the manifest as a string
ExtraLabels: c.labels,
ExtraAnnotations: extraAnnotations,
KubeContext: c.opts.KubeContext,
ReleaseName: releaseName,
ReleaseNamespace: namespace,
ReleaseStorageDriver: c.opts.HelmDriver,
Remote: true,
ValuesFilesPaths: valuesPaths,
ValuesSets: setValues,
ForceAdoption: true,
}

chartRenderResult, err := c.actions.ChartRender(context.TODO(), renderOpts)
if err != nil {
if !debug {
return "", fmt.Errorf("render nelm chart %q: %w\n\nUse --debug flag to render out invalid YAML", chartName, err)
return "", fmt.Errorf("render nelm chart %q: %w\n\nUse --debug flag to render out invalid YAML", chart.Metadata.Name, err)
}
return "", fmt.Errorf("render nelm chart %q: %w", chartName, err)
return "", fmt.Errorf("render nelm chart %q: %w", chart.Metadata.Name, err)
}

c.logger.Info("Render nelm templates for chart was successful", slog.String("chart", chartName))
c.logger.Info("Render nelm templates for chart was successful", slog.String("chart", chart.Metadata.Name))

var result strings.Builder
for _, resource := range chartRenderResult.Resources {
Expand Down
Loading
Loading