Skip to content

Instantly share code, notes, and snippets.

@jsimmons
Created September 14, 2010 08:32
Show Gist options
  • Save jsimmons/578726 to your computer and use it in GitHub Desktop.
Save jsimmons/578726 to your computer and use it in GitHub Desktop.
Mongrel2 config loading, in lua
local chat_demo = Handler {
send_spec = 'tcp://127.0.0.1:9999';
send_ident = '8b7c7833-0932-4d9a-92c3-3b8c06d9b855';
recv_spec = 'tcp://127.0.0.1:9998';
recv_ident = '';
}
local chat_demo_dir = Dir {
base = 'static/chatdemo/';
index_file = 'index.html';
default_ctype = 'text/plain';
}
local handler_test = Handler {
send_spec = 'tcp://127.0.0.1:9997';
send_ident = '8b7c7833-0932-4d9a-92c3-3b8c06d9b855';
recv_spec = 'tcp://127.0.0.1:9996';
recv_ident = '';
}
local mp3stream = Handler {
send_spec = 'tcp://127.0.0.1:9995';
send_ident = '8b7c7833-0932-4d9a-92c3-3b8c06d9b855';
recv_spec = 'tcp://127.0.0.1:9994';
recv_ident = '';
}
local lua_test = Handler {
send_spec = 'tcp://127.0.0.1:9989';
send_ident = '8b7c7833-0932-4d9a-92c3-3b8c06d9b855';
recv_spec = 'tcp://127.0.0.1:9988';
recv_ident = '';
}
--[[
--local lua_test = Handler()
--lua_test.send_spec = 'tcpLabsdabf'
--etc
--]]
local localhost_routes = {
['@chat'] = chat_demo;
['/handlertest/'] = handler_test;
['/magic/'] = handler_test;
['/chatdemo/'] = chat_demo_dir;
['/static/'] = chat_demo_dir;
['/mp3stream/'] = mp3stream;
['/lua/'] = lua_test;
}
local host = Host 'localhost'
host.routes = localhost_routes
-- local host = Host('localhost', {'/test/' = Handler {blah blah blah}})
local server = Server {
name = 'my_server';
uuid = '3d815ade-9081-4c36-94dc-77a9b060b021';
access_log = '/logs/access.log';
error_log = '/logs/error.log';
chroot = '/home/josh/Projects/mongrel2-playground';
pid_file = '/run/mongrel2.pid';
default_host = 'localhost';
port = 6767;
hosts = {host};
}
server.port = 6768
local settings = Settings {
['zeromq.threads'] = 1;
}
settings.other = 9000
#!/usr/bin/env lua
local sqlite3 = require 'lsqlite3'
local function sql_escape(sql, ...)
local args = {...}
for k, v in pairs(args) do
local t = type(v)
if t == 'boolean' then
args[k] = v and '1' or '0'
elseif t == 'number' then
args[k] = tostring(v)
elseif t == 'string' then
args[k] = ('"%s"'):format(v)
elseif t == 'nil' then
args[k] = 'NULL'
else
error('invalid type')
end
end
return sql:format(unpack(args))
end
local function lazy_write_sql(db, obj, sql)
if not obj.id then
db:exec(sql)
obj.id = db:last_insert_rowid()
print(('WROTE SQL "%s" to %s'):format(sql, tostring(obj.id)))
end
return obj.id
end
local function Handler(tab)
tab = tab or {}
tab.type = 'handler'
return tab
end
local handler_sql = 'INSERT INTO handler(send_spec, send_ident, recv_spec, recv_ident) VALUES(%s, %s, %s, %s)'
local function write_handler(db, handler)
local sql = sql_escape(handler_sql, handler.send_spec, handler.send_ident, handler.recv_spec, handler.recv_ident)
return lazy_write_sql(db, handler, sql)
end
local function Dir(tab)
tab = tab or {}
tab.type = 'dir'
return tab
end
local dir_sql = 'INSERT INTO directory(base, index_file, default_ctype) VALUES(%s, %s, %s)'
local function write_directory(db, dir)
local sql = sql_escape(dir_sql, dir.base, dir.index_file, dir.default_ctype)
return lazy_write_sql(db, dir, sql)
end
local function Proxy(tab)
tab = tab or {}
tab.type = 'proxy'
return tab
end
local proxy_sql = 'INSERT INTO proxy(addr, port) VALUES(%s, %s)'
local function write_proxy(db, proxy)
local sql = sql_escape(proxy_sql, proxy.addr, proxy.port)
return lazy_write_sql(db, proxy, sql)
end
local function write_target(db, target)
if target.type == 'dir' then
return write_directory(db, target)
elseif target.type == 'proxy' then
return write_proxy(db, target)
elseif target.type == 'handler' then
return write_handler(db, target)
else
error('invalid target for route')
end
end
local function Host(name, routes)
local tab = {}
tab.type = 'host'
tab.name = name
tab.routes = routes or {}
return tab
end
local host_sql = 'INSERT INTO host(server_id, maintenance, name, matching) VALUES(%s, %s, %s, %s)'
local function write_host(db, host, server_id)
local sql = sql_escape(host_sql, server_id, host.maintenance or false, host.name, host.matching or host.name)
return lazy_write_sql(db, host, sql)
end
local servers = {}
local function Server(tab)
tab = tab or {}
tab.type = 'server'
table.insert(servers, tab)
return tab
end
local server_sql = 'INSERT INTO server(uuid, access_log, error_log, chroot, pid_File, default_host, name, port) VALUES(%s, %s, %s, %s, %s, %s, %s, %s)'
local function write_server(db, server)
local sql = sql_escape(server_sql, server.uuid, server.access_log, server.error_log, server.chroot, server.pid_file, server.default_host, server.name, server.port)
return lazy_write_sql(db, server, sql)
end
local settings = {}
local function Settings(tab, value)
if type(tab) == 'table' then
for k, v in pairs(tab) do settings[k] = v end
return settings
elseif tab then
settings[tab] = value
return settings
else
return settings
end
end
local setting_sql = 'INSERT INTO setting(key, value) VALUES(%s, %s)'
local function write_settings(db)
for k, v in pairs(settings) do
local sql = sql_escape(setting_sql, k, v)
db:exec(sql)
end
end
local route_sql = 'INSERT INTO route(path, reversed, host_id, target_id, target_type) VALUES(%s, %s, %s, %s, %s)'
local function write_route(db, path, reversed, host_id, target)
local target_id = write_target(db, target)
local sql = sql_escape(route_sql, path, reversed, host_id, target_id, target.type)
db:exec(sql)
end
local function load_config(config_file)
local env = {}
env.__index = env
env.Settings = Settings
env.Server = Server
env.Host = Host
env.Proxy = Proxy
env.Dir = Dir
env.Handler = Handler
local chunk, err = loadfile(config_file)
if not chunk then print('Error: ' .. tostring(err)) return end
chunk = setfenv(chunk, env)
local success, msg = pcall(chunk)
if not success then print("Error: " .. tostring(msg)) return end
end
local function write_sqlite(db_file)
local db = sqlite3.open(db_file)
db:exec([[
DELETE FROM server;
DELETE FROM route;
DELETE FROM host;
DELETE FROM setting;
DELETE FROM proxy;
DELETE FROM directory;
DELETE FROM handler;
]])
for _, server in pairs(servers) do
print 'writing a server'
local server_id = write_server(db, server)
for _, host in pairs(server.hosts) do
print 'writing a host'
local host_id = write_host(db, host, server_id)
for path, target in pairs(host.routes) do
print(('writing a route %s -> %s'):format(tostring(path), tostring(target)))
write_route(db, path, '0', host_id, target)
end
end
write_settings(db)
end
db:close()
end
print('running')
load_config("config.lua")
write_sqlite("config.sqlite")
print('done')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment