Skip to content

Commit

Permalink
feat: add control API (#3048)
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <[email protected]>
Co-authored-by: John Bampton <[email protected]
  • Loading branch information
spacewander authored Dec 18, 2020
1 parent 952854d commit 924a30d
Show file tree
Hide file tree
Showing 16 changed files with 497 additions and 24 deletions.
31 changes: 31 additions & 0 deletions .travis/apisix_cli_test/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# 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.
#

# 'make init' operates scripts and related configuration files in the current directory
# The 'apisix' command is a command in the /usr/local/apisix,
# and the configuration file for the operation is in the /usr/local/apisix/conf

set -ex

clean_up() {
make stop || true
git checkout conf/config.yaml
}

trap clean_up EXIT

unset APISIX_PROFILE
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,10 @@
# limitations under the License.
#

# This file is like apisix_cli_test.sh, but requires extra dependencies which
# you don't need them in daily development.
# This file is like other test_*.sh, but requires extra dependencies which
# you don't need in daily development.

set -ex

clean_up() {
git checkout conf/config.yaml
}

trap clean_up EXIT

unset APISIX_PROFILE
. ./.travis/apisix_cli_test/common.sh

# check error handling when connecting to old etcd
git checkout conf/config.yaml
Expand Down
118 changes: 118 additions & 0 deletions .travis/apisix_cli_test/test_control.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env bash

#
# 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.
#

. ./.travis/apisix_cli_test/common.sh

# control server
echo '
apisix:
enable_control: true
' > conf/config.yaml

make init

if ! grep "listen 127.0.0.1:9090;" conf/nginx.conf > /dev/null; then
echo "failed: find default address for control server"
exit 1
fi

make run

sleep 0.1
code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9090/v1/schema)

if [ ! $code -eq 200 ]; then
echo "failed: access control server"
exit 1
fi

code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9090/v0/schema)

if [ ! $code -eq 404 ]; then
echo "failed: handle route not found"
exit 1
fi

make stop

echo '
apisix:
enable_control: true
control:
ip: 127.0.0.2
' > conf/config.yaml

make init

if ! grep "listen 127.0.0.2:9090;" conf/nginx.conf > /dev/null; then
echo "failed: customize address for control server"
exit 1
fi

make run

sleep 0.1
code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.2:9090/v1/schema)

if [ ! $code -eq 200 ]; then
echo "failed: access control server"
exit 1
fi

make stop

echo '
apisix:
enable_control: true
control:
port: 9091
' > conf/config.yaml

make init

if ! grep "listen 127.0.0.1:9091;" conf/nginx.conf > /dev/null; then
echo "failed: customize address for control server"
exit 1
fi

make run

sleep 0.1
code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code} http://127.0.0.1:9091/v1/schema)

if [ ! $code -eq 200 ]; then
echo "failed: access control server"
exit 1
fi

make stop

echo '
apisix:
enable_control: false
' > conf/config.yaml

make init

if grep "listen 127.0.0.1:9090;" conf/nginx.conf > /dev/null; then
echo "failed: disable control server"
exit 1
fi

echo "pass: access control server"
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,7 @@
# The 'apisix' command is a command in the /usr/local/apisix,
# and the configuration file for the operation is in the /usr/local/apisix/conf

set -ex

clean_up() {
git checkout conf/config.yaml
}

trap clean_up EXIT

unset APISIX_PROFILE
. ./.travis/apisix_cli_test/common.sh

git checkout conf/config.yaml

Expand Down Expand Up @@ -546,7 +538,7 @@ if [ $count_test_access_log -eq 0 ]; then
fi

count_access_log_off=`grep -c "access_log off;" conf/nginx.conf || true`
if [ $count_access_log_off -eq 2 ]; then
if [ $count_access_log_off -eq 3 ]; then
echo "failed: nginx.conf file find access_log off; when enable access log"
exit 1
fi
Expand Down Expand Up @@ -581,7 +573,7 @@ if [ $count_test_access_log -eq 1 ]; then
fi

count_access_log_off=`grep -c "access_log off;" conf/nginx.conf || true`
if [ $count_access_log_off -ne 2 ]; then
if [ $count_access_log_off -ne 3 ]; then
echo "failed: nginx.conf file doesn't find access_log off; when disable access log"
exit 1
fi
Expand Down
5 changes: 3 additions & 2 deletions .travis/linux_apisix_current_luarocks_runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ script() {
cd ..

# apisix cli test
sudo PATH=$PATH .travis/apisix_cli_test.sh
sudo PATH=$PATH .travis/apisix_cli_test_in_ci.sh
for f in ./.travis/apisix_cli_test/test_*.sh; do
sudo PATH="$PATH" "$f"
done
}

case_opt=$1
Expand Down
14 changes: 14 additions & 0 deletions apisix/cli/ngx_tpl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,20 @@ http {
apisix.http_init_worker()
}
{% if enable_control then %}
server {
listen {* control_server_addr *};
access_log off;
location / {
content_by_lua_block {
apisix.http_control()
}
}
}
{% end %}
{% if enable_admin and port_admin then %}
server {
{%if https_admin then%}
Expand Down
19 changes: 19 additions & 0 deletions apisix/cli/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,25 @@ Please modify "admin_key" in conf/config.yaml .
sys_conf[k] = v
end

if yaml_conf.apisix.enable_control then
if not yaml_conf.apisix.control then
sys_conf.control_server_addr = "127.0.0.1:9090"
else
local ip = yaml_conf.apisix.control.ip
local port = tonumber(yaml_conf.apisix.control.port)

if ip == nil then
ip = "127.0.0.1"
end

if not port then
port = 9090
end

sys_conf.control_server_addr = ip .. ":" .. port
end
end

local wrn = sys_conf["worker_rlimit_nofile"]
local wc = sys_conf["event"]["worker_connections"]
if not wrn or wrn <= wc then
Expand Down
119 changes: 119 additions & 0 deletions apisix/control/router.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
--
-- 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 require = require
local router = require("resty.radixtree")
local builtin_v1_routes = require("apisix.control.v1")
local plugin_mod = require("apisix.plugin")
local core = require("apisix.core")
local str_sub = string.sub
local ipairs = ipairs
local type = type
local ngx = ngx
local get_method = ngx.req.get_method


local _M = {}
local current_version = 1


local fetch_control_api_router
do
local function register_api_routes(routes, api_routes)
for _, route in ipairs(api_routes) do
core.table.insert(routes, {
methods = route.methods,
-- note that it is 'uris' for control API, which is an array of strings
paths = route.uris,
handler = function (api_ctx)
local code, body = route.handler(api_ctx)
if code or body then
if type(body) == "table" and ngx.header["Content-Type"] == nil then
core.response.set_header("Content-Type", "application/json")
end

core.response.exit(code, body)
end
end
})
end
end

local routes = {}
local v1_routes = {}
local function empty_func() end

function fetch_control_api_router()
core.table.clear(v1_routes)

register_api_routes(v1_routes, builtin_v1_routes)

for _, plugin in ipairs(plugin_mod.plugins) do
local api_fun = plugin.control_api
if api_fun then
local api_routes = api_fun(current_version)
register_api_routes(v1_routes, api_routes)
end
end

local v1_router, err = router.new(v1_routes)
if not v1_router then
return nil, err
end

core.table.clear(routes)
core.table.insert(routes, {
paths = {"/v1/*"},
filter_fun = function(vars, opts, ...)
local uri = str_sub(vars.uri, #"/v1" + 1)
return v1_router:dispatch(uri, opts, ...)
end,
handler = empty_func,
})

return router.new(routes)
end

end -- do


do
local match_opts = {}
local cached_version
local router

function _M.match(uri)
if cached_version ~= plugin_mod.load_times then
local err
router, err = fetch_control_api_router()
if router == nil then
core.log.error("failed to fetch valid api router: ", err)
return false
end

cached_version = plugin_mod.load_times
end

core.table.clear(match_opts)
match_opts.method = get_method()

return router:dispatch(uri, match_opts)
end

end -- do


return _M
Loading

0 comments on commit 924a30d

Please sign in to comment.