From 05bd88b0160cb7d054ce3845f82d3088edeaf53c Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 18 Apr 2026 01:52:31 -0400 Subject: [PATCH] pxe-setup: handle quoted defaults whose comments contain quotes The production yaml ships `interface: "" # e.g. "eth0"`. The old extractor did `gsub(/^"|"$/, "")` which only strips outer quotes, so with an inline comment containing quotes it produced garbage like `" # e.g. "eth0`, tripping the idempotency check. Replaces the two inline extractors with one `extract_yaml_value` helper that first tries to match `"[^"]*"` (grabbing only the first quoted value), falling back to strip-trailing-comment + trim for unquoted values. Co-Authored-By: Claude Opus 4.7 --- deploy/pxe-setup.sh | 51 +++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/deploy/pxe-setup.sh b/deploy/pxe-setup.sh index 9e06b8f..d5853cf 100755 --- a/deploy/pxe-setup.sh +++ b/deploy/pxe-setup.sh @@ -195,24 +195,39 @@ fi # outside the pxe: block is passed through unchanged, so hand-tuned # server:/database:/notifiers: blocks survive intact. -existing_iface="$(awk ' - /^pxe:/ { in_pxe=1; next } - in_pxe && /^[A-Za-z_][A-Za-z0-9_]*:/ { in_pxe=0 } - in_pxe && /^[[:space:]]+interface:/ { - sub(/^[[:space:]]+interface:[[:space:]]*/, "") - gsub(/^"|"$/, "") - print; exit - } -' "${CONFIG}")" -existing_range="$(awk ' - /^pxe:/ { in_pxe=1; next } - in_pxe && /^[A-Za-z_][A-Za-z0-9_]*:/ { in_pxe=0 } - in_pxe && /^[[:space:]]+dhcp_range:/ { - sub(/^[[:space:]]+dhcp_range:[[:space:]]*/, "") - gsub(/^"|"$/, "") - print; exit - } -' "${CONFIG}")" +# extract_yaml_value : reads ` key: "value" # comment` +# from inside the pxe: block and prints the bare `value`. Empty or missing +# key → empty output. The production yaml ships default values like +# `interface: "" # e.g. "eth0"` — so we must +# strip the trailing comment BEFORE unquoting, or the comment's inner +# quotes get picked up. +extract_yaml_value() { + local key="$1" path="$2" + awk -v key="${key}" ' + /^pxe:/ { in_pxe=1; next } + in_pxe && /^[A-Za-z_][A-Za-z0-9_]*:/ { in_pxe=0 } + in_pxe { + re = "^[[:space:]]+" key ":[[:space:]]*" + if ($0 ~ re) { + line = $0 + sub(re, "", line) + # Quoted value: extract between the first pair of quotes. + if (match(line, /"[^"]*"/)) { + print substr(line, RSTART+1, RLENGTH-2) + exit + } + # Unquoted value: drop any trailing comment + whitespace. + sub(/[[:space:]]*#.*$/, "", line) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", line) + print line + exit + } + } + ' "${path}" +} + +existing_iface="$(extract_yaml_value interface "${CONFIG}")" +existing_range="$(extract_yaml_value dhcp_range "${CONFIG}")" if [[ -n "${existing_iface}" && "${existing_iface}" != "${INTERFACE}" && ${FORCE} -eq 0 ]]; then echo "ERROR: pxe.interface in ${CONFIG} is already set to ${existing_iface}, which" >&2