From 1969153443b694fb1a46cae1585b0cf8fb8b00ad Mon Sep 17 00:00:00 2001 From: asdf2014 Date: Fri, 10 Jul 2026 01:15:25 +0800 Subject: [PATCH] fix(cli): skip commented-out lines when resolving env vars in apisix.yaml Since #13078 (3.17.0), env vars in apisix.yaml are substituted on the raw text before YAML parsing, so a commented-out `# ${{VAR}}` aborted startup when VAR was unset. Substitute line by line and keep comment / blank / no-reference lines verbatim (reusing is_empty_yaml_line); detach a leading UTF-8 BOM so a first-line comment is still recognized. Both the CLI init path and the runtime hot-reload path share the fixed function. Fixes #13685 --- apisix/cli/file.lua | 29 +++++++++++++++++++---- t/cli/test_standalone.sh | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua index bbdb738e3d53..7f1bf3f89d0e 100644 --- a/apisix/cli/file.lua +++ b/apisix/cli/file.lua @@ -31,6 +31,7 @@ local getenv = os.getenv local str_gmatch = string.gmatch local str_find = string.find local str_sub = string.sub +local table_concat = table.concat local print = print local _M = {} @@ -92,12 +93,32 @@ end -- Substitute env vars in raw text before parsing. YAML parser then infers -- types naturally: `"${{VAR}}"` stays string, `${{VAR}}` infers from value. +-- Substitution runs line by line so that full-line comments stay untouched: +-- a commented-out `# ${{VAR}}` must not fail startup when VAR is unset. +-- Known limits of this text-level heuristic: an inline trailing comment is +-- still substituted (`#` may legally appear inside YAML strings), and a +-- block-scalar content line starting with `#` is skipped like a comment. local function resolve_conf_var_in_text(text) - local new_text, _, err = var_sub(text) - if err then - return nil, err + local parts = {} + -- a UTF-8 BOM would hide the `#` of a first-line comment, so detach it + if str_sub(text, 1, 3) == "\239\187\191" then + parts[1] = str_sub(text, 1, 3) + text = str_sub(text, 4) + end + for line, eol in str_gmatch(text, "([^\n]*)(\n?)") do + if is_empty_yaml_line(line) or not str_find(line, "${{", 1, true) then + -- comment / blank / no reference: keep the line as-is + parts[#parts + 1] = line + else + local new_line, _, err = var_sub(line) + if err then + return nil, err + end + parts[#parts + 1] = new_line + end + parts[#parts + 1] = eol end - return new_text + return table_concat(parts) end diff --git a/t/cli/test_standalone.sh b/t/cli/test_standalone.sh index c1e728d7ace9..1b1396ad1b37 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -660,5 +660,55 @@ fi echo "passed: missing env var produces clear startup error" +# test: unset env vars referenced only in commented-out lines must be ignored +echo ' +apisix: + enable_admin: false +deployment: + role: data_plane + role_data_plane: + config_provider: yaml +' > conf/config.yaml + +echo ' +# ${{COMMENTED_UNSET_VAR}} +routes: + - + uri: /test-commented-var + # indented comment: ${{ANOTHER_COMMENTED_UNSET_VAR}} + plugins: + response-rewrite: + body: "commented-ok" + status_code: 200 + upstream: + nodes: + "127.0.0.1:9091": 1 + type: roundrobin +#END +' > conf/apisix.yaml + +unset COMMENTED_UNSET_VAR +unset ANOTHER_COMMENTED_UNSET_VAR +make init + +if ! make run > output.log 2>&1; then + cat output.log + echo "failed: make run should ignore env vars in commented-out lines" + exit 1 +fi +sleep 0.1 + +code=$(curl -o /tmp/response_body -s -m 5 -w %{http_code} http://127.0.0.1:9080/test-commented-var) +body=$(cat /tmp/response_body) +if [ "$code" -ne 200 ] || [ "$body" != "commented-ok" ]; then + echo "failed: expected 200/commented-ok for /test-commented-var, got code: $code body: $body" + exit 1 +fi + +make stop +sleep 0.5 + +echo "passed: commented-out env var references are not resolved" + git checkout conf/config.yaml git checkout conf/apisix.yaml