chatai/docker-kong_v2.8.1/customize/packer.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")