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,24 +3065,12 @@ func unmarkNeedsDirectOnly(filteredReleases []Release) {
|
|||
|
||||
func collectDirectNeedsOnly(filteredReleases []Release) 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 {
|
||||
if !r.Filtered {
|
||||
for _, need := range r.ReleaseSpec.Needs {
|
||||
if fullID, ok := nameToID[need]; ok {
|
||||
directNeeds[fullID] = struct{}{}
|
||||
} else {
|
||||
parts := strings.Split(need, "/")
|
||||
needName := parts[len(parts)-1]
|
||||
if fullID, ok := nameToID[needName]; ok {
|
||||
directNeeds[fullID] = struct{}{}
|
||||
} else {
|
||||
directNeeds[need] = struct{}{}
|
||||
}
|
||||
}
|
||||
// After ApplyOverrides/reformat(), need IDs are already fully-qualified
|
||||
// (matching ReleaseToID format), so we collect them as-is.
|
||||
directNeeds[need] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue