Skip to content

Commit

Permalink
refactor(cli) start/stop with Serf service refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaultcha committed May 27, 2016
1 parent ed83280 commit 2500c8e
Show file tree
Hide file tree
Showing 23 changed files with 653 additions and 257 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -4,6 +4,8 @@
.project
.idea

servroot*

# kong
nginx_tmp/
kong*.yml
Expand Down
55 changes: 2 additions & 53 deletions bin/kong
@@ -1,54 +1,3 @@
#!/usr/bin/env luajit
#!/usr/bin/env resty

-- Kong CLI entry-point (bin/kong).
--
-- Kong's CLI is a set of small commands invoked by a global executable, this file.
--
-- All commands are invoked by this script, then parsed (arguments and options)
-- by lapp (see http://lua-users.org/wiki/LappFramework).
--
-- This script is not parsed by lapp due to limitations of the said framework as it
-- is currently implemented.

local meta = require "kong.meta"
local commands = {
db = "kong.cli.cmds.db",
stop = "kong.cli.cmds.stop",
quit = "kong.cli.cmds.quit",
start = "kong.cli.cmds.start",
reload = "kong.cli.cmds.reload",
config = "kong.cli.cmds.config",
restart = "kong.cli.cmds.restart",
version = "kong.cli.cmds.version",
status = "kong.cli.cmds.status",
migrations = "kong.cli.cmds.migrations",
cluster = "kong.cli.cmds.cluster",
["--version"] = "kong.cli.cmds.version"
}

local help_message = string.format([[
Usage: kong <command>

where <command> is one of:
start, restart, reload, stop, quit, cluster, status, migrations, version

kong --help print this message
kong <command> --help print the help message of a command

%s@%s]], meta._NAME, meta._VERSION)

-- Determine validity of the given command
local cmd = arg[1]
if not cmd then
print("Missing <command>\n\n"..help_message)
os.exit(1)
elseif cmd == "-h" or cmd == "--help" then
print(help_message)
os.exit(0)
elseif not commands[cmd] then
print("Invalid <command>: "..cmd.."\n\n"..help_message)
os.exit(1)
end

-- Load and execute desired command
require(commands[cmd])
require("kong.cmd.init")(arg)
68 changes: 2 additions & 66 deletions kong/cli/services/serf.lua
Expand Up @@ -12,14 +12,8 @@ local SERVICE_NAME = "serf"
local START_TIMEOUT = 10
local EVENT_NAME = "kong"

function Serf:new(configuration)
local nginx_working_dir = configuration.nginx_working_dir

self._configuration = configuration
local path_prefix = nginx_working_dir
..(stringy.endswith(nginx_working_dir, "/") and "" or "/")
self._script_path = path_prefix.."serf_event.sh"
self._log_path = path_prefix.."serf.log"
function Serf:new(kong_config)
self._configuration = kong_config
self._dao_factory = dao_loader.load(self._configuration)
Serf.super.new(self, SERVICE_NAME, nginx_working_dir)
end
Expand All @@ -37,47 +31,6 @@ function Serf:_get_cmd()
return cmd, err
end

function Serf:prepare()
-- Create working directory if missing
local ok, err = Serf.super.prepare(self, self._configuration.nginx_working_dir)
if not ok then
return nil, err
end

-- Create serf event handler
local luajit_path = BaseService.find_cmd("luajit")
if not luajit_path then
return nil, "Can't find luajit"
end

local script = [[
#!/bin/sh
PAYLOAD=`cat` # Read from stdin
if [ "$SERF_EVENT" != "user" ]; then
PAYLOAD="{\"type\":\"${SERF_EVENT}\",\"entity\": \"${PAYLOAD}\"}"
fi
echo $PAYLOAD > /tmp/payload
COMMAND='require("kong.tools.http_client").post("http://]]..self._configuration.admin_api_listen..[[/cluster/events/", ]].."[=['${PAYLOAD}']=]"..[[, {["content-type"] = "application/json"})'
echo $COMMAND | ]]..luajit_path..[[
]]
local _, err = IO.write_to_file(self._script_path, script)
if err then
return false, err
end

-- Adding executable permissions
local res, code = IO.os_execute("chmod +x "..self._script_path)
if code ~= 0 then
return false, res
end

return true
end

function Serf:_join_node(address)
local _, err = self:invoke_signal("join", {address})
if err then
Expand Down Expand Up @@ -260,21 +213,4 @@ function Serf:event(t_payload)
return self:invoke_signal("event "..tostring(args).." kong", {"'"..encoded_payload.."'", "&"}, true)
end

function Serf:stop()
logger:info("Leaving cluster..")
local _, err = self:invoke_signal("leave")
if err then
return false, err
else
-- Remove the node from the datastore.
-- This is useful when this is the only node running in the cluster.
self._dao_factory.nodes:delete({
name = cluster_utils.get_node_name(self._configuration)
})

-- Finally stop Serf
Serf.super.stop(self, true)
end
end

return Serf
56 changes: 56 additions & 0 deletions kong/cmd/init.lua
@@ -0,0 +1,56 @@
local pl_app = require "pl.lapp"
local help = [[
Kong, open-source API gateway.
Usage: kong COMMAND [OPTIONS]
The available commands are:
start
stop
Options:
--trace (optional boolean) with traceback
]]

local DEFAULT_NGINX_PREFIX = "servroot"

local cmds = {
start = "start",
stop = "stop",
--reload = "reload",
--migrate = "migrate",
--reset = "reset"
}

return function(args)
local cmd_name = args[1]
if cmd_name == nil 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
local cmd_exec = cmd.execute

cmd_lapp = cmd_lapp.."\n --trace (optional boolean) with traceback\n"
args = pl_app(cmd_lapp)
args.prefix = args.prefix or DEFAULT_NGINX_PREFIX

xpcall(function() cmd_exec(args) end, function(err)
if not args.trace then
err = err:match "^.-:.-:.(.*)$"
io.stderr:write("Error: "..err.."\n")
io.stderr:write("\n Run with --trace to see traceback\n")
else
local trace = debug.traceback(err, 2)
io.stderr:write("Error: \n")
io.stderr:write(trace.."\n")
end

pl_app.quit(nil, true)
end)
end
26 changes: 26 additions & 0 deletions kong/cmd/start.lua
@@ -0,0 +1,26 @@
local nginx_conf_compiler = require "kong.cmd.utils.nginx_conf_compiler"
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 function execute(args)
local conf = assert(conf_loader(args.conf))
assert(nginx_conf_compiler.prepare_prefix(conf, args.prefix))
assert(serf_signals.start(conf, args.prefix, DAOFactory(conf)))
assert(nginx_signals.start(args.prefix))
print("Started")
end

local lapp = [[
Usage: kong start [OPTIONS]
Options:
-c,--conf (optional string) configuration file
--prefix (optional string) Nginx prefix path
]]

return {
lapp = lapp,
execute = execute
}
20 changes: 20 additions & 0 deletions kong/cmd/stop.lua
@@ -0,0 +1,20 @@
local nginx_signals = require "kong.cmd.utils.nginx_signals"
local serf_signals = require "kong.cmd.utils.serf_signals"

local function execute(args)
assert(nginx_signals.stop(args.prefix))
assert(serf_signals.stop(args.prefix))
print("Stopped")
end

local lapp = [[
Usage: kong stop [OPTIONS]
Options:
--prefix (optional string) Nginx prefix path
]]

return {
lapp = lapp,
execute = execute
}
2 changes: 2 additions & 0 deletions kong/cmd/utils/nginx_conf_compiler.lua
Expand Up @@ -24,6 +24,8 @@ local function compile_conf(kong_config, conf_template)

if kong_config.cassandra_ssl and kong_config.cassandra_ssl_trusted_cert then
compile_env["lua_ssl_trusted_certificate"] = kong_config.cassandra_ssl_trusted_cert
--compile_env["ssl_certificate"] =
--compile_env["ssl_certificate_key"] =
end

if kong_config.nginx_optimizations then
Expand Down
80 changes: 80 additions & 0 deletions kong/cmd/utils/nginx_signals.lua
@@ -0,0 +1,80 @@
local pl_utils = require "pl.utils"
local pl_path = require "pl.path"
local pl_file = require "pl.file"
local fmt = string.format

local nginx_bin_name = "nginx"
local nginx_search_paths = {
"/usr/local/openresty/nginx/sbin",
""
}

local function is_openresty(bin_path)
local cmd = fmt("%s -v", bin_path)
local ok, _, _, v_str = pl_utils.executeex(cmd)
if ok and v_str then
return v_str:match "^nginx version: ngx_openresty/" or
v_str:match "^nginx version: openresty/"
end
end

local function get_pid(nginx_prefix)
local pid_path = pl_path.join(nginx_prefix, "logs", "nginx.pid")
if pl_path.exists(pid_path) then
return pl_file.read(pid_path)
end
end

local function send_signal(nginx_prefix, signal)
local pid = get_pid(nginx_prefix)
if not pid then return nil, "could not get Nginx pid (is Kong running?)" end

local cmd = fmt("kill -s %s %s", signal, pid)

local ok = pl_utils.execute(cmd)
if not ok then return nil, "could not send signal" end

return true
end

local _M = {}

function _M.find_bin()
local found
for _, path in ipairs(nginx_search_paths) do
local path_to_check = pl_path.join(path, nginx_bin_name)
local ok = is_openresty(path_to_check)
if ok then
found = path_to_check
break
end
end

if not found then
return nil, "could not find OpenResty 'nginx' executable"
end

return found
end

function _M.start(nginx_prefix)
local nginx_bin, err = _M.find_bin()
if not nginx_bin then return nil, err end

local cmd = fmt("%s -p %s -c %s", nginx_bin, nginx_prefix, "nginx.conf")

local ok, _, _, stderr = pl_utils.executeex(cmd)
if not ok then return nil, stderr end

return true
end

function _M.stop(nginx_prefix)
return send_signal(nginx_prefix, "QUIT")
end

function _M.reload(nginx_prefix)
return send_signal(nginx_prefix, "HUP")
end

return _M

0 comments on commit 2500c8e

Please sign in to comment.