You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by "yuqiquan (via GitHub)" <gi...@apache.org> on 2023/02/13 02:49:49 UTC

[GitHub] [apisix] yuqiquan opened a new issue, #8843: help request: use cjson.decode resolve router values failed

yuqiquan opened a new issue, #8843:
URL: https://github.com/apache/apisix/issues/8843

   ### Description
   
   我想自定义个插件 ,提供一个control api接口获得apisix启动后缓存的路由信息,于是
   
   ```lua
   local core = require("apisix.core")
   local rotateutil = require("apisix.plugins.util.rotateutil")
   local plugin = require("apisix.plugin")
   local httpUtil = require("apisix.plugins.util.httputil")
   local commonutil = require("apisix.plugins.util.commonutil")
   local wafupdate = require("apisix.plugins.wafupdate")
   local router = require("apisix.router")
   local cjson = require("cjson.safe")
   local ngx = ngx
   local ngx_time = ngx.time
   local ngx_update_time = ngx.update_time
   local os_date = os.date
   local json_decode = cjson.decode
   
   local process = require("ngx.process")
   
   local plugin_name = "info-report"
   local INTERVAL = 3600    -- 默认轮询时间
   local taskThreads = {}
   local instance_taskThreads = {}
   local resolveResult
   
   -- 默认时是否执行
   local isExcuteStarting = false
   local ip
   local openresty_version
   local startTime
   local fwd_dc
   
   
   local schema = {
       type = "object",
       properties = {},
   }
   
   local _M = {
       version = 1.0,
       priority = -1700,
       name = plugin_name,
       schema = schema,
       -- 这样设置全局
       scope = "global",
   }
   
   -- 上报apisix实例信息
   local function report_instance(args)
       if args.isExcuting then
           return
       end
       args.isExcuting = true
       local ok,result = pcall(function()
           ngx_update_time()
           local now_time = ngx_time()
           core.log.warn("plugin#info-report --- > report Apisix instance info ,now time : " ,os_date("%Y-%m-%d_%H-%M-%S",now_time))
           local ip =ip
           local fwd_dc = fwd_dc
           -- 获得端口号
           local local_conf = core.config.local_conf()
           local port = local_conf.apisix.node_listen[1] or "9080"
           -- 获取apisix 集群前缀
           local prefix = local_conf.etcd.prefix
           -- 设置etcd key值
           local key = "/fwd/instance/".. fwd_dc .. "_" .. ip ..":" .. port
           core.log.warn("key --- > ", key)
           -- 设置etcd value值
           local value = {}
           value.ip = ip
           value.port = port
           value.fwd_dc = fwd_dc
           value.openresty_version = openresty_version
           value.apisix_version = core.version.VERSION
           value.apisix_prefix = prefix
           --------------------
           --配置文件内容
           local conf = {}
           --plugins
           local getPlugins = {}
           for k,v in pairs(plugin.plugins) do
               local info = {}
               info.version = v.version
               info.priority = v.priority
               info.attr = v.attr
               getPlugins[v.name] = info
           end
           conf.plugins = getPlugins
           -- apisix
           local apisix = {}
           apisix.node_listen = local_conf.apisix.node_listen
           apisix.extra_lua_path = local_conf.apisix.extra_lua_path
           apisix.extra_lua_cpath = local_conf.apisix.extra_lua_cpath
           apisix.proxy_cache = local_conf.apisix.proxy_cache
           apisix.router = local_conf.apisix.router
           local ssl = {}
           ssl.listen = local_conf.apisix.ssl.listen
           ssl.fallback_sni = local_conf.apisix.ssl.fallback_sni
           apisix.ssl = ssl
           apisix.enable_control = local_conf.apisix.enable_control
           apisix.control = local_conf.apisix.control
           conf.apisix = apisix
           -- nginx_config
           local nginx_config = {}
           nginx_config.user = local_conf.nginx_config.user
           nginx_config.main_configuration_snippet = local_conf.nginx_config.main_configuration_snippet
           nginx_config.http_configuration_snippet = local_conf.nginx_config.http_configuration_snippet
           nginx_config.http_server_configuration_snippet = local_conf.nginx_config.http_server_configuration_snippet
           nginx_config.http_server_location_configuration_snippet = local_conf.nginx_config.http_server_location_configuration_snippet
           nginx_config.http_admin_configuration_snippet = local_conf.nginx_config.http_admin_configuration_snippet
           nginx_config.http_end_configuration_snippet = local_conf.nginx_config.http_end_configuration_snippet
           nginx_config.stream_configuration_snippet = local_conf.nginx_config.stream_configuration_snippet
           local http = {}
           for k,v in pairs(local_conf.nginx_config.http) do
               if k == "lua_shared_dict" then
                   http[k] = nil
               else
                   http[k] = v
               end
           end
           nginx_config.http = http
           conf.nginx_config = nginx_config
           -- etcd
           local etcd = {}
           etcd.host = local_conf.etcd.host
           etcd.timeout = local_conf.etcd.timeout
           etcd.user = local_conf.etcd.user
           conf.etcd = etcd
           -- ext-plugin
           conf["ext-plugin"] = local_conf["ext-plugin"]
   
           value.conf = conf
   
           --cpu负载,内存占用
           value.machine_info = commonutil.getMachineInfo()
           --------------------------
           ngx_update_time()
           value.report_time = ngx_time()
           -- 将value值存入etcd中
           -- 存入值
           local res, err = commonutil.insertEtcd(key,value)
           if err then
               core.log.error("etcd insert value failed , key --->  ", key,"   error ---> ",err)
           end
       end)
       if not ok then
           core.log.warn("report machine instance info occur error ---> ",result)
       end
       args.isExcuting = false
       return
   end
   
   -- 上报具体应用信息
   local function reportInfo(args)
       if args.isExcuting then
           return
       end
       args.isExcuting = true
       local ok,result = pcall(function()
           ngx_update_time()
           local now_time = ngx_time()
           core.log.warn("plugin#info-report --- > report info application  ",args.name,"   ,now_time : " ,os_date("%Y-%m-%d_%H-%M-%S",now_time))
           if args.name == "waf" then
               -- 将waf所需信息存入etcd中
               wafupdate.insertInfo(fwd_dc,ip)
           end
       end)
       if not ok then
           core.log.warn("report waf info occur error ---> ", result)
       end
       args.isExcuting = false
   end
   local function reportInstanceStarting(premature,args)
       --core.log.warn("================= report Apisix Instance excute  while apisix starting =====================")
       if premature then
           return
       end
       report_instance(args)
   
   end
   local function reportInfoStarting(premature,args)
       --core.log.warn("================= report Application info excute  while apisix starting =====================")
       if premature then
           return
       end
       reportInfo(args)
   
   end
   
   
   -- 解析插件配置属性,封装多个子任务
   local function resolveInfo()
       if not process.type() == "privileged agent" then
           return true
       end
       -- 获取插件元数据配置信息
       local attr = plugin.plugin_attr(plugin_name) or {}
       ip =  core.table.try_read_attr(core.config.local_conf(),"fwd","ip")
       openresty_version = core.table.try_read_attr(core.config.local_conf(),"fwd","openresty_version")
       fwd_dc = core.table.try_read_attr(core.config.local_conf(),"fwd","dc")
       if (not ip) or (not openresty_version) or (not fwd_dc ) then
           core.log.warn("APISIX instance required info is incomplete,info include : IP  FWD_DC  openresty_version")
           return false
       end
       isExcuteStarting = attr.isExcuteStarting or isExcuteStarting
       startTime = attr.startTime
       local applications = attr.applications
       local index = 1
       if applications then
           for k,v in pairs(applications) do
               local taskThread = {}
               taskThread.rotate_time = startTime
               taskThread.interval = v.interval or INTERVAL
               taskThread.f = reportInfo
               local args = {}
               args.name = k
               taskThread.args =  args
               taskThreads[index] = taskThread
               index = index + 1
           end
       end
       local taskThread = {}
       taskThread.rotate_time = startTime
       taskThread.interval = attr.instance_interval or INTERVAL
       taskThread.f = report_instance
       taskThread.args = {}
       instance_taskThreads[1] = taskThread
       return true
   end
   
   function _M.init()
       -- 让定时器开始启动
       rotateutil.startRotate()
   
       resolveResult = resolveInfo()
   
       if not resolveResult then
           core.log.error("plugin " .. plugin_name .. "  atttr occur  error,please check !")
           return
       end
   
       -- 将这个插件的应用任务添加进定时器
       rotateutil.register_task("plugin#info-report#instance",true,instance_taskThreads)
   
       rotateutil.register_task("plugin#info-report",true,taskThreads)
   
       -- 启动时默认执行
       if isExcuteStarting and process.type() == "privileged agent" then
           rotateutil.excuteWhileStart(reportInstanceStarting,instance_taskThreads)
           rotateutil.excuteWhileStart(reportInfoStarting,taskThreads)
       end
   end
   
   function _M.destroy()
       if not resolveResult then
           return
       end
       rotateutil.unregister_task("plugin#info-report#instance",true)
       rotateutil.unregister_task("plugin#info-report",true)
   end
   
   
   local function getCacheInfo()
       core.log.warn("获取当前缓存路由和证书信息")
       -- 获取访问apisix admin api的token
       local result = {}
       local routes = {}
       local ssls = {}
       --路由信息
       local routesvalues = router.router_http.user_routes.values
       routesvalues = json_decode(core.json.encode(routesvalues,true))
       for k, v in pairs(routesvalues) do
           if v and type(v) == "table" then
               local value = v.value
               if value and type(value) == "table" then
                   table.insert(routes,value)
               end
           end
       end
       --证书信息
       local sslsvalues, sslsversion = router.router_ssl.ssls()
       sslsvalues = json_decode(core.json.encode(sslsvalues,true))
       for k, v in pairs(sslsvalues) do
           if v and type(v) == "table" then
               local value = v.value
               local sslInfo = {}
               if value and type(value) == "table" then
                   sslInfo.id = value.id
                   sslInfo.snis = value.snis
                   sslInfo.status = value.status
                   sslInfo.validity_end = value.validity_end
                   table.insert(ssls,sslInfo)
               end
           end
       end
       result.routes = routes
       result.ssls = ssls
       return 200, result
   end
   
   function _M.control_api()
       return {
           {
               methods = { "GET" },
               uris = { "/v1/plugin/info-report/getCacheInfo" },
               handler = getCacheInfo,
           }
       }
   end
   
   return _M
   ```
   
   通过访问 ,一般情况下是没有问题的,但是有时候就会报错
   ` bad argument #1 to 'json_decode' (expected 1 argument)`
   
   难道是encode结果有问题,是不是不应该这样解析
   
   
   ### Environment
   
   - APISIX version (run `apisix version`): 2.15.0
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [apisix] An-DJ commented on issue #8843: help request: use cjson.decode resolve router values failed

Posted by "An-DJ (via GitHub)" <gi...@apache.org>.
An-DJ commented on issue #8843:
URL: https://github.com/apache/apisix/issues/8843#issuecomment-1427838107

   @yuqiquan It seems that you could log the encode and decode contents to further find why. Maybe the argument is missing.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [apisix] shreemaan-abhishek closed issue #8843: help request: use cjson.decode resolve router values failed

Posted by "shreemaan-abhishek (via GitHub)" <gi...@apache.org>.
shreemaan-abhishek closed issue #8843: help request: use cjson.decode resolve router values failed
URL: https://github.com/apache/apisix/issues/8843


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [apisix] shreemaan-abhishek commented on issue #8843: help request: use cjson.decode resolve router values failed

Posted by "shreemaan-abhishek (via GitHub)" <gi...@apache.org>.
shreemaan-abhishek commented on issue #8843:
URL: https://github.com/apache/apisix/issues/8843#issuecomment-1709452897

   @yuqiquan you are getting that error because in your code:
   ```lua
   sslsvalues = json_decode(core.json.encode(sslsvalues,true))
   ```
   
   `json_decode` expects one parameter, but `core.json.encode` returns two values.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org