mirror of
https://github.com/helmfile/helmfile.git
synced 2026-09-30 08:32:48 +02:00
fix: skip subhelmfiles when selectors conflict with CLI selectors (#2545)
* fix: skip subhelmfiles when selectors conflict with CLI selectors (#2544) When CLI selectors are provided (e.g. -l name=b), subhelmfiles whose explicit selectors are provably incompatible are now skipped entirely, avoiding unnecessary YAML loading and template rendering. Two selector sets are incompatible when every pair has a positive label conflict: same key with different values (e.g. name=b vs name=a). Negative labels are not compared. Fixes #2544 Signed-off-by: yxxhero <aiopsclub@163.com> * fix: address PR review comments - use CLI selectors, fix doc comment, add malformed selector test Agent-Logs-Url: https://github.com/helmfile/helmfile/sessions/1f1c33ce-e50d-4781-85b8-d606b5d4ca54 Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com> * fix: add debug logging, unit tests, docs, and fix integration test for subhelmfile selector skip - Add debug log when skipping subhelmfile due to selector conflict - Add TestSubhelmfileSelectorsConflict with 11 cases for direct unit coverage - Document the selector-based subhelmfile skip optimization in docs/index.md - Fix integration test: use 'app' label key instead of reserved 'name' key (GetReleasesWithLabels overwrites labels["name"] with the release name) Signed-off-by: yxxhero <aiopsclub@163.com> * refactor: avoid map allocation in positiveLabelsCompatibleWith Compare positive label slices directly instead of allocating a map per comparison, as label counts are typically small (1-3 entries). Addresses Copilot review comment on PR #2545. Signed-off-by: yxxhero <aiopsclub@163.com> * docs: clarify subhelmfile selector docs per Copilot review feedback Reword the first two bullets to avoid the contradiction between 'CLI selectors are ignored' and the new skip optimization. Signed-off-by: yxxhero <aiopsclub@163.com> * fix: address Copilot review comments round 3 - Log parse errors from SelectorsAreCompatible at debug level instead of silently discarding them - Hoist regex compilation to package-level vars in ParseLabels to avoid repeated compilation per selector - Replace EXIT traps with explicit cleanup calls in integration test to avoid interfering with the parent runner's trap Signed-off-by: yxxhero <aiopsclub@163.com> --------- Signed-off-by: yxxhero <aiopsclub@163.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
copilot-swe-agent[bot]
parent
c57134cda7
commit
5368ab8d95
@@ -139,6 +139,7 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes
|
||||
. ${dir}/test-cases/issue-2418.sh
|
||||
. ${dir}/test-cases/issue-2424-sequential-values-paths.sh
|
||||
. ${dir}/test-cases/issue-2431.sh
|
||||
. ${dir}/test-cases/issue-2544.sh
|
||||
. ${dir}/test-cases/kubedog-tracking.sh
|
||||
|
||||
# ALL DONE -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Test for issue #2544: subhelmfiles should only be evaluated if their selectors match
|
||||
# When CLI selectors are provided, subhelmfiles with incompatible selectors are skipped.
|
||||
|
||||
issue_2544_input_dir="${cases_dir}/issue-2544/input"
|
||||
issue_2544_tmp_dir=$(mktemp -d)
|
||||
|
||||
cleanup_issue_2544() {
|
||||
rm -rf "${issue_2544_tmp_dir}"
|
||||
}
|
||||
|
||||
test_start "issue-2544: subhelmfiles skipped when selectors conflict with CLI"
|
||||
|
||||
# --- Test 1: -l app=b should only produce output from subhelmfile-b ---------------------------
|
||||
|
||||
info "Running helmfile template -l app=b"
|
||||
${helmfile} -f "${issue_2544_input_dir}/helmfile.yaml" template -l app=b \
|
||||
> "${issue_2544_tmp_dir}/output-b.txt" 2>&1 || {
|
||||
cat "${issue_2544_tmp_dir}/output-b.txt"
|
||||
cleanup_issue_2544
|
||||
fail "helmfile template -l app=b failed"
|
||||
}
|
||||
|
||||
# Should contain release-b
|
||||
grep -q "release-b" "${issue_2544_tmp_dir}/output-b.txt" \
|
||||
|| { cleanup_issue_2544; fail "output should contain release-b (matching selector app=b)"; }
|
||||
|
||||
# Should NOT contain release-a or release-c (their subhelmfiles have incompatible selectors)
|
||||
grep -q "release-a" "${issue_2544_tmp_dir}/output-b.txt" \
|
||||
&& { cleanup_issue_2544; fail "output should NOT contain release-a (subhelmfile selectors app=a conflict with app=b)"; }
|
||||
|
||||
grep -q "release-c" "${issue_2544_tmp_dir}/output-b.txt" \
|
||||
&& { cleanup_issue_2544; fail "output should NOT contain release-c (subhelmfile selectors app=c conflict with app=b)"; }
|
||||
|
||||
info "PASS: -l app=b produces only release-b"
|
||||
|
||||
# --- Test 2: no selector should produce all releases -----------------------------------------
|
||||
|
||||
info "Running helmfile template without selector"
|
||||
${helmfile} -f "${issue_2544_input_dir}/helmfile.yaml" template \
|
||||
> "${issue_2544_tmp_dir}/output-all.txt" 2>&1 || {
|
||||
cat "${issue_2544_tmp_dir}/output-all.txt"
|
||||
cleanup_issue_2544
|
||||
fail "helmfile template without selector failed"
|
||||
}
|
||||
|
||||
grep -q "release-a" "${issue_2544_tmp_dir}/output-all.txt" \
|
||||
|| { cleanup_issue_2544; fail "output should contain release-a"; }
|
||||
grep -q "release-b" "${issue_2544_tmp_dir}/output-all.txt" \
|
||||
|| { cleanup_issue_2544; fail "output should contain release-b"; }
|
||||
grep -q "release-c" "${issue_2544_tmp_dir}/output-all.txt" \
|
||||
|| { cleanup_issue_2544; fail "output should contain release-c"; }
|
||||
|
||||
info "PASS: no selector produces all releases"
|
||||
|
||||
# --- Test 3: -l app=a should skip subhelmfiles with selectors app=b and app=c ---------------
|
||||
|
||||
info "Running helmfile template -l app=a"
|
||||
${helmfile} -f "${issue_2544_input_dir}/helmfile.yaml" template -l app=a \
|
||||
> "${issue_2544_tmp_dir}/output-a.txt" 2>&1 || {
|
||||
cat "${issue_2544_tmp_dir}/output-a.txt"
|
||||
cleanup_issue_2544
|
||||
fail "helmfile template -l app=a failed"
|
||||
}
|
||||
|
||||
grep -q "release-a" "${issue_2544_tmp_dir}/output-a.txt" \
|
||||
|| { cleanup_issue_2544; fail "output should contain release-a (matching selector app=a)"; }
|
||||
|
||||
grep -q "release-b" "${issue_2544_tmp_dir}/output-a.txt" \
|
||||
&& { cleanup_issue_2544; fail "output should NOT contain release-b (subhelmfile selectors app=b conflict with app=a)"; }
|
||||
|
||||
grep -q "release-c" "${issue_2544_tmp_dir}/output-a.txt" \
|
||||
&& { cleanup_issue_2544; fail "output should NOT contain release-c (subhelmfile selectors app=c conflict with app=a)"; }
|
||||
|
||||
info "PASS: -l app=a produces only release-a"
|
||||
|
||||
cleanup_issue_2544
|
||||
test_pass "issue-2544: subhelmfiles skipped when selectors conflict with CLI"
|
||||
@@ -0,0 +1,10 @@
|
||||
helmfiles:
|
||||
- path: subhelmfile-a.yaml
|
||||
selectors:
|
||||
- app=a
|
||||
- path: subhelmfile-b.yaml
|
||||
selectors:
|
||||
- app=b
|
||||
- path: subhelmfile-c.yaml
|
||||
selectors:
|
||||
- app=c
|
||||
@@ -0,0 +1,15 @@
|
||||
releases:
|
||||
- name: release-a
|
||||
chart: ../../../charts/raw
|
||||
labels:
|
||||
app: a
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: release-a
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
group: a
|
||||
@@ -0,0 +1,15 @@
|
||||
releases:
|
||||
- name: release-b
|
||||
chart: ../../../charts/raw
|
||||
labels:
|
||||
app: b
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: release-b
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
group: b
|
||||
@@ -0,0 +1,15 @@
|
||||
releases:
|
||||
- name: release-c
|
||||
chart: ../../../charts/raw
|
||||
labels:
|
||||
app: c
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: release-c
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
group: c
|
||||
Reference in New Issue
Block a user