Skip to content

Commit

Permalink
fix(cmd): lack of necessary nginx directives in kong cli nginx.conf
Browse files Browse the repository at this point in the history
This is an alternative of (#10675)[#10675].
The primary logic keeps the same. The inject logic is further moved forward
from `kong/cmd/init.lua` to `bin/kong` so that the execution flow won't enter
`kong/cmd/init.lua` twice.

We still keep the `bin/kong` a resty script because many files such as
`kong.conf_loader`, `kong.cmd.utils.process_secrets` rely on `ngx`. If we change
`bin/kong` into a pure lua or other language script, we need to rewrite
the conf_loader and compile part logic.

[FTI-4937](https://konghq.atlassian.net/browse/FTI-4937)
  • Loading branch information
catbro666 committed Jul 21, 2023
1 parent 9d52b5e commit 82a41a6
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 169 deletions.
125 changes: 124 additions & 1 deletion bin/kong
Original file line number Diff line number Diff line change
@@ -1,11 +1,134 @@
#!/usr/bin/env resty

setmetatable(_G, nil)
pcall(require, "luarocks.loader")
package.path = (os.getenv("KONG_LUA_PATH_OVERRIDE") or "") .. "./?.lua;./?/init.lua;" .. package.path

local pl_app = require "pl.lapp"
local pl_utils = require "pl.utils"
local pl_tablex = require "pl.tablex"
local inject_confs = require "kong.cmd.utils.inject_confs"

local options = [[
--v verbose
--vv debug
]]

local cmds_arr = {}
local cmds = {
start = true,
stop = true,
quit = true,
restart = true,
reload = true,
health = true,
check = true,
prepare = true,
migrations = true,
version = true,
config = true,
roar = true,
hybrid = true,
vault = true,
}

-- unnecessary to inject nginx directives for these simple cmds
local skip_inject_cmds = {
version = true,
roar = true,
}

for k in pairs(cmds) do
cmds_arr[#cmds_arr+1] = k
end

table.sort(cmds_arr)

local help = string.format([[
Usage: kong COMMAND [OPTIONS]
The available commands are:
%s
Options:
%s]], table.concat(cmds_arr, "\n "), options)

local cmd_name = table.remove(arg, 1)
if not cmd_name then
pl_app(help)
pl_app.quit()
elseif not cmds[cmd_name] then
pl_app(help)
pl_app.quit("No such command: " .. cmd_name)
end

local cmd = require("kong.cmd." .. cmd_name)
local cmd_lapp = cmd.lapp

if cmd_lapp then
cmd_lapp = cmd_lapp .. options -- append universal options
arg = pl_app(cmd_lapp)
end

-- check sub-commands
if cmd.sub_commands then
local sub_cmd = table.remove(arg, 1)
if not sub_cmd then
pl_app.quit()
elseif not cmd.sub_commands[sub_cmd] then
pl_app.quit("No such command for " .. cmd_name .. ": " .. sub_cmd)
else
arg.command = sub_cmd
end
end

-- inject necessary nginx directives (e.g. lmdb_*, lua_ssl_*)
-- into the temporary nginx.conf that `resty` will create
local main_conf = ""
local http_conf = ""
local stream_conf = ""

if not skip_inject_cmds[cmd_name] then
local confs, err = inject_confs.compile_confs(arg)
if not confs then
error(err)
end

main_conf = confs.main_conf
http_conf = confs.http_conf
stream_conf = confs.stream_conf
end

-- construct the args table
local args_table = { "{" }
for k, v in pairs(arg) do
if type(k) == "string" then
k = "\"" .. k .. "\""
end
if type(v) == "string" then
v = "\"" .. v .. "\""
end

table.insert(args_table, string.format("[%s] = %s,", k, v))
end
table.insert(args_table, "}")

local args_str = table.concat(args_table, " ")

local inline_code = string.format([[
setmetatable(_G, nil)
pcall(require, "luarocks.loader")
package.path = (os.getenv("KONG_LUA_PATH_OVERRIDE") or "") .. "./?.lua;./?/init.lua;" .. package.path
require("kong.cmd.init")(arg)
require("kong.cmd.init")("%s", %s)
]], cmd_name, args_str)

local resty_cmd = string.format(
"resty --main-conf \"%s\" --http-conf \"%s\" --stream-conf \"%s\" -e '%s'",
main_conf, http_conf, stream_conf, inline_code)

local _, code = pl_utils.execute(resty_cmd)
os.exit(code)
-- vim: set ft=lua ts=2 sw=2 sts=2 et :
2 changes: 1 addition & 1 deletion kong-3.4.0-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ build = {
["kong.cmd.utils.nginx_signals"] = "kong/cmd/utils/nginx_signals.lua",
["kong.cmd.utils.prefix_handler"] = "kong/cmd/utils/prefix_handler.lua",
["kong.cmd.utils.process_secrets"] = "kong/cmd/utils/process_secrets.lua",
["kong.cmd.utils.inject_directives"] = "kong/cmd/utils/inject_directives.lua",
["kong.cmd.utils.inject_confs"] = "kong/cmd/utils/inject_confs.lua",

["kong.api"] = "kong/api/init.lua",
["kong.api.api_helpers"] = "kong/api/api_helpers.lua",
Expand Down
82 changes: 1 addition & 81 deletions kong/cmd/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ require("kong.globalpatches")({cli = true})
math.randomseed() -- Generate PRNG seed

local pl_app = require "pl.lapp"
local pl_tablex = require "pl.tablex"
local log = require "kong.cmd.utils.log"
local inject_directives = require "kong.cmd.utils.inject_directives"

local function stop_timers()
-- shutdown lua-resty-timer-ng to allow the nginx worker to stop quickly
Expand All @@ -14,95 +12,17 @@ local function stop_timers()
end
end

local options = [[
--v verbose
--vv debug
]]

local cmds_arr = {}
local cmds = {
start = true,
stop = true,
quit = true,
restart = true,
reload = true,
health = true,
check = true,
prepare = true,
migrations = true,
version = true,
config = true,
roar = true,
hybrid = true,
vault = true,
}

local inject_cmds = {
vault = true,
}

for k in pairs(cmds) do
cmds_arr[#cmds_arr+1] = k
end

table.sort(cmds_arr)

local help = string.format([[
Usage: kong COMMAND [OPTIONS]
The available commands are:
%s
Options:
%s]], table.concat(cmds_arr, "\n "), options)

return function(args)
-- preserve args table to make it available in kong/cmd/utils/inject_directives.lua
_G.cli_args = pl_tablex.deepcopy(args)

local cmd_name = table.remove(args, 1)
if not cmd_name then
pl_app(help)
pl_app.quit()
elseif not cmds[cmd_name] then
pl_app(help)
pl_app.quit("No such command: " .. cmd_name)
end

return function(cmd_name, args)
local cmd = require("kong.cmd." .. cmd_name)
local cmd_lapp = cmd.lapp
local cmd_exec = cmd.execute

if cmd_lapp then
cmd_lapp = cmd_lapp .. options -- append universal options
args = pl_app(cmd_lapp)
end

-- check sub-commands
if cmd.sub_commands then
local sub_cmd = table.remove(args, 1)
if not sub_cmd then
pl_app.quit()
elseif not cmd.sub_commands[sub_cmd] then
pl_app.quit("No such command for " .. cmd_name .. ": " .. sub_cmd)
else
args.command = sub_cmd
end
end

-- verbose mode
if args.v then
log.set_lvl(log.levels.verbose)
elseif args.vv then
log.set_lvl(log.levels.debug)
end

-- inject necessary nginx directives (e.g. lmdb_*, lua_ssl_*)
-- into the temporary nginx.conf that `resty` will create
if inject_cmds[cmd_name] then
inject_directives.run_command_with_injection(args)
end

log.verbose("Kong: %s", _KONG._VERSION)
log.debug("ngx_lua: %s", ngx.config.ngx_lua_version)
log.debug("nginx: %s", ngx.config.nginx_version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local fmt = string.format
local compile_nginx_main_inject_conf = prefix_handler.compile_nginx_main_inject_conf
local compile_nginx_http_inject_conf = prefix_handler.compile_nginx_http_inject_conf
local compile_nginx_stream_inject_conf = prefix_handler.compile_nginx_stream_inject_conf
local prepare_prefix = prefix_handler.prepare_prefix

local function load_conf(args)
-- retrieve default prefix or use given one
Expand All @@ -26,7 +27,7 @@ local function load_conf(args)
-- make sure necessary files like `.ca_combined` exist
-- but skip_write to avoid overwriting the existing nginx configurations
if not pl_path.exists(conf.lua_ssl_trusted_certificate_combined) then
assert(prefix_handler.prepare_prefix(conf, nil, true))
assert(prepare_prefix(conf, nil, true))
end

return conf
Expand Down Expand Up @@ -98,43 +99,28 @@ local function construct_cmd(conf)
if err then
return nil, err
end

-- terminate the recursion
local cmd = {"KONG_CLI_RESPAWNED=1"}
-- resty isn't necessarily in the position -1
table.insert(cmd, "resty")
for i = 0, #_G.cli_args do
table.insert(cmd, _G.cli_args[i])
end

table.insert(cmd, 3, fmt("--main-conf \"%s\"", main_conf))
table.insert(cmd, 4, fmt("--http-conf \"%s\"", http_conf))
table.insert(cmd, 5, fmt("--stream-conf \"%s\"", stream_conf))

return table.concat(cmd, " ")
end

local function run_command_with_injection(args)
if os.getenv("KONG_CLI_RESPAWNED") then
return
end

local function compile_confs(args)
local conf = load_conf(args)
local cmd, err = construct_cmd(conf)
local main_conf, err = compile_main_inject(conf)
if err then
return nil, err
end

local http_conf, err = compile_http_inject(conf)
if err then
error(err)
return nil, err
end

log.verbose("run_command_with_injection: %s", cmd)
local stream_conf, err = compile_stream_inject(conf)
if err then
return nil, err
end

local _, code = pl_utils.execute(cmd)
os.exit(code)
return { main_conf = main_conf, http_conf = http_conf, stream_conf = stream_conf, }, nil
end

return {
run_command_with_injection = run_command_with_injection,

-- for test purpose
_construct_cmd = construct_cmd,
compile_confs = compile_confs,
}
Loading

0 comments on commit 82a41a6

Please sign in to comment.