diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua index af071a840f35a..149c4e913c358 100644 --- a/apisix/cli/file.lua +++ b/apisix/cli/file.lua @@ -54,8 +54,59 @@ local function tab_is_array(t) end +local function var_sub(val) + local err + local var_used = false + -- we use '${{var}}' because '$var' and '${var}' are taken + -- by Nginx + local new_val = val:gsub("%$%{%{%s*([%w_]+[%:%=]?.-)%s*%}%}", function(var) + local i, j = var:find("%:%=") + local default + if i and j then + default = var:sub(i + 2, #var) + default = default:gsub('^%s*(.-)%s*$', '%1') + var = var:sub(1, i - 1) + end + + local v = getenv(var) or default + if v then + if not exported_vars then + exported_vars = {} + end + + exported_vars[var] = v + var_used = true + return v + end + + err = "failed to handle configuration: " .. + "can't find environment variable " .. var + return "" + end) + return new_val, var_used, err +end + + local function resolve_conf_var(conf) + local new_keys = {} for key, val in pairs(conf) do + -- avoid re-iterating the table for already iterated key + if new_keys[key] then + goto continue + end + -- substitute environment variables from conf keys + if type(key) == "string" then + local new_key, _, err = var_sub(key) + if err then + return nil, err + end + if new_key ~= key then + new_keys[new_key] = "dummy" -- we only care about checking the key + conf.key = nil + conf[new_key] = val + key = new_key + end + end if type(val) == "table" then local ok, err = resolve_conf_var(val) if not ok then @@ -63,34 +114,7 @@ local function resolve_conf_var(conf) end elseif type(val) == "string" then - local err - local var_used = false - -- we use '${{var}}' because '$var' and '${var}' are taken - -- by Nginx - local new_val = val:gsub("%$%{%{%s*([%w_]+[%:%=]?.-)%s*%}%}", function(var) - local i, j = var:find("%:%=") - local default - if i and j then - default = var:sub(i + 2, #var) - default = default:gsub('^%s*(.-)%s*$', '%1') - var = var:sub(1, i - 1) - end - - local v = getenv(var) or default - if v then - if not exported_vars then - exported_vars = {} - end - - exported_vars[var] = v - var_used = true - return v - end - - err = "failed to handle configuration: " .. - "can't find environment variable " .. var - return "" - end) + local new_val, var_used, err = var_sub(val) if err then return nil, err @@ -108,6 +132,7 @@ local function resolve_conf_var(conf) conf[key] = new_val end + ::continue:: end return true diff --git a/docs/en/latest/admin-api.md b/docs/en/latest/admin-api.md index 3071a3e00f86c..787a61e988962 100644 --- a/docs/en/latest/admin-api.md +++ b/docs/en/latest/admin-api.md @@ -103,6 +103,19 @@ deployment: This will find the environment variable `ADMIN_KEY` first, and if it does not exist, it will use `edd1c9f034335f136f87ad84b625c8f1` as the default value. +You can also specify environment variables in yaml keys. This is specifically useful in the `standalone` [mode](./deployment-modes.md#standalone) where you can specify the upstream nodes as follows: + +```yaml title="./conf/apisix.yaml" +routes: + - + uri: "/test" + upstream: + nodes: + "${{HOST_IP}}:${{PORT}}": 1 + type: roundrobin +#END +``` + ### Force Delete By default, the Admin API checks for references between resources and will refuse to delete resources in use. diff --git a/docs/zh/latest/admin-api.md b/docs/zh/latest/admin-api.md index ab2625d945985..e1fd063e8a613 100644 --- a/docs/zh/latest/admin-api.md +++ b/docs/zh/latest/admin-api.md @@ -105,6 +105,19 @@ deployment: 首先查找环境变量 `ADMIN_KEY`,如果该环境变量不存在,它将使用 `edd1c9f034335f136f87ad84b625c8f1` 作为默认值。 +您还可以在 yaml 键中指定环境变量。这在 `standalone` 模式 中特别有用,您可以在其中指定上游节点,如下所示: + +```yaml title="./conf/apisix.yaml" +routes: + - + uri: "/test" + upstream: + nodes: + "${{HOST_IP}}:${{PORT}}": 1 + type: roundrobin +#END +``` + ### 强制删除 {#force-delete} 默认情况下,Admin API 会检查资源间的引用关系,将会拒绝删除正在使用中的资源。 diff --git a/t/cli/test_standalone.sh b/t/cli/test_standalone.sh index 2a3add66662b6..a0d91c11c4a06 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -26,7 +26,7 @@ standalone() { trap standalone EXIT -# support environment variables +# support environment variables in yaml values echo ' apisix: enable_admin: false @@ -69,6 +69,33 @@ fi echo "passed: resolve variables in apisix.yaml conf success" +# support environment variables in yaml keys +echo ' +routes: + - + uri: "/test" + plugins: + proxy-rewrite: + uri: "/apisix/nginx_status" + upstream: + nodes: + "${{HOST_IP}}:${{PORT}}": 1 + type: roundrobin +#END +' > conf/apisix.yaml + +# variable is valid +HOST_IP="127.0.0.1" PORT="9091" make init +HOST_IP="127.0.0.1" PORT="9091" make run +sleep 0.1 + +code=$(curl -o /dev/null -s -m 5 -w %{http_code} http://127.0.0.1:9080/test) +if [ ! $code -eq 200 ]; then + echo "failed: resolve variables in apisix.yaml conf failed" +fi + +echo "passed: resolve variables in apisix.yaml conf success" + # configure standalone via deployment echo ' deployment: