This is an automated email from the ASF dual-hosted git repository.
juzhiyuan 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 3987963 fix: reload plugin when plugin attribute is cahnged (#2704)
3987963 is described below
commit 39879630ae9a23f9f195963fb75f5488b4f5195e
Author: 罗泽轩 <[email protected]>
AuthorDate: Fri Nov 13 00:23:30 2020 +0800
fix: reload plugin when plugin attribute is cahnged (#2704)
Close #2655
---
apisix/core/table.lua | 28 +++++++++++++++
apisix/plugin.lua | 34 ++++++++++++++++--
apisix/plugins/example-plugin.lua | 5 +++
t/admin/plugins-reload.t | 72 +++++++++++++++++++++++++++++++++++++++
t/core/table.t | 35 +++++++++++++++++++
5 files changed, 172 insertions(+), 2 deletions(-)
diff --git a/apisix/core/table.lua b/apisix/core/table.lua
index ed998d0..b0ef7c9 100644
--- a/apisix/core/table.lua
+++ b/apisix/core/table.lua
@@ -189,4 +189,32 @@ function _M.set_eq(a, b)
end
+-- Compare two elements, including their descendants
+local function deep_eq(a, b)
+ local type_a = type(a)
+ local type_b = type(b)
+
+ if type_a ~= 'table' or type_b ~= 'table' then
+ return a == b
+ end
+
+ local n_a = nkeys(a)
+ local n_b = nkeys(b)
+ if n_a ~= n_b then
+ return false
+ end
+
+ for k, v_a in pairs(a) do
+ local v_b = b[k]
+ local eq = deep_eq(v_a, v_b)
+ if not eq then
+ return false
+ end
+ end
+
+ return true
+end
+_M.deep_eq = deep_eq
+
+
return _M
diff --git a/apisix/plugin.lua b/apisix/plugin.lua
index ae1aedd..85a8f5b 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -51,6 +51,14 @@ local _M = {
}
+local function plugin_attr(name)
+ -- TODO: get attr from synchronized data
+ local local_conf = core.config.local_conf()
+ return core.table.try_read_attr(local_conf, "plugin_attr", name)
+end
+_M.plugin_attr = plugin_attr
+
+
local function sort_plugin(l, r)
return l.priority > r.priority
end
@@ -103,6 +111,7 @@ local function load_plugin(name, plugins_list,
is_stream_plugin)
end
plugin.name = name
+ plugin.attr = plugin_attr(name)
core.table.insert(plugins_list, plugin)
if plugin.init then
@@ -113,6 +122,25 @@ local function load_plugin(name, plugins_list,
is_stream_plugin)
end
+local function plugins_eq(old, new)
+ local eq = core.table.set_eq(old, new)
+ if not eq then
+ core.log.info("plugin list changed")
+ return false
+ end
+
+ for name, plugin in pairs(old) do
+ eq = core.table.deep_eq(plugin.attr, plugin_attr(name))
+ if not eq then
+ core.log.info("plugin_attr of ", name, " changed")
+ return false
+ end
+ end
+
+ return true
+end
+
+
local function load(plugin_names)
local processed = {}
for _, name in ipairs(plugin_names) do
@@ -122,7 +150,7 @@ local function load(plugin_names)
end
-- the same configure may be synchronized more than one
- if core.table.set_eq(local_plugins_hash, processed) then
+ if plugins_eq(local_plugins_hash, processed) then
core.log.info("plugins not changed")
return true
end
@@ -170,7 +198,7 @@ local function load_stream(plugin_names)
end
-- the same configure may be synchronized more than one
- if core.table.set_eq(stream_local_plugins_hash, processed) then
+ if plugins_eq(stream_local_plugins_hash, processed) then
core.log.info("plugins not changed")
return true
end
@@ -216,10 +244,12 @@ function _M.load(config)
local stream_plugin_names
if not config then
+ -- called during starting or hot reload in admin
local_conf = core.config.local_conf(true)
http_plugin_names = local_conf.plugins
stream_plugin_names = local_conf.stream_plugins
else
+ -- called during synchronizing plugin data
http_plugin_names = {}
stream_plugin_names = {}
for _, conf_value in config_util.iterate_values(config.values) do
diff --git a/apisix/plugins/example-plugin.lua
b/apisix/plugins/example-plugin.lua
index a590f43..0a58efd 100644
--- a/apisix/plugins/example-plugin.lua
+++ b/apisix/plugins/example-plugin.lua
@@ -15,6 +15,7 @@
-- limitations under the License.
--
local core = require("apisix.core")
+local plugin = require("apisix.plugin")
local upstream = require("apisix.upstream")
local schema = {
@@ -63,6 +64,10 @@ end
function _M.init()
-- call this function when plugin is loaded
+ local attr = plugin.plugin_attr(plugin_name)
+ if attr then
+ core.log.info(plugin_name, " get plugin attr val: ", attr.val)
+ end
end
diff --git a/t/admin/plugins-reload.t b/t/admin/plugins-reload.t
index d675306..294369d 100644
--- a/t/admin/plugins-reload.t
+++ b/t/admin/plugins-reload.t
@@ -123,3 +123,75 @@ reload plugins on node
reload plugins on node
--- error_log
filter(): [{"name":"jwt-auth"},{"name":"mqtt-proxy","stream":true}]
+
+
+
+=== TEST 3: reload plugins when attributes changed
+--- yaml_config
+apisix:
+ node_listen: 1984
+ admin_key: null
+plugins:
+ - example-plugin
+plugin_attr:
+ example-plugin:
+ val: 0
+--- config
+location /t {
+ content_by_lua_block {
+ local core = require "apisix.core"
+ local data = [[
+apisix:
+ node_listen: 1984
+ admin_key: null
+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('/apisix/admin/plugins/reload',
+ ngx.HTTP_PUT)
+
+ ngx.status = code
+ ngx.say(org_body)
+ ngx.sleep(0.1)
+
+ local data = [[
+apisix:
+ node_listen: 1984
+ admin_key: null
+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('/apisix/admin/plugins/reload',
+ ngx.HTTP_PUT)
+ ngx.say(org_body)
+ }
+}
+--- 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
+--- error_log
+plugin_attr of example-plugin changed
+plugins not changed
diff --git a/t/core/table.t b/t/core/table.t
index a466f62..fc5ea29 100644
--- a/t/core/table.t
+++ b/t/core/table.t
@@ -136,3 +136,38 @@ ok
GET /t
--- no_error_log
[error]
+
+
+
+=== TEST 5: deep_eq
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local cases = {
+ {expect = true, a = {}, b = {}},
+ {expect = true, a = nil, b = nil},
+ {expect = false, a = nil, b = {}},
+ {expect = false, a = {}, b = nil},
+ {expect = true, a = {a = {b = 1}}, b = {a = {b = 1}}},
+ {expect = false, a = {a = {b = 1}}, b = {a = {b = 1, c = 2}}},
+ {expect = false, a = {a = {b = 1}}, b = {a = {b = 2}}},
+ {expect = true, a = {{a = {b = 1}}}, b = {{a = {b = 1}}}},
+ }
+ for _, t in ipairs(cases) do
+ local actual = core.table.deep_eq(t.a, t.b)
+ local expect = t.expect
+ if actual ~= expect then
+ ngx.say("expect ", expect, ", actual ", actual)
+ return
+ end
+ end
+ ngx.say("ok")
+ }
+ }
+--- response_body
+ok
+--- request
+GET /t
+--- no_error_log
+[error]