Skip to content

Commit 3f7c79a

Browse files
committed
feat: add/expose cli flags
Signed-off-by: Hans Song <hans.m.song@gmail.com>
1 parent 5650661 commit 3f7c79a

21 files changed

+98
-31
lines changed

cmd/root.go

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ func setGlobalOptionsForRootCmd(fs *pflag.FlagSet, globalOptions *config.GlobalO
119119
fs.StringVarP(&globalOptions.Environment, "environment", "e", "", `specify the environment name. defaults to "default"`)
120120
fs.StringArrayVar(&globalOptions.StateValuesSet, "state-values-set", nil, "set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
121121
fs.StringArrayVar(&globalOptions.StateValuesFile, "state-values-file", nil, "specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).")
122+
fs.BoolVar(&globalOptions.SkipDeps, "skip-deps", false, `skip running "helm repo update" and "helm dependency build"`)
123+
fs.BoolVar(&globalOptions.DisableForceUpdate, "disable-force-update", false, `do not force helm repos to update when executing "helm repo add"`)
122124
fs.BoolVarP(&globalOptions.Quiet, "quiet", "q", false, "Silence output. Equivalent to log-level warn")
123125
fs.StringVar(&globalOptions.KubeContext, "kube-context", "", "Set kubectl context. Uses current context by default")
124126
fs.BoolVar(&globalOptions.Debug, "debug", false, "Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect")

pkg/app/app.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type App struct {
2929
OverrideKubeContext string
3030
OverrideHelmBinary string
3131
EnableLiveOutput bool
32+
DisableForceUpdate bool
3233

3334
Logger *zap.SugaredLogger
3435
Env string
@@ -66,6 +67,7 @@ func New(conf ConfigProvider) *App {
6667
OverrideKubeContext: conf.KubeContext(),
6768
OverrideHelmBinary: conf.HelmBinary(),
6869
EnableLiveOutput: conf.EnableLiveOutput(),
70+
DisableForceUpdate: conf.DisableForceUpdate(),
6971
Logger: conf.Logger(),
7072
Env: conf.Env(),
7173
Namespace: conf.Namespace(),
@@ -784,7 +786,7 @@ func (a *App) getHelm(st *state.HelmState) helmexec.Interface {
784786
key := createHelmKey(bin, kubectx)
785787

786788
if _, ok := a.helms[key]; !ok {
787-
a.helms[key] = helmexec.New(bin, a.EnableLiveOutput, a.Logger, kubectx, &helmexec.ShellRunner{
789+
a.helms[key] = helmexec.New(bin, helmexec.HelmExecOptions{EnableLiveOutput: a.EnableLiveOutput, DisableForceUpdate: a.DisableForceUpdate}, a.Logger, kubectx, &helmexec.ShellRunner{
788790
Logger: a.Logger,
789791
})
790792
}

pkg/app/app_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -2396,7 +2396,7 @@ func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string
23962396
}
23972397

23982398
func MockExecer(logger *zap.SugaredLogger, kubeContext string) helmexec.Interface {
2399-
execer := helmexec.New("helm", false, logger, kubeContext, &mockRunner{})
2399+
execer := helmexec.New("helm", helmexec.HelmExecOptions{}, logger, kubeContext, &mockRunner{})
24002400
return execer
24012401
}
24022402

@@ -2446,6 +2446,9 @@ func (helm *mockHelmExec) SetHelmBinary(bin string) {
24462446
func (helm *mockHelmExec) SetEnableLiveOutput(enableLiveOutput bool) {
24472447
}
24482448

2449+
func (helm *mockHelmExec) SetDisableForceUpdate(forceUpdate bool) {
2450+
}
2451+
24492452
func (helm *mockHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string, passCredentials string, skipTLSVerify string) error {
24502453
helm.repos = append(helm.repos, mockRepo{Name: name})
24512454
return nil

pkg/app/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ type ConfigProvider interface {
66
Args() string
77
HelmBinary() string
88
EnableLiveOutput() bool
9+
DisableForceUpdate() bool
910

1011
FileOrDir() string
1112
KubeContext() string

pkg/app/init.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ func (h *HelmfileInit) WhetherContinue(ask string) error {
163163

164164
func (h *HelmfileInit) CheckHelmPlugins() error {
165165
settings := cli.New()
166-
helm := helmexec.New(h.helmBinary, false, h.logger, "", h.runner)
166+
helm := helmexec.New(h.helmBinary, helmexec.HelmExecOptions{}, h.logger, "", h.runner)
167167
for _, p := range helmPlugins {
168168
pluginVersion, err := helmexec.GetPluginVersion(p.name, settings.PluginsDirectory)
169169
if err != nil {

pkg/app/mocks_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ func (helm *noCallHelmExec) SetHelmBinary(bin string) {
5353
func (helm *noCallHelmExec) SetEnableLiveOutput(enableLiveOutput bool) {
5454
helm.doPanic()
5555
}
56+
func (helm *noCallHelmExec) SetDisableForceUpdate(forceUpdate bool) {
57+
helm.doPanic()
58+
}
5659

5760
func (helm *noCallHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string, passCredentials string, skipTLSVerify string) error {
5861
helm.doPanic()

pkg/config/apply.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func (a *ApplyImpl) SkipCleanup() bool {
146146

147147
// SkipDeps returns the skip deps.
148148
func (a *ApplyImpl) SkipDeps() bool {
149-
return a.ApplyOptions.SkipDeps
149+
return a.GlobalOptions.SkipDeps || a.ApplyOptions.SkipDeps
150150
}
151151

152152
// SkipDiffOnInstall returns the skip diff on install.

pkg/config/delete.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (c *DeleteImpl) Purge() bool {
4444

4545
// SkipDeps returns the skip deps
4646
func (c *DeleteImpl) SkipDeps() bool {
47-
return c.DeleteOptions.SkipDeps
47+
return c.GlobalOptions.SkipDeps || c.DeleteOptions.SkipDeps
4848
}
4949

5050
// SkipCharts returns skipCharts flag

pkg/config/destroy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (c *DestroyImpl) Concurrency() int {
3636

3737
// SkipDeps returns the skip deps
3838
func (c *DestroyImpl) SkipDeps() bool {
39-
return c.DestroyOptions.SkipDeps
39+
return c.GlobalOptions.SkipDeps || c.DestroyOptions.SkipDeps
4040
}
4141

4242
// SkipCharts returns skipCharts flag

pkg/config/diff.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (t *DiffImpl) Set() []string {
8585

8686
// SkipDeps returns the skip deps
8787
func (t *DiffImpl) SkipDeps() bool {
88-
return t.DiffOptions.SkipDeps
88+
return t.GlobalOptions.SkipDeps || t.DiffOptions.SkipDeps
8989
}
9090

9191
// SkipNeeds returns the skip needs

pkg/config/fetch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (c *FetchImpl) Concurrency() int {
3838

3939
// SkipDeps returns the skip deps
4040
func (c *FetchImpl) SkipDeps() bool {
41-
return c.FetchOptions.SkipDeps
41+
return c.GlobalOptions.SkipDeps || c.FetchOptions.SkipDeps
4242
}
4343

4444
// OutputDir returns the args

pkg/config/global.go

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ type GlobalOptions struct {
2323
StateValuesSet []string
2424
// StateValuesFiles is a list of state values files to use.
2525
StateValuesFile []string
26+
// SkipDeps is true if the running "helm repo update" and "helm dependency build" should be skipped
27+
SkipDeps bool
28+
// DisableForceUpdate is true if force updating repos is not desirable when executing "helm repo add"
29+
DisableForceUpdate bool
2630
// Quiet is true if the output should be quiet.
2731
Quiet bool
2832
// KubeContext is the name of the kubectl context to use.
@@ -132,6 +136,11 @@ func (g *GlobalImpl) EnableLiveOutput() bool {
132136
return g.GlobalOptions.EnableLiveOutput
133137
}
134138

139+
// DisableForceUpdate return when to disable forcing updates to repos upon adding
140+
func (g *GlobalImpl) DisableForceUpdate() bool {
141+
return g.GlobalOptions.DisableForceUpdate
142+
}
143+
135144
// Logger returns the logger
136145
func (g *GlobalImpl) Logger() *zap.SugaredLogger {
137146
return g.GlobalOptions.logger

pkg/config/lint.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (l *LintImpl) Concurrency() int {
4545

4646
// SkipDeps returns the skip deps
4747
func (l *LintImpl) SkipDeps() bool {
48-
return l.LintOptions.SkipDeps
48+
return l.GlobalOptions.SkipDeps || l.LintOptions.SkipDeps
4949
}
5050

5151
// Set returns the Set

pkg/config/sync.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (t *SyncImpl) Set() []string {
7373

7474
// SkipDeps returns the skip deps
7575
func (t *SyncImpl) SkipDeps() bool {
76-
return t.SyncOptions.SkipDeps
76+
return t.GlobalOptions.SkipDeps || t.SyncOptions.SkipDeps
7777
}
7878

7979
// SkipNeeds returns the skip needs

pkg/config/template.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func (t *TemplateImpl) SkipCleanup() bool {
9999

100100
// SkipDeps returns the skip deps
101101
func (t *TemplateImpl) SkipDeps() bool {
102-
return t.TemplateOptions.SkipDeps
102+
return t.GlobalOptions.SkipDeps || t.TemplateOptions.SkipDeps
103103
}
104104

105105
// SkipNeeds returns the skip needs

pkg/config/test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (t *TestImpl) Concurrency() int {
4747

4848
// SkipDeps returns the skip deps
4949
func (t *TestImpl) SkipDeps() bool {
50-
return t.TestOptions.SkipDeps
50+
return t.GlobalOptions.SkipDeps || t.TestOptions.SkipDeps
5151
}
5252

5353
// Cleanup returns the cleanup

pkg/config/write-values.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (c *WriteValuesImpl) Concurrency() int {
4040

4141
// SkipDeps returns the skip deps
4242
func (c *WriteValuesImpl) SkipDeps() bool {
43-
return c.WriteValuesOptions.SkipDeps
43+
return c.GlobalOptions.SkipDeps || c.WriteValuesOptions.SkipDeps
4444
}
4545

4646
// Set returns the Set

pkg/exectest/helm.go

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ func (helm *Helm) SetHelmBinary(bin string) {
9292
}
9393
func (helm *Helm) SetEnableLiveOutput(enableLiveOutput bool) {
9494
}
95+
func (helm *Helm) SetDisableForceUpdate(forceUpdate bool) {
96+
}
9597
func (helm *Helm) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string, passCredentials string, skipTLSVerify string) error {
9698
helm.Repo = []string{name, repository, cafile, certfile, keyfile, username, password, managed, passCredentials, skipTLSVerify}
9799
return nil

pkg/helmexec/exec.go

+15-6
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,14 @@ type decryptedSecret struct {
2828
err error
2929
}
3030

31+
type HelmExecOptions struct {
32+
EnableLiveOutput bool
33+
DisableForceUpdate bool
34+
}
35+
3136
type execer struct {
3237
helmBinary string
33-
enableLiveOutput bool
38+
options HelmExecOptions
3439
version *semver.Version
3540
runner Runner
3641
logger *zap.SugaredLogger
@@ -110,15 +115,15 @@ func redactedURL(chart string) string {
110115
}
111116

112117
// New for running helm commands
113-
func New(helmBinary string, enableLiveOutput bool, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer {
118+
func New(helmBinary string, options HelmExecOptions, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer {
114119
// TODO: proper error handling
115120
version, err := GetHelmVersion(helmBinary, runner)
116121
if err != nil {
117122
panic(err)
118123
}
119124
return &execer{
120125
helmBinary: helmBinary,
121-
enableLiveOutput: enableLiveOutput,
126+
options: options,
122127
version: version,
123128
logger: logger,
124129
kubeContext: kubeContext,
@@ -136,7 +141,11 @@ func (helm *execer) SetHelmBinary(bin string) {
136141
}
137142

138143
func (helm *execer) SetEnableLiveOutput(enableLiveOutput bool) {
139-
helm.enableLiveOutput = enableLiveOutput
144+
helm.options.EnableLiveOutput = enableLiveOutput
145+
}
146+
147+
func (helm *execer) SetDisableForceUpdate(forceUpdate bool) {
148+
helm.options.DisableForceUpdate = forceUpdate
140149
}
141150

142151
func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string, passCredentials string, skipTLSVerify string) error {
@@ -156,7 +165,7 @@ func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, usernam
156165

157166
// See https://github.com/helm/helm/pull/8777
158167
if cons, err := semver.NewConstraint(">= 3.3.2"); err == nil {
159-
if cons.Check(helm.version) {
168+
if !helm.options.DisableForceUpdate && cons.Check(helm.version) {
160169
args = append(args, "--force-update")
161170
}
162171
} else {
@@ -525,7 +534,7 @@ func (helm *execer) exec(args []string, env map[string]string, overrideEnableLiv
525534
}
526535
cmd := fmt.Sprintf("exec: %s %s", helm.helmBinary, strings.Join(cmdargs, " "))
527536
helm.logger.Debug(cmd)
528-
enableLiveOutput := helm.enableLiveOutput
537+
enableLiveOutput := helm.options.EnableLiveOutput
529538
if overrideEnableLiveOutput != nil {
530539
enableLiveOutput = *overrideEnableLiveOutput
531540
}

pkg/helmexec/exec_test.go

+47-12
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string
3636
}
3737

3838
func MockExecer(logger *zap.SugaredLogger, kubeContext string) *execer {
39-
execer := New("helm", false, logger, kubeContext, &mockRunner{})
39+
execer := New("helm", HelmExecOptions{}, logger, kubeContext, &mockRunner{})
4040
return execer
4141
}
4242

@@ -85,12 +85,23 @@ func Test_SetHelmBinary(t *testing.T) {
8585

8686
func Test_SetEnableLiveOutput(t *testing.T) {
8787
helm := MockExecer(NewLogger(os.Stdout, "info"), "dev")
88-
if helm.enableLiveOutput {
89-
t.Error("helmexec.enableLiveOutput should not be enabled by default")
88+
if helm.options.EnableLiveOutput {
89+
t.Error("helmexec.options.EnableLiveOutput should not be enabled by default")
9090
}
9191
helm.SetEnableLiveOutput(true)
92-
if !helm.enableLiveOutput {
93-
t.Errorf("helmexec.SetEnableLiveOutput() - actual = %t expect = true", helm.enableLiveOutput)
92+
if !helm.options.EnableLiveOutput {
93+
t.Errorf("helmexec.SetEnableLiveOutput() - actual = %t expect = true", helm.options.EnableLiveOutput)
94+
}
95+
}
96+
97+
func Test_SetDisableForceUpdate(t *testing.T) {
98+
helm := MockExecer(NewLogger(os.Stdout, "info"), "dev")
99+
if !helm.options.DisableForceUpdate {
100+
t.Error("helmexec.options.ForceUpdate should be enabled by default")
101+
}
102+
helm.SetDisableForceUpdate(false)
103+
if !helm.options.DisableForceUpdate {
104+
t.Errorf("helmexec.SetDisableForceUpdate() - actual = %t expect = false", helm.options.DisableForceUpdate)
94105
}
95106
}
96107

@@ -117,6 +128,30 @@ exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --force-
117128
}
118129
}
119130

131+
func Test_AddRepo_Helm_3_3_2_NoForceUpdate(t *testing.T) {
132+
var buffer bytes.Buffer
133+
logger := NewLogger(&buffer, "debug")
134+
helm := &execer{
135+
helmBinary: "helm",
136+
options: HelmExecOptions{DisableForceUpdate: true},
137+
version: semver.MustParse("3.3.2"),
138+
logger: logger,
139+
kubeContext: "dev",
140+
runner: &mockRunner{},
141+
}
142+
err := helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "", "", "", "")
143+
expected := `Adding repo myRepo https://repo.example.com/
144+
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --force-update --cert-file cert.pem --key-file key.pem
145+
`
146+
if err != nil {
147+
t.Errorf("unexpected error: %v", err)
148+
}
149+
150+
if buffer.String() != expected {
151+
t.Errorf("helmexec.AddRepo()\nactual = %v\nexpect = %v", buffer.String(), expected)
152+
}
153+
}
154+
120155
func Test_AddRepo(t *testing.T) {
121156
var buffer bytes.Buffer
122157
logger := NewLogger(&buffer, "debug")
@@ -322,7 +357,7 @@ func Test_BuildDeps(t *testing.T) {
322357
var buffer bytes.Buffer
323358
logger := NewLogger(&buffer, "debug")
324359
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a")}
325-
helm := New("helm", false, logger, "dev", &helm3Runner)
360+
helm := New("helm", HelmExecOptions{}, logger, "dev", &helm3Runner)
326361
err := helm.BuildDeps("foo", "./chart/foo", []string{"--skip-refresh"}...)
327362
expected := `Building dependency release=foo, chart=./chart/foo
328363
exec: helm --kube-context dev dependency build ./chart/foo --skip-refresh
@@ -364,7 +399,7 @@ v3.2.4+ge29ce2a
364399

365400
buffer.Reset()
366401
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94")}
367-
helm = New("helm", false, logger, "dev", &helm2Runner)
402+
helm = New("helm", HelmExecOptions{}, logger, "dev", &helm2Runner)
368403
err = helm.BuildDeps("foo", "./chart/foo")
369404
expected = `Building dependency release=foo, chart=./chart/foo
370405
exec: helm --kube-context dev dependency build ./chart/foo
@@ -870,13 +905,13 @@ exec: helm --kube-context dev template release https://example_user:example_pass
870905

871906
func Test_IsHelm3(t *testing.T) {
872907
helm2Runner := mockRunner{output: []byte("Client: v2.16.0+ge13bc94\n")}
873-
helm := New("helm", false, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
908+
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
874909
if helm.IsHelm3() {
875910
t.Error("helmexec.IsHelm3() - Detected Helm 3 with Helm 2 version")
876911
}
877912

878913
helm3Runner := mockRunner{output: []byte("v3.0.0+ge29ce2a\n")}
879-
helm = New("helm", false, NewLogger(os.Stdout, "info"), "dev", &helm3Runner)
914+
helm = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "dev", &helm3Runner)
880915
if !helm.IsHelm3() {
881916
t.Error("helmexec.IsHelm3() - Failed to detect Helm 3")
882917
}
@@ -907,14 +942,14 @@ func Test_GetPluginVersion(t *testing.T) {
907942

908943
func Test_GetVersion(t *testing.T) {
909944
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
910-
helm := New("helm", false, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
945+
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
911946
ver := helm.GetVersion()
912947
if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 {
913948
t.Errorf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver)
914949
}
915950

916951
helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")}
917-
helm = New("helm", false, NewLogger(os.Stdout, "info"), "dev", &helm3Runner)
952+
helm = New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "dev", &helm3Runner)
918953
ver = helm.GetVersion()
919954
if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 {
920955
t.Errorf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver)
@@ -923,7 +958,7 @@ func Test_GetVersion(t *testing.T) {
923958

924959
func Test_IsVersionAtLeast(t *testing.T) {
925960
helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
926-
helm := New("helm", false, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
961+
helm := New("helm", HelmExecOptions{}, NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
927962
if !helm.IsVersionAtLeast("2.1.0") {
928963
t.Error("helmexec.IsVersionAtLeast - 2.16.1 not atleast 2.1")
929964
}

0 commit comments

Comments
 (0)