feat: feat: Configurable default values for --verify, --force, --recreate-pods, and --timeout (#241)
Resolves #230
This commit is contained in:
parent
815ee1f85b
commit
0ac8401d1e
11
README.md
11
README.md
|
|
@ -43,10 +43,15 @@ context: kube-context # kube-context (--kube-context)
|
||||||
helmDefaults:
|
helmDefaults:
|
||||||
tillerNamespace: tiller-namespace #dedicated default key for tiller-namespace
|
tillerNamespace: tiller-namespace #dedicated default key for tiller-namespace
|
||||||
kubeContext: kube-context #dedicated default key for kube-context
|
kubeContext: kube-context #dedicated default key for kube-context
|
||||||
|
# additional and global args passed to helm
|
||||||
args:
|
args:
|
||||||
- "--recreate-pods"
|
- "--set k=v"
|
||||||
- "--timeout=600"
|
# defaults for verify, wait, force, timeout and recreatePods under releases[]
|
||||||
- "--force"
|
verify: true
|
||||||
|
wait: true
|
||||||
|
timeout: 600
|
||||||
|
recreatePods: true
|
||||||
|
force: true
|
||||||
|
|
||||||
releases:
|
releases:
|
||||||
# Published chart example
|
# Published chart example
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,15 @@ type HelmSpec struct {
|
||||||
KubeContext string `yaml:"kubeContext"`
|
KubeContext string `yaml:"kubeContext"`
|
||||||
TillerNamespace string `yaml:"tillerNamespace"`
|
TillerNamespace string `yaml:"tillerNamespace"`
|
||||||
Args []string `yaml:"args"`
|
Args []string `yaml:"args"`
|
||||||
|
Verify bool `yaml:"verify"`
|
||||||
|
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
||||||
|
Wait bool `yaml:"wait"`
|
||||||
|
// Timeout is the time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
||||||
|
Timeout int `yaml:"timeout"`
|
||||||
|
// RecreatePods, when set to true, instruct helmfile to perform pods restart for the resource if applicable
|
||||||
|
RecreatePods bool `yaml:"recreatePods"`
|
||||||
|
// Force, when set to true, forces resource update through delete/recreate if needed
|
||||||
|
Force bool `yaml:"force"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepositorySpec that defines values for a helm repo
|
// RepositorySpec that defines values for a helm repo
|
||||||
|
|
@ -59,15 +68,15 @@ type ReleaseSpec struct {
|
||||||
// Chart is the name of the chart being installed to create this release
|
// Chart is the name of the chart being installed to create this release
|
||||||
Chart string `yaml:"chart"`
|
Chart string `yaml:"chart"`
|
||||||
Version string `yaml:"version"`
|
Version string `yaml:"version"`
|
||||||
Verify bool `yaml:"verify"`
|
Verify *bool `yaml:"verify"`
|
||||||
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
// Wait, if set to true, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful
|
||||||
Wait bool `yaml:"wait"`
|
Wait *bool `yaml:"wait"`
|
||||||
// Timeout is the time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
// Timeout is the time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
||||||
Timeout int `yaml:"timeout"`
|
Timeout *int `yaml:"timeout"`
|
||||||
// RecreatePods, when set to true, instruct helmfile to perform pods restart for the resource if applicable
|
// RecreatePods, when set to true, instruct helmfile to perform pods restart for the resource if applicable
|
||||||
RecreatePods bool `yaml:"recreatePods"`
|
RecreatePods *bool `yaml:"recreatePods"`
|
||||||
// Force, when set to true, forces resource update through delete/recreate if needed
|
// Force, when set to true, forces resource update through delete/recreate if needed
|
||||||
Force bool `yaml:"force"`
|
Force *bool `yaml:"force"`
|
||||||
|
|
||||||
// Name is the name of this release
|
// Name is the name of this release
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
|
|
@ -224,7 +233,7 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [
|
||||||
go func() {
|
go func() {
|
||||||
for release := range jobQueue {
|
for release := range jobQueue {
|
||||||
state.applyDefaultsTo(release)
|
state.applyDefaultsTo(release)
|
||||||
flags, flagsErr := state.flagsForUpgrade(helm, state.BaseChartPath, release)
|
flags, flagsErr := state.flagsForUpgrade(helm, release)
|
||||||
if flagsErr != nil {
|
if flagsErr != nil {
|
||||||
errQueue <- &ReleaseError{release, flagsErr}
|
errQueue <- &ReleaseError{release, flagsErr}
|
||||||
doneQueue <- true
|
doneQueue <- true
|
||||||
|
|
@ -659,27 +668,37 @@ func chartNameWithoutRepository(chart string) string {
|
||||||
return chartSplit[len(chartSplit)-1]
|
return chartSplit[len(chartSplit)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *HelmState) flagsForUpgrade(helm helmexec.Interface, basePath string, release *ReleaseSpec) ([]string, error) {
|
func (state *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSpec) ([]string, error) {
|
||||||
flags := []string{}
|
flags := []string{}
|
||||||
if release.Version != "" {
|
if release.Version != "" {
|
||||||
flags = append(flags, "--version", release.Version)
|
flags = append(flags, "--version", release.Version)
|
||||||
}
|
}
|
||||||
if release.Verify {
|
|
||||||
|
if release.Verify != nil && *release.Verify || state.HelmDefaults.Verify {
|
||||||
flags = append(flags, "--verify")
|
flags = append(flags, "--verify")
|
||||||
}
|
}
|
||||||
if release.Wait {
|
|
||||||
|
if release.Wait != nil && *release.Wait || state.HelmDefaults.Wait {
|
||||||
flags = append(flags, "--wait")
|
flags = append(flags, "--wait")
|
||||||
}
|
}
|
||||||
if release.Timeout != 0 {
|
|
||||||
flags = append(flags, "--timeout", fmt.Sprintf("%d", release.Timeout))
|
timeout := state.HelmDefaults.Timeout
|
||||||
|
if release.Timeout != nil {
|
||||||
|
timeout = *release.Timeout
|
||||||
}
|
}
|
||||||
if release.Force {
|
if timeout != 0 {
|
||||||
|
flags = append(flags, "--timeout", fmt.Sprintf("%d", timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
if release.Force != nil && *release.Force || state.HelmDefaults.Force {
|
||||||
flags = append(flags, "--force")
|
flags = append(flags, "--force")
|
||||||
}
|
}
|
||||||
if release.RecreatePods {
|
|
||||||
|
if release.RecreatePods != nil && *release.RecreatePods || state.HelmDefaults.RecreatePods {
|
||||||
flags = append(flags, "--recreate-pods")
|
flags = append(flags, "--recreate-pods")
|
||||||
}
|
}
|
||||||
common, err := state.namespaceAndValuesFlags(helm, basePath, release)
|
|
||||||
|
common, err := state.namespaceAndValuesFlags(helm, state.BaseChartPath, release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ func TestLabelParsing(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHelmState_applyDefaultsTo(t *testing.T) {
|
func TestHelmState_applyDefaultsTo(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
BaseChartPath string
|
BaseChartPath string
|
||||||
|
|
@ -200,10 +201,11 @@ func TestHelmState_applyDefaultsTo(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
spec ReleaseSpec
|
spec ReleaseSpec
|
||||||
}
|
}
|
||||||
|
verify := false
|
||||||
specWithNamespace := ReleaseSpec{
|
specWithNamespace := ReleaseSpec{
|
||||||
Chart: "test/chart",
|
Chart: "test/chart",
|
||||||
Version: "0.1",
|
Version: "0.1",
|
||||||
Verify: false,
|
Verify: &verify,
|
||||||
Name: "test-charts",
|
Name: "test-charts",
|
||||||
Namespace: "test-namespace",
|
Namespace: "test-namespace",
|
||||||
Values: nil,
|
Values: nil,
|
||||||
|
|
@ -278,6 +280,238 @@ func TestHelmState_applyDefaultsTo(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||||
|
enable := true
|
||||||
|
disable := false
|
||||||
|
|
||||||
|
some := func(v int) *int {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaults HelmSpec
|
||||||
|
release *ReleaseSpec
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no-options",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Verify: false,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Verify: &disable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "verify",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Verify: false,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Verify: &enable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--verify",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "verify-from-default",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Verify: true,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Verify: &disable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--verify",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "force",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Force: false,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Force: &enable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--force",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "force-from-default",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Force: true,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Force: &disable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--force",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recreate-pods",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
RecreatePods: false,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
RecreatePods: &enable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--recreate-pods",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recreate-pods-from-default",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
RecreatePods: true,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
RecreatePods: &disable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--recreate-pods",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wait",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Wait: false,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Wait: &enable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--wait",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wait-from-default",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Wait: true,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Wait: &disable,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--wait",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "timeout",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Timeout: some(123),
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--timeout", "123",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "timeout-from-default",
|
||||||
|
defaults: HelmSpec{
|
||||||
|
Timeout: 123,
|
||||||
|
},
|
||||||
|
release: &ReleaseSpec{
|
||||||
|
Chart: "test/chart",
|
||||||
|
Version: "0.1",
|
||||||
|
Timeout: nil,
|
||||||
|
Name: "test-charts",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
want: []string{
|
||||||
|
"--version", "0.1",
|
||||||
|
"--timeout", "123",
|
||||||
|
"--namespace", "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
state := &HelmState{
|
||||||
|
BaseChartPath: "./",
|
||||||
|
Context: "default",
|
||||||
|
Releases: []ReleaseSpec{*tt.release},
|
||||||
|
HelmDefaults: tt.defaults,
|
||||||
|
}
|
||||||
|
helm := helmexec.New(logger, "default")
|
||||||
|
args, err := state.flagsForUpgrade(helm, tt.release)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error flagsForUpgade: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(args, tt.want) {
|
||||||
|
t.Errorf("flagsForUpgrade returned = %v, want %v", args, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_renderTemplateString(t *testing.T) {
|
func Test_renderTemplateString(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
s string
|
s string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue