fix: simplify collectDirectNeedsOnly to use need IDs as-is
After ApplyOverrides/reformat(), need IDs are already fully-qualified (matching ReleaseToID format). The previous name-based lookup could select the wrong dependency when multiple releases share the same name across namespaces/kubecontexts. Also adds a cross-namespace test case to verify correct behavior when releases share names across different namespaces. Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com> Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/e8effb99-17de-4b2e-ae14-cc90c2108146
This commit is contained in:
parent
a1bf95e9ba
commit
02a5de3330
|
|
@ -225,3 +225,53 @@ func TestSelectReleasesWithOverridesWithIncludedTransitives(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSelectReleasesWithIncludeNeedsCrossNamespace(t *testing.T) {
|
||||||
|
// When multiple releases share the same name across different namespaces,
|
||||||
|
// includeNeeds should resolve the correct dependency using fully-qualified IDs
|
||||||
|
// rather than name-based lookup (which would be ambiguous).
|
||||||
|
example := []byte(`releases:
|
||||||
|
- name: frontend
|
||||||
|
namespace: team-a
|
||||||
|
chart: stable/testchart
|
||||||
|
needs:
|
||||||
|
- team-a/backend
|
||||||
|
- name: backend
|
||||||
|
namespace: team-a
|
||||||
|
chart: stable/testchart
|
||||||
|
- name: backend
|
||||||
|
namespace: team-b
|
||||||
|
chart: stable/testchart
|
||||||
|
`)
|
||||||
|
|
||||||
|
state := stateTestEnv{
|
||||||
|
Files: map[string]string{
|
||||||
|
"/helmfile.yaml": string(example),
|
||||||
|
},
|
||||||
|
WorkDir: "/",
|
||||||
|
}.MustLoadState(t, "/helmfile.yaml", "default")
|
||||||
|
|
||||||
|
state.Selectors = []string{"name=frontend"}
|
||||||
|
var err error
|
||||||
|
state.Releases, err = state.GetReleasesWithOverrides()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
state.Releases = state.GetReleasesWithLabels()
|
||||||
|
|
||||||
|
rs, err := state.GetSelectedReleases(true, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got []string
|
||||||
|
for _, r := range rs {
|
||||||
|
got = append(got, r.Namespace+"/"+r.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should include team-a/backend (direct need) but NOT team-b/backend
|
||||||
|
want := []string{"team-a/frontend", "team-a/backend"}
|
||||||
|
if d := cmp.Diff(want, got); d != "" {
|
||||||
|
t.Errorf("cross-namespace include-needs: %s", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3065,27 +3065,15 @@ func unmarkNeedsDirectOnly(filteredReleases []Release) {
|
||||||
|
|
||||||
func collectDirectNeedsOnly(filteredReleases []Release) map[string]struct{} {
|
func collectDirectNeedsOnly(filteredReleases []Release) map[string]struct{} {
|
||||||
directNeeds := map[string]struct{}{}
|
directNeeds := map[string]struct{}{}
|
||||||
nameToID := map[string]string{}
|
|
||||||
for _, r := range filteredReleases {
|
|
||||||
nameToID[r.Name] = ReleaseToID(&r.ReleaseSpec)
|
|
||||||
}
|
|
||||||
for _, r := range filteredReleases {
|
for _, r := range filteredReleases {
|
||||||
if !r.Filtered {
|
if !r.Filtered {
|
||||||
for _, need := range r.ReleaseSpec.Needs {
|
for _, need := range r.ReleaseSpec.Needs {
|
||||||
if fullID, ok := nameToID[need]; ok {
|
// After ApplyOverrides/reformat(), need IDs are already fully-qualified
|
||||||
directNeeds[fullID] = struct{}{}
|
// (matching ReleaseToID format), so we collect them as-is.
|
||||||
} else {
|
|
||||||
parts := strings.Split(need, "/")
|
|
||||||
needName := parts[len(parts)-1]
|
|
||||||
if fullID, ok := nameToID[needName]; ok {
|
|
||||||
directNeeds[fullID] = struct{}{}
|
|
||||||
} else {
|
|
||||||
directNeeds[need] = struct{}{}
|
directNeeds[need] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return directNeeds
|
return directNeeds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue