diff --git a/internal/vm/vm.go b/internal/vm/vm.go index 669e9b1..13c3336 100644 --- a/internal/vm/vm.go +++ b/internal/vm/vm.go @@ -11,11 +11,13 @@ import ( "github.com/kong/goks" "github.com/kong/goks/internal/fs" "github.com/kong/goks/lualibs/go/cjson/safe" + "github.com/kong/goks/lualibs/go/hex" "github.com/kong/goks/lualibs/go/ipmatcher" "github.com/kong/goks/lualibs/go/jsonschema" "github.com/kong/goks/lualibs/go/lyaml" "github.com/kong/goks/lualibs/go/ngx" "github.com/kong/goks/lualibs/go/rand" + "github.com/kong/goks/lualibs/go/sha256" "github.com/kong/goks/lualibs/go/uuid" "github.com/kong/goks/lualibs/go/x509" json "github.com/layeh/gopher-json" @@ -63,6 +65,8 @@ func New(opts Opts) (*VM, error) { l.PreloadModule("go.jsonschema", jsonschema.Loader) l.PreloadModule("cjson.safe", safe.Loader) l.PreloadModule("lyaml", lyaml.Loader) + l.PreloadModule("go.sha256", sha256.Loader) + l.PreloadModule("go.hex", hex.Loader) ngx.LoadNgx(l) if err := setup(l); err != nil { diff --git a/lua-tree/share/lua/5.1/kong/constants.lua b/lua-tree/share/lua/5.1/kong/constants.lua index 775eae0..be9ed67 100644 --- a/lua-tree/share/lua/5.1/kong/constants.lua +++ b/lua-tree/share/lua/5.1/kong/constants.lua @@ -218,25 +218,6 @@ local constants = { KEY_FORMATS_MAP = key_formats_map, KEY_FORMATS = key_formats, - - LOG_LEVELS = { - debug = ngx.DEBUG, - info = ngx.INFO, - notice = ngx.NOTICE, - warn = ngx.WARN, - error = ngx.ERR, - crit = ngx.CRIT, - alert = ngx.ALERT, - emerg = ngx.EMERG, - [ngx.DEBUG] = "debug", - [ngx.INFO] = "info", - [ngx.NOTICE] = "notice", - [ngx.WARN] = "warn", - [ngx.ERR] = "error", - [ngx.CRIT] = "crit", - [ngx.ALERT] = "alert", - [ngx.EMERG] = "emerg", - }, } for _, v in ipairs(constants.CLUSTERING_SYNC_STATUS) do diff --git a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua index 753281a..389d7dc 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua +++ b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua @@ -1,8 +1,6 @@ local typedefs = require("kong.db.schema.typedefs") local deprecation = require("kong.deprecation") -local CACHED_SCHEMA = require("kong.router.atc").schema - -- ATC router is incompatible with goks local kong_router_flavor = "traditional" @@ -48,13 +46,6 @@ if kong_router_flavor == "expressions" then { custom_entity_check = { field_sources = { "expression", "id", }, fn = function(entity) - local r = router.new(CACHED_SCHEMA) - - local res, err = r:add_matcher(0, entity.id, entity.expression) - if not res then - return nil, "Router Expression failed validation: " .. err - end - return true end, } }, diff --git a/lua-tree/share/lua/5.1/kong/db/schema/init.lua b/lua-tree/share/lua/5.1/kong/db/schema/init.lua index 5783eb3..41cf3b3 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/init.lua +++ b/lua-tree/share/lua/5.1/kong/db/schema/init.lua @@ -1,7 +1,8 @@ local tablex = require "pl.tablex" local pretty = require "pl.pretty" local utils = require "kong.tools.utils" -local nkeys = require "table.nkeys" +local nkeys = utils.nkeys +local new_tab = utils.new_tab local cjson = { array_mt = {} } --- TODO(hbagdi) XXX analyze the impact local is_reference = function(value) return false end @@ -43,19 +44,6 @@ Schema.__index = Schema local _cache = {} local _workspaceable = {} --- `table.new()` is a LuaJIT function and is not available to the Lua VM that goks uses. -local new_tab -do - local ok - ok, new_tab = pcall(require, "table.new") - if not ok then - new_tab = function(narr, nrec) - return {} - end - end -end - - local validation_errors = { -- general message ERROR = "Validation error: %s", diff --git a/lua-tree/share/lua/5.1/kong/pdk/node.lua b/lua-tree/share/lua/5.1/kong/pdk/node.lua index 60e6489..85fc2fd 100644 --- a/lua-tree/share/lua/5.1/kong/pdk/node.lua +++ b/lua-tree/share/lua/5.1/kong/pdk/node.lua @@ -1,283 +1 @@ ---- Node-level utilities. --- --- @module kong.node - -local utils = require "kong.tools.utils" -local ffi = require "ffi" -local private_node = require "kong.pdk.private.node" - - -local floor = math.floor -local lower = string.lower -local match = string.match -local gsub = string.gsub -local sort = table.sort -local insert = table.insert -local ngx = ngx -local shared = ngx.shared -local C = ffi.C -local ffi_new = ffi.new -local ffi_str = ffi.string - -local NODE_ID_KEY = "kong:node_id" - - -local node_id -local shms = {} -local n_workers = ngx.worker.count() - - -for shm_name, shm in pairs(shared) do - insert(shms, { - zone = shm, - name = shm_name, - capacity = shm:capacity(), - }) -end - - -local function convert_bytes(bytes, unit, scale) - if not unit or lower(unit) == "b" then - return floor(bytes) - end - - return utils.bytes_to_str(bytes, unit, scale) -end - - -local function sort_pid_asc(a, b) - return a.pid < b.pid -end - - -local function new(self) - local _NODE = {} - - - --- - -- Returns the ID used by this node to describe itself. - -- - -- @function kong.node.get_id - -- @treturn string The v4 UUID used by this node as its ID. - -- @usage - -- local id = kong.node.get_id() - function _NODE.get_id() - if node_id then - return node_id - end - - local shm = ngx.shared.kong - - local ok, err = shm:safe_add(NODE_ID_KEY, utils.uuid()) - if not ok and err ~= "exists" then - error("failed to set 'node_id' in shm: " .. err) - end - - node_id, err = shm:get(NODE_ID_KEY) - if err then - error("failed to get 'node_id' in shm: " .. err) - end - - if not node_id then - error("no 'node_id' set in shm") - end - - return node_id - end - - - --- - -- Returns memory usage statistics about this node. - -- - -- @function kong.node.get_memory_stats - -- @tparam[opt] string unit The unit that memory is reported in. Can be - -- any of `b/B`, `k/K`, `m/M`, or `g/G` for bytes, kibibytes, mebibytes, - -- or gibibytes, respectively. Defaults to `b` (bytes). - -- @tparam[opt] number scale The number of digits to the right of the decimal - -- point. Defaults to 2. - -- @treturn table A table containing memory usage statistics for this node. - -- If `unit` is `b/B` (the default), reported values are Lua numbers. - -- Otherwise, reported values are strings with the unit as a suffix. - -- @usage - -- local res = kong.node.get_memory_stats() - -- -- res will have the following structure: - -- { - -- lua_shared_dicts = { - -- kong = { - -- allocated_slabs = 12288, - -- capacity = 24576 - -- }, - -- kong_db_cache = { - -- allocated_slabs = 12288, - -- capacity = 12288 - -- } - -- }, - -- workers_lua_vms = { - -- { - -- http_allocated_gc = 1102, - -- pid = 18004 - -- }, - -- { - -- http_allocated_gc = 1102, - -- pid = 18005 - -- } - -- } - -- } - -- - -- local res = kong.node.get_memory_stats("k", 1) - -- -- res will have the following structure: - -- { - -- lua_shared_dicts = { - -- kong = { - -- allocated_slabs = "12.0 KiB", - -- capacity = "24.0 KiB", - -- }, - -- kong_db_cache = { - -- allocated_slabs = "12.0 KiB", - -- capacity = "12.0 KiB", - -- } - -- }, - -- workers_lua_vms = { - -- { - -- http_allocated_gc = "1.1 KiB", - -- pid = 18004 - -- }, - -- { - -- http_allocated_gc = "1.1 KiB", - -- pid = 18005 - -- } - -- } - -- } - function _NODE.get_memory_stats(unit, scale) - -- validate arguments - - do - unit = unit or "b" - scale = scale or 2 - - local pok, perr = pcall(utils.bytes_to_str, 0, unit, scale) - if not pok then - error(perr, 2) - end - end - - local res = { - workers_lua_vms = self.table.new(n_workers, 0), - lua_shared_dicts = self.table.new(0, #shms), - } - - -- get workers Lua VM allocated memory - - do - if not shared.kong then - goto lua_shared_dicts - end - - local keys, err = shared.kong:get_keys() - if not keys then - res.workers_lua_vms.err = "could not get kong shm keys: " .. err - goto lua_shared_dicts - end - - if #keys == 1024 then - -- Preventive warning log for future Kong developers, in case 'kong' - -- shm becomes mis-used or over-used. - ngx.log(ngx.WARN, "ngx.shared.kong:get_keys() returned 1024 keys, ", - "but it may have more") - end - - for i = 1, #keys do - local pid = match(keys[i], "kong:mem:(%d+)") - if not pid then - goto continue - end - - local w = self.table.new(0, 2) - w.pid = tonumber(pid) - - local count, err = shared.kong:get("kong:mem:" .. pid) - if err then - w.err = "could not get worker's HTTP Lua VM memory (pid: " .. - pid .. "): " .. err - - elseif type(count) ~= "number" then - w.err = "could not get worker's HTTP Lua VM memory (pid: " .. - pid .. "): reported value is corrupted" - - else - count = count * 1024 -- reported value is in kb - w.http_allocated_gc = convert_bytes(count, unit, scale) - end - - insert(res.workers_lua_vms, w) - - ::continue:: - end - - sort(res.workers_lua_vms, sort_pid_asc) - end - - -- get lua_shared_dicts allocated slabs - ::lua_shared_dicts:: - - for _, shm in ipairs(shms) do - local allocated = shm.capacity - shm.zone:free_space() - - res.lua_shared_dicts[shm.name] = { - capacity = convert_bytes(shm.capacity, unit, scale), - allocated_slabs = convert_bytes(allocated, unit, scale), - } - end - - return res - end - - - --- - -- Returns the name used by the local machine. - -- - -- @function kong.node.get_hostname - -- @treturn string The local machine hostname. - -- @usage - -- local hostname = kong.node.get_hostname() - function _NODE.get_hostname() - local SIZE = 253 -- max number of chars for a hostname - - local buf = ffi_new("unsigned char[?]", SIZE) - local res = C.gethostname(buf, SIZE) - - if res == 0 then - local hostname = ffi_str(buf, SIZE) - return gsub(hostname, "%z+$", "") - end - - local f = io.popen("/bin/hostname") - local hostname = f:read("*a") or "" - f:close() - return gsub(hostname, "\n$", "") - end - - - local prefix = self and self.configuration and self.configuration.prefix - if prefix and self.configuration.role == "data_plane" then - local id, err = private_node.load_node_id(prefix) - if id then - node_id = id - ngx.log(ngx.DEBUG, "restored node_id from the filesystem: ", node_id) - - else - id = _NODE.get_id() - if err then - ngx.log(ngx.WARN, "failed to restore node_id from the filesystem: ", - err, ", so a new one was generated: ", id) - end - end - end - - return _NODE -end - - -return { - new = new, -} +-- not used in koko at this time diff --git a/lua-tree/share/lua/5.1/kong/pdk/private/node.lua b/lua-tree/share/lua/5.1/kong/pdk/private/node.lua index ed299c9..85fc2fd 100644 --- a/lua-tree/share/lua/5.1/kong/pdk/private/node.lua +++ b/lua-tree/share/lua/5.1/kong/pdk/private/node.lua @@ -1,103 +1 @@ -local log = require "kong.cmd.utils.log" -local utils = require "kong.tools.utils" -local pl_file = require "pl.file" -local pl_path = require "pl.path" -local pl_dir = require "pl.dir" - -local fmt = string.format - -local cached_node_id - -local function node_id_filename(prefix) - return pl_path.join(prefix, "kong.id") -end - - -local function initialize_node_id(prefix) - if not pl_path.exists(prefix) then - local ok, err = pl_dir.makepath(prefix) - if not ok then - return nil, fmt("failed to create directory %s: %s", prefix, err) - end - end - - local filename = node_id_filename(prefix) - - local file_exists = pl_path.exists(filename) - - if file_exists then - local id, err = pl_file.read(filename) - if err then - return nil, fmt("failed to access file %s: %s", filename, err) - end - - if not utils.is_valid_uuid(id) then - log.debug("file %s contains invalid uuid: %s", filename, id) - -- set false to override it when it contains an invalid uuid. - file_exists = false - end - end - - if not file_exists then - local id = utils.uuid() - log.debug("persisting node_id (%s) to %s", id, filename) - - local ok, write_err = pl_file.write(filename, id) - if not ok then - return nil, fmt("failed to persist node_id to %s: %s", filename, write_err) - end - cached_node_id = id - end - - return true -end - - -local function init_node_id(config) - if not config then - return - end - - if not config.prefix or config.role ~= "data_plane" then - return - end - - local ok, err = initialize_node_id(config.prefix) - if not ok then - log.warn(err) - end -end - - -local function load_node_id(prefix) - if not prefix then - return nil, nil - end - - if cached_node_id then - return cached_node_id, nil - end - - local filename = node_id_filename(prefix) - - if not pl_path.exists(filename) then - return nil, fmt("file %s does not exist", filename) - end - - local id, read_err = pl_file.read(filename) - if read_err then - return nil, fmt("failed to access file %s: %s", filename, read_err) - end - - if not utils.is_valid_uuid(id) then - return nil, fmt("file %s contains invalid uuid: %q", filename, id) - end - - return id, nil -end - - -return { - init_node_id = init_node_id, - load_node_id = load_node_id, -} +-- not used in koko at this time diff --git a/lua-tree/share/lua/5.1/kong/router/atc.lua b/lua-tree/share/lua/5.1/kong/router/atc.lua index cd07a00..85fc2fd 100644 --- a/lua-tree/share/lua/5.1/kong/router/atc.lua +++ b/lua-tree/share/lua/5.1/kong/router/atc.lua @@ -1,597 +1 @@ -local _M = {} -local _MT = { __index = _M, } - - -local schema = require("resty.router.schema") -local router = require("resty.router.router") -local context = require("resty.router.context") -local lrucache = require("resty.lrucache") -local server_name = require("ngx.ssl").server_name -local tb_new = require("table.new") -local tb_clear = require("table.clear") -local utils = require("kong.router.utils") -local yield = require("kong.tools.utils").yield - - -local type = type -local assert = assert -local setmetatable = setmetatable -local pairs = pairs -local ipairs = ipairs - - -local max = math.max -local tb_concat = table.concat -local tb_sort = table.sort - - -local ngx = ngx -local header = ngx.header -local var = ngx.var -local ngx_log = ngx.log -local get_phase = ngx.get_phase -local get_method = ngx.req.get_method -local get_headers = ngx.req.get_headers -local ngx_WARN = ngx.WARN -local ngx_ERR = ngx.ERR - - -local sanitize_uri_postfix = utils.sanitize_uri_postfix -local check_select_params = utils.check_select_params -local strip_uri_args = utils.strip_uri_args -local get_service_info = utils.get_service_info -local add_debug_headers = utils.add_debug_headers -local get_upstream_uri_v0 = utils.get_upstream_uri_v0 -local route_match_stat = utils.route_match_stat - - -local MAX_REQ_HEADERS = 100 -local DEFAULT_MATCH_LRUCACHE_SIZE = utils.DEFAULT_MATCH_LRUCACHE_SIZE - - -local LOGICAL_OR = " || " -local LOGICAL_AND = " && " - - --- reuse table objects -local gen_values_t = tb_new(10, 0) - - -local CACHED_SCHEMA -do - local str_fields = {"net.protocol", "tls.sni", - "http.method", "http.host", - "http.path", "http.raw_path", - "http.headers.*", - } - - local int_fields = {"net.port", - } - - CACHED_SCHEMA = schema.new() - - for _, v in ipairs(str_fields) do - assert(CACHED_SCHEMA:add_field(v, "String")) - end - - for _, v in ipairs(int_fields) do - assert(CACHED_SCHEMA:add_field(v, "Int")) - end -end - - -local is_empty_field -do - local null = ngx.null - local isempty = require("table.isempty") - - is_empty_field = function(f) - return f == nil or f == null or isempty(f) - end -end - - -local function escape_str(str) - return "\"" .. str:gsub([[\]], [[\\]]):gsub([["]], [[\"]]) .. "\"" -end - - -local function gen_for_field(name, op, vals, val_transform) - if is_empty_field(vals) then - return nil - end - - tb_clear(gen_values_t) - - local values_n = 0 - local values = gen_values_t - - for _, p in ipairs(vals) do - values_n = values_n + 1 - local op = (type(op) == "string") and op or op(p) - values[values_n] = name .. " " .. op .. " " .. - escape_str(val_transform and val_transform(op, p) or p) - end - - if values_n > 0 then - return "(" .. tb_concat(values, LOGICAL_OR) .. ")" - end - - return nil -end - - -local function add_atc_matcher(inst, route, route_id, - get_exp_and_priority, - remove_existing) - - local exp, priority = get_exp_and_priority(route) - - if not exp then - return nil, "could not find expression, route: " .. route_id - end - - if remove_existing then - assert(inst:remove_matcher(route_id)) - end - - local ok, err = inst:add_matcher(priority, route_id, exp) - if not ok then - return nil, "could not add route: " .. route_id .. ", err: " .. err - end - - return true -end - - -local function is_http_headers_field(field) - return field:sub(1, 13) == "http.headers." -end - - -local function has_header_matching_field(fields) - for _, field in ipairs(fields) do - if is_http_headers_field(field) then - return true - end - end - - return false -end - - -local function new_from_scratch(routes, get_exp_and_priority) - local phase = get_phase() - local inst = router.new(CACHED_SCHEMA) - - local routes_n = #routes - local routes_t = tb_new(0, routes_n) - local services_t = tb_new(0, routes_n) - - local new_updated_at = 0 - - for _, r in ipairs(routes) do - local route = r.route - local route_id = route.id - - if not route_id then - return nil, "could not categorize route" - end - - routes_t[route_id] = route - services_t[route_id] = r.service - - local ok, err = add_atc_matcher(inst, route, route_id, - get_exp_and_priority, false) - if ok then - new_updated_at = max(new_updated_at, route.updated_at or 0) - - else - ngx_log(ngx_ERR, err) - - routes_t[route_id] = nil - services_t[route_id] = nil - end - - yield(true, phase) - end - - local fields = inst:get_fields() - local match_headers = has_header_matching_field(fields) - - return setmetatable({ - schema = CACHED_SCHEMA, - router = inst, - routes = routes_t, - services = services_t, - fields = fields, - match_headers = match_headers, - updated_at = new_updated_at, - rebuilding = false, - }, _MT) -end - - -local function new_from_previous(routes, get_exp_and_priority, old_router) - if old_router.rebuilding then - return nil, "concurrent incremental router rebuild without mutex, this is unsafe" - end - - old_router.rebuilding = true - - local phase = get_phase() - - local inst = old_router.router - local old_routes = old_router.routes - local old_services = old_router.services - - local updated_at = old_router.updated_at - local new_updated_at = 0 - - -- create or update routes - for _, r in ipairs(routes) do - local route = r.route - local route_id = route.id - - if not route_id then - return nil, "could not categorize route" - end - - local old_route = old_routes[route_id] - local route_updated_at = route.updated_at - - route.seen = true - - old_routes[route_id] = route - old_services[route_id] = r.service - - local ok = true - local err - - if not old_route then - -- route is new - ok, err = add_atc_matcher(inst, route, route_id, get_exp_and_priority, false) - - elseif route_updated_at >= updated_at or - route_updated_at ~= old_route.updated_at then - - -- route is modified (within a sec) - ok, err = add_atc_matcher(inst, route, route_id, get_exp_and_priority, true) - end - - if ok then - new_updated_at = max(new_updated_at, route_updated_at) - - else - ngx_log(ngx_ERR, err) - - old_routes[route_id] = nil - old_services[route_id] = nil - end - - yield(true, phase) - end - - -- remove routes - for id, r in pairs(old_routes) do - if r.seen then - r.seen = nil - - else - assert(inst:remove_matcher(id)) - - old_routes[id] = nil - old_services[id] = nil - end - - yield(true, phase) - end - - local fields = inst:get_fields() - - old_router.fields = fields - old_router.match_headers = has_header_matching_field(fields) - old_router.updated_at = new_updated_at - old_router.rebuilding = false - - return old_router -end - - -function _M.new(routes, cache, cache_neg, old_router, get_exp_and_priority) - if type(routes) ~= "table" then - return error("expected arg #1 routes to be a table") - end - - local router, err - - if not old_router then - router, err = new_from_scratch(routes, get_exp_and_priority) - - else - router, err = new_from_previous(routes, get_exp_and_priority, old_router) - end - - if not router then - return nil, err - end - - router.cache = cache or lrucache.new(DEFAULT_MATCH_LRUCACHE_SIZE) - router.cache_neg = cache_neg or lrucache.new(DEFAULT_MATCH_LRUCACHE_SIZE) - - return router -end - - --- split port in host, ignore form '[...]' --- example.com:123 => example.com, 123 --- example.*:123 => example.*, 123 -local split_host_port -do - local tonumber = tonumber - local DEFAULT_HOSTS_LRUCACHE_SIZE = DEFAULT_MATCH_LRUCACHE_SIZE - - local memo_hp = lrucache.new(DEFAULT_HOSTS_LRUCACHE_SIZE) - - split_host_port = function(key) - if not key then - return nil, nil - end - - local m = memo_hp:get(key) - - if m then - return m[1], m[2] - end - - local p = key:find(":", nil, true) - if not p then - memo_hp:set(key, { key, nil }) - return key, nil - end - - local port = tonumber(key:sub(p + 1)) - - if not port then - memo_hp:set(key, { key, nil }) - return key, nil - end - - local host = key:sub(1, p - 1) - - memo_hp:set(key, { host, port }) - - return host, port - end -end - - -function _M:select(req_method, req_uri, req_host, req_scheme, - src_ip, src_port, - dst_ip, dst_port, - sni, req_headers) - - check_select_params(req_method, req_uri, req_host, req_scheme, - src_ip, src_port, - dst_ip, dst_port, - sni, req_headers) - - local c = context.new(self.schema) - - local host, port = split_host_port(req_host) - - for _, field in ipairs(self.fields) do - if field == "http.method" then - assert(c:add_value("http.method", req_method)) - - elseif field == "http.path" then - assert(c:add_value("http.path", req_uri)) - - elseif field == "http.host" then - assert(c:add_value("http.host", host)) - - elseif field == "net.port" then - assert(c:add_value("net.port", port)) - - elseif field == "net.protocol" then - assert(c:add_value("net.protocol", req_scheme)) - - elseif field == "tls.sni" then - assert(c:add_value("tls.sni", sni)) - - elseif req_headers and is_http_headers_field(field) then - local h = field:sub(14) - local v = req_headers[h] - - if v then - if type(v) == "string" then - assert(c:add_value(field, v:lower())) - - else - for _, v in ipairs(v) do - assert(c:add_value(field, v:lower())) - end - end - end - end - end - - local matched = self.router:execute(c) - if not matched then - return nil - end - - local uuid, matched_path, captures = c:get_result("http.path") - - local service = self.services[uuid] - local matched_route = self.routes[uuid] - - local service_protocol, _, --service_type - service_host, service_port, - service_hostname_type, service_path = get_service_info(service) - - local request_prefix = matched_route.strip_path and matched_path or nil - local request_postfix = request_prefix and req_uri:sub(#matched_path + 1) or req_uri:sub(2, -1) - request_postfix = sanitize_uri_postfix(request_postfix) or "" - local upstream_base = service_path or "/" - - local upstream_uri = get_upstream_uri_v0(matched_route, request_postfix, req_uri, - upstream_base) - - return { - route = matched_route, - service = service, - prefix = request_prefix, - matches = { - uri_captures = (captures and captures[1]) and captures or nil, - }, - upstream_url_t = { - type = service_hostname_type, - host = service_host, - port = service_port, - }, - upstream_scheme = service_protocol, - upstream_uri = upstream_uri, - upstream_host = matched_route.preserve_host and req_host or nil, - } -end - - -local get_headers_key -do - local headers_t = tb_new(8, 0) - - get_headers_key = function(headers) - tb_clear(headers_t) - - local headers_count = 0 - - for name, value in pairs(headers) do - local name = name:gsub("-", "_"):lower() - - if type(value) == "table" then - for i, v in ipairs(value) do - value[i] = v:lower() - end - tb_sort(value) - value = tb_concat(value, ", ") - - else - value = value:lower() - end - - headers_t[headers_count + 1] = "|" - headers_t[headers_count + 2] = name - headers_t[headers_count + 3] = "=" - headers_t[headers_count + 4] = value - - headers_count = headers_count + 4 - end - - return tb_concat(headers_t, nil, 1, headers_count) - end -end - - -function _M:exec(ctx) - local req_method = get_method() - local req_uri = ctx and ctx.request_uri or var.request_uri - local req_host = var.http_host - local sni = server_name() - - local headers, headers_key - if self.match_headers then - local err - headers, err = get_headers(MAX_REQ_HEADERS) - if err == "truncated" then - ngx_log(ngx_WARN, "retrieved ", MAX_REQ_HEADERS, " headers for evaluation ", - "(max) but request had more; other headers will be ignored") - end - - headers["host"] = nil - - headers_key = get_headers_key(headers) - end - - req_uri = strip_uri_args(req_uri) - - -- cache lookup - - local cache_key = (req_method or "") .. "|" .. - (req_uri or "") .. "|" .. - (req_host or "") .. "|" .. - (sni or "") .. (headers_key or "") - - local match_t = self.cache:get(cache_key) - if not match_t then - if self.cache_neg:get(cache_key) then - route_match_stat(ctx, "neg") - return nil - end - - local req_scheme = ctx and ctx.scheme or var.scheme - - match_t = self:select(req_method, req_uri, req_host, req_scheme, - nil, nil, nil, nil, - sni, headers) - if not match_t then - self.cache_neg:set(cache_key, true) - return nil - end - - self.cache:set(cache_key, match_t) - - else - route_match_stat(ctx, "pos") - end - - -- found a match - - -- debug HTTP request header logic - add_debug_headers(var, header, match_t) - - return match_t -end - - -function _M._set_ngx(mock_ngx) - if type(mock_ngx) ~= "table" then - return - end - - if mock_ngx.header then - header = mock_ngx.header - end - - if mock_ngx.var then - var = mock_ngx.var - end - - if mock_ngx.log then - ngx_log = mock_ngx.log - end - - if type(mock_ngx.req) == "table" then - if mock_ngx.req.get_method then - get_method = mock_ngx.req.get_method - end - - if mock_ngx.req.get_headers then - get_headers = mock_ngx.req.get_headers - end - end -end - - -_M.schema = CACHED_SCHEMA - -_M.LOGICAL_OR = LOGICAL_OR -_M.LOGICAL_AND = LOGICAL_AND - -_M.escape_str = escape_str -_M.is_empty_field = is_empty_field -_M.gen_for_field = gen_for_field -_M.split_host_port = split_host_port - - -return _M +-- not used in koko at this time diff --git a/lua-tree/share/lua/5.1/kong/tools/uri.lua b/lua-tree/share/lua/5.1/kong/tools/uri.lua index ecc5991..e8ae945 100644 --- a/lua-tree/share/lua/5.1/kong/tools/uri.lua +++ b/lua-tree/share/lua/5.1/kong/tools/uri.lua @@ -1,4 +1,4 @@ -local table_new = require "table.new" +local table_new = require "kong.tools.utils".new_tab local string_char = string.char local string_upper = string.upper @@ -40,7 +40,7 @@ end local ESCAPE_PATTERN = "[^!#$&'()*+,/:;=?@[\\]A-Z\\d-_.~%]" -local TMP_OUTPUT = require("table.new")(16, 0) +local TMP_OUTPUT = table_new(16, 0) local DOT = string_byte(".") local SLASH = string_byte("/") diff --git a/lua-tree/share/lua/5.1/kong/tools/utils.lua b/lua-tree/share/lua/5.1/kong/tools/utils.lua index c570bda..375970d 100644 --- a/lua-tree/share/lua/5.1/kong/tools/utils.lua +++ b/lua-tree/share/lua/5.1/kong/tools/utils.lua @@ -1267,7 +1267,7 @@ _M.yield = function() return end local try_decode_base64 do local decode_base64 = ngx.decode_base64 - local decode_base64url = require "ngx.base64".decode_base64url + local decode_base64url = ngx.decode_base64url local function decode_base64_str(str) if type(str) == "string" then @@ -1299,42 +1299,15 @@ end _M.try_decode_base64 = try_decode_base64 -local sha256_bin -do - local digest = require "resty.openssl.digest" - local sha256_digest - - function sha256_bin(key) - local _, bin, err - if not sha256_digest then - sha256_digest, err = digest.new("sha256") - if err then - return nil, err - end - end - - bin, err = sha256_digest:final(key) - if err then - sha256_digest = nil - return nil, err - end - - _, err = sha256_digest:reset() - if err then - sha256_digest = nil - end - - return bin - end -end +local sha256_bin = require "go.sha256".sha256_bin _M.sha256_bin = sha256_bin local sha256_hex, sha256_base64, sha256_base64url do - local to_hex = require "resty.string".to_hex + local to_hex = require "go.hex".to_hex local to_base64 = ngx.encode_base64 - local to_base64url = require "ngx.base64".encode_base64url + local to_base64url = ngx.encode_base64url local function sha256_encode(encode_alg, key) local bin, err = sha256_bin(key) @@ -1361,4 +1334,36 @@ _M.sha256_hex = sha256_hex _M.sha256_base64 = sha256_base64 _M.sha256_base64url = sha256_base64url +-- `table.new()` is a LuaJIT function and is not available to the Lua VM that goks uses. +local new_tab +do + local ok + ok, new_tab = pcall(require, "table.new") + if not ok then + new_tab = function(narr, nrec) + return {} + end + end +end + +-- `table.nkeys()` is a LuaJIT function and is not available to the Lua VM that goks uses. +local nkeys +do + local ok + ok, nkeys = pcall(require, "table.nkeys") + if not ok then + nkeys = function (tab) + local count = 0 + for _, v in pairs(tab) do + if v ~= nil then + count = count + 1 + end + end + return count + end + end +end +_M.new_tab = new_tab +_M.nkeys = nkeys + return _M diff --git a/lualibs/go/hex/api.go b/lualibs/go/hex/api.go new file mode 100644 index 0000000..3b06a99 --- /dev/null +++ b/lualibs/go/hex/api.go @@ -0,0 +1,20 @@ +package hex + +import ( + "encoding/hex" + + lua "github.com/yuin/gopher-lua" +) + +// Encode encodes input string into hex bytes. It is a wrapper around +// encoding/hex.Encode and replaces resty.string.to_hex. +// See: https://github.com/openresty/lua-resty-string/blob/master/lib/resty/string.lua +func Encode(l *lua.LState) int { + input := l.CheckString(1) + + dst := make([]byte, hex.EncodedLen(len(input))) + hex.Encode(dst, []byte(input)) + + l.Push(lua.LString(dst)) + return 1 +} diff --git a/lualibs/go/hex/loader.go b/lualibs/go/hex/loader.go new file mode 100644 index 0000000..138e3ff --- /dev/null +++ b/lualibs/go/hex/loader.go @@ -0,0 +1,14 @@ +package hex + +import lua "github.com/yuin/gopher-lua" + +func Loader(l *lua.LState) int { + t := l.NewTable() + l.SetFuncs(t, api) + l.Push(t) + return 1 +} + +var api = map[string]lua.LGFunction{ + "to_hex": Encode, +} diff --git a/lualibs/go/sha256/api.go b/lualibs/go/sha256/api.go new file mode 100644 index 0000000..85c213a --- /dev/null +++ b/lualibs/go/sha256/api.go @@ -0,0 +1,16 @@ +package sha256 + +import ( + "crypto/sha256" + + lua "github.com/yuin/gopher-lua" +) + +func BinarySha256(l *lua.LState) int { + input := l.CheckString(1) + h := sha256.New() + h.Write([]byte(input)) + l.Push(lua.LString(h.Sum(nil))) + h.Reset() + return 1 +} diff --git a/lualibs/go/sha256/loader.go b/lualibs/go/sha256/loader.go new file mode 100644 index 0000000..6be0425 --- /dev/null +++ b/lualibs/go/sha256/loader.go @@ -0,0 +1,14 @@ +package sha256 + +import lua "github.com/yuin/gopher-lua" + +func Loader(l *lua.LState) int { + t := l.NewTable() + l.SetFuncs(t, api) + l.Push(t) + return 1 +} + +var api = map[string]lua.LGFunction{ + "sha256_bin": BinarySha256, +} diff --git a/patches/lua-tree.patch b/patches/lua-tree.patch index bb459b9..a2cc771 100644 --- a/patches/lua-tree.patch +++ b/patches/lua-tree.patch @@ -48,6 +48,7 @@ schema/init.lua: - remove log statements - ensure custom_entity_checks in schemas return error message - Reintroducing fallback `new_tab()` function, as `table.new()` LuaJIT function is not available for use. +- Fallback `nkeys()` function, as `table.nkeys` LuaJIT function is not available for use. schema/typedefs.lua: @@ -72,6 +73,8 @@ tools/utils.lua: - Use go.ipmatcher instead of resty.ipmatcher - Reintroducing fallback `is_array_fast()` function, as `table.isarray()` OpenResty function is not available for use. - Reintroducing fallback `clone()` function, as `table.clone()` OpenResty function is not available for use. +- Use `ngx.decode_base64url` instead of `require "ngx.base64".decode_base64url` +- Use go.sha256 instead of unavailable OpenResty `digest.new("sha256")` function. entities/plugins.lua: @@ -86,6 +89,21 @@ tools/sandbox.lua lua-tree/share/lua/5.1/socket/url.lua - override all imports of socket.url by returning patched.url +lua-tree/share/lua/5.1/kong/constants.lua +- remove LOG_LEVELS (depends on ngx) + +lua-tree/share/lua/5.1/kong/pdk/node.lua +- maintain import references but remove package contents + +lua-tree/share/lua/5.1/kong/pdk/private/node.lua +- maintain import references but remove package contents + +lua-tree/share/lua/5.1/kong/router/atc.lua +- maintain import references but remove package contents + +tools/uri.lua +- replace "table.new" with local definition + --- diff --git a/lua-tree/share/lua/5.1/kong/db/schema/entities/certificates.lua b/lua-tree/share/lua/5.1/kong/db/schema/entities/certificates.lua index dbe2d4a..a17dc93 100644 @@ -183,40 +201,31 @@ diff --git a/lua-tree/share/lua/5.1/kong/db/schema/init.lua b/lua-tree/share/lua index 489a666..1c660ed 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/init.lua +++ b/lua-tree/share/lua/5.1/kong/db/schema/init.lua -@@ -1,10 +1,10 @@ +@@ -1,10 +1,11 @@ local tablex = require "pl.tablex" local pretty = require "pl.pretty" local utils = require "kong.tools.utils" -local cjson = require "cjson" -local new_tab = require "table.new" - local nkeys = require "table.nkeys" +-local nkeys = require "table.nkeys" -local is_reference = require "kong.pdk.vault".new().is_reference ++local nkeys = utils.nkeys ++local new_tab = utils.new_tab + +local cjson = { array_mt = {} } --- TODO(hbagdi) XXX analyze the impact +local is_reference = function(value) return false end local setmetatable = setmetatable -@@ -43,6 +43,18 @@ Schema.__index = Schema +@@ -43,7 +44,6 @@ Schema.__index = Schema local _cache = {} local _workspaceable = {} -+-- `table.new()` is a LuaJIT function and is not available to the Lua VM that goks uses. -+local new_tab -+do -+ local ok -+ ok, new_tab = pcall(require, "table.new") -+ if not ok then -+ new_tab = function(narr, nrec) -+ return {} -+ end -+ end -+end -+ - +- local validation_errors = { -- general message -@@ -315,7 +327,7 @@ Schema.validators = { + ERROR = "Validation error: %s", +@@ -315,7 +315,7 @@ Schema.validators = { if #value ~= 36 then return nil end @@ -225,7 +234,7 @@ index 489a666..1c660ed 100644 end, contains = function(array, wanted) -@@ -956,10 +968,6 @@ function Schema:validate_field(field, value) +@@ -956,10 +956,6 @@ function Schema:validate_field(field, value) field.len_min = 1 end @@ -236,7 +245,7 @@ index 489a666..1c660ed 100644 elseif field.type == "function" then if type(value) ~= "function" then return nil, validation_errors.FUNCTION -@@ -1116,10 +1124,8 @@ validate_fields = function(self, input) +@@ -1116,10 +1112,8 @@ validate_fields = function(self, input) pok, err, errors[k] = pcall(self.validate_field, self, input, v) if not pok then errors[k] = validation_errors.SCHEMA_CANNOT_VALIDATE @@ -247,7 +256,7 @@ index 489a666..1c660ed 100644 else field, err = resolve_field(self, k, field, subschema) if field then -@@ -1208,12 +1214,6 @@ local function run_entity_check(self, name, input, arg, full_check, errors) +@@ -1208,12 +1202,6 @@ local function run_entity_check(self, name, input, arg, full_check, errors) end else all_nil = false @@ -260,7 +269,7 @@ index 489a666..1c660ed 100644 end if errors[fname] then all_ok = false -@@ -1250,7 +1250,7 @@ local function run_entity_check(self, name, input, arg, full_check, errors) +@@ -1250,7 +1238,7 @@ local function run_entity_check(self, name, input, arg, full_check, errors) else local error_fmt = validation_errors[name:upper()] @@ -269,7 +278,7 @@ index 489a666..1c660ed 100644 if not err then local data = pretty.write({ name = arg }):gsub("%s+", " ") err = validation_errors.ENTITY_CHECK:format(name, data) -@@ -1654,14 +1654,7 @@ function Schema:process_auto_fields(data, context, nulls, opts) +@@ -1654,14 +1642,7 @@ function Schema:process_auto_fields(data, context, nulls, opts) -- detected with ngx.ctx.KONG_PHASE, but to limit context -- access we use nulls that admin api sets to true. local kong = kong @@ -285,7 +294,7 @@ index 489a666..1c660ed 100644 local refs local prev_refs = resolve_references and data["$refs"] -@@ -1677,7 +1670,7 @@ function Schema:process_auto_fields(data, context, nulls, opts) +@@ -1677,7 +1658,7 @@ function Schema:process_auto_fields(data, context, nulls, opts) end elseif ftype == "string" then @@ -294,7 +303,7 @@ index 489a666..1c660ed 100644 value = random_string() end -@@ -1722,15 +1715,13 @@ function Schema:process_auto_fields(data, context, nulls, opts) +@@ -1722,15 +1703,13 @@ function Schema:process_auto_fields(data, context, nulls, opts) refs = { [key] = value } end @@ -311,7 +320,7 @@ index 489a666..1c660ed 100644 end value = nil -@@ -1761,15 +1752,13 @@ function Schema:process_auto_fields(data, context, nulls, opts) +@@ -1761,15 +1740,13 @@ function Schema:process_auto_fields(data, context, nulls, opts) refs[key][i] = value[i] @@ -328,6 +337,7 @@ index 489a666..1c660ed 100644 end value[i] = nil + diff --git a/lua-tree/share/lua/5.1/kong/db/schema/plugin_loader.lua b/lua-tree/share/lua/5.1/kong/db/schema/plugin_loader.lua index 5ec62ec..7d0dc4b 100644 --- a/lua-tree/share/lua/5.1/kong/db/schema/plugin_loader.lua @@ -836,7 +846,7 @@ index 08405b8..2b1157d 100644 local get_mime_type local get_error_template do -@@ -1455,19 +1260,9 @@ do +@@ -1455,24 +1260,14 @@ do end end @@ -859,6 +869,96 @@ index 08405b8..2b1157d 100644 local try_decode_base64 do + local decode_base64 = ngx.decode_base64 +- local decode_base64url = require "ngx.base64".decode_base64url ++ local decode_base64url = ngx.decode_base64url + + local function decode_base64_str(str) + if type(str) == "string" then +@@ -1504,42 +1299,15 @@ end + _M.try_decode_base64 = try_decode_base64 + + +-local sha256_bin +-do +- local digest = require "resty.openssl.digest" +- local sha256_digest +- +- function sha256_bin(key) +- local _, bin, err +- if not sha256_digest then +- sha256_digest, err = digest.new("sha256") +- if err then +- return nil, err +- end +- end +- +- bin, err = sha256_digest:final(key) +- if err then +- sha256_digest = nil +- return nil, err +- end +- +- _, err = sha256_digest:reset() +- if err then +- sha256_digest = nil +- end +- +- return bin +- end +-end ++local sha256_bin = require "go.sha256".sha256_bin + _M.sha256_bin = sha256_bin + + + local sha256_hex, sha256_base64, sha256_base64url + do +- local to_hex = require "resty.string".to_hex ++ local to_hex = require "go.hex".to_hex + local to_base64 = ngx.encode_base64 +- local to_base64url = require "ngx.base64".encode_base64url ++ local to_base64url = ngx.encode_base64url + + local function sha256_encode(encode_alg, key) + local bin, err = sha256_bin(key) +@@ -1566,4 +1334,36 @@ _M.sha256_hex = sha256_hex + _M.sha256_base64 = sha256_base64 + _M.sha256_base64url = sha256_base64url + ++-- `table.new()` is a LuaJIT function and is not available to the Lua VM that goks uses. ++local new_tab ++do ++ local ok ++ ok, new_tab = pcall(require, "table.new") ++ if not ok then ++ new_tab = function(narr, nrec) ++ return {} ++ end ++ end ++end ++ ++-- `table.nkeys()` is a LuaJIT function and is not available to the Lua VM that goks uses. ++local nkeys ++do ++ local ok ++ ok, nkeys = pcall(require, "table.nkeys") ++ if not ok then ++ nkeys = function (tab) ++ local count = 0 ++ for _, v in pairs(tab) do ++ if v ~= nil then ++ count = count + 1 ++ end ++ end ++ return count ++ end ++ end ++end ++_M.new_tab = new_tab ++_M.nkeys = nkeys ++ + return _M + diff --git a/lua-tree/share/lua/5.1/patched/url.lua b/lua-tree/share/lua/5.1/patched/url.lua new file mode 100644 index 0000000..360ff39 @@ -1569,3 +1669,1083 @@ index 7809535..b36f576 100644 - -return _M +return require "patched.url" + +diff --git a/lua-tree/share/lua/5.1/kong/constants.lua b/lua-tree/share/lua/5.1/kong/constants.lua +index 775eae0..be9ed67 100644 +--- a/lua-tree/share/lua/5.1/kong/constants.lua ++++ b/lua-tree/share/lua/5.1/kong/constants.lua +@@ -218,25 +218,6 @@ local constants = { + + KEY_FORMATS_MAP = key_formats_map, + KEY_FORMATS = key_formats, +- +- LOG_LEVELS = { +- debug = ngx.DEBUG, +- info = ngx.INFO, +- notice = ngx.NOTICE, +- warn = ngx.WARN, +- error = ngx.ERR, +- crit = ngx.CRIT, +- alert = ngx.ALERT, +- emerg = ngx.EMERG, +- [ngx.DEBUG] = "debug", +- [ngx.INFO] = "info", +- [ngx.NOTICE] = "notice", +- [ngx.WARN] = "warn", +- [ngx.ERR] = "error", +- [ngx.CRIT] = "crit", +- [ngx.ALERT] = "alert", +- [ngx.EMERG] = "emerg", +- }, + } + + for _, v in ipairs(constants.CLUSTERING_SYNC_STATUS) do + +diff --git a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua +index 753281a..389d7dc 100644 +--- a/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua ++++ b/lua-tree/share/lua/5.1/kong/db/schema/entities/routes.lua +@@ -1,8 +1,6 @@ + local typedefs = require("kong.db.schema.typedefs") + local deprecation = require("kong.deprecation") + +-local CACHED_SCHEMA = require("kong.router.atc").schema +- + -- ATC router is incompatible with goks + local kong_router_flavor = "traditional" + +@@ -48,13 +46,6 @@ if kong_router_flavor == "expressions" then + { custom_entity_check = { + field_sources = { "expression", "id", }, + fn = function(entity) +- local r = router.new(CACHED_SCHEMA) +- +- local res, err = r:add_matcher(0, entity.id, entity.expression) +- if not res then +- return nil, "Router Expression failed validation: " .. err +- end +- + return true + end, + } }, + +diff --git a/lua-tree/share/lua/5.1/kong/pdk/node.lua b/lua-tree/share/lua/5.1/kong/pdk/node.lua +index 60e6489..85fc2fd 100644 +--- a/lua-tree/share/lua/5.1/kong/pdk/node.lua ++++ b/lua-tree/share/lua/5.1/kong/pdk/node.lua +@@ -1,283 +1 @@ +---- Node-level utilities. +--- +--- @module kong.node +- +-local utils = require "kong.tools.utils" +-local ffi = require "ffi" +-local private_node = require "kong.pdk.private.node" +- +- +-local floor = math.floor +-local lower = string.lower +-local match = string.match +-local gsub = string.gsub +-local sort = table.sort +-local insert = table.insert +-local ngx = ngx +-local shared = ngx.shared +-local C = ffi.C +-local ffi_new = ffi.new +-local ffi_str = ffi.string +- +-local NODE_ID_KEY = "kong:node_id" +- +- +-local node_id +-local shms = {} +-local n_workers = ngx.worker.count() +- +- +-for shm_name, shm in pairs(shared) do +- insert(shms, { +- zone = shm, +- name = shm_name, +- capacity = shm:capacity(), +- }) +-end +- +- +-local function convert_bytes(bytes, unit, scale) +- if not unit or lower(unit) == "b" then +- return floor(bytes) +- end +- +- return utils.bytes_to_str(bytes, unit, scale) +-end +- +- +-local function sort_pid_asc(a, b) +- return a.pid < b.pid +-end +- +- +-local function new(self) +- local _NODE = {} +- +- +- --- +- -- Returns the ID used by this node to describe itself. +- -- +- -- @function kong.node.get_id +- -- @treturn string The v4 UUID used by this node as its ID. +- -- @usage +- -- local id = kong.node.get_id() +- function _NODE.get_id() +- if node_id then +- return node_id +- end +- +- local shm = ngx.shared.kong +- +- local ok, err = shm:safe_add(NODE_ID_KEY, utils.uuid()) +- if not ok and err ~= "exists" then +- error("failed to set 'node_id' in shm: " .. err) +- end +- +- node_id, err = shm:get(NODE_ID_KEY) +- if err then +- error("failed to get 'node_id' in shm: " .. err) +- end +- +- if not node_id then +- error("no 'node_id' set in shm") +- end +- +- return node_id +- end +- +- +- --- +- -- Returns memory usage statistics about this node. +- -- +- -- @function kong.node.get_memory_stats +- -- @tparam[opt] string unit The unit that memory is reported in. Can be +- -- any of `b/B`, `k/K`, `m/M`, or `g/G` for bytes, kibibytes, mebibytes, +- -- or gibibytes, respectively. Defaults to `b` (bytes). +- -- @tparam[opt] number scale The number of digits to the right of the decimal +- -- point. Defaults to 2. +- -- @treturn table A table containing memory usage statistics for this node. +- -- If `unit` is `b/B` (the default), reported values are Lua numbers. +- -- Otherwise, reported values are strings with the unit as a suffix. +- -- @usage +- -- local res = kong.node.get_memory_stats() +- -- -- res will have the following structure: +- -- { +- -- lua_shared_dicts = { +- -- kong = { +- -- allocated_slabs = 12288, +- -- capacity = 24576 +- -- }, +- -- kong_db_cache = { +- -- allocated_slabs = 12288, +- -- capacity = 12288 +- -- } +- -- }, +- -- workers_lua_vms = { +- -- { +- -- http_allocated_gc = 1102, +- -- pid = 18004 +- -- }, +- -- { +- -- http_allocated_gc = 1102, +- -- pid = 18005 +- -- } +- -- } +- -- } +- -- +- -- local res = kong.node.get_memory_stats("k", 1) +- -- -- res will have the following structure: +- -- { +- -- lua_shared_dicts = { +- -- kong = { +- -- allocated_slabs = "12.0 KiB", +- -- capacity = "24.0 KiB", +- -- }, +- -- kong_db_cache = { +- -- allocated_slabs = "12.0 KiB", +- -- capacity = "12.0 KiB", +- -- } +- -- }, +- -- workers_lua_vms = { +- -- { +- -- http_allocated_gc = "1.1 KiB", +- -- pid = 18004 +- -- }, +- -- { +- -- http_allocated_gc = "1.1 KiB", +- -- pid = 18005 +- -- } +- -- } +- -- } +- function _NODE.get_memory_stats(unit, scale) +- -- validate arguments +- +- do +- unit = unit or "b" +- scale = scale or 2 +- +- local pok, perr = pcall(utils.bytes_to_str, 0, unit, scale) +- if not pok then +- error(perr, 2) +- end +- end +- +- local res = { +- workers_lua_vms = self.table.new(n_workers, 0), +- lua_shared_dicts = self.table.new(0, #shms), +- } +- +- -- get workers Lua VM allocated memory +- +- do +- if not shared.kong then +- goto lua_shared_dicts +- end +- +- local keys, err = shared.kong:get_keys() +- if not keys then +- res.workers_lua_vms.err = "could not get kong shm keys: " .. err +- goto lua_shared_dicts +- end +- +- if #keys == 1024 then +- -- Preventive warning log for future Kong developers, in case 'kong' +- -- shm becomes mis-used or over-used. +- ngx.log(ngx.WARN, "ngx.shared.kong:get_keys() returned 1024 keys, ", +- "but it may have more") +- end +- +- for i = 1, #keys do +- local pid = match(keys[i], "kong:mem:(%d+)") +- if not pid then +- goto continue +- end +- +- local w = self.table.new(0, 2) +- w.pid = tonumber(pid) +- +- local count, err = shared.kong:get("kong:mem:" .. pid) +- if err then +- w.err = "could not get worker's HTTP Lua VM memory (pid: " .. +- pid .. "): " .. err +- +- elseif type(count) ~= "number" then +- w.err = "could not get worker's HTTP Lua VM memory (pid: " .. +- pid .. "): reported value is corrupted" +- +- else +- count = count * 1024 -- reported value is in kb +- w.http_allocated_gc = convert_bytes(count, unit, scale) +- end +- +- insert(res.workers_lua_vms, w) +- +- ::continue:: +- end +- +- sort(res.workers_lua_vms, sort_pid_asc) +- end +- +- -- get lua_shared_dicts allocated slabs +- ::lua_shared_dicts:: +- +- for _, shm in ipairs(shms) do +- local allocated = shm.capacity - shm.zone:free_space() +- +- res.lua_shared_dicts[shm.name] = { +- capacity = convert_bytes(shm.capacity, unit, scale), +- allocated_slabs = convert_bytes(allocated, unit, scale), +- } +- end +- +- return res +- end +- +- +- --- +- -- Returns the name used by the local machine. +- -- +- -- @function kong.node.get_hostname +- -- @treturn string The local machine hostname. +- -- @usage +- -- local hostname = kong.node.get_hostname() +- function _NODE.get_hostname() +- local SIZE = 253 -- max number of chars for a hostname +- +- local buf = ffi_new("unsigned char[?]", SIZE) +- local res = C.gethostname(buf, SIZE) +- +- if res == 0 then +- local hostname = ffi_str(buf, SIZE) +- return gsub(hostname, "%z+$", "") +- end +- +- local f = io.popen("/bin/hostname") +- local hostname = f:read("*a") or "" +- f:close() +- return gsub(hostname, "\n$", "") +- end +- +- +- local prefix = self and self.configuration and self.configuration.prefix +- if prefix and self.configuration.role == "data_plane" then +- local id, err = private_node.load_node_id(prefix) +- if id then +- node_id = id +- ngx.log(ngx.DEBUG, "restored node_id from the filesystem: ", node_id) +- +- else +- id = _NODE.get_id() +- if err then +- ngx.log(ngx.WARN, "failed to restore node_id from the filesystem: ", +- err, ", so a new one was generated: ", id) +- end +- end +- end +- +- return _NODE +-end +- +- +-return { +- new = new, +-} ++-- not used in koko at this time +diff --git a/lua-tree/share/lua/5.1/kong/pdk/private/node.lua b/lua-tree/share/lua/5.1/kong/pdk/private/node.lua +index ed299c9..85fc2fd 100644 +--- a/lua-tree/share/lua/5.1/kong/pdk/private/node.lua ++++ b/lua-tree/share/lua/5.1/kong/pdk/private/node.lua +@@ -1,103 +1 @@ +-local log = require "kong.cmd.utils.log" +-local utils = require "kong.tools.utils" +-local pl_file = require "pl.file" +-local pl_path = require "pl.path" +-local pl_dir = require "pl.dir" +- +-local fmt = string.format +- +-local cached_node_id +- +-local function node_id_filename(prefix) +- return pl_path.join(prefix, "kong.id") +-end +- +- +-local function initialize_node_id(prefix) +- if not pl_path.exists(prefix) then +- local ok, err = pl_dir.makepath(prefix) +- if not ok then +- return nil, fmt("failed to create directory %s: %s", prefix, err) +- end +- end +- +- local filename = node_id_filename(prefix) +- +- local file_exists = pl_path.exists(filename) +- +- if file_exists then +- local id, err = pl_file.read(filename) +- if err then +- return nil, fmt("failed to access file %s: %s", filename, err) +- end +- +- if not utils.is_valid_uuid(id) then +- log.debug("file %s contains invalid uuid: %s", filename, id) +- -- set false to override it when it contains an invalid uuid. +- file_exists = false +- end +- end +- +- if not file_exists then +- local id = utils.uuid() +- log.debug("persisting node_id (%s) to %s", id, filename) +- +- local ok, write_err = pl_file.write(filename, id) +- if not ok then +- return nil, fmt("failed to persist node_id to %s: %s", filename, write_err) +- end +- cached_node_id = id +- end +- +- return true +-end +- +- +-local function init_node_id(config) +- if not config then +- return +- end +- +- if not config.prefix or config.role ~= "data_plane" then +- return +- end +- +- local ok, err = initialize_node_id(config.prefix) +- if not ok then +- log.warn(err) +- end +-end +- +- +-local function load_node_id(prefix) +- if not prefix then +- return nil, nil +- end +- +- if cached_node_id then +- return cached_node_id, nil +- end +- +- local filename = node_id_filename(prefix) +- +- if not pl_path.exists(filename) then +- return nil, fmt("file %s does not exist", filename) +- end +- +- local id, read_err = pl_file.read(filename) +- if read_err then +- return nil, fmt("failed to access file %s: %s", filename, read_err) +- end +- +- if not utils.is_valid_uuid(id) then +- return nil, fmt("file %s contains invalid uuid: %q", filename, id) +- end +- +- return id, nil +-end +- +- +-return { +- init_node_id = init_node_id, +- load_node_id = load_node_id, +-} ++-- not used in koko at this time +diff --git a/lua-tree/share/lua/5.1/kong/router/atc.lua b/lua-tree/share/lua/5.1/kong/router/atc.lua +index cd07a00..85fc2fd 100644 +--- a/lua-tree/share/lua/5.1/kong/router/atc.lua ++++ b/lua-tree/share/lua/5.1/kong/router/atc.lua +@@ -1,597 +1 @@ +-local _M = {} +-local _MT = { __index = _M, } +- +- +-local schema = require("resty.router.schema") +-local router = require("resty.router.router") +-local context = require("resty.router.context") +-local lrucache = require("resty.lrucache") +-local server_name = require("ngx.ssl").server_name +-local tb_new = require("table.new") +-local tb_clear = require("table.clear") +-local utils = require("kong.router.utils") +-local yield = require("kong.tools.utils").yield +- +- +-local type = type +-local assert = assert +-local setmetatable = setmetatable +-local pairs = pairs +-local ipairs = ipairs +- +- +-local max = math.max +-local tb_concat = table.concat +-local tb_sort = table.sort +- +- +-local ngx = ngx +-local header = ngx.header +-local var = ngx.var +-local ngx_log = ngx.log +-local get_phase = ngx.get_phase +-local get_method = ngx.req.get_method +-local get_headers = ngx.req.get_headers +-local ngx_WARN = ngx.WARN +-local ngx_ERR = ngx.ERR +- +- +-local sanitize_uri_postfix = utils.sanitize_uri_postfix +-local check_select_params = utils.check_select_params +-local strip_uri_args = utils.strip_uri_args +-local get_service_info = utils.get_service_info +-local add_debug_headers = utils.add_debug_headers +-local get_upstream_uri_v0 = utils.get_upstream_uri_v0 +-local route_match_stat = utils.route_match_stat +- +- +-local MAX_REQ_HEADERS = 100 +-local DEFAULT_MATCH_LRUCACHE_SIZE = utils.DEFAULT_MATCH_LRUCACHE_SIZE +- +- +-local LOGICAL_OR = " || " +-local LOGICAL_AND = " && " +- +- +--- reuse table objects +-local gen_values_t = tb_new(10, 0) +- +- +-local CACHED_SCHEMA +-do +- local str_fields = {"net.protocol", "tls.sni", +- "http.method", "http.host", +- "http.path", "http.raw_path", +- "http.headers.*", +- } +- +- local int_fields = {"net.port", +- } +- +- CACHED_SCHEMA = schema.new() +- +- for _, v in ipairs(str_fields) do +- assert(CACHED_SCHEMA:add_field(v, "String")) +- end +- +- for _, v in ipairs(int_fields) do +- assert(CACHED_SCHEMA:add_field(v, "Int")) +- end +-end +- +- +-local is_empty_field +-do +- local null = ngx.null +- local isempty = require("table.isempty") +- +- is_empty_field = function(f) +- return f == nil or f == null or isempty(f) +- end +-end +- +- +-local function escape_str(str) +- return "\"" .. str:gsub([[\]], [[\\]]):gsub([["]], [[\"]]) .. "\"" +-end +- +- +-local function gen_for_field(name, op, vals, val_transform) +- if is_empty_field(vals) then +- return nil +- end +- +- tb_clear(gen_values_t) +- +- local values_n = 0 +- local values = gen_values_t +- +- for _, p in ipairs(vals) do +- values_n = values_n + 1 +- local op = (type(op) == "string") and op or op(p) +- values[values_n] = name .. " " .. op .. " " .. +- escape_str(val_transform and val_transform(op, p) or p) +- end +- +- if values_n > 0 then +- return "(" .. tb_concat(values, LOGICAL_OR) .. ")" +- end +- +- return nil +-end +- +- +-local function add_atc_matcher(inst, route, route_id, +- get_exp_and_priority, +- remove_existing) +- +- local exp, priority = get_exp_and_priority(route) +- +- if not exp then +- return nil, "could not find expression, route: " .. route_id +- end +- +- if remove_existing then +- assert(inst:remove_matcher(route_id)) +- end +- +- local ok, err = inst:add_matcher(priority, route_id, exp) +- if not ok then +- return nil, "could not add route: " .. route_id .. ", err: " .. err +- end +- +- return true +-end +- +- +-local function is_http_headers_field(field) +- return field:sub(1, 13) == "http.headers." +-end +- +- +-local function has_header_matching_field(fields) +- for _, field in ipairs(fields) do +- if is_http_headers_field(field) then +- return true +- end +- end +- +- return false +-end +- +- +-local function new_from_scratch(routes, get_exp_and_priority) +- local phase = get_phase() +- local inst = router.new(CACHED_SCHEMA) +- +- local routes_n = #routes +- local routes_t = tb_new(0, routes_n) +- local services_t = tb_new(0, routes_n) +- +- local new_updated_at = 0 +- +- for _, r in ipairs(routes) do +- local route = r.route +- local route_id = route.id +- +- if not route_id then +- return nil, "could not categorize route" +- end +- +- routes_t[route_id] = route +- services_t[route_id] = r.service +- +- local ok, err = add_atc_matcher(inst, route, route_id, +- get_exp_and_priority, false) +- if ok then +- new_updated_at = max(new_updated_at, route.updated_at or 0) +- +- else +- ngx_log(ngx_ERR, err) +- +- routes_t[route_id] = nil +- services_t[route_id] = nil +- end +- +- yield(true, phase) +- end +- +- local fields = inst:get_fields() +- local match_headers = has_header_matching_field(fields) +- +- return setmetatable({ +- schema = CACHED_SCHEMA, +- router = inst, +- routes = routes_t, +- services = services_t, +- fields = fields, +- match_headers = match_headers, +- updated_at = new_updated_at, +- rebuilding = false, +- }, _MT) +-end +- +- +-local function new_from_previous(routes, get_exp_and_priority, old_router) +- if old_router.rebuilding then +- return nil, "concurrent incremental router rebuild without mutex, this is unsafe" +- end +- +- old_router.rebuilding = true +- +- local phase = get_phase() +- +- local inst = old_router.router +- local old_routes = old_router.routes +- local old_services = old_router.services +- +- local updated_at = old_router.updated_at +- local new_updated_at = 0 +- +- -- create or update routes +- for _, r in ipairs(routes) do +- local route = r.route +- local route_id = route.id +- +- if not route_id then +- return nil, "could not categorize route" +- end +- +- local old_route = old_routes[route_id] +- local route_updated_at = route.updated_at +- +- route.seen = true +- +- old_routes[route_id] = route +- old_services[route_id] = r.service +- +- local ok = true +- local err +- +- if not old_route then +- -- route is new +- ok, err = add_atc_matcher(inst, route, route_id, get_exp_and_priority, false) +- +- elseif route_updated_at >= updated_at or +- route_updated_at ~= old_route.updated_at then +- +- -- route is modified (within a sec) +- ok, err = add_atc_matcher(inst, route, route_id, get_exp_and_priority, true) +- end +- +- if ok then +- new_updated_at = max(new_updated_at, route_updated_at) +- +- else +- ngx_log(ngx_ERR, err) +- +- old_routes[route_id] = nil +- old_services[route_id] = nil +- end +- +- yield(true, phase) +- end +- +- -- remove routes +- for id, r in pairs(old_routes) do +- if r.seen then +- r.seen = nil +- +- else +- assert(inst:remove_matcher(id)) +- +- old_routes[id] = nil +- old_services[id] = nil +- end +- +- yield(true, phase) +- end +- +- local fields = inst:get_fields() +- +- old_router.fields = fields +- old_router.match_headers = has_header_matching_field(fields) +- old_router.updated_at = new_updated_at +- old_router.rebuilding = false +- +- return old_router +-end +- +- +-function _M.new(routes, cache, cache_neg, old_router, get_exp_and_priority) +- if type(routes) ~= "table" then +- return error("expected arg #1 routes to be a table") +- end +- +- local router, err +- +- if not old_router then +- router, err = new_from_scratch(routes, get_exp_and_priority) +- +- else +- router, err = new_from_previous(routes, get_exp_and_priority, old_router) +- end +- +- if not router then +- return nil, err +- end +- +- router.cache = cache or lrucache.new(DEFAULT_MATCH_LRUCACHE_SIZE) +- router.cache_neg = cache_neg or lrucache.new(DEFAULT_MATCH_LRUCACHE_SIZE) +- +- return router +-end +- +- +--- split port in host, ignore form '[...]' +--- example.com:123 => example.com, 123 +--- example.*:123 => example.*, 123 +-local split_host_port +-do +- local tonumber = tonumber +- local DEFAULT_HOSTS_LRUCACHE_SIZE = DEFAULT_MATCH_LRUCACHE_SIZE +- +- local memo_hp = lrucache.new(DEFAULT_HOSTS_LRUCACHE_SIZE) +- +- split_host_port = function(key) +- if not key then +- return nil, nil +- end +- +- local m = memo_hp:get(key) +- +- if m then +- return m[1], m[2] +- end +- +- local p = key:find(":", nil, true) +- if not p then +- memo_hp:set(key, { key, nil }) +- return key, nil +- end +- +- local port = tonumber(key:sub(p + 1)) +- +- if not port then +- memo_hp:set(key, { key, nil }) +- return key, nil +- end +- +- local host = key:sub(1, p - 1) +- +- memo_hp:set(key, { host, port }) +- +- return host, port +- end +-end +- +- +-function _M:select(req_method, req_uri, req_host, req_scheme, +- src_ip, src_port, +- dst_ip, dst_port, +- sni, req_headers) +- +- check_select_params(req_method, req_uri, req_host, req_scheme, +- src_ip, src_port, +- dst_ip, dst_port, +- sni, req_headers) +- +- local c = context.new(self.schema) +- +- local host, port = split_host_port(req_host) +- +- for _, field in ipairs(self.fields) do +- if field == "http.method" then +- assert(c:add_value("http.method", req_method)) +- +- elseif field == "http.path" then +- assert(c:add_value("http.path", req_uri)) +- +- elseif field == "http.host" then +- assert(c:add_value("http.host", host)) +- +- elseif field == "net.port" then +- assert(c:add_value("net.port", port)) +- +- elseif field == "net.protocol" then +- assert(c:add_value("net.protocol", req_scheme)) +- +- elseif field == "tls.sni" then +- assert(c:add_value("tls.sni", sni)) +- +- elseif req_headers and is_http_headers_field(field) then +- local h = field:sub(14) +- local v = req_headers[h] +- +- if v then +- if type(v) == "string" then +- assert(c:add_value(field, v:lower())) +- +- else +- for _, v in ipairs(v) do +- assert(c:add_value(field, v:lower())) +- end +- end +- end +- end +- end +- +- local matched = self.router:execute(c) +- if not matched then +- return nil +- end +- +- local uuid, matched_path, captures = c:get_result("http.path") +- +- local service = self.services[uuid] +- local matched_route = self.routes[uuid] +- +- local service_protocol, _, --service_type +- service_host, service_port, +- service_hostname_type, service_path = get_service_info(service) +- +- local request_prefix = matched_route.strip_path and matched_path or nil +- local request_postfix = request_prefix and req_uri:sub(#matched_path + 1) or req_uri:sub(2, -1) +- request_postfix = sanitize_uri_postfix(request_postfix) or "" +- local upstream_base = service_path or "/" +- +- local upstream_uri = get_upstream_uri_v0(matched_route, request_postfix, req_uri, +- upstream_base) +- +- return { +- route = matched_route, +- service = service, +- prefix = request_prefix, +- matches = { +- uri_captures = (captures and captures[1]) and captures or nil, +- }, +- upstream_url_t = { +- type = service_hostname_type, +- host = service_host, +- port = service_port, +- }, +- upstream_scheme = service_protocol, +- upstream_uri = upstream_uri, +- upstream_host = matched_route.preserve_host and req_host or nil, +- } +-end +- +- +-local get_headers_key +-do +- local headers_t = tb_new(8, 0) +- +- get_headers_key = function(headers) +- tb_clear(headers_t) +- +- local headers_count = 0 +- +- for name, value in pairs(headers) do +- local name = name:gsub("-", "_"):lower() +- +- if type(value) == "table" then +- for i, v in ipairs(value) do +- value[i] = v:lower() +- end +- tb_sort(value) +- value = tb_concat(value, ", ") +- +- else +- value = value:lower() +- end +- +- headers_t[headers_count + 1] = "|" +- headers_t[headers_count + 2] = name +- headers_t[headers_count + 3] = "=" +- headers_t[headers_count + 4] = value +- +- headers_count = headers_count + 4 +- end +- +- return tb_concat(headers_t, nil, 1, headers_count) +- end +-end +- +- +-function _M:exec(ctx) +- local req_method = get_method() +- local req_uri = ctx and ctx.request_uri or var.request_uri +- local req_host = var.http_host +- local sni = server_name() +- +- local headers, headers_key +- if self.match_headers then +- local err +- headers, err = get_headers(MAX_REQ_HEADERS) +- if err == "truncated" then +- ngx_log(ngx_WARN, "retrieved ", MAX_REQ_HEADERS, " headers for evaluation ", +- "(max) but request had more; other headers will be ignored") +- end +- +- headers["host"] = nil +- +- headers_key = get_headers_key(headers) +- end +- +- req_uri = strip_uri_args(req_uri) +- +- -- cache lookup +- +- local cache_key = (req_method or "") .. "|" .. +- (req_uri or "") .. "|" .. +- (req_host or "") .. "|" .. +- (sni or "") .. (headers_key or "") +- +- local match_t = self.cache:get(cache_key) +- if not match_t then +- if self.cache_neg:get(cache_key) then +- route_match_stat(ctx, "neg") +- return nil +- end +- +- local req_scheme = ctx and ctx.scheme or var.scheme +- +- match_t = self:select(req_method, req_uri, req_host, req_scheme, +- nil, nil, nil, nil, +- sni, headers) +- if not match_t then +- self.cache_neg:set(cache_key, true) +- return nil +- end +- +- self.cache:set(cache_key, match_t) +- +- else +- route_match_stat(ctx, "pos") +- end +- +- -- found a match +- +- -- debug HTTP request header logic +- add_debug_headers(var, header, match_t) +- +- return match_t +-end +- +- +-function _M._set_ngx(mock_ngx) +- if type(mock_ngx) ~= "table" then +- return +- end +- +- if mock_ngx.header then +- header = mock_ngx.header +- end +- +- if mock_ngx.var then +- var = mock_ngx.var +- end +- +- if mock_ngx.log then +- ngx_log = mock_ngx.log +- end +- +- if type(mock_ngx.req) == "table" then +- if mock_ngx.req.get_method then +- get_method = mock_ngx.req.get_method +- end +- +- if mock_ngx.req.get_headers then +- get_headers = mock_ngx.req.get_headers +- end +- end +-end +- +- +-_M.schema = CACHED_SCHEMA +- +-_M.LOGICAL_OR = LOGICAL_OR +-_M.LOGICAL_AND = LOGICAL_AND +- +-_M.escape_str = escape_str +-_M.is_empty_field = is_empty_field +-_M.gen_for_field = gen_for_field +-_M.split_host_port = split_host_port +- +- +-return _M ++-- not used in koko at this time + +diff --git a/lua-tree/share/lua/5.1/kong/tools/uri.lua b/lua-tree/share/lua/5.1/kong/tools/uri.lua +index ecc5991..e8ae945 100644 +--- a/lua-tree/share/lua/5.1/kong/tools/uri.lua ++++ b/lua-tree/share/lua/5.1/kong/tools/uri.lua +@@ -1,4 +1,4 @@ +-local table_new = require "table.new" ++local table_new = require "kong.tools.utils".new_tab + + local string_char = string.char + local string_upper = string.upper +@@ -40,7 +40,7 @@ end + + local ESCAPE_PATTERN = "[^!#$&'()*+,/:;=?@[\\]A-Z\\d-_.~%]" + +-local TMP_OUTPUT = require("table.new")(16, 0) ++local TMP_OUTPUT = table_new(16, 0) + local DOT = string_byte(".") + local SLASH = string_byte("/")