diff --git a/conf/config.yaml b/conf/config.yaml index c8ca617598c1..7b5ac2d989ef 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -5,3 +5,4 @@ etcd: plugins: - example_plugin + - not_exist_plugin diff --git a/lua/apimeta/core/config.lua b/lua/apimeta/core/config.lua index afc35e2285ed..e8dfc757f638 100644 --- a/lua/apimeta/core/config.lua +++ b/lua/apimeta/core/config.lua @@ -1,16 +1,15 @@ -- Copyright (C) Yuansheng Wang local ngx = ngx -local pcall = pcall local yaml = require("apimeta.core.yaml") local io_open = io.open - +local type = type local config_path = ngx.config.prefix() .. "conf/config.yaml" local _M = {} local function read_file(path) - local file = io_open(path, "rb") -- r read mode and b binary mode + local file = io_open(path, "rb") -- read and binary mode if not file then return nil end diff --git a/lua/apimeta/plugin.lua b/lua/apimeta/plugin.lua index e1f01a5ad986..c71bb8b3af8b 100644 --- a/lua/apimeta/plugin.lua +++ b/lua/apimeta/plugin.lua @@ -1,6 +1,14 @@ +local require = require +local config = require("apimeta.core.config") local typeof = require("apimeta.core.typeof") local log = require("apimeta.core.log") +local new_tab = require("table.new") +local insert_tab = table.insert +local sort_tab = table.sort local tostring = tostring +local pcall = pcall +local ipairs = ipairs +local pairs = pairs local _M = { @@ -19,5 +27,44 @@ function _M.check_args(args, scheme) return true end +local function sort_plugin(l, r) + return l.priority > r.priority +end + +function _M.load() + local plugin_names = config.read().plugins + if not plugin_names then + return nil, "failed to read plugin list form local file" + end + + local plugins = new_tab(#plugin_names, 0) + for _, name in ipairs(plugin_names) do + local ok, plugin = pcall(require, "apimeta.plugins." .. name) + if not ok then + log.error("failed to load plugin ", name, " err: ", plugin) + + elseif not plugin.priority then + log.error("invalid plugin", name, ", missing field: priority") + + elseif not plugin.check_args then + log.error("invalid plugin", name, ", missing method: check_args") + + elseif not plugin.version then + log.error("invalid plugin", name, ", missing field: version") + + else + plugin.name = name + insert_tab(plugins, plugin) + end + end + + -- sort by plugin's priority + if #plugins > 1 then + sort_tab(plugins, sort_plugin) + end + + return plugins +end + return _M diff --git a/lua/apimeta/plugins/example_plugin.lua b/lua/apimeta/plugins/example_plugin.lua index 63d395811c9a..6924f99cd491 100644 --- a/lua/apimeta/plugins/example_plugin.lua +++ b/lua/apimeta/plugins/example_plugin.lua @@ -1,14 +1,19 @@ local plugin = require("apimeta.plugin") +-- TODO: need a more powerful way to define the schema local args_schema = { - i = "int", -- value list: apimeta.core.typeof#92 + i = "int", -- value list: apimeta.core.typeof#92 s = "string", t = "table", } -local _M = {version = 0.1} +local _M = { + version = 0.1, + priority = 1000, -- TODO: add a type field, may be a good idea + name = "example_plugin", +} function _M.check_args(config) diff --git a/t/example-plugin.t b/t/example-plugin.t index 50a360772237..4ef3286fade2 100644 --- a/t/example-plugin.t +++ b/t/example-plugin.t @@ -1,15 +1,14 @@ use t::APIMeta 'no_plan'; -repeat_each(1); +repeat_each(2); no_long_string(); -no_shuffle(); log_level('info'); run_tests; __DATA__ -=== TEST 1: sanity +=== TEST 1: check arguments --- config location /t { content_by_lua_block { @@ -44,3 +43,31 @@ failed to check args: args.i expect int value but got: [nil] failed to check args: args.s expect string value but got: [3] failed to check args: args.t expect table value but got: [] done + + + +=== TEST 2: load plugins +--- config + location /t { + content_by_lua_block { + local plugins, err = require("apimeta.plugin").load() + if not plugins then + ngx.say("failed to load plugins: ", err) + end + + local encode_json = require "cjson.safe" .encode + for _, plugin in ipairs(plugins) do + ngx.say("plugin name: ", plugin.name, + " priority: ", plugin.priority) + + plugin.rewrite() + end + } + } +--- request +GET /t +--- response_body +plugin name: example_plugin priority: 1000 +--- error_log +failed to load plugin not_exist_plugin err: module 'apimeta.plugins.not_exist_plugin' not found +rewrite(): plugin rewrite phase diff --git a/t/sanity.t b/t/sanity.t index 9fcc8037cda2..a90a67c1623b 100644 --- a/t/sanity.t +++ b/t/sanity.t @@ -1,8 +1,7 @@ use t::APIMeta 'no_plan'; -repeat_each(1); +repeat_each(2); no_long_string(); -no_shuffle(); log_level('info'); run_tests(); diff --git a/t/yaml-config.t b/t/yaml-config.t index 3bef3c6ffebc..ebaeb1d34316 100644 --- a/t/yaml-config.t +++ b/t/yaml-config.t @@ -1,8 +1,7 @@ use t::APIMeta 'no_plan'; -repeat_each(1); +repeat_each(2); no_long_string(); -no_shuffle(); log_level('info'); run_tests; @@ -26,4 +25,4 @@ GET /t --- response_body etcd host: http://127.0.0.1:2379 etcd prefix: /v2/keys -plugins: ["example_plugin"] +plugins: ["example_plugin","not_exist_plugin"]