feat: feat: Configurable default values for --verify, --force, --recreate-pods, and --timeout (#241)

Resolves #230
This commit is contained in:
KUOKA Yusuke 2018-08-28 15:11:05 +09:00 committed by GitHub
parent 815ee1f85b
commit 0ac8401d1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 276 additions and 18 deletions

View File

@ -43,10 +43,15 @@ context: kube-context # kube-context (--kube-context)
helmDefaults:
tillerNamespace: tiller-namespace #dedicated default key for tiller-namespace
kubeContext: kube-context #dedicated default key for kube-context
# additional and global args passed to helm
args:
- "--recreate-pods"
- "--timeout=600"
- "--force"
- "--set k=v"
# defaults for verify, wait, force, timeout and recreatePods under releases[]
verify: true
wait: true
timeout: 600
recreatePods: true
force: true
releases:
# Published chart example

View File

@ -42,6 +42,15 @@ type HelmSpec struct {
KubeContext string `yaml:"kubeContext"`
TillerNamespace string `yaml:"tillerNamespace"`
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
@ -59,15 +68,15 @@ type ReleaseSpec struct {
// Chart is the name of the chart being installed to create this release
Chart string `yaml:"chart"`
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 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 int `yaml:"timeout"`
Timeout *int `yaml:"timeout"`
// 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 bool `yaml:"force"`
Force *bool `yaml:"force"`
// Name is the name of this release
Name string `yaml:"name"`
@ -224,7 +233,7 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [
go func() {
for release := range jobQueue {
state.applyDefaultsTo(release)
flags, flagsErr := state.flagsForUpgrade(helm, state.BaseChartPath, release)
flags, flagsErr := state.flagsForUpgrade(helm, release)
if flagsErr != nil {
errQueue <- &ReleaseError{release, flagsErr}
doneQueue <- true
@ -659,27 +668,37 @@ func chartNameWithoutRepository(chart string) string {
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{}
if release.Version != "" {
flags = append(flags, "--version", release.Version)
}
if release.Verify {
if release.Verify != nil && *release.Verify || state.HelmDefaults.Verify {
flags = append(flags, "--verify")
}
if release.Wait {
if release.Wait != nil && *release.Wait || state.HelmDefaults.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")
}
if release.RecreatePods {
if release.RecreatePods != nil && *release.RecreatePods || state.HelmDefaults.RecreatePods {
flags = append(flags, "--recreate-pods")
}
common, err := state.namespaceAndValuesFlags(helm, basePath, release)
common, err := state.namespaceAndValuesFlags(helm, state.BaseChartPath, release)
if err != nil {
return nil, err
}

View File

@ -188,6 +188,7 @@ func TestLabelParsing(t *testing.T) {
}
}
}
func TestHelmState_applyDefaultsTo(t *testing.T) {
type fields struct {
BaseChartPath string
@ -200,10 +201,11 @@ func TestHelmState_applyDefaultsTo(t *testing.T) {
type args struct {
spec ReleaseSpec
}
verify := false
specWithNamespace := ReleaseSpec{
Chart: "test/chart",
Version: "0.1",
Verify: false,
Verify: &verify,
Name: "test-charts",
Namespace: "test-namespace",
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) {
type args struct {
s string