feat: use helm status to find helm release (#1640)
* feat: use helm status to find helm release Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
		
							parent
							
								
									8f44f12f07
								
							
						
					
					
						commit
						75ad24e6dc
					
				|  | @ -534,6 +534,7 @@ Helmfile uses some OS environment variables to override default behaviour: | ||||||
| * `HELMFILE_DISABLE_INSECURE_FEATURES` - disable insecure features, expecting `true` lower case | * `HELMFILE_DISABLE_INSECURE_FEATURES` - disable insecure features, expecting `true` lower case | ||||||
| * `HELMFILE_DISABLE_RUNNER_UNIQUE_ID` - disable unique logging ID, expecting any non-empty value | * `HELMFILE_DISABLE_RUNNER_UNIQUE_ID` - disable unique logging ID, expecting any non-empty value | ||||||
| * `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` - disable insecure template functions, expecting `true` lower case | * `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` - disable insecure template functions, expecting `true` lower case | ||||||
|  | * `HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE` - expecting non-empty value to use `helm status` to check release existence, instead of `helm list` which is the default behaviour  | ||||||
| * `HELMFILE_EXPERIMENTAL` - enable experimental features, expecting `true` lower case | * `HELMFILE_EXPERIMENTAL` - enable experimental features, expecting `true` lower case | ||||||
| * `HELMFILE_ENVIRONMENT` - specify [Helmfile environment](https://helmfile.readthedocs.io/en/latest/#environment), it has lower priority than CLI argument `--environment` | * `HELMFILE_ENVIRONMENT` - specify [Helmfile environment](https://helmfile.readthedocs.io/en/latest/#environment), it has lower priority than CLI argument `--environment` | ||||||
| * `HELMFILE_TEMPDIR` - specify directory to store temporary files | * `HELMFILE_TEMPDIR` - specify directory to store temporary files | ||||||
|  |  | ||||||
|  | @ -2729,8 +2729,34 @@ func TestApply(t *testing.T) { | ||||||
| 		diffs             map[exectest.DiffKey]error | 		diffs             map[exectest.DiffKey]error | ||||||
| 		upgraded          []exectest.Release | 		upgraded          []exectest.Release | ||||||
| 		deleted           []exectest.Release | 		deleted           []exectest.Release | ||||||
|  | 		envs              map[string]string | ||||||
| 		log               string | 		log               string | ||||||
| 	}{ | 	}{ | ||||||
|  | 		//
 | ||||||
|  | 		// helm-status-check-to-release-existence
 | ||||||
|  | 		//
 | ||||||
|  | 		{ | ||||||
|  | 			name: "helm-status-check-to-release-existence", | ||||||
|  | 			loc:  location(), | ||||||
|  | 			files: map[string]string{ | ||||||
|  | 				"/path/to/helmfile.yaml": ` | ||||||
|  | releases: | ||||||
|  | - name: bar | ||||||
|  |   chart: stable/mychart2 | ||||||
|  | - name: foo_notFound | ||||||
|  |   chart: stable/mychart1 | ||||||
|  |   installed: false | ||||||
|  | `, | ||||||
|  | 			}, | ||||||
|  | 			diffs: map[exectest.DiffKey]error{ | ||||||
|  | 				{Name: "bar", Chart: "stable/mychart2", Flags: "--kube-context default --detailed-exitcode --reset-values"}:          nil, | ||||||
|  | 				{Name: "foo_notFound", Chart: "stable/mychart1", Flags: "--kube-context default --detailed-exitcode --reset-values"}: nil, | ||||||
|  | 			}, | ||||||
|  | 			lists:    map[exectest.ListKey]string{}, | ||||||
|  | 			upgraded: []exectest.Release{}, | ||||||
|  | 			deleted:  []exectest.Release{}, | ||||||
|  | 			envs:     map[string]string{"HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE": "true"}, | ||||||
|  | 		}, | ||||||
| 		//
 | 		//
 | ||||||
| 		// complex test cases for smoke testing
 | 		// complex test cases for smoke testing
 | ||||||
| 		//
 | 		//
 | ||||||
|  | @ -3457,73 +3483,6 @@ releases: | ||||||
| 			upgraded: []exectest.Release{}, | 			upgraded: []exectest.Release{}, | ||||||
| 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 | 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 			log: `processing file "helmfile.yaml" in directory "." |  | ||||||
| changing working directory to "/path/to" |  | ||||||
| first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> |  | ||||||
| first-pass uses: &{default  map[] map[]} |  | ||||||
| first-pass rendering output of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1:  |  | ||||||
|  2:  |  | ||||||
|  3: releases: |  | ||||||
|  4: - name: kubernetes-external-secrets |  | ||||||
|  5:   chart: incubator/raw |  | ||||||
|  6:   namespace: kube-system |  | ||||||
|  7:  |  | ||||||
|  8: - name: external-secrets |  | ||||||
|  9:   chart: incubator/raw |  | ||||||
| 10:   namespace: default |  | ||||||
| 11:   labels: |  | ||||||
| 12:     app: test |  | ||||||
| 13:   needs: |  | ||||||
| 14:   - kube-system/kubernetes-external-secrets |  | ||||||
| 15:  |  | ||||||
| 16: - name: my-release |  | ||||||
| 17:   chart: incubator/raw |  | ||||||
| 18:   namespace: default |  | ||||||
| 19:   labels: |  | ||||||
| 20:     app: test |  | ||||||
| 21:   needs: |  | ||||||
| 22:   - default/external-secrets |  | ||||||
| 23:  |  | ||||||
| 
 |  | ||||||
| first-pass produced: &{default  map[] map[]} |  | ||||||
| first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} |  | ||||||
| vals: |  | ||||||
| map[] |  | ||||||
| defaultVals:[] |  | ||||||
| second-pass rendering result of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1:  |  | ||||||
|  2:  |  | ||||||
|  3: releases: |  | ||||||
|  4: - name: kubernetes-external-secrets |  | ||||||
|  5:   chart: incubator/raw |  | ||||||
|  6:   namespace: kube-system |  | ||||||
|  7:  |  | ||||||
|  8: - name: external-secrets |  | ||||||
|  9:   chart: incubator/raw |  | ||||||
| 10:   namespace: default |  | ||||||
| 11:   labels: |  | ||||||
| 12:     app: test |  | ||||||
| 13:   needs: |  | ||||||
| 14:   - kube-system/kubernetes-external-secrets |  | ||||||
| 15:  |  | ||||||
| 16: - name: my-release |  | ||||||
| 17:   chart: incubator/raw |  | ||||||
| 18:   namespace: default |  | ||||||
| 19:   labels: |  | ||||||
| 20:     app: test |  | ||||||
| 21:   needs: |  | ||||||
| 22:   - default/external-secrets |  | ||||||
| 23:  |  | ||||||
| 
 |  | ||||||
| merged environment: &{default  map[] map[]} |  | ||||||
| 2 release(s) matching app=test found in helmfile.yaml |  | ||||||
| 
 |  | ||||||
| err: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies |  | ||||||
| changing working directory back to "/path/to" |  | ||||||
| `, |  | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			// see https://github.com/roboll/helmfile/issues/919#issuecomment-549831747
 | 			// see https://github.com/roboll/helmfile/issues/919#issuecomment-549831747
 | ||||||
|  | @ -3561,72 +3520,6 @@ releases: | ||||||
| 			error:     "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile", | 			error:     "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile", | ||||||
| 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 | 			// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
 | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 			log: `processing file "helmfile.yaml" in directory "." |  | ||||||
| changing working directory to "/path/to" |  | ||||||
| first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> |  | ||||||
| first-pass uses: &{default  map[] map[]} |  | ||||||
| first-pass rendering output of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1:  |  | ||||||
|  2:  |  | ||||||
|  3: releases: |  | ||||||
|  4: - name: kubernetes-external-secrets |  | ||||||
|  5:   chart: incubator/raw |  | ||||||
|  6:   namespace: kube-system |  | ||||||
|  7:  |  | ||||||
|  8: - name: external-secrets |  | ||||||
|  9:   chart: incubator/raw |  | ||||||
| 10:   namespace: default |  | ||||||
| 11:   labels: |  | ||||||
| 12:     app: test |  | ||||||
| 13:   needs: |  | ||||||
| 14:   - kube-system/kubernetes-external-secrets |  | ||||||
| 15:  |  | ||||||
| 16: - name: my-release |  | ||||||
| 17:   chart: incubator/raw |  | ||||||
| 18:   namespace: default |  | ||||||
| 19:   labels: |  | ||||||
| 20:     app: test |  | ||||||
| 21:   needs: |  | ||||||
| 22:   - default/external-secrets |  | ||||||
| 23:  |  | ||||||
| 
 |  | ||||||
| first-pass produced: &{default  map[] map[]} |  | ||||||
| first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} |  | ||||||
| vals: |  | ||||||
| map[] |  | ||||||
| defaultVals:[] |  | ||||||
| second-pass rendering result of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1:  |  | ||||||
|  2:  |  | ||||||
|  3: releases: |  | ||||||
|  4: - name: kubernetes-external-secrets |  | ||||||
|  5:   chart: incubator/raw |  | ||||||
|  6:   namespace: kube-system |  | ||||||
|  7:  |  | ||||||
|  8: - name: external-secrets |  | ||||||
|  9:   chart: incubator/raw |  | ||||||
| 10:   namespace: default |  | ||||||
| 11:   labels: |  | ||||||
| 12:     app: test |  | ||||||
| 13:   needs: |  | ||||||
| 14:   - kube-system/kubernetes-external-secrets |  | ||||||
| 15:  |  | ||||||
| 16: - name: my-release |  | ||||||
| 17:   chart: incubator/raw |  | ||||||
| 18:   namespace: default |  | ||||||
| 19:   labels: |  | ||||||
| 20:     app: test |  | ||||||
| 21:   needs: |  | ||||||
| 22:   - default/external-secrets |  | ||||||
| 23:  |  | ||||||
| 
 |  | ||||||
| merged environment: &{default  map[] map[]} |  | ||||||
| 0 release(s) matching app=test_non_existent found in helmfile.yaml |  | ||||||
| 
 |  | ||||||
| changing working directory back to "/path/to" |  | ||||||
| `, |  | ||||||
| 		}, | 		}, | ||||||
| 		//
 | 		//
 | ||||||
| 		// error cases
 | 		// error cases
 | ||||||
|  | @ -3656,45 +3549,6 @@ releases: | ||||||
| 			deleted:     []exectest.Release{}, | 			deleted:     []exectest.Release{}, | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 			error:       `in ./helmfile.yaml: release "default//foo" depends on "default/ns1/bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`, | 			error:       `in ./helmfile.yaml: release "default//foo" depends on "default/ns1/bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`, | ||||||
| 			log: `processing file "helmfile.yaml" in directory "." |  | ||||||
| changing working directory to "/path/to" |  | ||||||
| first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> |  | ||||||
| first-pass uses: &{default  map[] map[]} |  | ||||||
| first-pass rendering output of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: bar |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart1 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9:  |  | ||||||
| 
 |  | ||||||
| first-pass produced: &{default  map[] map[]} |  | ||||||
| first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} |  | ||||||
| vals: |  | ||||||
| map[] |  | ||||||
| defaultVals:[] |  | ||||||
| second-pass rendering result of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: bar |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart1 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9:  |  | ||||||
| 
 |  | ||||||
| merged environment: &{default  map[] map[]} |  | ||||||
| 1 release(s) matching name=foo found in helmfile.yaml |  | ||||||
| 
 |  | ||||||
| err: release "default//foo" depends on "default/ns1/bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies |  | ||||||
| changing working directory back to "/path/to" |  | ||||||
| `, |  | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name: "non-existent release in needs", | 			name: "non-existent release in needs", | ||||||
|  | @ -3720,46 +3574,6 @@ releases: | ||||||
| 			deleted:     []exectest.Release{}, | 			deleted:     []exectest.Release{}, | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 			error:       "in ./helmfile.yaml: release(s) \"default//foo\" depend(s) on an undefined release \"default/ns1/bar\". Perhaps you made a typo in \"needs\" or forgot defining a release named \"bar\" with appropriate \"namespace\" and \"kubeContext\"?", | 			error:       "in ./helmfile.yaml: release(s) \"default//foo\" depend(s) on an undefined release \"default/ns1/bar\". Perhaps you made a typo in \"needs\" or forgot defining a release named \"bar\" with appropriate \"namespace\" and \"kubeContext\"?", | ||||||
| 			log: `processing file "helmfile.yaml" in directory "." |  | ||||||
| changing working directory to "/path/to" |  | ||||||
| first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> |  | ||||||
| first-pass uses: &{default  map[] map[]} |  | ||||||
| first-pass rendering output of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: baz |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart1 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9:  |  | ||||||
| 
 |  | ||||||
| first-pass produced: &{default  map[] map[]} |  | ||||||
| first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} |  | ||||||
| vals: |  | ||||||
| map[] |  | ||||||
| defaultVals:[] |  | ||||||
| second-pass rendering result of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: baz |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart1 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9:  |  | ||||||
| 
 |  | ||||||
| merged environment: &{default  map[] map[]} |  | ||||||
| WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs |  | ||||||
| 2 release(s) found in helmfile.yaml |  | ||||||
| 
 |  | ||||||
| err: release(s) "default//foo" depend(s) on an undefined release "default/ns1/bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"? |  | ||||||
| changing working directory back to "/path/to" |  | ||||||
| `, |  | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name: "duplicate releases", | 			name: "duplicate releases", | ||||||
|  | @ -3789,56 +3603,17 @@ releases: | ||||||
| 			deleted:     []exectest.Release{}, | 			deleted:     []exectest.Release{}, | ||||||
| 			concurrency: 1, | 			concurrency: 1, | ||||||
| 			error:       "in ./helmfile.yaml: found 2 duplicate releases with ID \"default//foo\"", | 			error:       "in ./helmfile.yaml: found 2 duplicate releases with ID \"default//foo\"", | ||||||
| 			log: `processing file "helmfile.yaml" in directory "." |  | ||||||
| changing working directory to "/path/to" |  | ||||||
| first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> |  | ||||||
| first-pass uses: &{default  map[] map[]} |  | ||||||
| first-pass rendering output of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: bar |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart2 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9: - name: foo |  | ||||||
| 10:   chart: mychart1 |  | ||||||
| 11:   needs: |  | ||||||
| 12:   - ns1/bar |  | ||||||
| 13:  |  | ||||||
| 
 |  | ||||||
| first-pass produced: &{default  map[] map[]} |  | ||||||
| first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} |  | ||||||
| vals: |  | ||||||
| map[] |  | ||||||
| defaultVals:[] |  | ||||||
| second-pass rendering result of "helmfile.yaml.part.0": |  | ||||||
|  0:  |  | ||||||
|  1: releases: |  | ||||||
|  2: - name: bar |  | ||||||
|  3:   namespace: ns1 |  | ||||||
|  4:   chart: mychart3 |  | ||||||
|  5: - name: foo |  | ||||||
|  6:   chart: mychart2 |  | ||||||
|  7:   needs: |  | ||||||
|  8:   - ns1/bar |  | ||||||
|  9: - name: foo |  | ||||||
| 10:   chart: mychart1 |  | ||||||
| 11:   needs: |  | ||||||
| 12:   - ns1/bar |  | ||||||
| 13:  |  | ||||||
| 
 |  | ||||||
| merged environment: &{default  map[] map[]} |  | ||||||
| err: found 2 duplicate releases with ID "default//foo" |  | ||||||
| changing working directory back to "/path/to" |  | ||||||
| `, |  | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, tc := range testcases { | 	for _, tc := range testcases { | ||||||
| 		t.Run(tc.name, func(t *testing.T) { | 		t.Run(tc.name, func(t *testing.T) { | ||||||
|  | 			if tc.envs != nil { | ||||||
|  | 				for k, v := range tc.envs { | ||||||
|  | 					os.Setenv(k, v) | ||||||
|  | 					defer os.Unsetenv(k) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 			wantUpgrades := tc.upgraded | 			wantUpgrades := tc.upgraded | ||||||
| 			wantDeletes := tc.deleted | 			wantDeletes := tc.deleted | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,44 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart2 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9: - name: foo | ||||||
|  | 10:   chart: mychart1 | ||||||
|  | 11:   needs: | ||||||
|  | 12:   - ns1/bar | ||||||
|  | 13:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart2 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9: - name: foo | ||||||
|  | 10:   chart: mychart1 | ||||||
|  | 11:   needs: | ||||||
|  | 12:   - ns1/bar | ||||||
|  | 13:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | err: found 2 duplicate releases with ID "default//foo" | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -0,0 +1,39 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   chart: stable/mychart2 | ||||||
|  |  4: - name: foo_notFound | ||||||
|  |  5:   chart: stable/mychart1 | ||||||
|  |  6:   installed: false | ||||||
|  |  7:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   chart: stable/mychart2 | ||||||
|  |  4: - name: foo_notFound | ||||||
|  |  5:   chart: stable/mychart1 | ||||||
|  |  6:   installed: false | ||||||
|  |  7:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | 2 release(s) found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | Checking release existence using `helm status` for release foo_notFound | ||||||
|  | invoking preapply hooks for 1 groups of releases in this order: | ||||||
|  | GROUP RELEASES | ||||||
|  | 1     default//bar, default//foo_notFound | ||||||
|  | 
 | ||||||
|  | invoking preapply hooks for releases in group 1/1: default//bar, default//foo_notFound | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -0,0 +1,39 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: baz | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart1 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: baz | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart1 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | WARNING: release foo needs bar, but bar is not installed due to installed: false. Either mark bar as installed or remove bar from foo's needs | ||||||
|  | 2 release(s) found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | err: release(s) "default//foo" depend(s) on an undefined release "default/ns1/bar". Perhaps you made a typo in "needs" or forgot defining a release named "bar" with appropriate "namespace" and "kubeContext"? | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -0,0 +1,38 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart1 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: bar | ||||||
|  |  3:   namespace: ns1 | ||||||
|  |  4:   chart: mychart3 | ||||||
|  |  5: - name: foo | ||||||
|  |  6:   chart: mychart1 | ||||||
|  |  7:   needs: | ||||||
|  |  8:   - ns1/bar | ||||||
|  |  9:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | 1 release(s) matching name=foo found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | err: release "default//foo" depends on "default/ns1/bar" which does not match the selectors. Please add a selector like "--selector name=bar", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -0,0 +1,65 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1:  | ||||||
|  |  2:  | ||||||
|  |  3: releases: | ||||||
|  |  4: - name: kubernetes-external-secrets | ||||||
|  |  5:   chart: incubator/raw | ||||||
|  |  6:   namespace: kube-system | ||||||
|  |  7:  | ||||||
|  |  8: - name: external-secrets | ||||||
|  |  9:   chart: incubator/raw | ||||||
|  | 10:   namespace: default | ||||||
|  | 11:   labels: | ||||||
|  | 12:     app: test | ||||||
|  | 13:   needs: | ||||||
|  | 14:   - kube-system/kubernetes-external-secrets | ||||||
|  | 15:  | ||||||
|  | 16: - name: my-release | ||||||
|  | 17:   chart: incubator/raw | ||||||
|  | 18:   namespace: default | ||||||
|  | 19:   labels: | ||||||
|  | 20:     app: test | ||||||
|  | 21:   needs: | ||||||
|  | 22:   - default/external-secrets | ||||||
|  | 23:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1:  | ||||||
|  |  2:  | ||||||
|  |  3: releases: | ||||||
|  |  4: - name: kubernetes-external-secrets | ||||||
|  |  5:   chart: incubator/raw | ||||||
|  |  6:   namespace: kube-system | ||||||
|  |  7:  | ||||||
|  |  8: - name: external-secrets | ||||||
|  |  9:   chart: incubator/raw | ||||||
|  | 10:   namespace: default | ||||||
|  | 11:   labels: | ||||||
|  | 12:     app: test | ||||||
|  | 13:   needs: | ||||||
|  | 14:   - kube-system/kubernetes-external-secrets | ||||||
|  | 15:  | ||||||
|  | 16: - name: my-release | ||||||
|  | 17:   chart: incubator/raw | ||||||
|  | 18:   namespace: default | ||||||
|  | 19:   labels: | ||||||
|  | 20:     app: test | ||||||
|  | 21:   needs: | ||||||
|  | 22:   - default/external-secrets | ||||||
|  | 23:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | 0 release(s) matching app=test_non_existent found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1:  | ||||||
|  |  2:  | ||||||
|  |  3: releases: | ||||||
|  |  4: - name: kubernetes-external-secrets | ||||||
|  |  5:   chart: incubator/raw | ||||||
|  |  6:   namespace: kube-system | ||||||
|  |  7:  | ||||||
|  |  8: - name: external-secrets | ||||||
|  |  9:   chart: incubator/raw | ||||||
|  | 10:   namespace: default | ||||||
|  | 11:   labels: | ||||||
|  | 12:     app: test | ||||||
|  | 13:   needs: | ||||||
|  | 14:   - kube-system/kubernetes-external-secrets | ||||||
|  | 15:  | ||||||
|  | 16: - name: my-release | ||||||
|  | 17:   chart: incubator/raw | ||||||
|  | 18:   namespace: default | ||||||
|  | 19:   labels: | ||||||
|  | 20:     app: test | ||||||
|  | 21:   needs: | ||||||
|  | 22:   - default/external-secrets | ||||||
|  | 23:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1:  | ||||||
|  |  2:  | ||||||
|  |  3: releases: | ||||||
|  |  4: - name: kubernetes-external-secrets | ||||||
|  |  5:   chart: incubator/raw | ||||||
|  |  6:   namespace: kube-system | ||||||
|  |  7:  | ||||||
|  |  8: - name: external-secrets | ||||||
|  |  9:   chart: incubator/raw | ||||||
|  | 10:   namespace: default | ||||||
|  | 11:   labels: | ||||||
|  | 12:     app: test | ||||||
|  | 13:   needs: | ||||||
|  | 14:   - kube-system/kubernetes-external-secrets | ||||||
|  | 15:  | ||||||
|  | 16: - name: my-release | ||||||
|  | 17:   chart: incubator/raw | ||||||
|  | 18:   namespace: default | ||||||
|  | 19:   labels: | ||||||
|  | 20:     app: test | ||||||
|  | 21:   needs: | ||||||
|  | 22:   - default/external-secrets | ||||||
|  | 23:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | 2 release(s) matching app=test found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | err: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -3,6 +3,9 @@ package envvar | ||||||
| const ( | const ( | ||||||
| 	DisableInsecureFeatures = "HELMFILE_DISABLE_INSECURE_FEATURES" | 	DisableInsecureFeatures = "HELMFILE_DISABLE_INSECURE_FEATURES" | ||||||
| 
 | 
 | ||||||
|  | 	// use helm status to check if a release exists before installing it
 | ||||||
|  | 	UseHelmStatusToCheckReleaseExistence = "HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE" | ||||||
|  | 
 | ||||||
| 	// TODO: Remove this function once Helmfile v0.x
 | 	// TODO: Remove this function once Helmfile v0.x
 | ||||||
| 	SkipInsecureTemplateFunctions = "HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS" | 	SkipInsecureTemplateFunctions = "HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -138,6 +138,9 @@ func (helm *Helm) DiffRelease(context helmexec.HelmContext, name, chart, namespa | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| func (helm *Helm) ReleaseStatus(context helmexec.HelmContext, release string, flags ...string) error { | func (helm *Helm) ReleaseStatus(context helmexec.HelmContext, release string, flags ...string) error { | ||||||
|  | 	if strings.Contains(release, "notFound") { | ||||||
|  | 		return errors.New("Error: release: not found") | ||||||
|  | 	} | ||||||
| 	if strings.Contains(release, "error") { | 	if strings.Contains(release, "error") { | ||||||
| 		return errors.New("error") | 		return errors.New("error") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/helmfile/helmfile/pkg/argparser" | 	"github.com/helmfile/helmfile/pkg/argparser" | ||||||
| 	"github.com/helmfile/helmfile/pkg/environment" | 	"github.com/helmfile/helmfile/pkg/environment" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/envvar" | ||||||
| 	"github.com/helmfile/helmfile/pkg/event" | 	"github.com/helmfile/helmfile/pkg/event" | ||||||
| 	"github.com/helmfile/helmfile/pkg/filesystem" | 	"github.com/helmfile/helmfile/pkg/filesystem" | ||||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||||
|  | @ -698,13 +699,25 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) isReleaseInstalled(context helmexec.HelmContext, helm helmexec.Interface, release ReleaseSpec) (bool, error) { | func (st *HelmState) isReleaseInstalled(context helmexec.HelmContext, helm helmexec.Interface, release ReleaseSpec) (bool, error) { | ||||||
|  | 	if os.Getenv(envvar.UseHelmStatusToCheckReleaseExistence) != "" { | ||||||
|  | 		st.logger.Debugf("Checking release existence using `helm status` for release %s", release.Name) | ||||||
|  | 
 | ||||||
|  | 		flags := st.kubeConnectionFlags(&release) | ||||||
|  | 		if release.Namespace != "" { | ||||||
|  | 			flags = append(flags, "--namespace", release.Namespace) | ||||||
|  | 		} | ||||||
|  | 		err := helm.ReleaseStatus(context, release.Name, flags...) | ||||||
|  | 		if err != nil && strings.Contains(err.Error(), "Error: release: not found") { | ||||||
|  | 			return false, nil | ||||||
|  | 		} | ||||||
|  | 		return true, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	out, err := st.listReleases(context, helm, &release) | 	out, err := st.listReleases(context, helm, &release) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return false, err | 		return false, err | ||||||
| 	} else if out != "" { |  | ||||||
| 		return true, nil |  | ||||||
| 	} | 	} | ||||||
| 	return false, nil | 	return out != "", nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) DetectReleasesToBeDeletedForSync(helm helmexec.Interface, releases []ReleaseSpec) ([]ReleaseSpec, error) { | func (st *HelmState) DetectReleasesToBeDeletedForSync(helm helmexec.Interface, releases []ReleaseSpec) ([]ReleaseSpec, error) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue