You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by mo...@apache.org on 2024/02/19 07:13:42 UTC
(apisix) branch master updated: feat: add plugins/reload to control api (#10905)
This is an automated email from the ASF dual-hosted git repository.
monkeydluffy 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 21d9ceeac feat: add plugins/reload to control api (#10905)
21d9ceeac is described below
commit 21d9ceeac9715dcdad37335fe402e325ee74a43d
Author: Shehar Yaar <sh...@gmail.com>
AuthorDate: Mon Feb 19 12:43:36 2024 +0530
feat: add plugins/reload to control api (#10905)
---
apisix/control/router.lua | 12 +-
apisix/control/v1.lua | 18 +++
apisix/init.lua | 1 +
docs/en/latest/control-api.md | 10 ++
t/control/plugins-reload.t | 341 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 381 insertions(+), 1 deletion(-)
diff --git a/apisix/control/router.lua b/apisix/control/router.lua
index 851dbc872..e6e5ff9b3 100644
--- a/apisix/control/router.lua
+++ b/apisix/control/router.lua
@@ -27,7 +27,7 @@ local pairs = pairs
local type = type
local ngx = ngx
local get_method = ngx.req.get_method
-
+local events = require("apisix.events")
local _M = {}
@@ -198,5 +198,15 @@ end
end -- do
+local function reload_plugins()
+ core.log.info("start to hot reload plugins")
+ plugin_mod.load()
+end
+
+
+function _M.init_worker()
+ -- register reload plugin handler
+ events:register(reload_plugins, builtin_v1_routes.reload_event, "PUT")
+end
return _M
diff --git a/apisix/control/v1.lua b/apisix/control/v1.lua
index 6838ee4cb..213ed0ac4 100644
--- a/apisix/control/v1.lua
+++ b/apisix/control/v1.lua
@@ -25,11 +25,14 @@ local collectgarbage = collectgarbage
local ipairs = ipairs
local pcall = pcall
local str_format = string.format
+local ngx = ngx
local ngx_var = ngx.var
+local events = require("apisix.events")
local _M = {}
+_M.RELOAD_EVENT = 'control-api-plugin-reload'
function _M.schema()
local http_plugins, stream_plugins = plugin.get_all({
@@ -400,6 +403,14 @@ function _M.dump_plugin_metadata()
return 200, metadata.value
end
+function _M.post_reload_plugins()
+ local success, err = events:post(_M.RELOAD_EVENT, ngx.req.get_method(), ngx.time())
+ if not success then
+ core.response.exit(503, err)
+ end
+
+ core.response.exit(200, "done")
+end
return {
-- /v1/schema
@@ -474,5 +485,12 @@ return {
uris = {"/plugin_metadata/*"},
handler = _M.dump_plugin_metadata,
},
+ -- /v1/plugins/reload
+ {
+ methods = {"PUT"},
+ uris = {"/plugins/reload"},
+ handler = _M.post_reload_plugins,
+ },
get_health_checkers = _get_health_checkers,
+ reload_event = _M.RELOAD_EVENT,
}
diff --git a/apisix/init.lua b/apisix/init.lua
index 9a13fae8e..91dc83f0b 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -155,6 +155,7 @@ function _M.http_init_worker()
apisix_upstream.init_worker()
require("apisix.plugins.ext-plugin.init").init_worker()
+ control_api_router.init_worker()
local_conf = core.config.local_conf()
if local_conf.apisix and local_conf.apisix.enable_server_tokens == false then
diff --git a/docs/en/latest/control-api.md b/docs/en/latest/control-api.md
index e21ca86d5..8bd147869 100644
--- a/docs/en/latest/control-api.md
+++ b/docs/en/latest/control-api.md
@@ -475,3 +475,13 @@ Dumps the metadata with the specified `plugin_name`:
"id": "file-logger"
}
```
+
+### PUT /v1/plugins/reload
+
+Introduced in [v3.9.0](https://github.com/apache/apisix/releases/tag/3.9.0)
+
+Triggers a hot reload of the plugins.
+
+```shell
+curl "http://127.0.0.1:9090/v1/plugins/reload" -X PUT
+```
diff --git a/t/control/plugins-reload.t b/t/control/plugins-reload.t
new file mode 100644
index 000000000..cb9e18623
--- /dev/null
+++ b/t/control/plugins-reload.t
@@ -0,0 +1,341 @@
+#
+# 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';
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+no_shuffle();
+log_level("info");
+workers(2);
+
+add_block_preprocessor(sub {
+ my ($block) = @_;
+
+ $block;
+});
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: reload plugins
+--- yaml_config
+apisix:
+ node_listen: 1984
+ enable_control: true
+ control:
+ ip: "127.0.0.1"
+ port: 9090
+--- config
+location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin")
+
+ local code, body, res = t.test('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+ ngx.say(res)
+ ngx.sleep(1)
+ }
+}
+--- request
+GET /t
+--- response_body
+done
+--- error_log
+load plugin times: 2
+load plugin times: 2
+start to hot reload plugins
+start to hot reload plugins
+
+
+
+=== TEST 2: reload plugins when attributes changed
+--- yaml_config
+apisix:
+ node_listen: 1984
+ enable_admin: true
+ node_listen: 1984
+plugins:
+ - example-plugin
+plugin_attr:
+ example-plugin:
+ val: 0
+--- config
+location /t {
+ content_by_lua_block {
+ local core = require "apisix.core"
+ ngx.sleep(0.1)
+ local data = [[
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ admin:
+ admin_key: null
+apisix:
+ node_listen: 1984
+ enable_control: true
+ control:
+ ip: "127.0.0.1"
+ port: 9090
+plugins:
+ - example-plugin
+plugin_attr:
+ example-plugin:
+ val: 1
+ ]]
+ require("lib.test_admin").set_config_yaml(data)
+
+ local t = require("lib.test_admin").test
+ local code, _, org_body = t('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+
+ ngx.status = code
+ ngx.say(org_body)
+ ngx.sleep(0.1)
+
+ local data = [[
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ admin:
+ admin_key: null
+apisix:
+ node_listen: 1984
+plugins:
+ - example-plugin
+plugin_attr:
+ example-plugin:
+ val: 1
+ ]]
+ require("lib.test_admin").set_config_yaml(data)
+
+ local t = require("lib.test_admin").test
+ local code, _, org_body = t('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+ ngx.say(org_body)
+ ngx.sleep(0.1)
+ }
+}
+--- request
+GET /t
+--- response_body
+done
+done
+--- grep_error_log eval
+qr/example-plugin get plugin attr val: \d+/
+--- grep_error_log_out
+example-plugin get plugin attr val: 0
+example-plugin get plugin attr val: 0
+example-plugin get plugin attr val: 0
+example-plugin get plugin attr val: 1
+example-plugin get plugin attr val: 1
+example-plugin get plugin attr val: 1
+example-plugin get plugin attr val: 1
+example-plugin get plugin attr val: 1
+example-plugin get plugin attr val: 1
+
+
+
+=== TEST 3: reload plugins to change prometheus' export uri
+--- yaml_config
+apisix:
+ node_listen: 1984
+plugins:
+ - public-api
+ - prometheus
+plugin_attr:
+ prometheus:
+ export_uri: /metrics
+--- config
+location /t {
+ content_by_lua_block {
+ local core = require "apisix.core"
+ ngx.sleep(0.1)
+ local t = require("lib.test_admin").test
+
+ -- setup public API route
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "public-api": {}
+ },
+ "uri": "/apisix/metrics"
+ }]]
+ )
+ ngx.say(code)
+
+ local code, _, org_body = t('/apisix/metrics',
+ ngx.HTTP_GET)
+ ngx.say(code)
+
+ local data = [[
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ admin:
+ admin_key: null
+apisix:
+ node_listen: 1984
+ enable_control: true
+ control:
+ ip: "127.0.0.1"
+ port: 9090
+plugins:
+ - public-api
+ - prometheus
+plugin_attr:
+ prometheus:
+ export_uri: /apisix/metrics
+ ]]
+ require("lib.test_admin").set_config_yaml(data)
+
+ local code, _, org_body = t('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+
+ ngx.say(org_body)
+
+ ngx.sleep(0.1)
+ local code, _, org_body = t('/apisix/metrics',
+ ngx.HTTP_GET)
+ ngx.say(code)
+ }
+}
+--- request
+GET /t
+--- response_body
+201
+404
+done
+200
+
+
+
+=== TEST 4: reload plugins to disable skywalking
+--- yaml_config
+apisix:
+ node_listen: 1984
+ enable_control: true
+ control:
+ ip: "127.0.0.1"
+ port: 9090
+plugins:
+ - skywalking
+plugin_attr:
+ skywalking:
+ service_name: APISIX
+ service_instance_name: "APISIX Instance Name"
+ endpoint_addr: http://127.0.0.1:12801
+ report_interval: 1
+--- config
+location /t {
+ content_by_lua_block {
+ local core = require "apisix.core"
+ ngx.sleep(1.2)
+ local t = require("lib.test_admin").test
+
+ local data = [[
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ admin:
+ admin_key: null
+apisix:
+ node_listen: 1984
+plugins:
+ - prometheus
+ ]]
+ require("lib.test_admin").set_config_yaml(data)
+
+ local code, _, org_body = t('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+
+ ngx.say(org_body)
+
+ ngx.sleep(2)
+ }
+}
+--- request
+GET /t
+--- response_body
+done
+--- no_error_log
+[alert]
+--- grep_error_log eval
+qr/Instance report fails/
+--- grep_error_log_out
+Instance report fails
+
+
+
+=== TEST 5: wrong method to reload plugins
+--- request
+GET /v1/plugins/reload
+--- error_code: 404
+
+
+
+=== TEST 6: wrong method to reload plugins
+--- request
+POST /v1/plugins/reload
+--- error_code: 404
+
+
+
+=== TEST 7: reload plugin with data_plane deployment
+--- yaml_config
+apisix:
+ node_listen: 1984
+ enable_admin: false
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ nodes:
+ "127.0.0.1:1980": 1
+ type: roundrobin
+#END
+--- config
+location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin")
+
+ local code, body, res = t.test('/v1/plugins/reload',
+ ngx.HTTP_PUT)
+ ngx.say(res)
+ ngx.sleep(1)
+ }
+}
+--- request
+GET /t
+--- response_body
+done
+--- error_log
+load plugin times: 2
+load plugin times: 2
+start to hot reload plugins
+start to hot reload plugins