Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add control API #3048

Merged
merged 5 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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