Skip to content

Commit

Permalink
templating prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
mikz committed Oct 25, 2017
1 parent dcf4498 commit 2edfa68
Show file tree
Hide file tree
Showing 14 changed files with 529 additions and 129 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ test-builder-image: export IMAGE_NAME = apicast-test
test-builder-image: builder-image clean-containers ## Smoke test the builder image. Pass any docker image in IMAGE_NAME parameter.
$(DOCKER_COMPOSE) --version
@echo -e $(SEPARATOR)
$(DOCKER_COMPOSE) run --rm --user 100001 gateway openresty -c /opt/app-root/src/conf/nginx.conf -g 'error_log stderr info; pid /tmp/nginx.pid;' -t
$(DOCKER_COMPOSE) run --rm --user 100001 gateway bin/apicast --test
@echo -e $(SEPARATOR)
$(DOCKER_COMPOSE) run --rm --user 100001 gateway openresty -c /opt/app-root/src/conf/nginx.conf -g 'error_log stderr info; pid /tmp/nginx.pid;'
$(DOCKER_COMPOSE) run --rm --user 100001 gateway bin/apicast --daemon
@echo -e $(SEPARATOR)
$(DOCKER_COMPOSE) run --rm test bash -c 'for i in {1..5}; do curl --fail http://gateway:8090/status/live && break || sleep 1; done'
$(DOCKER_COMPOSE) logs gateway
Expand Down
4 changes: 4 additions & 0 deletions apicast/Roverfile.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
ansicolors 1.0.2-3
argparse 0.5.0-1
busted 2.0.rc12-1
dkjson 2.5-2
inspect 3.1.0-1
ldoc 1.4.6-2
liquid scm-1
lua-resty-env 0.4.0-1
lua-resty-execvp 0.1.0-1
lua-resty-http 0.10-0
lua-resty-iputils 0.3.0-1
lua-resty-jwt 0.1.10-1
Expand Down
1 change: 1 addition & 0 deletions apicast/apicast-0.1-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dependencies = {
'lua-resty-jwt',
'lua-resty-url',
'lua-resty-env',
'lua-resty-execvp',
}
build = {
type = "builtin",
Expand Down
137 changes: 12 additions & 125 deletions apicast/bin/apicast
Original file line number Diff line number Diff line change
@@ -1,130 +1,17 @@
#!/bin/bash
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';

set -euo pipefail
IFS=$'\n\t'
use File::Basename;
use Cwd qw(abs_path);

script=${BASH_SOURCE[0]}
if (readlink -f "${script}" > /dev/null 2>&1); then
path=$(readlink -f "${script}")
elif (readlink "${script}" > /dev/null 2>&1); then
path="$(dirname "${script}")/$(readlink "${script}")"
else
path="${script}"
fi
my $apicast = $ENV{APICAST_DIR} || abs_path(dirname(abs_path(__FILE__)) . '/..');
my $bindir = $apicast . '/bin';
my $lua_path = $ENV{LUA_PATH} || ';';

bin_dir=$(dirname "${path}")
apicast_dir=${APICAST_DIR:-"$( cd "${bin_dir}/.." && pwd )"}
chdir $apicast;

pick_openresty() {
for cmd in "$@"
do
if (${cmd} -V > /dev/null 2>&1); then
echo "${cmd}"
exit 0
fi
done
$ENV{LUA_PATH} = "$apicast/src/?.lua;${lua_path}";

(>&2 echo "ERROR: Could not find openresty executable in your PATH.")
(>&2 echo "Make sure you have one of: $(printf "%s " "$@")")
exit 1
}

openresty_binary=${APICAST_OPENRESTY_BINARY:-$(pick_openresty openresty-debug openresty nginx)}
log_level=${APICAST_LOG_LEVEL:-warn}
log_file=${APICAST_LOG_FILE:-stderr}
log_levels=(emerg alert crit error warn notice info debug)
((max_log_level=${#log_levels[@]}-1))

for ((i=0; i < ${#log_levels[@]}; i++)); do
ll=${log_levels[i]}
declare -r "log_level_${ll}=$i"
done

log="log_level_${log_level}"
log_level="${!log}"

daemon=off
worker_processes=${APICAST_WORKERS:-1}

usage () {
cat <<-USAGE
Usage $0
-h Show this help
-c <file> Path to custom config file (JSON).
-d Daemonize
-v Increase verbosity (can be repeated)
-i Cache configuration for N seconds. Using 0 will reload on every request (not for production).
-w <workers> Number of worker processes to start.
-m <on|off> Whether to start worker processes. Only for development.
-s <signal> Send signal to a master process: stop, quit, reopen, reload
-p <pid> Path to the PID file.
-b Load configuration on boot.
-e Deployment environment. Can be staging or production.
USAGE
}

main=("")
args=("")

while getopts ":dc:hvbqi:rw:m:s:p:e:" opt; do
case "${opt}" in
d)
daemon="on"
;;
c)
export APICAST_CONFIGURATION="$OPTARG"
;;
b)
export APICAST_CONFIGURATION_LOADER="boot"
;;
v)
log_level=$((log_level == max_log_level ? max_log_level : log_level+1))
;;
q)
log_level=$((log_level == 0 ? 0 : log_level-1))
;;
i)
export APICAST_CONFIGURATION_CACHE="${OPTARG}"
;;
e)
export THREESCALE_DEPLOYMENT_ENV="${OPTARG}"
;;
w)
worker_processes=${OPTARG}
;;
m)
main+=("master_process ${OPTARG};")
;;
p)
main+=("pid ${PWD}/${OPTARG};")
;;
s)
args+=("-s" "${OPTARG}")
;;
h)
usage
exit 0
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo
usage
exit 1
;;
esac
done

export THREESCALE_DEPLOYMENT_ENV=${THREESCALE_DEPLOYMENT_ENV-production}

main+=("daemon ${daemon};")
main+=("worker_processes ${worker_processes};")
main+=$(printenv | awk '$1 ~ /^(APICAST|THREESCALE)_/ {split($0,env,"="); print "env", env[1] ";"}')

function join_by { local IFS="$1"; shift; echo "$*"; }
args=$(join_by '' "${args[@]}")
main=$(join_by '' "${main[@]}")

cd "${apicast_dir}"

# shellcheck disable=SC2086
exec "${openresty_binary}" -c "${apicast_dir}/conf/nginx.conf" ${args} -g "${main} error_log ${log_file} ${log_levels[log_level]};"
exec '/usr/bin/env', 'resty',
"$bindir/cli", @ARGV;
11 changes: 11 additions & 0 deletions apicast/bin/cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env resty

local ok, setup = pcall(require, 'rover.setup')

if ok then
setup()
else
package.path = './src/?.lua;' .. package.path
end

require('apicast.cli')(arg)
92 changes: 92 additions & 0 deletions apicast/conf/nginx.conf.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
env REDIS_HOST;
env REDIS_PORT;
env REDIS_URL;
env RESOLVER;
env BACKEND_ENDPOINT_OVERRIDE;
env OPENSSL_VERIFY;

{% for env in env -%}
{%- if env.name | starts_with: 'APICAST_', 'THREESCALE_' %}
env {{ env.name }};
{%- endif -%}
{%- endfor %}

daemon {{ daemon | default: 'off' }};
master_process {{ master_process | default: 'on' }};
worker_processes {{ worker_processes | default: 'auto' }};

{% for file in "main.d/*.conf" | filesystem %}
{% include file %}
{% endfor %}

error_log /dev/null emerg;

events {
worker_connections 16192;
multi_accept on;
}

http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# Enabling the Lua code cache is strongly encouraged for production use
# Disabling it should only be done for testing and development purposes
lua_code_cache {{ lua_code_cache | default: 'on' }};

server_names_hash_bucket_size 128;

log_format time '[$time_local] $host:$server_port $remote_addr:$remote_port "$request" $status $body_bytes_sent ($request_time) $post_action_impact';
access_log off;

lua_package_path ";;{{prefix}}/?.lua;{{prefix}}/src/?.lua";

{% for file in "http.d/*.conf" | filesystem %}
{% include file %}
{% endfor %}

server {
listen 8090;

server_name _;

{% include "conf.d/management.conf" %}
}

server {
listen 8081;

server_name backend;

{% include "conf.d/backend.conf" %}
}

server {
listen 8081 default_server;

server_name echo _;

{% include "conf.d/echo.conf" %}
}

server {
access_log /dev/stdout time;

listen 8080;

server_name _;
underscores_in_headers on;

{% include "http.d/ssl.conf" %}

{% for file in "apicast.d/*.conf" | filesystem %}
{% include file %}
{% endfor %}
{% include "conf.d/apicast.conf" %}
}

{% for file in "sites.d/*.conf" | filesystem %}
{% include file %}
{% endfor %}
}
12 changes: 12 additions & 0 deletions apicast/config/development.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
local lr_path, lr_cpath, lr_bin = require('luarocks.cfg').package_paths()

return {
worker_processes = '1',
master_process = 'off',
lua_code_cache = 'off',
lua_path = "./src/?.lua;./src/?/init.lua;"..lr_path,
lua_cpath = lr_cpath,
env = {
PATH = lr_bin -- this probably also needs to use the previous value
}
}
5 changes: 5 additions & 0 deletions apicast/config/production.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
return {
worker_processes = 'auto',
master_process = 'on',
lua_code_cache = 'on',
}
4 changes: 2 additions & 2 deletions apicast/http.d/ssl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
## it really hard to have working cross platform configuration.
#
lua_ssl_verify_depth 5;
lua_ssl_trusted_certificate ca-bundle.crt;
lua_ssl_trusted_certificate "{{ ca_bundle | default: 'ca-bundle.crt' }}";

proxy_ssl_server_name on;
proxy_ssl_name $http_host;
proxy_ssl_verify_depth 5;

proxy_ssl_trusted_certificate ca-bundle.crt;
proxy_ssl_trusted_certificate "{{ ca_bundle | default: 'ca-bundle.crt' }}";
54 changes: 54 additions & 0 deletions apicast/src/apicast/cli.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local command_target = '_cmd'
local parser = require('argparse')() {
name = "APIcast",
description = "APIcast - 3scale API Management Platform Gateway."
}
:command_target(command_target)
:require_command(false)
:handle_options(false)

local _M = { }

local mt = {}

local function load_commands(commands, argparse)
for i=1, #commands do
commands[commands[i]] = require('apicast.cli.' .. commands[i]):new(argparse)
end
return commands
end

_M.commands = load_commands({ 'start' }, parser)

function mt.__call(self, arg)
-- now we parse the options like usual:
local ok, ret = self.parse(arg)

if not ok and ret then
local err = ret
table.insert(arg, 1, 'start')
ok, ret = self.parse(arg)
if not ok then
ret = err
table.remove(arg, 1)
end
end

local cmd = ok and ret[command_target]

if ok and cmd then
self.commands[cmd](ret)
elseif ret and not next(ret) then
local start = self.commands.start
start(start:parse(arg))
else
print(ret)
os.exit(1)
end
end

function _M.parse(arg)
return parser:pparse(arg)
end

return setmetatable(_M, mt)
Loading

0 comments on commit 2edfa68

Please sign in to comment.