This is an automated email from the ASF dual-hosted git repository.

spacewander 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 9bcca2c  fix(skywalking): handle conflict between global rule and 
route (#4589)
9bcca2c is described below

commit 9bcca2c1f2677d934337ca40bec28923ba4aed43
Author: 罗泽轩 <[email protected]>
AuthorDate: Wed Jul 14 10:56:13 2021 +0800

    fix(skywalking): handle conflict between global rule and route (#4589)
    
    Fix #4571
    
    Signed-off-by: spacewander <[email protected]>
---
 apisix/init.lua                  |  11 ++-
 apisix/plugin.lua                |  17 ++++-
 apisix/plugins/skywalking.lua    |   1 +
 docs/en/latest/plugin-develop.md |  20 ++++-
 docs/zh/latest/plugin-develop.md |  18 ++++-
 t/plugin/skywalking.t            | 158 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 215 insertions(+), 10 deletions(-)

diff --git a/apisix/init.lua b/apisix/init.lua
index 3fc3ac4..7c2f092 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -355,11 +355,11 @@ function _M.http_access_phase()
 
     router.router_http.match(api_ctx)
 
-    -- run global rule
-    plugin.run_global_rules(api_ctx, router.global_rules, nil)
-
     local route = api_ctx.matched_route
     if not route then
+        -- run global rule
+        plugin.run_global_rules(api_ctx, router.global_rules, nil)
+
         core.log.info("not find any matched route")
         return core.response.exit(404,
                     {error_msg = "404 Route Not Found"})
@@ -409,9 +409,13 @@ function _M.http_access_phase()
     api_ctx.route_id = route.value.id
     api_ctx.route_name = route.value.name
 
+    -- run global rule
+    plugin.run_global_rules(api_ctx, router.global_rules, nil)
+
     if route.value.script then
         script.load(route, api_ctx)
         script.run("access", api_ctx)
+
     else
         local plugins = plugin.filter(route)
         api_ctx.plugins = plugins
@@ -429,6 +433,7 @@ function _M.http_access_phase()
                           ", config changed: ", changed)
 
             if changed then
+                api_ctx.matched_route = route
                 core.table.clear(api_ctx.plugins)
                 api_ctx.plugins = plugin.filter(route, api_ctx.plugins)
             end
diff --git a/apisix/plugin.lua b/apisix/plugin.lua
index 7dead03..c8824df 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -300,8 +300,8 @@ local function trace_plugins_info_for_debug(plugins)
 end
 
 
-function _M.filter(user_route, plugins)
-    local user_plugin_conf = user_route.value.plugins
+function _M.filter(conf, plugins, route_conf)
+    local user_plugin_conf = conf.value.plugins
     if user_plugin_conf == nil or
        core.table.nkeys(user_plugin_conf) == 0 then
         trace_plugins_info_for_debug(nil)
@@ -310,14 +310,24 @@ function _M.filter(user_route, plugins)
         return plugins or core.empty_tab
     end
 
+    local route_plugin_conf = route_conf and route_conf.value.plugins
     plugins = plugins or core.tablepool.fetch("plugins", 32, 0)
     for _, plugin_obj in ipairs(local_plugins) do
         local name = plugin_obj.name
         local plugin_conf = user_plugin_conf[name]
 
         if type(plugin_conf) == "table" and not plugin_conf.disable then
+            if plugin_obj.run_policy == "prefer_route" and route_plugin_conf 
~= nil then
+                local plugin_conf_in_route = route_plugin_conf[name]
+                if plugin_conf_in_route and not plugin_conf_in_route.disable 
then
+                    goto continue
+                end
+            end
+
             core.table.insert(plugins, plugin_obj)
             core.table.insert(plugins, plugin_conf)
+
+            ::continue::
         end
     end
 
@@ -684,13 +694,14 @@ function _M.run_global_rules(api_ctx, global_rules, 
phase_name)
 
         local plugins = core.tablepool.fetch("plugins", 32, 0)
         local values = global_rules.values
+        local route = api_ctx.matched_route
         for _, global_rule in config_util.iterate_values(values) do
             api_ctx.conf_type = "global_rule"
             api_ctx.conf_version = global_rule.modifiedIndex
             api_ctx.conf_id = global_rule.value.id
 
             core.table.clear(plugins)
-            plugins = _M.filter(global_rule, plugins)
+            plugins = _M.filter(global_rule, plugins, route)
             if phase_name == nil then
                 _M.run_plugin("rewrite", plugins, api_ctx)
                 _M.run_plugin("access", plugins, api_ctx)
diff --git a/apisix/plugins/skywalking.lua b/apisix/plugins/skywalking.lua
index 41fe814..94c7215 100644
--- a/apisix/plugins/skywalking.lua
+++ b/apisix/plugins/skywalking.lua
@@ -68,6 +68,7 @@ local _M = {
     name = plugin_name,
     schema = schema,
     attr_schema = attr_schema,
+    run_policy = "prefer_route",
 }
 
 
diff --git a/docs/en/latest/plugin-develop.md b/docs/en/latest/plugin-develop.md
index 0708428..0f81940 100644
--- a/docs/en/latest/plugin-develop.md
+++ b/docs/en/latest/plugin-develop.md
@@ -92,7 +92,7 @@ method "http_init" in the file __apisix/init.lua__, and you 
may need to add some
 configuration file in __apisix/cli/ngx_tpl.lua__ file. But it is easy to have 
an impact on the overall situation according to the
 existing plugin mechanism, **we do not recommend this unless you have a 
complete grasp of the code**.
 
-## name and config
+## name, priority and the others
 
 Determine the name and priority of the plugin, and add to conf/config.yaml. 
For example, for the example-plugin plugin,
 you need to specify the plugin name in the code (the name is the unique 
identifier of the plugin and cannot be
@@ -157,9 +157,25 @@ $(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
 $(INSTALL) apisix/plugins/skywalking/*.lua 
$(INST_LUADIR)/apisix/plugins/skywalking/
 ```
 
+There are other fields in the `_M` which affect the plugin's behavior.
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` field can be used to control the behavior of the plugin execution.
+When this field set to `prefer_route`, and the plugin has been configured both
+in the global and at the route level, only the route level one will take 
effect.
+
+`type` field is required to be set to `auth` if your plugin needs to work with 
consumer. See the section below.
+
 ## schema and check
 
-Write [Json Schema](https://json-schema.org) descriptions and check functions. 
Similarly, take the example-plugin plugin as an example to see its
+Write [JSON Schema](https://json-schema.org) descriptions and check functions. 
Similarly, take the example-plugin plugin as an example to see its
 configuration data:
 
 ```json
diff --git a/docs/zh/latest/plugin-develop.md b/docs/zh/latest/plugin-develop.md
index fedb29a..1a428f3 100644
--- a/docs/zh/latest/plugin-develop.md
+++ b/docs/zh/latest/plugin-develop.md
@@ -56,7 +56,7 @@ nginx_config:
 可能需要在 __apisix/cli/ngx_tpl.lua__ 文件中,对 Nginx 
配置文件生成的部分,添加一些你需要的处理。但是这样容易对全局产生影响,根据现有的
 插件机制,**我们不建议这样做,除非你已经对代码完全掌握**。
 
-## 插件命名与配置
+## 插件命名,优先级和其他
 
 给插件取一个很棒的名字,确定插件的加载优先级,然后在 __conf/config.yaml__ 文件中添加上你的插件名。例如 example-plugin 
这个插件,
 需要在代码里指定插件名称(名称是插件的唯一标识,不可重名),在 __apisix/plugins/example-plugin.lua__ 文件中可以看到:
@@ -106,9 +106,23 @@ $(INSTALL) -d $(INST_LUADIR)/apisix/plugins/skywalking
 $(INSTALL) apisix/plugins/skywalking/*.lua 
$(INST_LUADIR)/apisix/plugins/skywalking/
 ```
 
+`_M` 中还有其他字段会影响到插件的行为。
+
+```lua
+local _M = {
+    ...
+    type = 'auth',
+    run_policy = 'prefer_route',
+}
+```
+
+`run_policy` 字段可以用来控制插件执行。当这个字段设置成 `prefer_route` 
时,且该插件同时配置在全局和路由级别,那么只有路由级别的配置生效。
+
+如果你的插件需要跟 `consumer` 一起使用,需要把 `type` 设置成 `auth`。详情见下文。
+
 ## 配置描述与校验
 
-定义插件的配置项,以及对应的 [Json Schema](https://json-schema.org) 描述,并完成对 json 
的校验,这样方便对配置的数据规
+定义插件的配置项,以及对应的 [JSON Schema](https://json-schema.org) 描述,并完成对 JSON 
的校验,这样方便对配置的数据规
 格进行验证,以确保数据的完整性以及程序的健壮性。同样,我们以 example-plugin 插件为例,看看他的配置数据:
 
 ```json
diff --git a/t/plugin/skywalking.t b/t/plugin/skywalking.t
index e58fb69..5c5f03f 100644
--- a/t/plugin/skywalking.t
+++ b/t/plugin/skywalking.t
@@ -37,6 +37,23 @@ _EOC_
 
     $block->set_value("extra_yaml_config", $extra_yaml_config);
 
+    my $extra_init_by_lua = <<_EOC_;
+    local sw_tracer = require("skywalking.tracer")
+    local inject = function(mod, name)
+        local old_f = mod[name]
+        mod[name] = function (...)
+            ngx.log(ngx.WARN, "skywalking run ", name)
+            return old_f(...)
+        end
+    end
+
+    inject(sw_tracer, "start")
+    inject(sw_tracer, "finish")
+    inject(sw_tracer, "prepareForReport")
+_EOC_
+
+    $block->set_value("extra_init_by_lua", $extra_init_by_lua);
+
     $block;
 });
 
@@ -316,3 +333,144 @@ opentracing
 --- no_error_log
 [error]
 --- wait: 4
+
+
+
+=== TEST 9: enable at both global and route levels
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "skywalking": {
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/opentracing"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                return
+            end
+
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/global_rules/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "skywalking": {
+                        }
+                    }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                return
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 10: run once
+--- request
+GET /opentracing
+--- response_body
+opentracing
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/skywalking run \w+/
+--- grep_error_log_out
+skywalking run start
+skywalking run finish
+skywalking run prepareForReport
+
+
+
+=== TEST 11: enable at global but disable at route levels
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "skywalking": {
+                            "disable": 1
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/opentracing"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                return
+            end
+
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/global_rules/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "skywalking": {
+                        }
+                    }
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                return
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 12: run once
+--- request
+GET /opentracing
+--- response_body
+opentracing
+--- no_error_log
+[error]
+--- grep_error_log eval
+qr/skywalking run \w+/
+--- grep_error_log_out
+skywalking run start
+skywalking run finish
+skywalking run prepareForReport

Reply via email to