mirror of
https://github.com/helmfile/helmfile.git
synced 2026-10-21 11:33:39 +02:00
Merge remote-tracking branch 'origin/main' into fix-include-needs-transitive-1003
Resolve merge conflicts in pkg/app/app.go: - WithPreparedCharts rename (withPreparedCharts -> WithPreparedCharts) - WriteOutput handling for fetch command - DetailedExitcode handling for sync command - GetPlannedAndSelectedReleasesWithNeeds new function (pass both includeNeeds params) - SyncState using GetPlannedAndSelectedReleasesWithNeeds Also fix ForEachState call signatures in tests to include both bool params.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
Adding repo myrepo http://localhost:18080/
|
||||
"myrepo" has been added to your repositories
|
||||
|
||||
Building dependency release=foo, chart=$WD/temp1/foo
|
||||
Hang tight while we grab the latest from your chart repositories...
|
||||
...Successfully got an update from the "myrepo" chart repository
|
||||
Update Complete. ⎈Happy Helming!⎈
|
||||
Saving 1 charts
|
||||
Downloading raw from repo http://localhost:18080/
|
||||
Deleting outdated charts
|
||||
|
||||
Templating release=foo, chart=$WD/temp1/foo
|
||||
---
|
||||
# Source: raw/charts/dep/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-2
|
||||
namespace: default
|
||||
data:
|
||||
bar: BAR
|
||||
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-1
|
||||
namespace: default
|
||||
data:
|
||||
foo: FOO
|
||||
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
Live output is enabled
|
||||
Adding repo myrepo http://localhost:18081/
|
||||
"myrepo" has been added to your repositories
|
||||
|
||||
Building dependency release=foo, chart=$WD/temp1/foo
|
||||
Hang tight while we grab the latest from your chart repositories...
|
||||
...Successfully got an update from the "myrepo" chart repository
|
||||
Update Complete. ⎈Happy Helming!⎈
|
||||
Saving 1 charts
|
||||
Downloading raw from repo http://localhost:18081/
|
||||
Deleting outdated charts
|
||||
|
||||
Templating release=foo, chart=$WD/temp1/foo
|
||||
---
|
||||
# Source: raw/charts/dep/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-2
|
||||
namespace: default
|
||||
data:
|
||||
bar: BAR
|
||||
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-1
|
||||
namespace: default
|
||||
data:
|
||||
foo: FOO
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
Building dependency release=foo, chart=$WD/temp1/foo
|
||||
Saving 1 charts
|
||||
Downloading raw from repo oci://localhost:$REGISTRY_PORT/myrepo
|
||||
Deleting outdated charts
|
||||
|
||||
Templating release=foo, chart=$WD/temp1/foo
|
||||
---
|
||||
# Source: raw/charts/dep/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-2
|
||||
namespace: default
|
||||
data:
|
||||
bar: BAR
|
||||
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-1
|
||||
namespace: default
|
||||
data:
|
||||
foo: FOO
|
||||
|
||||
@@ -13,6 +13,7 @@ data:
|
||||
two: TWO
|
||||
metadata:
|
||||
name: cm2
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
@@ -32,6 +33,7 @@ data:
|
||||
one: ONE
|
||||
metadata:
|
||||
name: cm1
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
|
||||
@@ -27,7 +27,7 @@ export HELM_DATA_HOME="${helm_dir}/data"
|
||||
export HELM_HOME="${HELM_DATA_HOME}"
|
||||
export HELM_PLUGINS="${HELM_DATA_HOME}/plugins"
|
||||
export HELM_CONFIG_HOME="${helm_dir}/config"
|
||||
HELM_DIFF_VERSION="${HELM_DIFF_VERSION:-3.15.3}"
|
||||
HELM_DIFF_VERSION="${HELM_DIFF_VERSION:-3.15.7}"
|
||||
HELM_GIT_VERSION="${HELM_GIT_VERSION:-1.4.1}"
|
||||
HELM_SECRETS_VERSION="${HELM_SECRETS_VERSION:-4.7.4}"
|
||||
export GNUPGHOME="${PWD}/${dir}/.gnupg"
|
||||
@@ -96,8 +96,10 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes
|
||||
|
||||
# TEST CASES----------------------------------------------------------------------------------------------------------
|
||||
|
||||
. ${dir}/test-cases/issue-2502-race-condition-local-chart.sh
|
||||
. ${dir}/test-cases/chart-deps-condition.sh
|
||||
. ${dir}/test-cases/fetch-forl-local-chart.sh
|
||||
. ${dir}/test-cases/fetch-write-output.sh
|
||||
. ${dir}/test-cases/suppress-output-line-regex.sh
|
||||
. ${dir}/test-cases/chartify-jsonPatches-and-strategicMergePatches.sh
|
||||
. ${dir}/test-cases/include-template-func.sh
|
||||
@@ -114,6 +116,8 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes
|
||||
. ${dir}/test-cases/yaml-overwrite.sh
|
||||
. ${dir}/test-cases/chart-needs.sh
|
||||
. ${dir}/test-cases/postrender.sh
|
||||
. ${dir}/test-cases/postrender-defaults-args.sh
|
||||
. ${dir}/test-cases/issue-2515.sh
|
||||
. ${dir}/test-cases/chartify.sh
|
||||
. ${dir}/test-cases/deps-mr-1011.sh
|
||||
. ${dir}/test-cases/deps-kustomization-i-1402.sh
|
||||
@@ -138,6 +142,9 @@ ${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/issue-2596-local-deps-multiple-files.sh
|
||||
. ${dir}/test-cases/issue-2599-default-inherit.sh
|
||||
. ${dir}/test-cases/kubedog-tracking.sh
|
||||
. ${dir}/test-cases/include-needs-transitive.sh
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
fetch_write_output_input_dir="${cases_dir}/fetch-write-output/input"
|
||||
|
||||
fetch_write_output_tmp=$(mktemp -d)
|
||||
|
||||
case_title="fetch with --write-output for air-gapped environments"
|
||||
|
||||
test_start "$case_title"
|
||||
|
||||
info "Testing helmfile fetch --write-output with local chart"
|
||||
output=$(${helmfile} -f "${fetch_write_output_input_dir}/helmfile.yaml.gotmpl" fetch --output-dir "${fetch_write_output_tmp}" --write-output 2>/dev/null) \
|
||||
|| fail "\"helmfile fetch --write-output\" shouldn't fail"
|
||||
|
||||
info "Verifying stdout does not contain non-YAML status messages"
|
||||
echo "${output}" | grep -q "^Charts will be downloaded to:" && fail "stdout should not contain 'Charts will be downloaded to:' (should be on stderr)" || true
|
||||
|
||||
info "Verifying output contains YAML document separator"
|
||||
echo "${output}" | grep -q "^---" || fail "output should contain YAML document separator"
|
||||
|
||||
info "Verifying output contains source helmfile reference"
|
||||
echo "${output}" | grep -q "# Source:" || fail "output should contain source helmfile reference"
|
||||
|
||||
info "Verifying output contains release name"
|
||||
echo "${output}" | grep -q "name: local-chart" || fail "output should contain release name"
|
||||
|
||||
info "Verifying output contains updated chart path pointing to output dir"
|
||||
echo "${output}" | grep -q "chart:" || fail "output should contain chart field"
|
||||
|
||||
info "Verifying chart files exist in output directory"
|
||||
cat "${fetch_write_output_tmp}/helmfile-tests/local-chart/raw/latest/Chart.yaml" || fail "Chart.yaml should exist in fetched output directory"
|
||||
|
||||
info "Verifying the chart path in output matches the actual downloaded location"
|
||||
chart_path=$(echo "${output}" | grep -E "^[[:space:]]+(-[[:space:]]+)?chart:" | head -1 | sed 's/.*chart: *//' | tr -d '"')
|
||||
if [ ! -f "${chart_path}/Chart.yaml" ]; then
|
||||
fail "chart path '${chart_path}' from output should point to a directory containing Chart.yaml"
|
||||
fi
|
||||
|
||||
rm -rf "${fetch_write_output_tmp}"
|
||||
|
||||
test_pass "$case_title"
|
||||
@@ -0,0 +1,4 @@
|
||||
releases:
|
||||
- name: local-chart
|
||||
chart: ../../../charts/raw
|
||||
namespace: local-chart
|
||||
@@ -1,5 +1,10 @@
|
||||
// server.go is a small HTTP server used by the issue-2103 integration test.
|
||||
// It serves different YAML content based on the "ref" query parameter.
|
||||
// It is excluded from normal `go test ./...` runs; the integration test builds it
|
||||
// explicitly via its file path.
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Test for issue #2271: lookup function should work with strategicMergePatches
|
||||
# Test for issue #2271: lookup function should work with strategicMergePatches and jsonPatches
|
||||
# Without this fix, helm template runs client-side and lookup() returns empty values
|
||||
|
||||
issue_2271_input_dir="${cases_dir}/issue-2271/input"
|
||||
@@ -8,7 +8,7 @@ issue_2271_tmp_dir=$(mktemp -d)
|
||||
|
||||
cd "${issue_2271_input_dir}"
|
||||
|
||||
test_start "issue-2271: lookup function with strategicMergePatches"
|
||||
test_start "issue-2271: lookup function with strategicMergePatches and jsonPatches"
|
||||
|
||||
# Test 1: Install chart without kustomize patches
|
||||
info "Installing chart without kustomize patches"
|
||||
@@ -36,26 +36,44 @@ fi
|
||||
|
||||
info "ConfigMap value updated to: $current_value"
|
||||
|
||||
assert_lookup_preserved() {
|
||||
local label="$1"
|
||||
local helmfile_path="$2"
|
||||
local output_path="$3"
|
||||
local code
|
||||
|
||||
info "Testing diff with ${label} - lookup should preserve value"
|
||||
|
||||
${helmfile} -f "${helmfile_path}" diff > "${output_path}" 2>&1
|
||||
code=$?
|
||||
|
||||
if [ $code -ne 0 ] && [ $code -ne 2 ]; then
|
||||
cat "${output_path}"
|
||||
rm -rf "${issue_2271_tmp_dir}"
|
||||
fail "Unexpected error during diff with ${label}"
|
||||
fi
|
||||
|
||||
# Check if the diff contains the preserved value (not "initial-value")
|
||||
if grep -q "preserved-value.*test-preserved-value" "${output_path}"; then
|
||||
info "SUCCESS: lookup function preserved the value with ${label}"
|
||||
elif grep -q "preserved-value.*initial-value" "${output_path}"; then
|
||||
cat "${output_path}"
|
||||
rm -rf "${issue_2271_tmp_dir}"
|
||||
fail "Issue #2271 regression: lookup function returned empty value with ${label}"
|
||||
else
|
||||
# No diff for ConfigMap means value is perfectly preserved
|
||||
info "SUCCESS: No ConfigMap changes detected for ${label} (value perfectly preserved)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Test 3: Diff with strategicMergePatches should preserve the lookup value
|
||||
info "Testing diff with strategicMergePatches - lookup should preserve value"
|
||||
assert_lookup_preserved "strategicMergePatches" "helmfile.yaml" "${issue_2271_tmp_dir}/test-2271-strategic-diff.txt"
|
||||
|
||||
${helmfile} -f helmfile.yaml diff > "${issue_2271_tmp_dir}/test-2271-diff.txt" 2>&1
|
||||
code=$?
|
||||
|
||||
# Check if the diff contains the preserved value (not "initial-value")
|
||||
if grep -q "preserved-value.*test-preserved-value" "${issue_2271_tmp_dir}/test-2271-diff.txt"; then
|
||||
info "SUCCESS: lookup function preserved the value with kustomize patches"
|
||||
elif grep -q "preserved-value.*initial-value" "${issue_2271_tmp_dir}/test-2271-diff.txt"; then
|
||||
cat "${issue_2271_tmp_dir}/test-2271-diff.txt"
|
||||
rm -rf "${issue_2271_tmp_dir}"
|
||||
fail "Issue #2271 regression: lookup function returned empty value with kustomize"
|
||||
else
|
||||
# No diff for ConfigMap means value is perfectly preserved
|
||||
info "SUCCESS: No ConfigMap changes detected (value perfectly preserved)"
|
||||
fi
|
||||
# Test 4: Diff with jsonPatches should preserve the lookup value
|
||||
assert_lookup_preserved "jsonPatches" "helmfile-jsonpatch.yaml" "${issue_2271_tmp_dir}/test-2271-json-diff.txt"
|
||||
|
||||
# Cleanup
|
||||
${helm} uninstall test-release-2271 --namespace default 2>/dev/null || true
|
||||
rm -rf "${issue_2271_tmp_dir}"
|
||||
|
||||
test_pass "issue-2271: lookup function with strategicMergePatches"
|
||||
test_pass "issue-2271: lookup function with strategicMergePatches and jsonPatches"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
releases:
|
||||
- name: test-release-2271
|
||||
namespace: default
|
||||
chart: ./test-chart
|
||||
installed: true
|
||||
jsonPatches:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: test-release-2271-app
|
||||
namespace: default
|
||||
patch:
|
||||
- op: add
|
||||
path: /spec/template/metadata/labels/hello
|
||||
value: world
|
||||
@@ -0,0 +1,50 @@
|
||||
# Integration test for issue #2502: Race condition when multiple releases share a local chart
|
||||
# https://github.com/helmfile/helmfile/issues/2502
|
||||
#
|
||||
# When multiple releases reference the same local chart, concurrent goroutines
|
||||
# race on rewriting Chart.yaml dependencies, causing:
|
||||
# "Error: validation: chart.metadata.name is required"
|
||||
#
|
||||
# This test verifies the fix works WITHOUT --concurrency 1 workaround.
|
||||
|
||||
issue_2502_input_dir="${cases_dir}/issue-2502-race-condition-local-chart/input"
|
||||
|
||||
issue_2502_tmp=$(mktemp -d)
|
||||
actual="${issue_2502_tmp}/actual.yaml"
|
||||
|
||||
cleanup_issue_2502() {
|
||||
if [ -n "${issue_2502_tmp}" ] && [ -d "${issue_2502_tmp}" ]; then
|
||||
rm -rf "${issue_2502_tmp}"
|
||||
fi
|
||||
}
|
||||
trap cleanup_issue_2502 EXIT
|
||||
|
||||
test_start "issue #2502: race condition with shared local chart"
|
||||
|
||||
info "Running helmfile template with 5 releases sharing the same local chart (default concurrency)"
|
||||
|
||||
# Run WITHOUT --concurrency 1 to test the fix.
|
||||
# Before the fix, this would intermittently fail with:
|
||||
# "Error: validation: chart.metadata.name is required"
|
||||
# Run multiple iterations to increase chance of catching a race.
|
||||
pass=0
|
||||
iterations=5
|
||||
for i in $(seq 1 ${iterations}); do
|
||||
if ${helmfile} -f ${issue_2502_input_dir}/helmfile.yaml -e test template > ${actual} 2>&1; then
|
||||
pass=$((pass + 1))
|
||||
else
|
||||
cat ${actual}
|
||||
fail "helmfile template failed on iteration ${i}/${iterations} (race condition on shared local chart)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${pass} -ne ${iterations} ]; then
|
||||
fail "Expected ${iterations}/${iterations} passes but got ${pass}/${iterations}"
|
||||
fi
|
||||
|
||||
info "All ${iterations} iterations passed successfully"
|
||||
|
||||
cleanup_issue_2502
|
||||
trap - EXIT
|
||||
|
||||
test_pass "issue #2502: race condition with shared local chart"
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
dependencies:
|
||||
- name: raw
|
||||
repository: file://../../../../../charts/raw
|
||||
version: 0.0.1
|
||||
apiVersion: v2
|
||||
appVersion: "1.0.0"
|
||||
description: A test chart for race condition reproduction
|
||||
name: my-chart
|
||||
type: application
|
||||
version: 0.1.0
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
raw:
|
||||
templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
@@ -0,0 +1,49 @@
|
||||
environments:
|
||||
test: {}
|
||||
---
|
||||
releases:
|
||||
- name: app
|
||||
chart: helm/my-chart
|
||||
strategicMergePatches:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
- name: app-2
|
||||
chart: helm/my-chart
|
||||
strategicMergePatches:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
- name: app-3
|
||||
chart: helm/my-chart
|
||||
strategicMergePatches:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
- name: app-4
|
||||
chart: helm/my-chart
|
||||
strategicMergePatches:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
- name: app-5
|
||||
chart: helm/my-chart
|
||||
strategicMergePatches:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
data:
|
||||
key: value
|
||||
@@ -0,0 +1,62 @@
|
||||
issue_2515_case_dir="$(cd "${cases_dir}/issue-2515" && pwd)"
|
||||
issue_2515_tmp=$(mktemp -d)
|
||||
|
||||
# Determine the post-renderer argument.
|
||||
# Helm 3 accepts an executable script; Helm 4 requires a plugin name.
|
||||
if [ "${HELMFILE_HELM4}" = "1" ]; then
|
||||
test_start "issue-2515 post-renderer with output-dir-template (Helm 4)"
|
||||
info "Installing filter post-renderer plugin for Helm 4"
|
||||
${helm} plugin uninstall filter &>/dev/null || true
|
||||
${helm} plugin install ${issue_2515_case_dir}/input/helm-plugin-filter ${PLUGIN_INSTALL_FLAGS} || fail "Failed to install filter plugin"
|
||||
issue_2515_postrenderer_arg="filter"
|
||||
else
|
||||
test_start "issue-2515 post-renderer with output-dir-template"
|
||||
issue_2515_postrenderer_arg="${issue_2515_case_dir}/input/filter.bash"
|
||||
fi
|
||||
|
||||
info "Testing that --post-renderer output is written to files when --output-dir-template is set"
|
||||
|
||||
issue_2515_output_dir="${issue_2515_tmp}/output"
|
||||
|
||||
${helmfile} -f ${issue_2515_case_dir}/input/helmfile.yaml \
|
||||
template \
|
||||
--post-renderer ${issue_2515_postrenderer_arg} \
|
||||
--output-dir-template "${issue_2515_output_dir}/{{.Release.Name}}" \
|
||||
&> ${issue_2515_tmp}/log || fail "helmfile template should not fail"
|
||||
|
||||
if [ "${HELMFILE_HELM4}" = "1" ]; then
|
||||
# Helm 4 natively applies --post-renderer to --output-dir output.
|
||||
# The directory structure may differ from Helm 3 (no guaranteed templates/ subdir),
|
||||
# so search recursively for any YAML file. Fall back to stdout (log) if no files written.
|
||||
issue_2515_output_file=$(find "${issue_2515_output_dir}" -maxdepth 5 -type f \( -name '*.yaml' -o -name '*.yml' \) 2>/dev/null | head -n 1)
|
||||
if [ -z "${issue_2515_output_file}" ]; then
|
||||
# Helm 4 may write post-rendered output to stdout rather than files
|
||||
issue_2515_output_file="${issue_2515_tmp}/log"
|
||||
if ! grep -q "postrendered" "${issue_2515_output_file}"; then
|
||||
fail "Expected post-rendered YAML (namespace postrendered) in output files under ${issue_2515_output_dir} or stdout. Dir: $(find ${issue_2515_output_dir} 2>/dev/null || echo 'not found'). Log (last 50 lines): $(tail -50 ${issue_2515_output_file})"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
issue_2515_templates_dir="${issue_2515_output_dir}/issue-2515/templates"
|
||||
if [ ! -d "${issue_2515_templates_dir}" ]; then
|
||||
fail "Expected templates directory ${issue_2515_templates_dir} to exist"
|
||||
fi
|
||||
issue_2515_output_file=$(find "${issue_2515_templates_dir}" -type f \( -name '*.yaml' -o -name '*.yml' \) | head -n 1)
|
||||
if [ -z "${issue_2515_output_file}" ]; then
|
||||
fail "Expected rendered YAML file under ${issue_2515_templates_dir}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if grep -q "original-cm" "${issue_2515_output_file}"; then
|
||||
fail "Output should contain post-renderer output (Namespace), not original templates (original-cm). File contents: $(cat ${issue_2515_output_file})"
|
||||
fi
|
||||
|
||||
if ! grep -q "postrendered" "${issue_2515_output_file}"; then
|
||||
fail "Output should contain post-renderer content (namespace postrendered). File contents: $(cat ${issue_2515_output_file})"
|
||||
fi
|
||||
|
||||
if [ "${HELMFILE_HELM4}" = "1" ]; then
|
||||
test_pass "issue-2515 post-renderer with output-dir-template (Helm 4)"
|
||||
else
|
||||
test_pass "issue-2515 post-renderer with output-dir-template"
|
||||
fi
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
printf -- "---\napiVersion: v1\nkind: Namespace\nmetadata:\n name: postrendered\n"
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Discard stdin (pre-rendered content) and output a fixed Namespace resource.
|
||||
# This verifies that the post-renderer output — not the original templates — is
|
||||
# written to the output directory.
|
||||
cat > /dev/null
|
||||
printf -- "---\napiVersion: v1\nkind: Namespace\nmetadata:\n name: postrendered\n"
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
type: postrenderer/v1
|
||||
name: filter
|
||||
version: 0.1.0
|
||||
runtime: subprocess
|
||||
runtimeConfig:
|
||||
platformCommand:
|
||||
- command: ${HELM_PLUGIN_DIR}/filter.sh
|
||||
@@ -0,0 +1,13 @@
|
||||
releases:
|
||||
- name: issue-2515
|
||||
chart: ../../../charts/raw
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: original-cm
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
key: value
|
||||
@@ -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
|
||||
@@ -0,0 +1,49 @@
|
||||
# Integration test for issue #2596: Local dependencies with multiple release files
|
||||
# https://github.com/helmfile/helmfile/issues/2596
|
||||
# Reproduction: https://github.com/vgivanov/helmfile-deps-local-chart
|
||||
#
|
||||
# This test uses the exact same structure as the reproduction repo:
|
||||
# chart/Chart.yaml
|
||||
# helmfile.d/release1.yaml (chart: ../chart with dependencies)
|
||||
# helmfile.d/release2.yaml (chart: ../chart without dependencies)
|
||||
#
|
||||
# Before the fix, running `helmfile template` from this directory would fail with:
|
||||
# "failed reading adhoc dependencies: no helm list entry found for repository"
|
||||
# because the relative dependency chart path "../chart" was not normalized against
|
||||
# basePath before calling DirectoryExistsAt.
|
||||
|
||||
issue_2596_input_dir="${cases_dir}/issue-2596-local-deps-multiple-files/input"
|
||||
issue_2596_tmp=""
|
||||
|
||||
cleanup_issue_2596() {
|
||||
if [ -n "${issue_2596_tmp}" ] && [ -d "${issue_2596_tmp}" ]; then
|
||||
rm -rf "${issue_2596_tmp}"
|
||||
fi
|
||||
}
|
||||
trap cleanup_issue_2596 EXIT
|
||||
|
||||
issue_2596_tmp=$(mktemp -d)
|
||||
helmfile_real="$(pwd)/${helmfile}"
|
||||
|
||||
test_start "issue #2596: local deps with multiple release files"
|
||||
|
||||
info "Testing helmfile template with local chart dependencies across multiple release files"
|
||||
|
||||
cd "${issue_2596_input_dir}"
|
||||
|
||||
${helmfile_real} template > "${issue_2596_tmp}/output.yaml" 2>&1
|
||||
result=$?
|
||||
|
||||
cd - > /dev/null
|
||||
|
||||
if [ $result -ne 0 ]; then
|
||||
cat "${issue_2596_tmp}/output.yaml"
|
||||
fail "helmfile template with local chart dependencies should not fail"
|
||||
fi
|
||||
|
||||
info "Local chart dependencies with multiple release files works correctly"
|
||||
|
||||
cleanup_issue_2596
|
||||
trap - EXIT
|
||||
|
||||
test_pass "issue #2596: local deps with multiple release files"
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: chart
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.0"
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
---
|
||||
releases:
|
||||
- name: release1
|
||||
chart: ../chart
|
||||
version: "*"
|
||||
dependencies:
|
||||
- chart: ../chart
|
||||
version: "*"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
releases:
|
||||
- name: release2
|
||||
chart: ../chart
|
||||
version: "*"
|
||||
@@ -0,0 +1,75 @@
|
||||
# Issue #2599: Test that defaultInherit applies template inheritance to all releases
|
||||
# https://github.com/helmfile/helmfile/issues/2599
|
||||
#
|
||||
# This test verifies that:
|
||||
# - defaultInherit as a single string applies the template to all releases
|
||||
# - Releases without explicit inherit still get the template
|
||||
# - Releases with explicit inherit + except are not duplicated
|
||||
# - Non-existent template in defaultInherit produces a clear error
|
||||
|
||||
issue_2599_input_dir="${cases_dir}/issue-2599-default-inherit/input"
|
||||
issue_2599_tmp=""
|
||||
|
||||
cleanup_issue_2599() {
|
||||
if [ -n "${issue_2599_tmp}" ] && [ -d "${issue_2599_tmp}" ]; then
|
||||
rm -rf "${issue_2599_tmp}"
|
||||
fi
|
||||
}
|
||||
trap cleanup_issue_2599 EXIT
|
||||
|
||||
issue_2599_tmp=$(mktemp -d)
|
||||
|
||||
test_start "issue 2599 default inherit"
|
||||
|
||||
# Test 1: defaultInherit applies template to all releases
|
||||
info "Running helmfile build with defaultInherit"
|
||||
${helmfile} -f "${issue_2599_input_dir}/helmfile.yaml" build \
|
||||
> "${issue_2599_tmp}/output.log" 2>&1 \
|
||||
|| { cat "${issue_2599_tmp}/output.log"; fail "helmfile build with defaultInherit shouldn't fail"; }
|
||||
|
||||
# Verify namespace from template is applied to both releases
|
||||
grep -q "namespace: default-ns" "${issue_2599_tmp}/output.log" \
|
||||
|| fail "namespace from default template should be applied"
|
||||
|
||||
# Verify both releases are processed
|
||||
grep -q "app1" "${issue_2599_tmp}/output.log" \
|
||||
|| fail "release app1 should be in output"
|
||||
|
||||
grep -q "app2" "${issue_2599_tmp}/output.log" \
|
||||
|| fail "release app2 should be in output"
|
||||
grep -q "^templates:" "${issue_2599_tmp}/output.log" \
|
||||
|| fail "templates section should be in build output"
|
||||
|
||||
# Verify inherited values and labels per release
|
||||
sed -n '/name: app1/,/name: app2/p' "${issue_2599_tmp}/output.log" > "${issue_2599_tmp}/app1.log"
|
||||
sed -n '/name: app2/,/^templates:/{/^templates:/!p}' "${issue_2599_tmp}/output.log" > "${issue_2599_tmp}/app2.log"
|
||||
[ -s "${issue_2599_tmp}/app1.log" ] || fail "failed to extract release app1 section from build output"
|
||||
[ -s "${issue_2599_tmp}/app2.log" ] || fail "failed to extract release app2 section from build output"
|
||||
|
||||
grep -Eq 'managed:[[:space:]]*"?true"?([[:space:]]|$)' "${issue_2599_tmp}/app1.log" \
|
||||
|| fail "release app1 should inherit managed label from default template"
|
||||
grep -q "common.yaml" "${issue_2599_tmp}/app1.log" \
|
||||
|| fail "release app1 should inherit values from common.yaml"
|
||||
grep -q "common.yaml" "${issue_2599_tmp}/app2.log" \
|
||||
|| fail "release app2 should inherit values from common.yaml"
|
||||
if grep -Eq 'managed:[[:space:]]*"?true"?([[:space:]]|$)' "${issue_2599_tmp}/app2.log"; then
|
||||
fail "release app2 should not inherit managed label due to except"
|
||||
fi
|
||||
|
||||
# Test 2: non-existent template in defaultInherit should fail
|
||||
info "Running helmfile build with non-existent defaultInherit template"
|
||||
cat > "${issue_2599_tmp}/bad-helmfile.yaml" <<EOF
|
||||
defaultInherit: nonexistent
|
||||
releases:
|
||||
- name: app1
|
||||
chart: ${dir}/charts/raw
|
||||
EOF
|
||||
|
||||
${helmfile} -f "${issue_2599_tmp}/bad-helmfile.yaml" build \
|
||||
> "${issue_2599_tmp}/error.log" 2>&1 \
|
||||
&& fail "helmfile build with non-existent defaultInherit template should fail"
|
||||
|
||||
grep -q "inexistent release template" "${issue_2599_tmp}/error.log" \
|
||||
|| fail "error message should mention inexistent release template"
|
||||
|
||||
test_pass "issue 2599 default inherit"
|
||||
@@ -0,0 +1 @@
|
||||
testKey: testValue
|
||||
@@ -0,0 +1,19 @@
|
||||
templates:
|
||||
default:
|
||||
namespace: default-ns
|
||||
labels:
|
||||
managed: "true"
|
||||
values:
|
||||
- common.yaml
|
||||
|
||||
defaultInherit: default
|
||||
|
||||
releases:
|
||||
- name: app1
|
||||
chart: ../../../charts/raw
|
||||
- name: app2
|
||||
chart: ../../../charts/raw
|
||||
inherit:
|
||||
- template: default
|
||||
except:
|
||||
- labels
|
||||
@@ -0,0 +1,25 @@
|
||||
postrender_defaults_args_case_input_dir="${cases_dir}/postrender-defaults-args/input"
|
||||
postrender_defaults_args_case_output_dir="${cases_dir}/postrender-defaults-args/output"
|
||||
|
||||
# Helm 4 requires post-renderers to be plugins
|
||||
if [ "${HELMFILE_HELM4}" = "1" ]; then
|
||||
info "Installing echo-args post-renderer plugin for Helm 4"
|
||||
${helm} plugin uninstall echo-args &>/dev/null || true
|
||||
${helm} plugin install ${postrender_defaults_args_case_input_dir}/helm-plugin-echo-args ${PLUGIN_INSTALL_FLAGS} || fail "Failed to install echo-args plugin"
|
||||
fi
|
||||
|
||||
config_file="helmfile.yaml.gotmpl"
|
||||
postrender_defaults_args_tmp=$(mktemp -d)
|
||||
|
||||
test_start "postrender-defaults-args template"
|
||||
info "Running helmfile template with helmDefaults.postRendererArgs containing {{ .Release.Name }}"
|
||||
${helmfile} -f ${postrender_defaults_args_case_input_dir}/${config_file} template --concurrency 1 &> ${postrender_defaults_args_tmp}/template.out || fail "\"helmfile template\" shouldn't fail"
|
||||
|
||||
info "Verifying that helmDefaults.postRendererArgs were templated with release names"
|
||||
grep -q "name: rendered-arg-foo" ${postrender_defaults_args_tmp}/template.out || fail "Expected postRendererArg 'foo' for release foo, but not found in output"
|
||||
grep -q "name: rendered-arg-bar" ${postrender_defaults_args_tmp}/template.out || fail "Expected postRendererArg 'bar' for release bar, but not found in output"
|
||||
|
||||
info "Verifying that literal template expression was NOT passed"
|
||||
grep -q "rendered-arg-{{ .Release.Name }}" ${postrender_defaults_args_tmp}/template.out && fail "Template expression was NOT rendered (found literal {{ .Release.Name }})"
|
||||
|
||||
test_pass "postrender-defaults-args template"
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
arg=$1
|
||||
cat
|
||||
echo "---"
|
||||
cat <<EOS
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: rendered-arg-${arg}
|
||||
data:
|
||||
arg: ${arg}
|
||||
EOS
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
arg=$2
|
||||
input=$(cat)
|
||||
|
||||
echo "$input"
|
||||
|
||||
echo "---"
|
||||
|
||||
cat <<EOS
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: rendered-arg-${arg}
|
||||
data:
|
||||
arg: ${arg}
|
||||
EOS
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
type: postrenderer/v1
|
||||
name: echo-args
|
||||
version: 0.1.0
|
||||
runtime: subprocess
|
||||
runtimeConfig:
|
||||
platformCommand:
|
||||
- command: ${HELM_PLUGIN_DIR}/echo-args.sh
|
||||
args:
|
||||
- ${HELM_POST_RENDERER_ARGS}
|
||||
@@ -0,0 +1,30 @@
|
||||
helmDefaults:
|
||||
postRenderer: {{ if eq (env "HELMFILE_HELM4") "1" }}echo-args{{ else }}./echo-args.bash{{ end }}
|
||||
postRendererArgs:
|
||||
- "{{ `{{ .Release.Name }}` }}"
|
||||
|
||||
releases:
|
||||
- name: foo
|
||||
chart: ../../../charts/raw
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{`{{ .Release.Name }}`}}-1
|
||||
namespace: {{`{{ .Release.Namespace }}`}}
|
||||
data:
|
||||
foo: FOO
|
||||
- name: bar
|
||||
chart: ../../../charts/raw
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{`{{ .Release.Name }}`}}-2
|
||||
namespace: {{`{{ .Release.Namespace }}`}}
|
||||
data:
|
||||
bar: BAR
|
||||
@@ -9,6 +9,7 @@ data:
|
||||
name: cm2
|
||||
metadata:
|
||||
name: cm2
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
@@ -28,6 +29,7 @@ data:
|
||||
name: cm1
|
||||
metadata:
|
||||
name: cm1
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
|
||||
@@ -10,6 +10,7 @@ data:
|
||||
name: cm2
|
||||
metadata:
|
||||
name: cm2
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
@@ -29,6 +30,7 @@ data:
|
||||
name: cm1
|
||||
metadata:
|
||||
name: cm1
|
||||
|
||||
---
|
||||
# Source: raw/templates/resources.yaml
|
||||
apiVersion: v1
|
||||
|
||||
Reference in New Issue
Block a user