Fix broken selector and DAG calculation logic after --{include,skip}-needs addition with correct Release IDs (#1823)

#1772 broke `--selector` with `needs` in many ways.

The two biggest problems I've encountered were:

- duplicate releases even if you've provided a proper `selector` to deduplicate
- sync/deletion ordering broken when you have `needs`

For the first issue, we had to update `getSelectedReleases` function to also calculate the "selected releases and releases needed by the selected releases", and use that to calculate the DAG. That should have been done in #1772.

The latter started happening after I've fixed the first issue. The source of the issue was that `needs` turned out to be ambiguous in a few cases.

Previously, `needs: ["foo/bar"]` had two meanings. One for "needs release bar in kubecontext foo", another for "needs release bar in namespace foo".

Moreover, `needs: ["foo/bar/baz"]` had three meanings.

- `needs release baz in tiller namespace foo and namespace baz`
- `needs release baz in namespace bar in kubecontext foo`
- `needs release baz in tiller namespace bar in kubecontext foo`.

Especially, the first meaning doesn't make sense at all. Helm 2 solely use tillerNamespace for namespacing the release and Helm 3 uses namespace for that.

This fix sorts all the bugs and issues I've found so far around that, by changing the meanings of the above two examples as follows:

- `foo/bar` means `namespace=foo,name=bar` for Helm 3 and `tillerNamespace=foo,name=bar` for Helm 2
  - `needs release bar in kubecontext foo` is now `foo//bar`. Notice the extra `/` between `foo` and `bar`.
- `foo/bar/baz` means `kubecontext=foo,namespace=bar,name=baz` for Helm 3 and `kubecontext=foo,tillerNamespace=bar,name=baz` in Helm 2

Fixes #1818
This commit is contained in:
Yusuke Kuoka
2021-05-01 21:59:25 +09:00
committed by GitHub
parent de8644a504
commit 08db073958
10 changed files with 517 additions and 123 deletions
+76 -8
View File
@@ -593,7 +593,7 @@ releases:
upgraded: []exectest.Release{},
},
{
name: "upgrade when ns2/bar needs ns1/foo",
name: "helm3: upgrade when ns2/bar needs ns1/foo",
loc: location(),
files: map[string]string{
"/path/to/helmfile.yaml": `
@@ -628,7 +628,7 @@ releases:
namespace: ns1
tillerNamespace: tns1
needs:
- tns2/ns2/bar
- tns2/bar
- name: bar
chart: mychart2
namespace: ns2
@@ -644,7 +644,7 @@ releases:
upgraded: []exectest.Release{},
},
{
name: "upgrade when tns2/ns2/bar needs tns1/ns1/foo",
name: "helm2: upgrade when tns2/bar needs tns1/foo",
loc: location(),
files: map[string]string{
"/path/to/helmfile.yaml": `
@@ -654,7 +654,7 @@ releases:
namespace: ns2
tillerNamespace: tns2
needs:
- tns1/ns1/foo
- tns1/foo
- name: foo
chart: mychart1
namespace: ns1
@@ -681,7 +681,7 @@ first-pass rendering output of "helmfile.yaml.part.0":
4: namespace: ns2
5: tillerNamespace: tns2
6: needs:
7: - tns1/ns1/foo
7: - tns1/foo
8: - name: foo
9: chart: mychart1
10: namespace: ns1
@@ -701,7 +701,7 @@ second-pass rendering result of "helmfile.yaml.part.0":
4: namespace: ns2
5: tillerNamespace: tns2
6: needs:
7: - tns1/ns1/foo
7: - tns1/foo
8: - name: foo
9: chart: mychart1
10: namespace: ns1
@@ -711,6 +711,74 @@ second-pass rendering result of "helmfile.yaml.part.0":
merged environment: &{default map[] map[]}
2 release(s) found in helmfile.yaml
Affected releases are:
bar (mychart2) UPDATED
foo (mychart1) UPDATED
`,
},
{
name: "helm3: upgrade when ns2/bar needs ns1/foo",
loc: location(),
files: map[string]string{
"/path/to/helmfile.yaml": `
releases:
- name: bar
chart: mychart2
namespace: ns2
needs:
- ns1/foo
- name: foo
chart: mychart1
namespace: ns1
`,
},
detailedExitcode: true,
error: "Identified at least one change",
diffs: map[exectest.DiffKey]error{
exectest.DiffKey{Name: "bar", Chart: "mychart2", Flags: "--kube-contextdefault--namespacens2--detailed-exitcode"}: helmexec.ExitError{Code: 2},
exectest.DiffKey{Name: "foo", Chart: "mychart1", Flags: "--kube-contextdefault--namespacens1--detailed-exitcode"}: helmexec.ExitError{Code: 2},
},
upgraded: []exectest.Release{},
// as we check for log output, set concurrency to 1 to avoid non-deterministic test result
concurrency: 1,
log: `processing file "helmfile.yaml" in directory "."
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: mychart2
4: namespace: ns2
5: needs:
6: - ns1/foo
7: - name: foo
8: chart: mychart1
9: namespace: ns1
10:
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: mychart2
4: namespace: ns2
5: needs:
6: - ns1/foo
7: - name: foo
8: chart: mychart1
9: namespace: ns1
10:
merged environment: &{default map[] map[]}
2 release(s) found in helmfile.yaml
Affected releases are:
bar (mychart2) UPDATED
foo (mychart1) UPDATED
@@ -1263,7 +1331,7 @@ releases:
upgraded: []exectest.Release{},
deleted: []exectest.Release{},
concurrency: 1,
error: `in ./helmfile.yaml: release "default/foo" depends on "default/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//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 "."
first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode=<nil>
first-pass uses: &{default map[] map[]}
@@ -1299,7 +1367,7 @@ second-pass rendering result of "helmfile.yaml.part.0":
merged environment: &{default map[] map[]}
2 release(s) found in helmfile.yaml
err: release "default/foo" depends on "default/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
err: release "default//foo" depends on "default//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
`,
},
}