Skip to content

Commit f7f4eb6

Browse files
yankawailexfrei
authored andcommitted
fix(kubevirt): reject incomplete migrations template blocks
Signed-off-by: Yan Bondarenko <[email protected]>
1 parent 5ed076c commit f7f4eb6

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

‎packages/system/kubevirt/Makefile‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ update:
7272
@# for, and their absence cannot surface as a value that stopped taking
7373
@# effect — the CR simply goes back to deploying virt-template, to letting
7474
@# KubeVirt skip NAD resource injection, and to image volumes an apiserver
75-
@# below 1.35 discards. The payload lines of the blocks above are exposed the
76-
@# same way; covering them is a wider change than this. `make update` cannot
75+
@# below 1.35 discards. The device/CPU payload lines remain outside these
76+
@# checks; migrations validates its complete block below. `make update` cannot
7777
@# repair a partial block — the directive guard is what stops the insert — so
7878
@# name the missing marker and let the operator restore it.
7979
@grep -q '{{- if .Values.cpuAllocationRatio }}' $(CR_FILE) || { echo "ERROR: directive '{{- if .Values.cpuAllocationRatio }}' not inserted — restore the 'developerConfiguration:' anchor in $(CR_FILE) and re-run" >&2; exit 1; }
@@ -90,3 +90,10 @@ update:
9090
@grep -q '{{- with .Values.permittedHostDevices }}' $(CR_FILE) || { echo "ERROR: directive '{{- with .Values.permittedHostDevices }}' not inserted — restore the 'evictionStrategy:' anchor in $(CR_FILE) and re-run" >&2; exit 1; }
9191
@grep -q '{{- with .Values.mediatedDevicesConfiguration }}' $(CR_FILE) || { echo "ERROR: directive '{{- with .Values.mediatedDevicesConfiguration }}' not inserted — restore the 'evictionStrategy:' anchor in $(CR_FILE) and re-run" >&2; exit 1; }
9292
@grep -q '{{- with .Values.migrations }}' $(CR_FILE) || { echo "ERROR: directive '{{- with .Values.migrations }}' not inserted — restore the 'evictionStrategy:' anchor in $(CR_FILE) and re-run" >&2; exit 1; }
93+
@# A retained directive skips insertion even if its body or end was lost.
94+
@# Check the whole block in order; only END decides the exit status.
95+
@awk '\
96+
$$0 == " migrations:" { keys++ } \
97+
$$0 == " {{- with .Values.migrations }}" { blocks++; step=1; next } \
98+
step { expected = step == 1 ? " migrations:" : step == 2 ? " {{- toYaml . | nindent 6 }}" : " {{- end }}"; if ($$0 != expected) bad=1; step=(step+1)%4 } \
99+
END { exit !(blocks == 1 && keys == 1 && step == 0 && !bad) }' $(CR_FILE) || { echo "ERROR: migrations block is partial or duplicated — restore the complete block or delete all its remaining lines from $(CR_FILE) and re-run" >&2; exit 1; }

‎packages/system/kubevirt/tests/update_idempotency_test.sh‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,53 @@ if ! grep -qF "directive '$MIG' not inserted" "$anchorless_migrations_log"; then
273273
fail "make update did not name the missing migrations directive: $(cat "$anchorless_migrations_log")"
274274
fi
275275

276+
# A retained opening directive must not hide a missing body or terminator.
277+
# The opening-less case also leaves an orphan key: inserting a second complete
278+
# block must not make that damaged template pass validation.
279+
for missing in key payload end body opening; do
280+
partial_migrations="$tmpdir/migrations-missing-$missing.yaml"
281+
awk -v missing="$missing" -v opening="$MIG" '
282+
index($0, opening) { inside=1; if (missing != "opening") print; next }
283+
inside && /{{- end }}/ { inside=0; if (missing != "end") print; next }
284+
inside && /^ migrations:$/ && (missing == "key" || missing == "body") { next }
285+
inside && /{{- toYaml \. \| nindent 6 }}/ && (missing == "payload" || missing == "body") { next }
286+
{ print }
287+
' "$src" >"$partial_migrations"
288+
partial_migrations_log="$tmpdir/migrations-missing-$missing.log"
289+
if run_update_logged "$partial_migrations" "$partial_migrations_log"; then
290+
fail "make update exited zero on a migrations block missing $missing"
291+
fi
292+
if ! grep -qF 'migrations block is partial or duplicated' "$partial_migrations_log"; then
293+
fail "make update did not diagnose migrations missing $missing: $(cat "$partial_migrations_log")"
294+
fi
295+
done
296+
297+
# Presence checks can also accept reordered lines, a duplicate complete block,
298+
# or a complete body with EOF in place of its closing directive.
299+
for malformed in reordered duplicate eof; do
300+
malformed_migrations="$tmpdir/migrations-$malformed.yaml"
301+
awk -v malformed="$malformed" -v opening="$MIG" '
302+
index($0, opening) { inside=1; block=$0 ORS; print; next }
303+
inside {
304+
block=block $0 ORS
305+
if (/{{- end }}/) {
306+
if (malformed == "eof") exit
307+
inside=0; print
308+
if (malformed == "duplicate") printf "%s", block
309+
next
310+
}
311+
if (malformed == "reordered" && /^ migrations:$/) { print " {{- toYaml . | nindent 6 }}"; next }
312+
if (malformed == "reordered" && /{{- toYaml \. \| nindent 6 }}/) { print " migrations:"; next }
313+
}
314+
{ print }
315+
' "$src" >"$malformed_migrations"
316+
malformed_migrations_log="$tmpdir/migrations-$malformed.log"
317+
if run_update_logged "$malformed_migrations" "$malformed_migrations_log"; then
318+
fail "make update exited zero on a $malformed migrations block"
319+
fi
320+
if ! grep -qF 'migrations block is partial or duplicated' "$malformed_migrations_log"; then
321+
fail "make update did not diagnose $malformed migrations: $(cat "$malformed_migrations_log")"
322+
fi
323+
done
324+
276325
echo "PASS update_idempotency_test"

0 commit comments

Comments
 (0)