388 lines
9.3 KiB
Lua
388 lines
9.3 KiB
Lua
local split = require("pl.utils").split
|
|
local pretty = require("pl.pretty").write
|
|
local strip = require("pl.stringx").strip
|
|
local lines = require("pl.stringx").splitlines
|
|
local _execex = require("pl.utils").executeex
|
|
local _exec = require("pl.utils").execute
|
|
local directories = require("pl.dir").getdirectories
|
|
local writefile = require("pl.utils").writefile
|
|
local readfile = require("pl.utils").readfile
|
|
local is_dir = require("pl.path").isdir
|
|
local is_file = require("pl.path").isfile
|
|
|
|
local CUSTOM_TEMPLATE="/custom_nginx.conf"
|
|
|
|
io.stdout:setvbuf("no")
|
|
io.stderr:setvbuf("no")
|
|
|
|
|
|
local function stderr(...)
|
|
io.stderr:write(...)
|
|
io.stderr:write("\n")
|
|
end
|
|
|
|
|
|
local function stdout(...)
|
|
io.stdout:write(...)
|
|
io.stdout:write("\n")
|
|
end
|
|
|
|
|
|
local function fail(msg)
|
|
stderr(msg)
|
|
os.exit(1)
|
|
end
|
|
|
|
|
|
local function header(msg)
|
|
local fill1 = math.floor((80 - 2 - #msg)/2)
|
|
local fill2 = 80 - 2 - #msg - fill1
|
|
stdout(
|
|
("*"):rep(80).."\n"..
|
|
"*"..(" "):rep(fill1)..msg..(" "):rep(fill2).."*\n"..
|
|
("*"):rep(80)
|
|
)
|
|
end
|
|
|
|
|
|
local platforms = {
|
|
{
|
|
check = "apk -V", -- check for alpine
|
|
commands = { -- run before anything else in build container
|
|
"apk update",
|
|
"apk add git",
|
|
"apk add wget",
|
|
"apk add zip",
|
|
"apk add gcc",
|
|
"apk add musl-dev",
|
|
},
|
|
}, {
|
|
check = "yum --version", -- check for rhel
|
|
commands = { -- run before anything else in build container
|
|
"yum -y install git",
|
|
"yum -y install unzip",
|
|
"yum -y install zip",
|
|
"yum -y install gcc gcc-c++ make",
|
|
},
|
|
}, {
|
|
check = "apt -v", -- check for Ubuntu
|
|
commands = { -- run before anything else in build container
|
|
"apt update",
|
|
"apt install -y zip",
|
|
"apt install -y wget",
|
|
"apt install -y build-essential",
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
local execex = function(cmd, ...)
|
|
stdout("\027[32m", "[packer exec] ", cmd, "\027[0m")
|
|
return _execex(cmd, ...)
|
|
end
|
|
|
|
|
|
local exec = function(cmd, ...)
|
|
stdout("\027[32m", "[packer exec] ", cmd, "\027[0m")
|
|
return _exec(cmd, ...)
|
|
end
|
|
|
|
|
|
local function prep_platform()
|
|
for _, platform in ipairs(platforms) do
|
|
local ok = exec(platform.check)
|
|
if not ok then
|
|
stdout(("platform test '%s' was negative"):format(platform.check))
|
|
else
|
|
stdout(("platform test '%s' was positive"):format(platform.check))
|
|
for _, cmd in ipairs(platform.commands) do
|
|
stdout(cmd)
|
|
ok = exec(cmd)
|
|
if not ok then
|
|
fail(("failed executing '%s'"):format(cmd))
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
stderr("WARNING: no platform match!")
|
|
end
|
|
|
|
|
|
local function is_empty_file(filename)
|
|
local t = readfile(filename)
|
|
if t then
|
|
if t:gsub("\n", ""):gsub("\t", ""):gsub(" ","") == "" then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
local function get_args()
|
|
if not arg or
|
|
not arg[1] or
|
|
arg[1] == "--" and not arg[2] then
|
|
-- no args, but maybe a custom config file?
|
|
|
|
if is_empty_file(CUSTOM_TEMPLATE) then
|
|
fail("no arguments to parse, commandline: " .. pretty(arg or {}))
|
|
else
|
|
stdout("no plugins specified, but a custom template exists")
|
|
return
|
|
end
|
|
end
|
|
|
|
local list = {}
|
|
for i = 1, #arg do
|
|
if arg[i] and arg[i] ~= "--" then
|
|
local sp = split(arg[i], ",")
|
|
for n = 1, #sp do
|
|
local rock = strip(sp[n])
|
|
if rock ~= "" then
|
|
table.insert(list, rock)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if #list == 0 then
|
|
if is_empty_file(CUSTOM_TEMPLATE) then
|
|
fail("no arguments to parse, commandline: " .. pretty(arg))
|
|
else
|
|
stdout("no plugins specified, but a custom template exists")
|
|
end
|
|
end
|
|
|
|
stdout("rocks to install: " .. pretty(list))
|
|
return list
|
|
end
|
|
|
|
|
|
local function get_plugins()
|
|
local plugins = {}
|
|
local cnt = 0
|
|
|
|
for i = 1, 2 do
|
|
local pattern, paths, extension
|
|
if i == 1 then
|
|
pattern = "%?%.lua$"
|
|
extension = ".lua"
|
|
paths = split(package.path, ";")
|
|
else
|
|
pattern = "%?%.so$"
|
|
extension = ".so"
|
|
paths = split(package.cpath, ";")
|
|
end
|
|
|
|
for _, path in ipairs(paths) do
|
|
path = path:gsub(pattern, "kong/plugins/")
|
|
if is_dir(path) then
|
|
for _, dir in ipairs(directories(path)) do
|
|
local plugin_name = dir:sub(#path + 1, -1)
|
|
if is_file(dir .. "/handler" .. extension) then
|
|
plugins[plugin_name] = true
|
|
cnt = cnt + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
stdout("Found ", cnt, " plugins installed")
|
|
return plugins
|
|
end
|
|
|
|
|
|
local function get_rocks()
|
|
local cmd = "luarocks list --tree=system --porcelain"
|
|
local ok, _, sout, serr = execex(cmd)
|
|
if not ok then
|
|
fail(("failed to retrieve list of installed rocks: '%s' failed with\n%s\n%s"):format(
|
|
cmd, sout, serr))
|
|
end
|
|
|
|
local rocks = {}
|
|
local cnt = 0
|
|
for _, rock in ipairs(lines(sout)) do
|
|
cnt = cnt + 1
|
|
local name, spec = rock:match("^(.-)\t(.-)\t")
|
|
local rock_id = name.."-"..spec
|
|
rocks[rock_id] = { name = name, spec = spec }
|
|
end
|
|
stdout("Found ", cnt, " rocks installed")
|
|
return rocks
|
|
end
|
|
|
|
|
|
local function install_plugins(plugins, lr_flag)
|
|
local cmd = "luarocks install --tree=system %s " .. lr_flag
|
|
for _, rock in ipairs(plugins) do
|
|
stdout(cmd:format(rock))
|
|
|
|
local ok = exec(cmd:format(rock))
|
|
if not ok then
|
|
fail(("failed installing rock: '%s' failed"):format(cmd:format(rock)))
|
|
end
|
|
|
|
stdout("installed: "..rock)
|
|
exec("luarocks show "..rock)
|
|
end
|
|
end
|
|
|
|
|
|
local function check_custom_template()
|
|
if is_empty_file(CUSTOM_TEMPLATE) then
|
|
-- it's the empty_file, delete it
|
|
os.remove(CUSTOM_TEMPLATE)
|
|
stdout("No custom template found")
|
|
return
|
|
end
|
|
stdout("Found a custom template")
|
|
end
|
|
|
|
|
|
local function start_rocks_server()
|
|
if is_empty_file("/rocks-server") then
|
|
stdout("No custom rocks found, using public luarocks.org as server")
|
|
return ""
|
|
end
|
|
assert(exec("luarocks-admin make_manifest /rocks-server"))
|
|
stdout("Local LuaRocks server manifest created")
|
|
assert(exec("mkdir /nginx"))
|
|
assert(exec("mkdir /nginx/logs"))
|
|
assert(writefile("/nginx/nginx.conf", [[
|
|
events {
|
|
}
|
|
|
|
http {
|
|
server {
|
|
listen 127.0.0.1:8080;
|
|
|
|
location / {
|
|
root /rocks-server;
|
|
}
|
|
}
|
|
}
|
|
]]))
|
|
assert(exec("touch /nginx/logs/error.log"))
|
|
assert(exec("/usr/local/openresty/nginx/sbin/nginx " ..
|
|
"-c /nginx/nginx.conf " ..
|
|
"-p /nginx"))
|
|
stdout("Nginx started as local LuaRocks server")
|
|
stdout("List of locally available rocks:")
|
|
assert(exec("luarocks search --all --porcelain --only-server=http://localhost:8080"))
|
|
return " --only-server=http://localhost:8080 "
|
|
end
|
|
|
|
|
|
-- **********************************************************
|
|
-- Do the actual work
|
|
-- **********************************************************
|
|
header("Set up platform")
|
|
prep_platform()
|
|
|
|
header("Set up LuaRocks server")
|
|
local lr_flag = start_rocks_server()
|
|
|
|
header("Get arguments")
|
|
local rocks = get_args()
|
|
|
|
|
|
header("Get existing rocks")
|
|
local pre_installed_rocks = get_rocks()
|
|
|
|
|
|
header("Get existing plugin list")
|
|
local pre_installed_plugins = get_plugins()
|
|
|
|
|
|
header("Getting custom template")
|
|
check_custom_template()
|
|
|
|
|
|
header("Install the requested plugins")
|
|
install_plugins(rocks, lr_flag)
|
|
|
|
|
|
header("Get post-install rocks list and get the delta")
|
|
local added_rocks
|
|
do
|
|
local post_installed_rocks = get_rocks()
|
|
for k in pairs(pre_installed_rocks) do
|
|
if post_installed_rocks[k] then
|
|
post_installed_rocks[k] = nil -- remove the ones we already had
|
|
end
|
|
end
|
|
added_rocks = post_installed_rocks
|
|
end
|
|
if (not next(added_rocks)) then
|
|
if is_empty_file(CUSTOM_TEMPLATE) then
|
|
fail("no additional rocks were added, nor a custom template specified")
|
|
end
|
|
stdout("No rocks were added")
|
|
else
|
|
for k in pairs(added_rocks) do
|
|
stdout("added rock: "..k)
|
|
end
|
|
end
|
|
|
|
|
|
header("Get post-install plugin list and get the delta")
|
|
local plugins = {}
|
|
for plugin_name in pairs(get_plugins()) do
|
|
if not pre_installed_plugins[plugin_name] then
|
|
table.insert(plugins, plugin_name)
|
|
stdout("added plugin: "..plugin_name)
|
|
end
|
|
end
|
|
if not next(plugins) then
|
|
stdout("No plugins were added")
|
|
end
|
|
|
|
|
|
header("Write new entry-point script")
|
|
assert(exec("mv /docker-entrypoint.sh /old-entrypoint.sh"))
|
|
local entrypoint = [=[
|
|
#!/bin/sh
|
|
set -e
|
|
|
|
if [ "$KONG_PLUGINS" = "" ]; then
|
|
KONG_PLUGINS="bundled"
|
|
fi
|
|
# replace 'bundled' with the new set, including the custom ones
|
|
export KONG_PLUGINS=$(echo ",$KONG_PLUGINS," | sed "s/,bundled,/,bundled,%s,/" | sed 's/^,//' | sed 's/,$//')
|
|
|
|
# prefix the custom template option, since the last one on the command line
|
|
# wins, so the user can still override this template
|
|
INITIAL="$1 $2"
|
|
if [ -f /custom_nginx.conf ]; then
|
|
# only for these commands support "--nginx-conf"
|
|
echo 1: $INITIAL
|
|
if [ "$INITIAL" = "kong prepare" ] || \
|
|
[ "$INITIAL" = "kong reload" ] || \
|
|
[ "$INITIAL" = "kong restart" ] || \
|
|
[ "$INITIAL" = "kong start" ] ; then
|
|
INITIAL="$1 $2 --nginx-conf=/custom_nginx.conf"
|
|
fi
|
|
fi
|
|
# shift 1 by 1; if there is only 1 arg, then "shift 2" fails
|
|
if [ ! "$1" = "" ]; then
|
|
shift
|
|
fi
|
|
if [ ! "$1" = "" ]; then
|
|
shift
|
|
fi
|
|
|
|
exec /old-entrypoint.sh $INITIAL "$@"
|
|
]=]
|
|
entrypoint = entrypoint:format(table.concat(plugins, ","))
|
|
assert(writefile("/docker-entrypoint.sh", entrypoint))
|
|
assert(exec("chmod +x /docker-entrypoint.sh"))
|
|
stdout(entrypoint)
|
|
|
|
|
|
header("Completed building plugins, rocks and/or template")
|
|
|