Skip to content

Commit

Permalink
fix(ext-plugin): pass environment variables
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
  • Loading branch information
spacewander committed Jun 1, 2021
1 parent 98d4447 commit 9d6f6d8
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 6 deletions.
1 change: 1 addition & 0 deletions apisix/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ return {
etcd = require("apisix.core.etcd"),
tablepool = require("tablepool"),
resolver = require("apisix.core.resolver"),
os = require("apisix.core.os"),
empty_tab = {},
}
55 changes: 55 additions & 0 deletions apisix/core/os.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local ffi = require("ffi")
local ffi_str = ffi.string
local ffi_errno = ffi.errno
local C = ffi.C
local tostring = tostring
local type = type


local _M = {}


ffi.cdef[[
int setenv(const char *name, const char *value, int overwrite);
char *strerror(int errnum);
]]


local function err()
return ffi_str(C.strerror(ffi_errno()))
end


-- setenv sets the value of the environment variable
function _M.setenv(name, value)
local tv = type(value)
if type(name) ~= "string" or (tv ~= "string" and tv ~= "number") then
return false, "invalid argument"
end

value = tostring(value)
local ok = C.setenv(name, value, 1) == 0
if not ok then
return false, err()
end
return true
end


return _M
15 changes: 11 additions & 4 deletions apisix/plugins/ext-plugin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -547,13 +547,20 @@ local function create_lrucache()
end


local function must_set(env, value)
local ok, err = core.os.setenv(env, value)
if not ok then
error(str_format("failed to set %s: %s", env, err), 2)
end
end


local function spawn_proc(cmd)
must_set("APISIX_CONF_EXPIRE_TIME", helper.get_conf_token_cache_time())
must_set("APISIX_LISTEN_ADDRESS", helper.get_path())

local opt = {
merge_stderr = true,
environ = {
"APISIX_CONF_EXPIRE_TIME=" .. helper.get_conf_token_cache_time(),
"APISIX_LISTEN_ADDRESS=" .. helper.get_path(),
},
}
local proc, err = ngx_pipe.spawn(cmd, opt)
if not proc then
Expand Down
18 changes: 16 additions & 2 deletions docs/en/latest/external-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ ext-plugin:
Then APISIX will manage the runner as its subprocess.
Note: APISIX can't manage the runner on the Mac. It is fine, we can run the runner by ourselves
during development.
Note: APISIX can't manage the runner on the Mac in `v2.6`.

During development, we want to run the runner separately so that we can restart it without
restarting APISIX first.
Expand All @@ -89,3 +88,18 @@ ext-plugin:

In the prod environment, `path_for_test` should not be used and the unix socket
path will be generated dynamically.

## FAQ

### When managing by APISIX, the runner can't access my environment variable

Since `v2.7`, APISIX can pass environment to the runner.

However, Nginx will hide all environment variables by default. So you need to
declare your variable first in the `conf/config.yaml`:

```yaml
nginx_config:
envs:
- MY_ENV_VAR
```
72 changes: 72 additions & 0 deletions t/core/os.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
use t::APISIX 'no_plan';

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->request) {
$block->set_value("request", "GET /t");
}

if (!$block->no_error_log && !$block->error_log) {
$block->set_value("no_error_log", "[error]\n[alert]");
}
});

run_tests;

__DATA__
=== TEST 1: setenv
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
core.os.setenv("TEST", "A")
ngx.say(os.getenv("TEST"))
core.os.setenv("TEST", 1)
ngx.say(os.getenv("TEST"))
}
}
--- response_body
A
1
=== TEST 2: setenv, bad arguments
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
for _, c in ipairs({
{name = "A"},
{value = "A"},
{name = 1, value = "A"},
}) do
local ok = core.os.setenv(c.name, c.value)
ngx.say(ok)
end
}
}
--- response_body
false
false
false
1 change: 1 addition & 0 deletions t/plugin/ext-plugin/runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@

echo "LISTEN $APISIX_LISTEN_ADDRESS"
echo "EXPIRE $APISIX_CONF_EXPIRE_TIME"
echo "MY_ENV_VAR $MY_ENV_VAR"
sleep "$1"
exit 111
14 changes: 14 additions & 0 deletions t/plugin/ext-plugin/sanity.t
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,17 @@ GET /hello
--- error_code: 503
--- error_log
failed to receive RPC_PREPARE_CONF: bad request
=== TEST 12: runner can access the environment variable
--- main_config
env MY_ENV_VAR=foo;
--- ext_plugin_cmd
["t/plugin/ext-plugin/runner.sh", "3600"]
--- config
location /t {
return 200;
}
--- error_log
MY_ENV_VAR foo

0 comments on commit 9d6f6d8

Please sign in to comment.