action: allow passing of config options

This to allow the Flux CLI to e.g. enable the dry-run flag on an action
outside of the HelmRelease spec, and inject other (user input based)
modifications.

Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
Hidde Beydals 2022-07-06 14:53:16 +02:00 committed by Hidde Beydals
parent 220e789481
commit 5843cc2ef0
No known key found for this signature in database
GPG Key ID: 979F380FC2341744
11 changed files with 611 additions and 57 deletions

View File

@ -30,6 +30,11 @@ import (
"github.com/fluxcd/helm-controller/internal/postrender"
)
// InstallOption can be used to modify Helm's action.Install after the instructions
// from the v2beta2.HelmRelease have been applied. This is for example useful to
// enable the dry-run setting as a CLI.
type InstallOption func(action *helmaction.Install)
// Install runs the Helm install action with the provided config, using the
// v2beta2.HelmReleaseSpec of the given object to determine the target release
// and rollback configuration.
@ -42,12 +47,8 @@ import (
// action result. The caller is expected to listen to this using a
// storage.ObserveFunc, which provides superior access to Helm storage writes.
func Install(ctx context.Context, config *helmaction.Configuration, obj *v2.HelmRelease,
chrt *helmchart.Chart, vals helmchartutil.Values) (*helmrelease.Release, error) {
install, err := newInstall(config, obj)
if err != nil {
return nil, err
}
chrt *helmchart.Chart, vals helmchartutil.Values, opts ...InstallOption) (*helmrelease.Release, error) {
install := newInstall(config, obj, opts)
policy, err := crdPolicyOrDefault(obj.Spec.GetInstall().CRDs)
if err != nil {
@ -60,7 +61,7 @@ func Install(ctx context.Context, config *helmaction.Configuration, obj *v2.Helm
return install.RunWithContext(ctx, chrt, vals.AsMap())
}
func newInstall(config *helmaction.Configuration, obj *v2.HelmRelease) (*helmaction.Install, error) {
func newInstall(config *helmaction.Configuration, obj *v2.HelmRelease, opts []InstallOption) *helmaction.Install {
install := helmaction.NewInstall(config)
install.ReleaseName = obj.GetReleaseName()
@ -83,11 +84,11 @@ func newInstall(config *helmaction.Configuration, obj *v2.HelmRelease) (*helmact
install.EnableDNS = allowDNS
}
renderer, err := postrender.BuildPostRenderers(obj)
if err != nil {
return nil, err
}
install.PostRenderer = renderer
install.PostRenderer = postrender.BuildPostRenderers(obj)
return install, nil
for _, opt := range opts {
opt(install)
}
return install
}

View File

@ -0,0 +1,97 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
. "github.com/onsi/gomega"
helmaction "helm.sh/helm/v3/pkg/action"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
func Test_newInstall(t *testing.T) {
t.Run("new install", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "install",
Namespace: "install-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
Install: &v2.Install{
Timeout: &metav1.Duration{Duration: 10 * time.Second},
Replace: true,
},
},
}
got := newInstall(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Install.Timeout.Duration))
g.Expect(got.Replace).To(Equal(obj.Spec.Install.Replace))
})
t.Run("timeout fallback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "install",
Namespace: "install-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
},
}
got := newInstall(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Timeout.Duration))
})
t.Run("applies options", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "install",
Namespace: "install-ns",
},
Spec: v2.HelmReleaseSpec{},
}
got := newInstall(&helmaction.Configuration{}, obj, []InstallOption{
func(install *helmaction.Install) {
install.Atomic = true
},
func(install *helmaction.Install) {
install.DryRun = true
},
})
g.Expect(got).ToNot(BeNil())
g.Expect(got.Atomic).To(BeTrue())
g.Expect(got.DryRun).To(BeTrue())
})
}

View File

@ -22,6 +22,11 @@ import (
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
// RollbackOption can be used to modify Helm's action.Rollback after the
// instructions from the v2beta2.HelmRelease have been applied. This is for
// example useful to enable the dry-run setting as a CLI.
type RollbackOption func(*helmaction.Rollback)
// Rollback runs the Helm rollback action with the provided config, using the
// v2beta2.HelmReleaseSpec of the given object to determine the target release
// and rollback configuration.
@ -30,25 +35,29 @@ import (
// expected to be done by the caller. In addition, it does not take note of the
// action result. The caller is expected to listen to this using a
// storage.ObserveFunc, which provides superior access to Helm storage writes.
func Rollback(config *helmaction.Configuration, obj *v2.HelmRelease) error {
rollback := newRollback(config, obj)
func Rollback(config *helmaction.Configuration, obj *v2.HelmRelease, opts ...RollbackOption) error {
rollback := newRollback(config, obj, opts)
return rollback.Run(obj.GetReleaseName())
}
func newRollback(config *helmaction.Configuration, rel *v2.HelmRelease) *helmaction.Rollback {
func newRollback(config *helmaction.Configuration, obj *v2.HelmRelease, opts []RollbackOption) *helmaction.Rollback {
rollback := helmaction.NewRollback(config)
rollback.Timeout = rel.Spec.GetRollback().GetTimeout(rel.GetTimeout()).Duration
rollback.Wait = !rel.Spec.GetRollback().DisableWait
rollback.WaitForJobs = !rel.Spec.GetRollback().DisableWaitForJobs
rollback.DisableHooks = rel.Spec.GetRollback().DisableHooks
rollback.Force = rel.Spec.GetRollback().Force
rollback.Recreate = rel.Spec.GetRollback().Recreate
rollback.CleanupOnFail = rel.Spec.GetRollback().CleanupOnFail
rollback.Timeout = obj.Spec.GetRollback().GetTimeout(obj.GetTimeout()).Duration
rollback.Wait = !obj.Spec.GetRollback().DisableWait
rollback.WaitForJobs = !obj.Spec.GetRollback().DisableWaitForJobs
rollback.DisableHooks = obj.Spec.GetRollback().DisableHooks
rollback.Force = obj.Spec.GetRollback().Force
rollback.Recreate = obj.Spec.GetRollback().Recreate
rollback.CleanupOnFail = obj.Spec.GetRollback().CleanupOnFail
if prev := rel.Status.Previous; prev != nil && prev.Name == rel.GetReleaseName() && prev.Namespace == rel.GetReleaseNamespace() {
if prev := obj.Status.Previous; prev != nil && prev.Name == obj.GetReleaseName() && prev.Namespace == obj.GetReleaseNamespace() {
rollback.Version = prev.Version
}
for _, opt := range opts {
opt(rollback)
}
return rollback
}

View File

@ -0,0 +1,139 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
. "github.com/onsi/gomega"
helmaction "helm.sh/helm/v3/pkg/action"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
func Test_newRollback(t *testing.T) {
t.Run("new rollback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "rollback",
Namespace: "rollback-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
Rollback: &v2.Rollback{
Timeout: &metav1.Duration{Duration: 10 * time.Second},
Force: true,
},
},
}
got := newRollback(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Timeout).To(Equal(obj.Spec.Rollback.Timeout.Duration))
g.Expect(got.Force).To(Equal(obj.Spec.Rollback.Force))
})
t.Run("rollback with previous", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "rollback",
Namespace: "rollback-ns",
},
Status: v2.HelmReleaseStatus{
Previous: &v2.HelmReleaseInfo{
Name: "rollback",
Namespace: "rollback-ns",
Version: 3,
},
},
}
got := newRollback(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Version).To(Equal(obj.Status.Previous.Version))
})
t.Run("rollback with stale previous", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "rollback",
Namespace: "rollback-ns",
},
Status: v2.HelmReleaseStatus{
Previous: &v2.HelmReleaseInfo{
Name: "rollback",
Namespace: "other-ns",
Version: 3,
},
},
}
got := newRollback(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Version).To(BeZero())
})
t.Run("timeout fallback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "rollback",
Namespace: "rollback-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
},
}
got := newRollback(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Timeout).To(Equal(obj.Spec.Timeout.Duration))
})
t.Run("applies options", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "rollback",
Namespace: "rollback-ns",
},
Spec: v2.HelmReleaseSpec{},
}
got := newRollback(&helmaction.Configuration{}, obj, []RollbackOption{
func(rollback *helmaction.Rollback) {
rollback.CleanupOnFail = true
},
func(rollback *helmaction.Rollback) {
rollback.DryRun = true
},
})
g.Expect(got).ToNot(BeNil())
g.Expect(got.CleanupOnFail).To(BeTrue())
g.Expect(got.DryRun).To(BeTrue())
})
}

View File

@ -25,6 +25,11 @@ import (
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
// TestOption can be used to modify Helm's action.ReleaseTesting after the
// instructions from the v2beta2.HelmRelease have been applied. This is for
// example useful to enable the dry-run setting as a CLI.
type TestOption func(action *helmaction.ReleaseTesting)
// Test runs the Helm test action with the provided config, using the
// v2beta2.HelmReleaseSpec of the given object to determine the target release
// and test configuration.
@ -33,16 +38,20 @@ import (
// expected to be done by the caller. In addition, it does not take note of the
// action result. The caller is expected to listen to this using a
// storage.ObserveFunc, which provides superior access to Helm storage writes.
func Test(_ context.Context, config *helmaction.Configuration, obj *v2.HelmRelease) (*helmrelease.Release, error) {
test := newTest(config, obj)
func Test(_ context.Context, config *helmaction.Configuration, obj *v2.HelmRelease, opts ...TestOption) (*helmrelease.Release, error) {
test := newTest(config, obj, opts)
return test.Run(obj.GetReleaseName())
}
func newTest(config *helmaction.Configuration, obj *v2.HelmRelease) *helmaction.ReleaseTesting {
func newTest(config *helmaction.Configuration, obj *v2.HelmRelease, opts []TestOption) *helmaction.ReleaseTesting {
test := helmaction.NewReleaseTesting(config)
test.Namespace = obj.GetReleaseNamespace()
test.Timeout = obj.Spec.GetTest().GetTimeout(obj.GetTimeout()).Duration
for _, opt := range opts {
opt(test)
}
return test
}

View File

@ -0,0 +1,96 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
. "github.com/onsi/gomega"
helmaction "helm.sh/helm/v3/pkg/action"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
func Test_newTest(t *testing.T) {
t.Run("new test", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
Test: &v2.Test{
Timeout: &metav1.Duration{Duration: 10 * time.Second},
},
},
}
got := newTest(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Test.Timeout.Duration))
})
t.Run("timeout fallback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
},
}
got := newTest(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Timeout.Duration))
})
t.Run("applies options", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test-ns",
},
Spec: v2.HelmReleaseSpec{},
}
got := newTest(&helmaction.Configuration{}, obj, []TestOption{
func(test *helmaction.ReleaseTesting) {
test.Filters = map[string][]string{
"test": {"test"},
}
},
func(test *helmaction.ReleaseTesting) {
test.Filters["test2"] = []string{"test2"}
},
})
g.Expect(got).ToNot(BeNil())
g.Expect(got.Filters).To(HaveLen(2))
})
}

View File

@ -25,6 +25,11 @@ import (
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
// UninstallOption can be used to modify Helm's action.Uninstall after the
// instructions from the v2beta2.HelmRelease have been applied. This is for
// example useful to enable the dry-run setting as a CLI.
type UninstallOption func(*helmaction.Uninstall)
// Uninstall runs the Helm uninstall action with the provided config, using the
// v2beta2.HelmReleaseSpec of the given object to determine the target release
// and uninstall configuration.
@ -33,12 +38,12 @@ import (
// expected to be done by the caller. In addition, it does not take note of the
// action result. The caller is expected to listen to this using a
// storage.ObserveFunc, which provides superior access to Helm storage writes.
func Uninstall(ctx context.Context, config *helmaction.Configuration, obj *v2.HelmRelease) (*helmrelease.UninstallReleaseResponse, error) {
uninstall := newUninstall(config, obj)
func Uninstall(_ context.Context, config *helmaction.Configuration, obj *v2.HelmRelease, opts ...UninstallOption) (*helmrelease.UninstallReleaseResponse, error) {
uninstall := newUninstall(config, obj, opts)
return uninstall.Run(obj.GetReleaseName())
}
func newUninstall(config *helmaction.Configuration, obj *v2.HelmRelease) *helmaction.Uninstall {
func newUninstall(config *helmaction.Configuration, obj *v2.HelmRelease, opts []UninstallOption) *helmaction.Uninstall {
uninstall := helmaction.NewUninstall(config)
uninstall.Timeout = obj.Spec.GetUninstall().GetTimeout(obj.GetTimeout()).Duration
@ -46,5 +51,9 @@ func newUninstall(config *helmaction.Configuration, obj *v2.HelmRelease) *helmac
uninstall.KeepHistory = obj.Spec.GetUninstall().KeepHistory
uninstall.Wait = !obj.Spec.GetUninstall().DisableWait
for _, opt := range opts {
opt(uninstall)
}
return uninstall
}

View File

@ -0,0 +1,95 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
. "github.com/onsi/gomega"
helmaction "helm.sh/helm/v3/pkg/action"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
func Test_newUninstall(t *testing.T) {
t.Run("new uninstall", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "uninstall",
Namespace: "uninstall-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
Uninstall: &v2.Uninstall{
Timeout: &metav1.Duration{Duration: 10 * time.Second},
KeepHistory: true,
},
},
}
got := newUninstall(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Timeout).To(Equal(obj.Spec.Uninstall.Timeout.Duration))
g.Expect(got.KeepHistory).To(Equal(obj.Spec.Uninstall.KeepHistory))
})
t.Run("timeout fallback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "uninstall",
Namespace: "uninstall-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
},
}
got := newUninstall(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Timeout).To(Equal(obj.Spec.Timeout.Duration))
})
t.Run("applies options", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "uninstall",
Namespace: "uninstall-ns",
},
Spec: v2.HelmReleaseSpec{},
}
got := newUninstall(&helmaction.Configuration{}, obj, []UninstallOption{
func(uninstall *helmaction.Uninstall) {
uninstall.Wait = true
},
func(uninstall *helmaction.Uninstall) {
uninstall.DisableHooks = true
},
})
g.Expect(got).ToNot(BeNil())
g.Expect(got.Wait).To(BeTrue())
g.Expect(got.DisableHooks).To(BeTrue())
})
}

View File

@ -30,6 +30,11 @@ import (
"github.com/fluxcd/helm-controller/internal/postrender"
)
// UpgradeOption can be used to modify Helm's action.Upgrade after the instructions
// from the v2beta2.HelmRelease have been applied. This is for example useful to
// enable the dry-run setting as a CLI.
type UpgradeOption func(upgrade *helmaction.Upgrade)
// Upgrade runs the Helm upgrade action with the provided config, using the
// v2beta2.HelmReleaseSpec of the given object to determine the target release
// and upgrade configuration.
@ -42,11 +47,8 @@ import (
// action result. The caller is expected to listen to this using a
// storage.ObserveFunc, which provides superior access to Helm storage writes.
func Upgrade(ctx context.Context, config *helmaction.Configuration, obj *v2.HelmRelease, chrt *helmchart.Chart,
vals helmchartutil.Values) (*helmrelease.Release, error) {
upgrade, err := newUpgrade(config, obj)
if err != nil {
return nil, err
}
vals helmchartutil.Values, opts ...UpgradeOption) (*helmrelease.Release, error) {
upgrade := newUpgrade(config, obj, opts)
policy, err := crdPolicyOrDefault(obj.Spec.GetInstall().CRDs)
if err != nil {
@ -59,20 +61,20 @@ func Upgrade(ctx context.Context, config *helmaction.Configuration, obj *v2.Helm
return upgrade.RunWithContext(ctx, obj.GetReleaseName(), chrt, vals.AsMap())
}
func newUpgrade(config *helmaction.Configuration, rel *v2.HelmRelease) (*helmaction.Upgrade, error) {
func newUpgrade(config *helmaction.Configuration, obj *v2.HelmRelease, opts []UpgradeOption) *helmaction.Upgrade {
upgrade := helmaction.NewUpgrade(config)
upgrade.Namespace = rel.GetReleaseNamespace()
upgrade.ResetValues = !rel.Spec.GetUpgrade().PreserveValues
upgrade.ReuseValues = rel.Spec.GetUpgrade().PreserveValues
upgrade.MaxHistory = rel.GetMaxHistory()
upgrade.Timeout = rel.Spec.GetUpgrade().GetTimeout(rel.GetTimeout()).Duration
upgrade.Wait = !rel.Spec.GetUpgrade().DisableWait
upgrade.WaitForJobs = !rel.Spec.GetUpgrade().DisableWaitForJobs
upgrade.DisableHooks = rel.Spec.GetUpgrade().DisableHooks
upgrade.DisableOpenAPIValidation = rel.Spec.GetUpgrade().DisableOpenAPIValidation
upgrade.Force = rel.Spec.GetUpgrade().Force
upgrade.CleanupOnFail = rel.Spec.GetUpgrade().CleanupOnFail
upgrade.Namespace = obj.GetReleaseNamespace()
upgrade.ResetValues = !obj.Spec.GetUpgrade().PreserveValues
upgrade.ReuseValues = obj.Spec.GetUpgrade().PreserveValues
upgrade.MaxHistory = obj.GetMaxHistory()
upgrade.Timeout = obj.Spec.GetUpgrade().GetTimeout(obj.GetTimeout()).Duration
upgrade.Wait = !obj.Spec.GetUpgrade().DisableWait
upgrade.WaitForJobs = !obj.Spec.GetUpgrade().DisableWaitForJobs
upgrade.DisableHooks = obj.Spec.GetUpgrade().DisableHooks
upgrade.DisableOpenAPIValidation = obj.Spec.GetUpgrade().DisableOpenAPIValidation
upgrade.Force = obj.Spec.GetUpgrade().Force
upgrade.CleanupOnFail = obj.Spec.GetUpgrade().CleanupOnFail
upgrade.Devel = true
// If the user opted-in to allow DNS lookups, enable it.
@ -80,11 +82,11 @@ func newUpgrade(config *helmaction.Configuration, rel *v2.HelmRelease) (*helmact
upgrade.EnableDNS = allowDNS
}
renderer, err := postrender.BuildPostRenderers(rel)
if err != nil {
return nil, err
}
upgrade.PostRenderer = renderer
upgrade.PostRenderer = postrender.BuildPostRenderers(obj)
return upgrade, err
for _, opt := range opts {
opt(upgrade)
}
return upgrade
}

View File

@ -0,0 +1,97 @@
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
. "github.com/onsi/gomega"
helmaction "helm.sh/helm/v3/pkg/action"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "github.com/fluxcd/helm-controller/api/v2beta2"
)
func Test_newUpgrade(t *testing.T) {
t.Run("new upgrade", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "upgrade",
Namespace: "upgrade-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
Upgrade: &v2.Upgrade{
Timeout: &metav1.Duration{Duration: 10 * time.Second},
Force: true,
},
},
}
got := newUpgrade(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Upgrade.Timeout.Duration))
g.Expect(got.Force).To(Equal(obj.Spec.Upgrade.Force))
})
t.Run("timeout fallback", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "upgrade",
Namespace: "upgrade-ns",
},
Spec: v2.HelmReleaseSpec{
Timeout: &metav1.Duration{Duration: time.Minute},
},
}
got := newUpgrade(&helmaction.Configuration{}, obj, nil)
g.Expect(got).ToNot(BeNil())
g.Expect(got.Namespace).To(Equal(obj.Namespace))
g.Expect(got.Timeout).To(Equal(obj.Spec.Timeout.Duration))
})
t.Run("applies options", func(t *testing.T) {
g := NewWithT(t)
obj := &v2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{
Name: "upgrade",
Namespace: "upgrade-ns",
},
Spec: v2.HelmReleaseSpec{},
}
got := newUpgrade(&helmaction.Configuration{}, obj, []UpgradeOption{
func(upgrade *helmaction.Upgrade) {
upgrade.Install = true
},
func(upgrade *helmaction.Upgrade) {
upgrade.DryRun = true
},
})
g.Expect(got).ToNot(BeNil())
g.Expect(got.Install).To(BeTrue())
g.Expect(got.DryRun).To(BeTrue())
})
}

View File

@ -24,9 +24,9 @@ import (
// BuildPostRenderers creates the post-renderer instances from a HelmRelease
// and combines them into a single Combined post renderer.
func BuildPostRenderers(rel *v2.HelmRelease) (helmpostrender.PostRenderer, error) {
func BuildPostRenderers(rel *v2.HelmRelease) helmpostrender.PostRenderer {
if rel == nil {
return nil, nil
return nil
}
renderers := make([]helmpostrender.PostRenderer, 0)
for _, r := range rel.Spec.PostRenderers {
@ -41,7 +41,7 @@ func BuildPostRenderers(rel *v2.HelmRelease) (helmpostrender.PostRenderer, error
}
renderers = append(renderers, NewOriginLabels(v2.GroupVersion.Group, rel.Namespace, rel.Name))
if len(renderers) == 0 {
return nil, nil
return nil
}
return NewCombined(renderers...), nil
return NewCombined(renderers...)
}