This is an automated email from the ASF dual-hosted git repository.
wenming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 85a84fb fix: avoid unnecessary type check and support var in
local_conf (#2990)
85a84fb is described below
commit 85a84fb191efd6a511aa2380cd15bb30362ae300
Author: 罗泽轩 <[email protected]>
AuthorDate: Thu Dec 10 15:48:47 2020 +0800
fix: avoid unnecessary type check and support var in local_conf (#2990)
Also merge bundle of repeated code.
Signed-off-by: spacewander <[email protected]>
---
.travis/apisix_cli_test.sh | 114 ++++++++++++++++++++++++++++++++++++++++++
apisix/cli/file.lua | 99 +++++++++++++++++++++++++++++++------
apisix/cli/ops.lua | 25 ++++++++++
apisix/core/config_local.lua | 115 +++----------------------------------------
conf/config.yaml | 2 +
doc/how-to-build.md | 3 ++
t/core/config.t | 42 ++++++++++++++++
7 files changed, 277 insertions(+), 123 deletions(-)
diff --git a/.travis/apisix_cli_test.sh b/.travis/apisix_cli_test.sh
index 5590ecf..b793284 100755
--- a/.travis/apisix_cli_test.sh
+++ b/.travis/apisix_cli_test.sh
@@ -166,6 +166,12 @@ if ! grep "env TEST_bar;" conf/nginx.conf > /dev/null; then
exit 1
fi
+out=$(make init 2>&1 || true)
+if ! echo "$out" | grep "can't find environment variable"; then
+ echo "failed: failed to resolve variables"
+ exit 1
+fi
+
echo "passed: resolve variables"
echo '
@@ -211,6 +217,114 @@ fi
echo "passed: resolve variables wrapped with whitespace"
+# support environment variables in local_conf
+echo '
+etcd:
+ host:
+ - "http://${{ETCD_HOST}}:${{ETCD_PORT}}"
+' > conf/config.yaml
+
+ETCD_HOST=127.0.0.1 ETCD_PORT=2379 make init
+
+if ! grep "env ETCD_HOST=127.0.0.1;" conf/nginx.conf > /dev/null; then
+ echo "failed: support environment variables in local_conf"
+ exit 1
+fi
+
+# don't override user's envs configuration
+echo '
+etcd:
+ host:
+ - "http://${{ETCD_HOST}}:${{ETCD_PORT}}"
+nginx_config:
+ envs:
+ - ETCD_HOST
+' > conf/config.yaml
+
+ETCD_HOST=127.0.0.1 ETCD_PORT=2379 make init
+
+if grep "env ETCD_HOST=127.0.0.1;" conf/nginx.conf > /dev/null; then
+ echo "failed: support environment variables in local_conf"
+ exit 1
+fi
+
+if ! grep "env ETCD_HOST;" conf/nginx.conf > /dev/null; then
+ echo "failed: support environment variables in local_conf"
+ exit 1
+fi
+
+echo '
+etcd:
+ host:
+ - "http://${{ETCD_HOST}}:${{ETCD_PORT}}"
+nginx_config:
+ envs:
+ - ETCD_HOST=1.1.1.1
+' > conf/config.yaml
+
+ETCD_HOST=127.0.0.1 ETCD_PORT=2379 make init
+
+if grep "env ETCD_HOST=127.0.0.1;" conf/nginx.conf > /dev/null; then
+ echo "failed: support environment variables in local_conf"
+ exit 1
+fi
+
+if ! grep "env ETCD_HOST=1.1.1.1;" conf/nginx.conf > /dev/null; then
+ echo "failed: support environment variables in local_conf"
+ exit 1
+fi
+
+echo "pass: support environment variables in local_conf"
+
+# support merging worker_processes
+echo '
+nginx_config:
+ worker_processes: 1
+' > conf/config.yaml
+
+make init
+
+if ! grep "worker_processes 1;" conf/nginx.conf > /dev/null; then
+ echo "failed: failed to merge worker_processes"
+ exit 1
+fi
+
+echo '
+nginx_config:
+ worker_processes: ${{nproc}}
+' > conf/config.yaml
+
+nproc=1 make init
+
+if ! grep "worker_processes 1;" conf/nginx.conf > /dev/null; then
+ echo "failed: failed to merge worker_processes"
+ exit 1
+fi
+
+echo '
+nginx_config:
+ worker_processes: true
+' > conf/config.yaml
+
+out=$(make init 2>&1 || true)
+if ! echo "$out" | grep 'path\[nginx_config->worker_processes\] expect'; then
+ echo "failed: failed to merge worker_processes"
+ exit 1
+fi
+
+echo '
+nginx_config:
+ worker_processes: ${{nproc}}
+' > conf/config.yaml
+
+out=$(nproc=false make init 2>&1 || true)
+if ! echo "$out" | grep 'path\[nginx_config->worker_processes\] expect'; then
+ echo "failed: failed to merge worker_processes"
+ exit 1
+fi
+
+echo "passed: merge worker_processes"
+
# check nameserver imported
git checkout conf/config.yaml
diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua
index 0bc604d..892e335 100644
--- a/apisix/cli/file.lua
+++ b/apisix/cli/file.lua
@@ -22,11 +22,19 @@ local util = require("apisix.cli.util")
local pairs = pairs
local type = type
local tonumber = tonumber
+local getmetatable = getmetatable
local getenv = os.getenv
local str_gmatch = string.gmatch
local str_find = string.find
+local str_sub = string.sub
local _M = {}
+local exported_vars
+
+
+function _M.get_exported_vars()
+ return exported_vars
+end
local function is_empty_yaml_line(line)
@@ -47,24 +55,37 @@ end
local function resolve_conf_var(conf)
for key, val in pairs(conf) do
if type(val) == "table" then
- resolve_conf_var(val)
+ local ok, err = resolve_conf_var(val)
+ if not ok then
+ return nil, err
+ 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 v = getenv(var)
if v then
+ if not exported_vars then
+ exported_vars = {}
+ end
+
+ exported_vars[var] = v
var_used = true
return v
end
- util.die("failed to handle configuration: ",
- "can't find environment variable ",
- var, "\n")
+ err = "failed to handle configuration: " ..
+ "can't find environment variable " .. var
+ return ""
end)
+ if err then
+ return nil, err
+ end
+
if var_used then
if tonumber(new_val) ~= nil then
new_val = tonumber(new_val)
@@ -78,22 +99,62 @@ local function resolve_conf_var(conf)
conf[key] = new_val
end
end
+
+ return true
+end
+
+
+local function tinyyaml_type(t)
+ local mt = getmetatable(t)
+ if mt then
+ return mt.__type
+ end
end
-local function merge_conf(base, new_tab)
+local function merge_conf(base, new_tab, ppath)
+ ppath = ppath or ""
+
for key, val in pairs(new_tab) do
if type(val) == "table" then
- if tab_is_array(val) then
- base[key] = val
- elseif base[key] == nil then
+ if tinyyaml_type(val) == "null" then
+ base[key] = nil
+
+ elseif tab_is_array(val) then
base[key] = val
+
else
- merge_conf(base[key], val)
- end
+ if base[key] == nil then
+ base[key] = {}
+ end
+ local ok, err = merge_conf(
+ base[key],
+ val,
+ ppath == "" and key or ppath .. "->" .. key
+ )
+ if not ok then
+ return nil, err
+ end
+ end
else
- base[key] = val
+ local type_val = type(val)
+
+ if base[key] == nil then
+ base[key] = val
+ elseif type(base[key]) ~= type_val then
+ if (ppath == "nginx_config" or str_sub(ppath, 1, 14) ==
"nginx_config->") and
+ (type_val == "number" or type_val == "string")
+ then
+ base[key] = val
+ else
+ local path = ppath == "" and key or ppath .. "->" .. key
+ return nil, "failed to merge, path[" .. path .. "]
expect: " ..
+ type(base[key]) .. ", but got: " .. type_val
+ end
+ else
+ base[key] = val
+ end
end
end
@@ -102,7 +163,10 @@ end
function _M.read_yaml_conf(apisix_home)
- profile.apisix_home = apisix_home .. "/"
+ if apisix_home then
+ profile.apisix_home = apisix_home .. "/"
+ end
+
local local_conf_path = profile:yaml_path("config-default")
local default_conf_yaml, err = util.read_file(local_conf_path)
if not default_conf_yaml then
@@ -134,8 +198,15 @@ function _M.read_yaml_conf(apisix_home)
return nil, "invalid config.yaml file"
end
- resolve_conf_var(user_conf)
- merge_conf(default_conf, user_conf)
+ local ok, err = resolve_conf_var(user_conf)
+ if not ok then
+ return nil, err
+ end
+
+ ok, err = merge_conf(default_conf, user_conf)
+ if not ok then
+ return nil, err
+ end
end
return default_conf
diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua
index 046df7f..f2523a5 100644
--- a/apisix/cli/ops.lua
+++ b/apisix/cli/ops.lua
@@ -38,6 +38,7 @@ local floor = math.floor
local str_find = string.find
local str_sub = string.sub
+
local _M = {}
@@ -300,6 +301,30 @@ Please modify "admin_key" in conf/config.yaml .
sys_conf["worker_processes"] = floor(tonumber(env_worker_processes))
end
+ local exported_vars = file.get_exported_vars()
+ if exported_vars then
+ if not sys_conf["envs"] then
+ sys_conf["envs"]= {}
+ end
+ for _, cfg_env in ipairs(sys_conf["envs"]) do
+ local cfg_name
+ local from = str_find(cfg_env, "=", 1, true)
+ if from then
+ cfg_name = str_sub(cfg_env, 1, from - 1)
+ else
+ cfg_name = cfg_env
+ end
+
+ exported_vars[cfg_name] = false
+ end
+
+ for name, value in pairs(exported_vars) do
+ if value then
+ table_insert(sys_conf["envs"], name .. "=" .. value)
+ end
+ end
+ end
+
local conf_render = template.compile(ngx_tpl)
local ngxconf = conf_render(sys_conf)
diff --git a/apisix/core/config_local.lua b/apisix/core/config_local.lua
index aa9252f..d17255b 100644
--- a/apisix/core/config_local.lua
+++ b/apisix/core/config_local.lua
@@ -15,134 +15,31 @@
-- limitations under the License.
--
-local log = require("apisix.core.log")
-local profile = require("apisix.core.profile")
-local table = require("apisix.core.table")
-local yaml = require("tinyyaml")
-
-local io_open = io.open
-local type = type
-local str_gmatch = string.gmatch
-local string = string
-local pairs = pairs
-local getmetatable = getmetatable
-
-
-local local_default_conf_path = profile:yaml_path("config-default")
-local local_conf_path = profile:yaml_path("config")
-local config_data
+local file = require("apisix.cli.file")
local _M = {}
-local function read_file(path)
- local file, err = io_open(path, "rb") -- read as binary mode
- if not file then
- log.error("failed to read config file:" .. path, ", error info:", err)
- return nil, err
- end
+local config_data
- local content = file:read("*a") -- `*a` reads the whole file
- file:close()
- return content
-end
function _M.clear_cache()
config_data = nil
end
-local function is_empty_yaml_line(line)
- return line == '' or string.find(line, '^%s*$') or
- string.find(line, '^%s*#')
-end
-
-
-local function tinyyaml_type(t)
- local mt = getmetatable(t)
- if mt then
- log.debug("table type: ", mt.__type)
- return mt.__type
- end
-end
-
-
-local function merge_conf(base, new_tab, ppath)
- ppath = ppath or ""
-
- for key, val in pairs(new_tab) do
- if type(val) == "table" then
- if tinyyaml_type(val) == "null" then
- base[key] = nil
-
- elseif table.isarray(val) then
- base[key] = val
-
- else
- if base[key] == nil then
- base[key] = {}
- end
-
- local ok, err = merge_conf(
- base[key],
- val,
- ppath == "" and key or ppath .. "->" .. key
- )
- if not ok then
- return nil, err
- end
- end
- else
- if base[key] == nil then
- base[key] = val
- elseif type(base[key]) ~= type(val) then
- return false, "failed to merge, path[" ..
- (ppath == "" and key or ppath .. "->" .. key) ..
- "] expect: " ..
- type(base[key]) .. ", but got: " .. type(val)
- else
- base[key] = val
- end
- end
- end
-
- return base
-end
-
-
function _M.local_conf(force)
if not force and config_data then
return config_data
end
- local default_conf_yaml, err = read_file(local_default_conf_path)
- if type(default_conf_yaml) ~= "string" then
- return nil, "failed to read config-default file:" .. err
- end
- config_data = yaml.parse(default_conf_yaml)
-
- local user_conf_yaml = read_file(local_conf_path) or ""
- local is_empty_file = true
- for line in str_gmatch(user_conf_yaml .. '\n', '(.-)\r?\n') do
- if not is_empty_yaml_line(line) then
- is_empty_file = false
- break
- end
- end
-
- if not is_empty_file then
- local user_conf = yaml.parse(user_conf_yaml)
- if not user_conf then
- return nil, "invalid config.yaml file"
- end
-
- config_data, err = merge_conf(config_data, user_conf)
- if err then
- return nil, err
- end
+ local default_conf, err = file.read_yaml_conf()
+ if not default_conf then
+ return nil, err
end
+ config_data = default_conf
return config_data
end
diff --git a/conf/config.yaml b/conf/config.yaml
index 335998b..3249e66 100644
--- a/conf/config.yaml
+++ b/conf/config.yaml
@@ -27,6 +27,8 @@
# host:
# - "http://${{ETCD_HOST}}:2379"
#
+# And then run `export ETCD_HOST=$your_host` before `make init`.
+#
# If the configured environment variable can't be found, an error will be
thrown.
apisix:
admin_key:
diff --git a/doc/how-to-build.md b/doc/how-to-build.md
index e30fa3f..013d764 100644
--- a/doc/how-to-build.md
+++ b/doc/how-to-build.md
@@ -106,6 +106,9 @@ Makefile rules:
license-check: Check Lua source code for Apache License
```
+Environment variable can be used to configure APISIX. Please take a look at
`conf/config.yaml` to
+see how to do it.
+
## 4. Test
1. Install perl's package manager `cpanminus` first
diff --git a/t/core/config.t b/t/core/config.t
index 115f4da..0e1bc74 100644
--- a/t/core/config.t
+++ b/t/core/config.t
@@ -300,3 +300,45 @@ GET /t
etcd host: http://127.0.0.1:2379
first plugin: "example-plugin"
seq: {"Block
style":["Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto"],"Flow
style":["Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto"]}
+
+
+
+=== TEST 3: allow environment variable
+--- config
+ location /t {
+ content_by_lua_block {
+ local config = require("apisix.core").config.local_conf()
+
+ ngx.say(config.apisix.id)
+ }
+ }
+--- main_config
+env AID=3;
+--- yaml_config
+#nginx_config:
+ #env: AID=3
+apisix:
+ id: ${{ AID }}
+--- request
+GET /t
+--- response_body
+3
+
+
+
+=== TEST 4: allow integer worker processes
+--- config
+ location /t {
+ content_by_lua_block {
+ local config = require("apisix.core").config.local_conf()
+
+ ngx.say(config.nginx_config.worker_processes)
+ }
+ }
+--- extra_yaml_config
+nginx_config:
+ worker_processes: 1
+--- request
+GET /t
+--- response_body
+1