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:
parent
220e789481
commit
5843cc2ef0
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue