Support for createNamespace (#1226)
- createNamespace is a new attribute that can be added to helmDefaults or an individual release to enforce the creation of a release namespace during sync if the namespace does not exist. This leverages helm's (3.2+) --create-namespace flag for the install/upgrade command. If running helm < 3.2, the createNamespace attribute has no effect. Resolves #891 Resolves #1140
This commit is contained in:
		
							parent
							
								
									b1190508b2
								
							
						
					
					
						commit
						eeb61e6174
					
				
							
								
								
									
										34
									
								
								README.md
								
								
								
								
							
							
						
						
									
										34
									
								
								README.md
								
								
								
								
							| 
						 | 
					@ -69,7 +69,7 @@ repositories:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# context: kube-context # this directive is deprecated, please consider using helmDefaults.kubeContext
 | 
					# context: kube-context # this directive is deprecated, please consider using helmDefaults.kubeContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Default values to set for args along with dedicated keys that can be set by contributors, cli args take precedence over these. 
 | 
					# Default values to set for args along with dedicated keys that can be set by contributors, cli args take precedence over these.
 | 
				
			||||||
# In other words, unset values results in no flags passed to helm.
 | 
					# In other words, unset values results in no flags passed to helm.
 | 
				
			||||||
# See the helm usage (helm SUBCOMMAND -h) for more info on default values when those flags aren't provided.
 | 
					# See the helm usage (helm SUBCOMMAND -h) for more info on default values when those flags aren't provided.
 | 
				
			||||||
helmDefaults:
 | 
					helmDefaults:
 | 
				
			||||||
| 
						 | 
					@ -91,15 +91,18 @@ helmDefaults:
 | 
				
			||||||
  # forces resource update through delete/recreate if needed (default false)
 | 
					  # forces resource update through delete/recreate if needed (default false)
 | 
				
			||||||
  force: false
 | 
					  force: false
 | 
				
			||||||
  # enable TLS for request to Tiller (default false)
 | 
					  # enable TLS for request to Tiller (default false)
 | 
				
			||||||
  tls: true        
 | 
					  tls: true
 | 
				
			||||||
  # path to TLS CA certificate file (default "$HELM_HOME/ca.pem")
 | 
					  # path to TLS CA certificate file (default "$HELM_HOME/ca.pem")
 | 
				
			||||||
  tlsCACert: "path/to/ca.pem"
 | 
					  tlsCACert: "path/to/ca.pem"
 | 
				
			||||||
  # path to TLS certificate file (default "$HELM_HOME/cert.pem")
 | 
					  # path to TLS certificate file (default "$HELM_HOME/cert.pem")
 | 
				
			||||||
  tlsCert: "path/to/cert.pem"
 | 
					  tlsCert: "path/to/cert.pem"
 | 
				
			||||||
  # path to TLS key file (default "$HELM_HOME/key.pem")
 | 
					  # path to TLS key file (default "$HELM_HOME/key.pem")
 | 
				
			||||||
  tlsKey: "path/to/key.pem"
 | 
					  tlsKey: "path/to/key.pem"
 | 
				
			||||||
  # limit the maximum number of revisions saved per release. Use 0 for no limit. (default 10) 
 | 
					  # limit the maximum number of revisions saved per release. Use 0 for no limit. (default 10)
 | 
				
			||||||
  historyMax: 10
 | 
					  historyMax: 10
 | 
				
			||||||
 | 
					  # when using helm 3.2+, automatically create release namespaces if they do not exist (default true)
 | 
				
			||||||
 | 
					  createNamespace: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The desired states of Helm releases.
 | 
					# The desired states of Helm releases.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -108,6 +111,7 @@ releases:
 | 
				
			||||||
  # Published chart example
 | 
					  # Published chart example
 | 
				
			||||||
  - name: vault                            # name of this release
 | 
					  - name: vault                            # name of this release
 | 
				
			||||||
    namespace: vault                       # target namespace
 | 
					    namespace: vault                       # target namespace
 | 
				
			||||||
 | 
					    createNamespace: true                  # helm 3.2+ automatically create release namespace (default true)
 | 
				
			||||||
    labels:                                # Arbitrary key value pairs for filtering releases
 | 
					    labels:                                # Arbitrary key value pairs for filtering releases
 | 
				
			||||||
      foo: bar
 | 
					      foo: bar
 | 
				
			||||||
    chart: roboll/vault-secret-manager     # the chart being installed to create this release, referenced by `repository/chart` syntax
 | 
					    chart: roboll/vault-secret-manager     # the chart being installed to create this release, referenced by `repository/chart` syntax
 | 
				
			||||||
| 
						 | 
					@ -152,21 +156,21 @@ releases:
 | 
				
			||||||
      value: {{ .Namespace }}
 | 
					      value: {{ .Namespace }}
 | 
				
			||||||
    # will attempt to decrypt it using helm-secrets plugin
 | 
					    # will attempt to decrypt it using helm-secrets plugin
 | 
				
			||||||
    secrets:
 | 
					    secrets:
 | 
				
			||||||
      - vault_secret.yaml    
 | 
					      - vault_secret.yaml
 | 
				
			||||||
    # Override helmDefaults options for verify, wait, timeout, recreatePods and force. 
 | 
					    # Override helmDefaults options for verify, wait, timeout, recreatePods and force.
 | 
				
			||||||
    verify: true              
 | 
					    verify: true
 | 
				
			||||||
    wait: true            
 | 
					    wait: true
 | 
				
			||||||
    timeout: 60           
 | 
					    timeout: 60
 | 
				
			||||||
    recreatePods: true    
 | 
					    recreatePods: true
 | 
				
			||||||
    force: false          
 | 
					    force: false
 | 
				
			||||||
    # set `false` to uninstall this release on sync.  (default true)
 | 
					    # set `false` to uninstall this release on sync.  (default true)
 | 
				
			||||||
    installed: true
 | 
					    installed: true
 | 
				
			||||||
    # restores previous state in case of failed release (default false)
 | 
					    # restores previous state in case of failed release (default false)
 | 
				
			||||||
    atomic: true          
 | 
					    atomic: true
 | 
				
			||||||
    # when true, cleans up any new resources created during a failed release (default false)
 | 
					    # when true, cleans up any new resources created during a failed release (default false)
 | 
				
			||||||
    cleanupOnFail: false  
 | 
					    cleanupOnFail: false
 | 
				
			||||||
    # name of the tiller namespace (default "") 
 | 
					    # name of the tiller namespace (default "")
 | 
				
			||||||
    tillerNamespace: vault  
 | 
					    tillerNamespace: vault
 | 
				
			||||||
    # if true, will use the helm-tiller plugin (default false)
 | 
					    # if true, will use the helm-tiller plugin (default false)
 | 
				
			||||||
    tillerless: false
 | 
					    tillerless: false
 | 
				
			||||||
    # enable TLS for request to Tiller (default false)
 | 
					    # enable TLS for request to Tiller (default false)
 | 
				
			||||||
| 
						 | 
					@ -280,7 +284,7 @@ bases:
 | 
				
			||||||
# 'helmfile template' renders releases locally without querying an actual cluster,
 | 
					# 'helmfile template' renders releases locally without querying an actual cluster,
 | 
				
			||||||
# and in this case `.Capabilities.APIVersions` cannot be populated.
 | 
					# and in this case `.Capabilities.APIVersions` cannot be populated.
 | 
				
			||||||
# When a chart queries for a specific CRD, this can lead to unexpected results.
 | 
					# When a chart queries for a specific CRD, this can lead to unexpected results.
 | 
				
			||||||
# 
 | 
					#
 | 
				
			||||||
# Configure a fixed list of api versions to pass to 'helm template' via the --api-versions flag:
 | 
					# Configure a fixed list of api versions to pass to 'helm template' via the --api-versions flag:
 | 
				
			||||||
apiVersions:
 | 
					apiVersions:
 | 
				
			||||||
- example/v1
 | 
					- example/v1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2168,6 +2168,14 @@ func (helm *mockHelmExec) IsHelm3() bool {
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *mockHelmExec) GetVersion() helmexec.Version {
 | 
				
			||||||
 | 
						return helmexec.Version{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *mockHelmExec) IsVersionAtLeast(major int, minor int) bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestTemplate_SingleStateFile(t *testing.T) {
 | 
					func TestTemplate_SingleStateFile(t *testing.T) {
 | 
				
			||||||
	files := map[string]string{
 | 
						files := map[string]string{
 | 
				
			||||||
		"/path/to/helmfile.yaml": `
 | 
							"/path/to/helmfile.yaml": `
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,3 +82,13 @@ func (helm *noCallHelmExec) IsHelm3() bool {
 | 
				
			||||||
	helm.doPanic()
 | 
						helm.doPanic()
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *noCallHelmExec) GetVersion() helmexec.Version {
 | 
				
			||||||
 | 
						helm.doPanic()
 | 
				
			||||||
 | 
						return helmexec.Version{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *noCallHelmExec) IsVersionAtLeast(major int, minor int) bool {
 | 
				
			||||||
 | 
						helm.doPanic()
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ type Helm struct {
 | 
				
			||||||
	Diffed               []Release
 | 
						Diffed               []Release
 | 
				
			||||||
	FailOnUnexpectedDiff bool
 | 
						FailOnUnexpectedDiff bool
 | 
				
			||||||
	FailOnUnexpectedList bool
 | 
						FailOnUnexpectedList bool
 | 
				
			||||||
 | 
						Version              *helmexec.Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UpdateDepsCallbacks map[string]func(string) error
 | 
						UpdateDepsCallbacks map[string]func(string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,6 +162,22 @@ func (helm *Helm) IsHelm3() bool {
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *Helm) GetVersion() helmexec.Version {
 | 
				
			||||||
 | 
						if helm.Version != nil {
 | 
				
			||||||
 | 
							return *helm.Version
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return helmexec.Version{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *Helm) IsVersionAtLeast(major int, minor int) bool {
 | 
				
			||||||
 | 
						if helm.Version == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return helm.Version.Major >= major && minor >= helm.Version.Minor
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (helm *Helm) sync(m *sync.Mutex, f func()) {
 | 
					func (helm *Helm) sync(m *sync.Mutex, f func()) {
 | 
				
			||||||
	if m != nil {
 | 
						if m != nil {
 | 
				
			||||||
		m.Lock()
 | 
							m.Lock()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
| 
						 | 
					@ -21,7 +22,7 @@ type decryptedSecret struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type execer struct {
 | 
					type execer struct {
 | 
				
			||||||
	helmBinary           string
 | 
						helmBinary           string
 | 
				
			||||||
	isHelm3              bool
 | 
						version              Version
 | 
				
			||||||
	runner               Runner
 | 
						runner               Runner
 | 
				
			||||||
	logger               *zap.SugaredLogger
 | 
						logger               *zap.SugaredLogger
 | 
				
			||||||
	kubeContext          string
 | 
						kubeContext          string
 | 
				
			||||||
| 
						 | 
					@ -47,25 +48,62 @@ func NewLogger(writer io.Writer, logLevel string) *zap.SugaredLogger {
 | 
				
			||||||
	return zap.New(core).Sugar()
 | 
						return zap.New(core).Sugar()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func detectHelm3(helmBinary string, logger *zap.SugaredLogger, runner Runner) bool {
 | 
					func getHelmVersion(helmBinary string, logger *zap.SugaredLogger, runner Runner) Version {
 | 
				
			||||||
	// Support explicit opt-in via environment variable
 | 
					 | 
				
			||||||
	if os.Getenv("HELMFILE_HELM3") != "" {
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Autodetect from `helm verison`
 | 
						// Autodetect from `helm verison`
 | 
				
			||||||
	bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil)
 | 
						bytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return strings.HasPrefix(string(bytes), "v3.")
 | 
					
 | 
				
			||||||
 | 
						if bytes == nil || len(bytes) == 0 {
 | 
				
			||||||
 | 
							return Version{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						re := regexp.MustCompile("v(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)")
 | 
				
			||||||
 | 
						matches := re.FindStringSubmatch(string(bytes))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := make(map[string]string)
 | 
				
			||||||
 | 
						for i, name := range re.SubexpNames() {
 | 
				
			||||||
 | 
							result[name] = matches[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						major, err := strconv.Atoi(result["major"])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						minor, err := strconv.Atoi(result["minor"])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						patch, err := strconv.Atoi(result["patch"])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Support explicit helm3 opt-in via environment variable
 | 
				
			||||||
 | 
						if os.Getenv("HELMFILE_HELM3") != "" && major < 3 {
 | 
				
			||||||
 | 
							return Version{
 | 
				
			||||||
 | 
								Major: 3,
 | 
				
			||||||
 | 
								Minor: 0,
 | 
				
			||||||
 | 
								Patch: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Version{
 | 
				
			||||||
 | 
							Major: major,
 | 
				
			||||||
 | 
							Minor: minor,
 | 
				
			||||||
 | 
							Patch: patch,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New for running helm commands
 | 
					// New for running helm commands
 | 
				
			||||||
func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer {
 | 
					func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer {
 | 
				
			||||||
	return &execer{
 | 
						return &execer{
 | 
				
			||||||
		helmBinary:       helmBinary,
 | 
							helmBinary:       helmBinary,
 | 
				
			||||||
		isHelm3:          detectHelm3(helmBinary, logger, runner),
 | 
							version:          getHelmVersion(helmBinary, logger, runner),
 | 
				
			||||||
		logger:           logger,
 | 
							logger:           logger,
 | 
				
			||||||
		kubeContext:      kubeContext,
 | 
							kubeContext:      kubeContext,
 | 
				
			||||||
		runner:           runner,
 | 
							runner:           runner,
 | 
				
			||||||
| 
						 | 
					@ -349,5 +387,13 @@ func (helm *execer) write(out []byte) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (helm *execer) IsHelm3() bool {
 | 
					func (helm *execer) IsHelm3() bool {
 | 
				
			||||||
	return helm.isHelm3
 | 
						return helm.version.Major == 3
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *execer) GetVersion() Version {
 | 
				
			||||||
 | 
						return helm.version
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *execer) IsVersionAtLeast(major int, minor int) bool {
 | 
				
			||||||
 | 
						return helm.version.Major >= major && helm.version.Minor >= minor
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -528,4 +528,45 @@ func Test_IsHelm3(t *testing.T) {
 | 
				
			||||||
	if !helm.IsHelm3() {
 | 
						if !helm.IsHelm3() {
 | 
				
			||||||
		t.Error("helmexec.IsHelm3() - Failed to detect Helm 3")
 | 
							t.Error("helmexec.IsHelm3() - Failed to detect Helm 3")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						os.Setenv("HELMFILE_HELM3", "1")
 | 
				
			||||||
 | 
						helm2Runner = mockRunner{output: []byte("Client: v2.16.0+ge13bc94\n")}
 | 
				
			||||||
 | 
						helm = New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
 | 
				
			||||||
 | 
						if !helm.IsHelm3() {
 | 
				
			||||||
 | 
							t.Error("helmexec.IsHelm3() - Helm3 not detected when HELMFILE_HELM3 is set")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						os.Setenv("HELMFILE_HELM3", "")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Test_GetVersion(t *testing.T) {
 | 
				
			||||||
 | 
						helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
 | 
				
			||||||
 | 
						helm := New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
 | 
				
			||||||
 | 
						ver := helm.GetVersion()
 | 
				
			||||||
 | 
						if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 {
 | 
				
			||||||
 | 
							t.Error(fmt.Sprintf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")}
 | 
				
			||||||
 | 
						helm = New("helm", NewLogger(os.Stdout, "info"), "dev", &helm3Runner)
 | 
				
			||||||
 | 
						ver = helm.GetVersion()
 | 
				
			||||||
 | 
						if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 {
 | 
				
			||||||
 | 
							t.Error(fmt.Sprintf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Test_IsVersionAtLeast(t *testing.T) {
 | 
				
			||||||
 | 
						helm2Runner := mockRunner{output: []byte("Client: v2.16.1+ge13bc94\n")}
 | 
				
			||||||
 | 
						helm := New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner)
 | 
				
			||||||
 | 
						if !helm.IsVersionAtLeast(2, 1) {
 | 
				
			||||||
 | 
							t.Error("helmexec.IsVersionAtLeast - 2.16.1 not atleast 2.1")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if helm.IsVersionAtLeast(2, 19) {
 | 
				
			||||||
 | 
							t.Error("helmexec.IsVersionAtLeast - 2.16.1 is atleast 2.19")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if helm.IsVersionAtLeast(3, 2) {
 | 
				
			||||||
 | 
							t.Error("helmexec.IsVersionAtLeast - 2.16.1 is atleast 3.2")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,12 @@
 | 
				
			||||||
package helmexec
 | 
					package helmexec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Version represents the version of helm
 | 
				
			||||||
 | 
					type Version struct {
 | 
				
			||||||
 | 
						Major int
 | 
				
			||||||
 | 
						Minor int
 | 
				
			||||||
 | 
						Patch int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Interface for executing helm commands
 | 
					// Interface for executing helm commands
 | 
				
			||||||
type Interface interface {
 | 
					type Interface interface {
 | 
				
			||||||
	SetExtraArgs(args ...string)
 | 
						SetExtraArgs(args ...string)
 | 
				
			||||||
| 
						 | 
					@ -20,6 +27,8 @@ type Interface interface {
 | 
				
			||||||
	List(context HelmContext, filter string, flags ...string) (string, error)
 | 
						List(context HelmContext, filter string, flags ...string) (string, error)
 | 
				
			||||||
	DecryptSecret(context HelmContext, name string, flags ...string) (string, error)
 | 
						DecryptSecret(context HelmContext, name string, flags ...string) (string, error)
 | 
				
			||||||
	IsHelm3() bool
 | 
						IsHelm3() bool
 | 
				
			||||||
 | 
						GetVersion() Version
 | 
				
			||||||
 | 
						IsVersionAtLeast(major int, minor int) bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DependencyUpdater interface {
 | 
					type DependencyUpdater interface {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,6 +114,8 @@ type HelmSpec struct {
 | 
				
			||||||
	CleanupOnFail bool `yaml:"cleanupOnFail,omitempty"`
 | 
						CleanupOnFail bool `yaml:"cleanupOnFail,omitempty"`
 | 
				
			||||||
	// HistoryMax, limit the maximum number of revisions saved per release. Use 0 for no limit (default 10)
 | 
						// HistoryMax, limit the maximum number of revisions saved per release. Use 0 for no limit (default 10)
 | 
				
			||||||
	HistoryMax *int `yaml:"historyMax,omitempty"`
 | 
						HistoryMax *int `yaml:"historyMax,omitempty"`
 | 
				
			||||||
 | 
						// CreateNamespace, when set to true (default), --create-namespace is passed to helm3 on install/upgrade (ignored for helm2)
 | 
				
			||||||
 | 
						CreateNamespace *bool `yaml:"createNamespace,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TLS       bool   `yaml:"tls"`
 | 
						TLS       bool   `yaml:"tls"`
 | 
				
			||||||
	TLSCACert string `yaml:"tlsCACert,omitempty"`
 | 
						TLSCACert string `yaml:"tlsCACert,omitempty"`
 | 
				
			||||||
| 
						 | 
					@ -158,6 +160,8 @@ type ReleaseSpec struct {
 | 
				
			||||||
	HistoryMax *int `yaml:"historyMax,omitempty"`
 | 
						HistoryMax *int `yaml:"historyMax,omitempty"`
 | 
				
			||||||
	// Condition, when set, evaluate the mapping specified in this string to a boolean which decides whether or not to process the release
 | 
						// Condition, when set, evaluate the mapping specified in this string to a boolean which decides whether or not to process the release
 | 
				
			||||||
	Condition string `yaml:"condition,omitempty"`
 | 
						Condition string `yaml:"condition,omitempty"`
 | 
				
			||||||
 | 
						// CreateNamespace, when set to true (default), --create-namespace is passed to helm3 on install (ignored for helm2)
 | 
				
			||||||
 | 
						CreateNamespace *bool `yaml:"createNamespace,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// MissingFileHandler is set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
 | 
						// MissingFileHandler is set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
 | 
				
			||||||
	// The default value for MissingFileHandler is "Error".
 | 
						// The default value for MissingFileHandler is "Error".
 | 
				
			||||||
| 
						 | 
					@ -1635,6 +1639,12 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
 | 
				
			||||||
		flags = append(flags, "--cleanup-on-fail")
 | 
							flags = append(flags, "--cleanup-on-fail")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if helm.IsVersionAtLeast(3, 2) &&
 | 
				
			||||||
 | 
							(release.CreateNamespace != nil && *release.CreateNamespace ||
 | 
				
			||||||
 | 
								release.CreateNamespace == nil && (st.HelmDefaults.CreateNamespace == nil || *st.HelmDefaults.CreateNamespace)) {
 | 
				
			||||||
 | 
							flags = append(flags, "--create-namespace")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flags = st.appendConnectionFlags(flags, release)
 | 
						flags = st.appendConnectionFlags(flags, release)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,6 +163,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name     string
 | 
							name     string
 | 
				
			||||||
 | 
							version  *helmexec.Version
 | 
				
			||||||
		defaults HelmSpec
 | 
							defaults HelmSpec
 | 
				
			||||||
		release  *ReleaseSpec
 | 
							release  *ReleaseSpec
 | 
				
			||||||
		want     []string
 | 
							want     []string
 | 
				
			||||||
| 
						 | 
					@ -573,6 +574,101 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
 | 
				
			||||||
				"--tls-ca-cert", "ca.pem",
 | 
									"--tls-ca-cert", "ca.pem",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "create-namespace-default-helm3.2",
 | 
				
			||||||
 | 
								defaults: HelmSpec{
 | 
				
			||||||
 | 
									Verify: false,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								version: &helmexec.Version{
 | 
				
			||||||
 | 
									Major: 3,
 | 
				
			||||||
 | 
									Minor: 2,
 | 
				
			||||||
 | 
									Patch: 0,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								release: &ReleaseSpec{
 | 
				
			||||||
 | 
									Chart:     "test/chart",
 | 
				
			||||||
 | 
									Version:   "0.1",
 | 
				
			||||||
 | 
									Verify:    &disable,
 | 
				
			||||||
 | 
									Name:      "test-charts",
 | 
				
			||||||
 | 
									Namespace: "test-namespace",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								want: []string{
 | 
				
			||||||
 | 
									"--version", "0.1",
 | 
				
			||||||
 | 
									"--create-namespace",
 | 
				
			||||||
 | 
									"--namespace", "test-namespace",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "create-namespace-disabled-helm3.2",
 | 
				
			||||||
 | 
								defaults: HelmSpec{
 | 
				
			||||||
 | 
									Verify:          false,
 | 
				
			||||||
 | 
									CreateNamespace: &disable,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								version: &helmexec.Version{
 | 
				
			||||||
 | 
									Major: 3,
 | 
				
			||||||
 | 
									Minor: 2,
 | 
				
			||||||
 | 
									Patch: 0,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								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: "create-namespace-release-override-enabled-helm3.2",
 | 
				
			||||||
 | 
								defaults: HelmSpec{
 | 
				
			||||||
 | 
									Verify:          false,
 | 
				
			||||||
 | 
									CreateNamespace: &disable,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								version: &helmexec.Version{
 | 
				
			||||||
 | 
									Major: 3,
 | 
				
			||||||
 | 
									Minor: 2,
 | 
				
			||||||
 | 
									Patch: 0,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								release: &ReleaseSpec{
 | 
				
			||||||
 | 
									Chart:           "test/chart",
 | 
				
			||||||
 | 
									Version:         "0.1",
 | 
				
			||||||
 | 
									Verify:          &disable,
 | 
				
			||||||
 | 
									Name:            "test-charts",
 | 
				
			||||||
 | 
									Namespace:       "test-namespace",
 | 
				
			||||||
 | 
									CreateNamespace: &enable,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								want: []string{
 | 
				
			||||||
 | 
									"--version", "0.1",
 | 
				
			||||||
 | 
									"--create-namespace",
 | 
				
			||||||
 | 
									"--namespace", "test-namespace",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "create-namespace-release-override-disabled-helm3.2",
 | 
				
			||||||
 | 
								defaults: HelmSpec{
 | 
				
			||||||
 | 
									Verify:          false,
 | 
				
			||||||
 | 
									CreateNamespace: &enable,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								version: &helmexec.Version{
 | 
				
			||||||
 | 
									Major: 3,
 | 
				
			||||||
 | 
									Minor: 2,
 | 
				
			||||||
 | 
									Patch: 0,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								release: &ReleaseSpec{
 | 
				
			||||||
 | 
									Chart:           "test/chart",
 | 
				
			||||||
 | 
									Version:         "0.1",
 | 
				
			||||||
 | 
									Verify:          &disable,
 | 
				
			||||||
 | 
									Name:            "test-charts",
 | 
				
			||||||
 | 
									Namespace:       "test-namespace",
 | 
				
			||||||
 | 
									CreateNamespace: &disable,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								want: []string{
 | 
				
			||||||
 | 
									"--version", "0.1",
 | 
				
			||||||
 | 
									"--namespace", "test-namespace",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i := range tests {
 | 
						for i := range tests {
 | 
				
			||||||
		tt := tests[i]
 | 
							tt := tests[i]
 | 
				
			||||||
| 
						 | 
					@ -584,10 +680,13 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
 | 
				
			||||||
				HelmDefaults:      tt.defaults,
 | 
									HelmDefaults:      tt.defaults,
 | 
				
			||||||
				valsRuntime:       valsRuntime,
 | 
									valsRuntime:       valsRuntime,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			helm := helmexec.New("helm", logger, "default", &mockRunner{})
 | 
								helm := &exectest.Helm{
 | 
				
			||||||
 | 
									Version: tt.version,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			args, err := state.flagsForUpgrade(helm, tt.release, 0)
 | 
								args, err := state.flagsForUpgrade(helm, tt.release, 0)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				t.Errorf("unexpected error flagsForUpgade: %v", err)
 | 
									t.Errorf("unexpected error flagsForUpgrade: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if !reflect.DeepEqual(args, tt.want) {
 | 
								if !reflect.DeepEqual(args, tt.want) {
 | 
				
			||||||
				t.Errorf("flagsForUpgrade returned = %v, want %v", args, tt.want)
 | 
									t.Errorf("flagsForUpgrade returned = %v, want %v", args, tt.want)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue