Skip to content

Commit

Permalink
Merge pull request #1366 from Mashape/refactor/restart
Browse files Browse the repository at this point in the history
feature: restart and health
  • Loading branch information
thibaultcha authored Jul 12, 2016
2 parents 1b47803 + 82f52d6 commit e17c192
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 40 deletions.
3 changes: 3 additions & 0 deletions kong-0.8.2-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ build = {
["kong.cmd.roar"] = "kong/cmd/roar.lua",
["kong.cmd.init"] = "kong/cmd/init.lua",
["kong.cmd.stop"] = "kong/cmd/stop.lua",
["kong.cmd.quit"] = "kong/cmd/quit.lua",
["kong.cmd.start"] = "kong/cmd/start.lua",
["kong.cmd.check"] = "kong/cmd/check.lua",
["kong.cmd.reload"] = "kong/cmd/reload.lua",
["kong.cmd.restart"] = "kong/cmd/restart.lua",
["kong.cmd.cluster"] = "kong/cmd/cluster.lua",
["kong.cmd.compile"] = "kong/cmd/compile.lua",
["kong.cmd.migrations"] = "kong/cmd/migrations.lua",
["kong.cmd.health"] = "kong/cmd/health.lua",
["kong.cmd.version"] = "kong/cmd/version.lua",
["kong.cmd.utils.log"] = "kong/cmd/utils/log.lua",
["kong.cmd.utils.kill"] = "kong/cmd/utils/kill.lua",
Expand Down
55 changes: 55 additions & 0 deletions kong/cmd/health.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
local log = require "kong.cmd.utils.log"
local kill = require "kong.cmd.utils.kill"
local pl_path = require "pl.path"
local pl_tablex = require "pl.tablex"
local pl_stringx = require "pl.stringx"
local conf_loader = require "kong.conf_loader"

local function execute(args)
-- retrieve default prefix or use given one
local default_conf = assert(conf_loader(nil, {
prefix = args.prefix
}))
assert(pl_path.exists(default_conf.prefix),
"no such prefix: "..default_conf.prefix)
assert(pl_path.exists(default_conf.kong_conf),
"Kong is not running at "..default_conf.prefix)

-- load <PREFIX>/kong.conf containing running node's config
local conf = assert(conf_loader(default_conf.kong_conf))

local pids = {
serf = conf.serf_pid,
nginx = conf.nginx_pid,
dnsmasq = conf.dnsmasq and conf.dnsmasq_pid or nil
}

local count = 0
for k, v in pairs(pids) do
local running = kill.is_running(v)
local msg = pl_stringx.ljust(k, 12, ".")..(running and "running" or "not running")
if running then
count = count + 1
end
log(msg)
end

log("") -- line jump

assert(count > 0, "Kong is not running at "..conf.prefix)
assert(count == pl_tablex.size(pids), "Some services are not running at "..conf.prefix)

log("Kong is healthy at %s", conf.prefix)
end

local lapp = [[
Usage: kong health [OPTIONS]
Options:
-p,--prefix (optional string) prefix at which Kong should be running
]]

return {
lapp = lapp,
execute = execute
}
9 changes: 7 additions & 2 deletions kong/cmd/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ Usage: kong COMMAND [OPTIONS]
The available commands are:
start
stop
quit
restart
reload
health
check
compile
migrations
Expand All @@ -26,7 +29,10 @@ Options:
local cmds = {
start = "start",
stop = "stop",
quit = "quit",
restart = "restart",
reload = "reload",
health = "health",
check = "check",
compile = "compile",
migrations = "migrations",
Expand Down Expand Up @@ -78,8 +84,7 @@ return function(args)
if not args.trace then
err = err:match "^.-:.-:.(.*)$"
io.stderr:write("Error: "..err.."\n")
io.stderr:write("\n Run with --trace to see traceback")
io.stderr:write("\n Please report issues to https://github.com/Mashape/kong/issues\n")
io.stderr:write("\n Run with --trace to see traceback\n")
else
local trace = debug.traceback(err, 2)
io.stderr:write("Error: \n")
Expand Down
58 changes: 58 additions & 0 deletions kong/cmd/quit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
local dnsmasq_signals = require "kong.cmd.utils.dnsmasq_signals"
local nginx_signals = require "kong.cmd.utils.nginx_signals"
local serf_signals = require "kong.cmd.utils.serf_signals"
local conf_loader = require "kong.conf_loader"
local DAOFactory = require "kong.dao.factory"
local pl_path = require "pl.path"
local kill = require "kong.cmd.utils.kill"
local log = require "kong.cmd.utils.log"

local function execute(args)
-- retrieve default prefix or use given one
local default_conf = assert(conf_loader(nil, {
prefix = args.prefix
}))
assert(pl_path.exists(default_conf.prefix),
"no such prefix: "..default_conf.prefix)

-- load <PREFIX>/kong.conf containing running node's config
local conf = assert(conf_loader(default_conf.kong_conf))

-- try graceful shutdown (QUIT)
assert(nginx_signals.quit(conf))

log.verbose("waiting for Nginx to finish processing requests...")

local tstart = ngx.time()
local texp, running = tstart + math.max(args.timeout, 1) -- min 1s timeout
repeat
ngx.sleep(0.2)
running = kill.is_running(conf.nginx_pid)
until not running or ngx.time() >= texp

if running then
log.verbose("Nginx is still running at %s, forcing shutdown", conf.prefix)
assert(nginx_signals.stop(conf))
end

assert(serf_signals.stop(conf, DAOFactory(conf)))

if conf.dnsmasq then
assert(dnsmasq_signals.stop(conf))
end

log("Stopped (gracefully)")
end

local lapp = [[
Usage: kong quit [OPTIONS]
Options:
-p,--prefix (optional string) prefix Kong is running at
-t,--timeout (default 10) timeout before forced shutdown
]]

return {
lapp = lapp,
execute = execute
}
27 changes: 27 additions & 0 deletions kong/cmd/restart.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local stop = require "kong.cmd.stop"
local start = require "kong.cmd.start"
local conf_loader = require "kong.conf_loader"

local function execute(args)
if args.conf then
-- retrieve the prefix for stop
local conf = assert(conf_loader(args.conf))
args.prefix = conf.prefix
end

pcall(stop.execute, args)
start.execute(args)
end

local lapp = [[
Usage: kong restart [OPTIONS]
Options:
-c,--conf (optional string) configuration file
-p,--prefix (optional string) prefix at which Kong should be running
]]

return {
lapp = lapp,
execute = execute
}
2 changes: 1 addition & 1 deletion kong/cmd/stop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ local lapp = [[
Usage: kong stop [OPTIONS]
Options:
-p,--prefix (optional string) prefix Kong is running at
-p,--prefix (optional string) prefix Kong is running at
]]

return {
Expand Down
10 changes: 2 additions & 8 deletions kong/cmd/utils/dnsmasq_signals.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,9 @@ function _M.find_bin()
return found
end

local function is_running(pid_path)
if not pl_path.exists(pid_path) then return nil end
local code = kill(pid_path, "-0")
return code == 0
end

function _M.start(kong_config)
-- is dnsmasq already running in this prefix?
if is_running(kong_config.dnsmasq_pid) then
if kill.is_running(kong_config.dnsmasq_pid) then
log.verbose("dnsmasq already running at %s", kong_config.dnsmasq_pid)
return true
else
Expand All @@ -71,7 +65,7 @@ end

function _M.stop(kong_config)
log.verbose("stopping dnsmasq at %s", kong_config.dnsmasq_pid)
return kill(kong_config.dnsmasq_pid, "-15") -- SIGTERM
return kill.kill(kong_config.dnsmasq_pid, "-15") -- SIGTERM
end

return _M
13 changes: 12 additions & 1 deletion kong/cmd/utils/kill.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local pl_path = require "pl.path"

local cmd_tmpl = [[
kill %s `cat %s` >/dev/null 2>&1
]]
Expand All @@ -7,4 +9,13 @@ local function kill(pid_file, args)
return os.execute(cmd)
end

return kill
local function is_running(pid_file)
if pl_path.exists(pid_file) then
return kill(pid_file) == 0
end
end

return {
kill = kill,
is_running = is_running
}
21 changes: 11 additions & 10 deletions kong/cmd/utils/nginx_signals.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
local pl_utils = require "pl.utils"
local pl_path = require "pl.path"
local kill = require "kong.cmd.utils.kill"
local log = require "kong.cmd.utils.log"
local kill = require "kong.cmd.utils.kill"
local pl_path = require "pl.path"
local version = require "version"
local pl_utils = require "pl.utils"
local fmt = string.format

local nginx_bin_name = "nginx"
Expand All @@ -13,7 +13,7 @@ local nginx_search_paths = {
local nginx_version_command = "-v" -- commandline param to get version
local nginx_version_pattern = "^nginx.-openresty.-([%d%.]+)" -- pattern to grab version from output
local nginx_compatible = version.set("1.9.3.2","1.9.7.5") -- compatible from-to versions

local function is_openresty(bin_path)
local cmd = fmt("%s %s", bin_path, nginx_version_command)
local ok, _, _, stderr = pl_utils.executeex(cmd)
Expand All @@ -36,7 +36,7 @@ local function send_signal(pid_path, signal)

log.verbose("sending %s signal to Nginx running at %s", signal, pid_path)

local code = kill(pid_path, "-s "..signal)
local code = kill.kill(pid_path, "-s "..signal)
if code ~= 0 then return nil, "could not send signal" end

return true
Expand Down Expand Up @@ -69,11 +69,8 @@ function _M.start(kong_conf)
local nginx_bin, err = _M.find_bin()
if not nginx_bin then return nil, err end

if pl_path.exists(kong_conf.nginx_pid) then
local code = kill(kong_conf.nginx_pid, "-0")
if code == 0 then
return nil, "Nginx is already running in "..kong_conf.prefix
end
if kill.is_running(kong_conf.nginx_pid) then
return nil, "Nginx is already running in "..kong_conf.prefix
end

local cmd = fmt("%s -p %s -c %s", nginx_bin, kong_conf.prefix, "nginx.conf")
Expand All @@ -87,6 +84,10 @@ function _M.start(kong_conf)
end

function _M.stop(kong_conf)
return send_signal(kong_conf.nginx_pid, "TERM")
end

function _M.quit(kong_conf, graceful)
return send_signal(kong_conf.nginx_pid, "QUIT")
end

Expand Down
17 changes: 5 additions & 12 deletions kong/cmd/utils/serf_signals.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

local pl_stringx = require "pl.stringx"
local pl_utils = require "pl.utils"
local pl_path = require "pl.path"
local pl_file = require "pl.file"
local Serf = require "kong.serf"
local kill = require "kong.cmd.utils.kill"
Expand Down Expand Up @@ -34,17 +33,11 @@ local function check_serf_bin()
return nil, "could not find Serf executable (is it in your $PATH?)"
end

local function is_running(pid_path)
if not pl_path.exists(pid_path) then return nil end
local code = kill(pid_path, "-0")
return code == 0
end

local _M = {}

function _M.start(kong_config, dao)
-- is Serf already running in this prefix?
if is_running(kong_config.serf_pid) then
if kill.is_running(kong_config.serf_pid) then
log.verbose("Serf agent already running at %s", kong_config.serf_pid)
return true
else
Expand Down Expand Up @@ -80,14 +73,14 @@ function _M.start(kong_config, dao)
local ok = pl_utils.execute(cmd)
if not ok then return nil end

log.verbose("waiting for Serf agent to be running...")

-- ensure started (just an improved version of previous Serf service)
local tstart = ngx.time()
local texp, started = tstart + start_timeout

repeat
log.debug("waiting for Serf agent to be running...")
ngx.sleep(0.2)
started = is_running(kong_config.serf_pid)
started = kill.is_running(kong_config.serf_pid)
until started or ngx.time() >= texp

if not started then
Expand Down Expand Up @@ -119,7 +112,7 @@ function _M.stop(kong_config, dao)
if not ok then return nil, err end

log.verbose("stopping Serf agent at %s", kong_config.serf_pid)
local code, res = kill(kong_config.serf_pid, "-15") --SIGTERM
local code, res = kill.kill(kong_config.serf_pid, "-15") --SIGTERM
if code == 256 then -- If no error is returned
pl_file.delete(kong_config.serf_pid)
end
Expand Down
14 changes: 11 additions & 3 deletions spec/02-integration/01-cmd/02-start_stop_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ describe("kong start/stop", function()
local _, stderr = helpers.kong_exec "stop --help"
assert.not_equal("", stderr)
end)
it("start/stop default conf/prefix", function()
it("start/stop gracefully with default conf/prefix", function()
-- don't want to force migrations to be run on default
-- keyspace/database
assert(helpers.kong_exec "start", {
assert(helpers.kong_exec("start", {
database = helpers.test_conf.database,
pg_database = helpers.test_conf.pg_database,
cassandra_keyspace = helpers.test_conf.cassandra_keyspace
})
}))
assert(helpers.kong_exec "stop")
end)
it("start/stop custom Kong conf/prefix", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
assert(helpers.kong_exec("stop --prefix "..helpers.test_conf.prefix))
end)
it("start/stop forcefully", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
assert(helpers.kong_exec("stop --prefix "..helpers.test_conf.prefix))
end)
it("start/quit gracefully with --timeout option", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
assert(helpers.kong_exec("quit --timeout 2 --prefix "..helpers.test_conf.prefix))
end)
it("start with inexistent prefix", function()
finally(function()
pcall(helpers.dir.rmtree, "foobar")
Expand Down
Loading

0 comments on commit e17c192

Please sign in to comment.