m2config 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +11 -0
- data/Guardfile +20 -0
- data/LICENSE +8 -0
- data/README.md +79 -0
- data/Rakefile +1 -0
- data/lib/m2config/dir.rb +17 -0
- data/lib/m2config/handler.rb +17 -0
- data/lib/m2config/host.rb +26 -0
- data/lib/m2config/proxy.rb +15 -0
- data/lib/m2config/route.rb +19 -0
- data/lib/m2config/schema.sql +54 -0
- data/lib/m2config/server.rb +37 -0
- data/lib/m2config/setting.rb +19 -0
- data/lib/m2config/version.rb +3 -0
- data/lib/m2config.rb +56 -0
- data/m2config.gemspec +26 -0
- data/sample/full.rb +20 -0
- data/spec/dir_spec.rb +43 -0
- data/spec/env.rb +8 -0
- data/spec/handler_spec.rb +43 -0
- data/spec/host_spec.rb +50 -0
- data/spec/m2config_spec.rb +61 -0
- data/spec/proxy_spec.rb +32 -0
- data/spec/route_spec.rb +47 -0
- data/spec/server_spec.rb +42 -0
- data/spec/setting_spec.rb +32 -0
- metadata +169 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
3
|
+
|
4
|
+
guard 'rspec', :cli => "--color --format nested --fail-fast" do # -t focus
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
14
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
watch('config/routes.rb') { "spec/routing" }
|
17
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
18
|
+
# Capybara request specs
|
19
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
20
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2013 Arnaud Meuret (arnaud@meuret.net)
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
CAVEAT EMPTOR
|
2
|
+
-------------
|
3
|
+
|
4
|
+
THIS LIB IS VERY YOUNG. ALTHOUGH IT SEEMS TO WORK SO FAR I AM JUST
|
5
|
+
STARTING TO USE IT IN THE FIELD SO EVEN THOUGH THE SPECS PASS IT MAY
|
6
|
+
BREAK STUFF.
|
7
|
+
|
8
|
+
|
9
|
+
M2config
|
10
|
+
========
|
11
|
+
[![Build Status](https://travis-ci.org/ameuret/m2config.png?branch=master)](https://travis-ci.org/ameuret/m2config)
|
12
|
+
[![Code Climate](https://codeclimate.com/github/ameuret/m2config.png)](https://codeclimate.com/github/ameuret/m2config)
|
13
|
+
|
14
|
+
Manage your Mongrel2 configuration database using handy model classes
|
15
|
+
that map Servers, Hosts, Routes, Directories, Proxies, Handlers and Settings.
|
16
|
+
|
17
|
+
Installation
|
18
|
+
------------
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
gem 'm2config'
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
$ gem install m2config
|
31
|
+
|
32
|
+
Usage
|
33
|
+
-----
|
34
|
+
|
35
|
+
Thanks to the sane default values set by M2Config, creating a basic
|
36
|
+
Mongrel2 configuration can be as simple as running:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
require "m2config"
|
40
|
+
|
41
|
+
cfg = M2Config::Config.new
|
42
|
+
server = M2Config::Server.new
|
43
|
+
exComHost = M2Config::Host.new({matching:"example.com"})
|
44
|
+
pubDir = M2Config::Dir.new({base:"/public"})
|
45
|
+
pubRoute = M2Config::Route.new({path:"/", target:pubDir})
|
46
|
+
|
47
|
+
exComHost.add_route pubRoute
|
48
|
+
server.add_host exComHost
|
49
|
+
```
|
50
|
+
|
51
|
+
### This is Sequel
|
52
|
+
|
53
|
+
The classes mapping the configuration are
|
54
|
+
[Sequel](http://sequel.rubyforge.org/) models. I just added some
|
55
|
+
syntactic sugar but you can use them as plain Sequel::Model objects.
|
56
|
+
|
57
|
+
TODO
|
58
|
+
----
|
59
|
+
|
60
|
+
A few features that you may miss if your needs go beyond mine:
|
61
|
+
|
62
|
+
- MIME types are not handled (trivial to add, just ask)
|
63
|
+
- Multiple DBs in same process
|
64
|
+
- A DSL-like syntax (probably improves readability in complex setups)
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
Contributing
|
69
|
+
------------
|
70
|
+
|
71
|
+
Start simply with an issue (even for a feature request).
|
72
|
+
|
73
|
+
Otherwise if you feel like helping directly:
|
74
|
+
|
75
|
+
1. Fork it
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/m2config/dir.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Dir < Sequel::Model(:directory)
|
3
|
+
plugin :validation_helpers
|
4
|
+
|
5
|
+
def initialize( fields )
|
6
|
+
fields[:default_ctype] ||= "application/octet-stream"
|
7
|
+
fields[:index_file] ||= "index.html"
|
8
|
+
super(fields, false)
|
9
|
+
save
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
"dir"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Handler < Sequel::Model(:handler)
|
3
|
+
plugin :validation_helpers
|
4
|
+
|
5
|
+
def initialize( fields )
|
6
|
+
raise ArgumentError, "The send and receive endpoints can not be the same" if
|
7
|
+
fields[:send_spec] == fields[:recv_spec]
|
8
|
+
super(fields, false)
|
9
|
+
save
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
"handler"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Host < Sequel::Model(:host)
|
3
|
+
plugin :validation_helpers
|
4
|
+
|
5
|
+
def initialize( fields )
|
6
|
+
if fields[:srv]
|
7
|
+
s=fields[:srv]
|
8
|
+
fields.delete :srv
|
9
|
+
else
|
10
|
+
if fields[:srvUuid]
|
11
|
+
s=Server.find({uuid: fields[:srvUuid]})
|
12
|
+
fields.delete :srvUuid
|
13
|
+
end
|
14
|
+
end
|
15
|
+
fields[:server_id] = s.id if s
|
16
|
+
super(fields, false)
|
17
|
+
save
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_route( route )
|
21
|
+
route.host = id
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Route < Sequel::Model(:route)
|
3
|
+
plugin :validation_helpers
|
4
|
+
|
5
|
+
def initialize( fields )
|
6
|
+
fields[:target_id] = fields[:target].id
|
7
|
+
fields[:target_type] = fields[:target].type
|
8
|
+
fields.delete(:target)
|
9
|
+
super(fields, false)
|
10
|
+
save
|
11
|
+
end
|
12
|
+
|
13
|
+
def host=( hostOrId )
|
14
|
+
self.host_id = hostOrId.kind_of?(Host) ? hostOrId.id : hostOrId
|
15
|
+
save
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
CREATE TABLE directory (id INTEGER PRIMARY KEY, base TEXT, index_file TEXT, default_ctype TEXT, cache_ttl INTEGER DEFAULT 0);
|
2
|
+
CREATE TABLE handler (id INTEGER PRIMARY KEY,
|
3
|
+
send_spec TEXT,
|
4
|
+
send_ident TEXT,
|
5
|
+
recv_spec TEXT,
|
6
|
+
recv_ident TEXT,
|
7
|
+
raw_payload INTEGER DEFAULT 0,
|
8
|
+
protocol TEXT DEFAULT 'json');
|
9
|
+
CREATE TABLE host (id INTEGER PRIMARY KEY,
|
10
|
+
server_id INTEGER,
|
11
|
+
maintenance BOOLEAN DEFAULT 0,
|
12
|
+
name TEXT,
|
13
|
+
matching TEXT);
|
14
|
+
CREATE TABLE log(id INTEGER PRIMARY KEY,
|
15
|
+
who TEXT,
|
16
|
+
what TEXT,
|
17
|
+
location TEXT,
|
18
|
+
happened_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
19
|
+
how TEXT,
|
20
|
+
why TEXT);
|
21
|
+
CREATE TABLE mimetype (id INTEGER PRIMARY KEY, mimetype TEXT, extension TEXT);
|
22
|
+
CREATE TABLE proxy (id INTEGER PRIMARY KEY,
|
23
|
+
addr TEXT,
|
24
|
+
port INTEGER);
|
25
|
+
CREATE TABLE route (id INTEGER PRIMARY KEY,
|
26
|
+
path TEXT,
|
27
|
+
reversed BOOLEAN DEFAULT 0,
|
28
|
+
host_id INTEGER,
|
29
|
+
target_id INTEGER,
|
30
|
+
target_type TEXT);
|
31
|
+
CREATE TABLE server (id INTEGER PRIMARY KEY,
|
32
|
+
uuid TEXT,
|
33
|
+
access_log TEXT,
|
34
|
+
error_log TEXT,
|
35
|
+
chroot TEXT DEFAULT '/var/www',
|
36
|
+
pid_file TEXT,
|
37
|
+
default_host TEXT,
|
38
|
+
name TEXT DEFAULT '',
|
39
|
+
bind_addr TEXT DEFAULT "0.0.0.0",
|
40
|
+
port INTEGER,
|
41
|
+
use_ssl INTEGER default 0);
|
42
|
+
CREATE TABLE setting (id INTEGER PRIMARY KEY, key TEXT, value TEXT);
|
43
|
+
CREATE TABLE statistic (id SERIAL,
|
44
|
+
other_type TEXT,
|
45
|
+
other_id INTEGER,
|
46
|
+
name text,
|
47
|
+
sum REAL,
|
48
|
+
sumsq REAL,
|
49
|
+
n INTEGER,
|
50
|
+
min REAL,
|
51
|
+
max REAL,
|
52
|
+
mean REAL,
|
53
|
+
sd REAL,
|
54
|
+
primary key (other_type, other_id, name));
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Server < Sequel::Model(:server)
|
3
|
+
ACCESS_LOG = '/logs/access.log'
|
4
|
+
ERROR_LOG = '/logs/error.log'
|
5
|
+
PID_FILE = '/run/mongrel2.pid'
|
6
|
+
CHROOT = './'
|
7
|
+
DEFAULT_HOST = 'localhost'
|
8
|
+
NAME = 'main'
|
9
|
+
BIND_ADDR = '0.0.0.0'
|
10
|
+
PORT = 6767
|
11
|
+
USE_SSL = 0
|
12
|
+
|
13
|
+
plugin :validation_helpers
|
14
|
+
one_to_many :hosts
|
15
|
+
|
16
|
+
def initialize( fields={} )
|
17
|
+
fields[:uuid] ||= UUID.new.generate
|
18
|
+
fields[:access_log] ||= M2Config::Server::ACCESS_LOG
|
19
|
+
fields[:error_log] ||= ERROR_LOG
|
20
|
+
fields[:pid_file] ||= PID_FILE
|
21
|
+
fields[:chroot] ||= CHROOT
|
22
|
+
fields[:default_host] ||= DEFAULT_HOST
|
23
|
+
fields[:name] ||= NAME
|
24
|
+
fields[:bind_addr] ||= BIND_ADDR
|
25
|
+
fields[:port] ||= PORT
|
26
|
+
fields[:use_ssl] ||= USE_SSL
|
27
|
+
super fields, false
|
28
|
+
save
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_host( host )
|
32
|
+
host.server_id = id
|
33
|
+
host.save
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module M2Config
|
2
|
+
class Setting < Sequel::Model(:setting)
|
3
|
+
plugin :validation_helpers
|
4
|
+
|
5
|
+
def initialize( key, value )
|
6
|
+
if s=Setting[key:key]
|
7
|
+
s.update({value:value})
|
8
|
+
return s
|
9
|
+
else
|
10
|
+
fields = {}
|
11
|
+
fields[:key] = key.to_s
|
12
|
+
fields[:value] = value.to_s
|
13
|
+
super(fields, false)
|
14
|
+
save
|
15
|
+
return self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/m2config.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "sequel"
|
2
|
+
require "uuid"
|
3
|
+
|
4
|
+
module M2Config
|
5
|
+
|
6
|
+
class Config
|
7
|
+
|
8
|
+
DEFAULT_CONFIG = "config.sqlite"
|
9
|
+
SCHEMA = File.read("#{File.dirname __FILE__}/m2config/schema.sql")
|
10
|
+
|
11
|
+
@@foundTables = []
|
12
|
+
|
13
|
+
def self.tables
|
14
|
+
return @@foundTables unless @@foundTables.empty?
|
15
|
+
SCHEMA.split("\n").each do
|
16
|
+
|l|
|
17
|
+
if l =~ /CREATE TABLE (\w+)/
|
18
|
+
@@foundTables.push $1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@@foundTables
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize( fileName = DEFAULT_CONFIG )
|
25
|
+
@fileName = fileName
|
26
|
+
creating = ! (File.exists? @fileName)
|
27
|
+
@db = Sequel.connect "sqlite://#{@fileName}"
|
28
|
+
|
29
|
+
@db.run SCHEMA if creating
|
30
|
+
|
31
|
+
require "m2config/server"
|
32
|
+
M2Config::Server.db = @db
|
33
|
+
require "m2config/host"
|
34
|
+
M2Config::Host.db = @db
|
35
|
+
require "m2config/dir"
|
36
|
+
M2Config::Dir.db = @db
|
37
|
+
require "m2config/route"
|
38
|
+
M2Config::Route.db = @db
|
39
|
+
require "m2config/proxy"
|
40
|
+
M2Config::Proxy.db = @db
|
41
|
+
require "m2config/handler"
|
42
|
+
M2Config::Handler.db = @db
|
43
|
+
require "m2config/setting"
|
44
|
+
M2Config::Setting.db = @db
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_server( settings = {} )
|
48
|
+
srv = Server.new settings
|
49
|
+
end
|
50
|
+
|
51
|
+
def []=( k, v )
|
52
|
+
Setting.new k, v
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/m2config.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'm2config/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "m2config"
|
8
|
+
spec.version = M2Config::VERSION
|
9
|
+
spec.authors = ["Arnaud Meuret"]
|
10
|
+
spec.email = ["arnaud@meuret.net"]
|
11
|
+
spec.description = %q{A library to easily manage a Mongrel2 configuration database}
|
12
|
+
spec.summary = %q{Manage your Mongrel2 configuration database using handy model classes that map Servers, Hosts, Routes, Directories, Proxies, Handlers and Settings}
|
13
|
+
spec.homepage = "https://github.com/ameuret/m2config"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "sqlite3"
|
21
|
+
spec.add_dependency "sequel"
|
22
|
+
spec.add_dependency "uuid"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
data/sample/full.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "m2config"
|
2
|
+
|
3
|
+
include M2Config
|
4
|
+
|
5
|
+
cfg = M2Config::Config.new
|
6
|
+
server = Server.new
|
7
|
+
exComHost = Host.new({matching:"example.com"})
|
8
|
+
pubDir = Dir.new({base:"/public"})
|
9
|
+
pubRoute = Route.new( {path:"/", target:pubDir} )
|
10
|
+
appHand = Handler.new({ send_spec:"tcp://10.0.0.1:8989",
|
11
|
+
recv_spec:"tcp://10.0.0.1:9898",
|
12
|
+
send_ident: "dev.example.com ID" })
|
13
|
+
appRoute = Route.new( {path:"/blog", target:appHand} )
|
14
|
+
|
15
|
+
exComHost.add_route appRoute
|
16
|
+
exComHost.add_route pubRoute
|
17
|
+
|
18
|
+
cfg["extra"] = 64
|
19
|
+
|
20
|
+
server.add_host exComHost
|
data/spec/dir_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
4
|
+
|
5
|
+
describe M2Config::Dir do
|
6
|
+
before(:each) do
|
7
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
8
|
+
@cfg = M2Config::Config.new
|
9
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
10
|
+
@db.results_as_hash = true
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
@db.close if @db && !@db.closed?
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "::new" do
|
18
|
+
it "needs to know the base path to handle" do
|
19
|
+
M2Config::Dir.new({base:"/images"})
|
20
|
+
res= @db.get_first_row("SELECT * FROM directory;")
|
21
|
+
res["base"].should eq("/images")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defaults to application/octet-stream for the default content type" do
|
25
|
+
M2Config::Dir.new({base:"/images"})
|
26
|
+
res= @db.get_first_row("SELECT * FROM directory;")
|
27
|
+
res["default_ctype"].should eq("application/octet-stream")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "defaults to index.html for the index file" do
|
31
|
+
dir = M2Config::Dir.new({base:"/"})
|
32
|
+
res= @db.get_first_row("SELECT * FROM directory;")
|
33
|
+
res["index_file"].should eq("index.html")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#type' do
|
38
|
+
it 'returns its type' do
|
39
|
+
M2Config::Dir.new({base:"/"}).type.should eq("dir")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/env.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "env"
|
3
|
+
|
4
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
5
|
+
|
6
|
+
describe M2Config::Handler do
|
7
|
+
before(:each) do
|
8
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
9
|
+
@cfg = M2Config::Config.new
|
10
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
11
|
+
@db.results_as_hash = true
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@db.close if @db && !@db.closed?
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "::new" do
|
19
|
+
it "needs the ØMQ addresses and a send identifier" do
|
20
|
+
M2Config::Handler.new({ send_spec:"tcp://10.0.0.1:8989",
|
21
|
+
recv_spec:"tcp://10.0.0.1:9898",
|
22
|
+
send_ident: "dev.example.com ID"})
|
23
|
+
res = @db.get_first_row("SELECT * FROM handler;")
|
24
|
+
res["send_spec"].should eq("tcp://10.0.0.1:8989")
|
25
|
+
res["recv_spec"].should eq("tcp://10.0.0.1:9898")
|
26
|
+
res["send_ident"].should eq("dev.example.com ID")
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "helps you spot common mistakes" do
|
30
|
+
it "yells when the addresses are the same" do
|
31
|
+
expect do
|
32
|
+
M2Config::Handler.new({send_spec:"tcp://10.0.0.1:8989", recv_spec:"tcp://10.0.0.1:8989", send_ident: "dev.example.com ID"})
|
33
|
+
end.to raise_exception(ArgumentError, /send and receive endpoints can not be the same/i)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#type' do
|
39
|
+
it 'returns its type' do
|
40
|
+
M2Config::Handler.new({send_spec:"tcp://10.0.0.1:8988", recv_spec:"tcp://10.0.0.1:8989", send_ident: "dev.example.com ID"}).type.should eq("handler")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/host_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
4
|
+
|
5
|
+
describe M2Config::Host do
|
6
|
+
before(:each) do
|
7
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
8
|
+
@cfg = M2Config::Config.new
|
9
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
10
|
+
@db.results_as_hash = true
|
11
|
+
@srv = @cfg.add_server
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@db.close if @db && !@db.closed?
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "::new" do
|
19
|
+
it "needs to know the domain name served" do
|
20
|
+
M2Config::Host.new({matching:"example.com"})
|
21
|
+
res = @db.get_first_row("SELECT * FROM host;")
|
22
|
+
res["matching"].should eq("example.com")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can use the uuid of a server" do
|
26
|
+
host = M2Config::Host.new({matching:"example.com", srvUuid: @srv.uuid})
|
27
|
+
res = @db.get_first_row("SELECT * FROM host WHERE id=?;", host.id)
|
28
|
+
res["server_id"].should eq(@srv.id)
|
29
|
+
res["matching"].should eq("example.com")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can use a server instance" do
|
33
|
+
host = M2Config::Host.new({matching:"example.com", srv: @srv})
|
34
|
+
res = @db.get_first_row("SELECT * FROM host WHERE id=?;", host.id)
|
35
|
+
res["server_id"].should eq(@srv.id)
|
36
|
+
res["matching"].should eq("example.com")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#add_route" do
|
41
|
+
it "activates a route (can be done using Route#host= too)" do
|
42
|
+
host = M2Config::Host.new({matching:"example.com"})
|
43
|
+
dirH = M2Config::Dir.new({base: "/static"})
|
44
|
+
dirR = M2Config::Route.new({path:"/blog", target: dirH})
|
45
|
+
host.add_route dirR
|
46
|
+
res = @db.get_first_row("SELECT * FROM route;")
|
47
|
+
res["host_id"].should eq(host.id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
TABLES = %w(directory handler host log mimetype proxy route server setting statistic)
|
4
|
+
|
5
|
+
File.delete EXISTING_DB_NAME rescue nil
|
6
|
+
emptyDB = SQLite3::Database.new EXISTING_DB_NAME
|
7
|
+
|
8
|
+
describe M2Config do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
12
|
+
File.delete CUSTOM_DB_NAME rescue nil
|
13
|
+
@cfg = M2Config::Config.new
|
14
|
+
end
|
15
|
+
|
16
|
+
after(:each) do
|
17
|
+
@db.close if @db && !@db.closed?
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates a default database when name absent' do
|
21
|
+
File.should exist DEFAULT_DB_NAME
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can create the database in a specific file' do
|
25
|
+
@cfg = M2Config::Config.new CUSTOM_DB_NAME
|
26
|
+
File.should exist CUSTOM_DB_NAME
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'learns the DB schema from the official schema dump' do
|
30
|
+
for table in TABLES do
|
31
|
+
M2Config::Config.tables.should include table
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'creates a valid database structure' do
|
36
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
37
|
+
for table in M2Config::Config.tables do
|
38
|
+
expect {@db.execute("SELECT * FROM #{table};")}.to_not raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not change the schema if the database file pre-exists' do
|
43
|
+
@cfg = M2Config::Config.new EXISTING_DB_NAME
|
44
|
+
expect {emptyDB.execute("SELECT * FROM server;")}.to raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#[]=' do
|
48
|
+
|
49
|
+
it 'creates or modifies the value of a setting' do
|
50
|
+
db = SQLite3::Database.new DEFAULT_DB_NAME
|
51
|
+
db.results_as_hash = true
|
52
|
+
@cfg["zeromq.threads"] = 8
|
53
|
+
res = db.get_first_row("SELECT * FROM setting WHERE key=?;", "zeromq.threads")
|
54
|
+
res["value"].should eq("8")
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
data/spec/proxy_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
4
|
+
|
5
|
+
describe M2Config::Proxy do
|
6
|
+
before(:each) do
|
7
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
8
|
+
@cfg = M2Config::Config.new
|
9
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
10
|
+
@db.results_as_hash = true
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
@db.close if @db && !@db.closed?
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "::new" do
|
18
|
+
it "needs an address and a port number" do
|
19
|
+
M2Config::Proxy.new({addr:"legacy.local", port: 8080})
|
20
|
+
res= @db.get_first_row("SELECT * FROM proxy;")
|
21
|
+
res["addr"].should eq("legacy.local")
|
22
|
+
res["port"].should eq(8080)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#type' do
|
27
|
+
it 'returns its type' do
|
28
|
+
M2Config::Proxy.new({addr:"legacy.local", port: 8080}).type.should eq("proxy")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/route_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
4
|
+
|
5
|
+
describe M2Config::Route do
|
6
|
+
before(:each) do
|
7
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
8
|
+
@cfg = M2Config::Config.new
|
9
|
+
@dirH = M2Config::Dir.new({base: "/static"})
|
10
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
11
|
+
@db.results_as_hash = true
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@db.close if @db && !@db.closed?
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "::new" do
|
19
|
+
it "needs to know the path pattern and the target handler" do
|
20
|
+
M2Config::Route.new({path:"/blog", target: @dirH})
|
21
|
+
res = @db.get_first_row("SELECT * FROM route;")
|
22
|
+
res["path"].should eq("/blog")
|
23
|
+
res["target_id"].should eq(@dirH.id)
|
24
|
+
res["target_type"].should eq(@dirH.type)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#host=" do
|
30
|
+
it "can be used if the host is not known at creation" do
|
31
|
+
host = M2Config::Host.new({matching:"example.com"})
|
32
|
+
r = M2Config::Route.new({path:"/blog", target: @dirH})
|
33
|
+
r.host = host.id
|
34
|
+
res = @db.get_first_row("SELECT * FROM route;")
|
35
|
+
res["host_id"].should eq(host.id)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can take a Host instance" do
|
39
|
+
host = M2Config::Host.new({matching:"example.com"})
|
40
|
+
r = M2Config::Route.new({path:"/blog", target: @dirH})
|
41
|
+
r.host = host
|
42
|
+
res = @db.get_first_row("SELECT * FROM route;")
|
43
|
+
res["host_id"].should eq(host.id)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "env"
|
2
|
+
|
3
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
4
|
+
|
5
|
+
describe M2Config::Server do
|
6
|
+
before(:each) do
|
7
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
8
|
+
@cfg = M2Config::Config.new
|
9
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
10
|
+
@db.results_as_hash = true
|
11
|
+
@srv = M2Config::Server.new
|
12
|
+
@host = M2Config::Host.new({matching:"example.com"})
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each) do
|
16
|
+
@db.close if @db && !@db.closed?
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '::new' do # , {focus: true}
|
20
|
+
it 'creates a server entry with reasonable default settings' do
|
21
|
+
res= @db.get_first_row("SELECT * FROM server;")
|
22
|
+
res["access_log"].should eq(M2Config::Server::ACCESS_LOG)
|
23
|
+
res["error_log"].should eq(M2Config::Server::ERROR_LOG)
|
24
|
+
res["pid_file"].should eq(M2Config::Server::PID_FILE)
|
25
|
+
res["chroot"].should eq(M2Config::Server::CHROOT)
|
26
|
+
res["default_host"].should eq(M2Config::Server::DEFAULT_HOST)
|
27
|
+
res["name"].should eq(M2Config::Server::NAME)
|
28
|
+
res["bind_addr"].should eq(M2Config::Server::BIND_ADDR)
|
29
|
+
res["port"].should eq(M2Config::Server::PORT)
|
30
|
+
res["use_ssl"].should eq(M2Config::Server::USE_SSL)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#add_host (assigns the given host to the server)' do
|
36
|
+
it 'accepts an existing Host instance' do
|
37
|
+
@srv.add_host @host
|
38
|
+
res= @db.get_first_row("SELECT * FROM host WHERE id=?;", @host.id)
|
39
|
+
res["server_id"].should eq(@srv.id)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "env"
|
3
|
+
|
4
|
+
M2Config::Config.new # Dummy call to ensure that model classes are required (cf. M2Config::new)
|
5
|
+
|
6
|
+
describe M2Config::Setting do
|
7
|
+
before(:each) do
|
8
|
+
File.delete DEFAULT_DB_NAME rescue nil
|
9
|
+
@cfg = M2Config::Config.new
|
10
|
+
@db = SQLite3::Database.new DEFAULT_DB_NAME
|
11
|
+
@db.results_as_hash = true
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@db.close if @db && !@db.closed?
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "::new" do
|
19
|
+
it "stores the given value under the given key" do
|
20
|
+
M2Config::Setting.new("answer",42)
|
21
|
+
res = @db.get_first_row("SELECT * FROM setting;")
|
22
|
+
res["value"].should eq("42")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "updates the existing value if the given key is already present" do
|
26
|
+
M2Config::Setting.new("answer",41)
|
27
|
+
M2Config::Setting.new("answer",42)
|
28
|
+
res = @db.get_first_row("SELECT * FROM setting;")
|
29
|
+
res["value"].should eq("42")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: m2config
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Arnaud Meuret
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sqlite3
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sequel
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: uuid
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.3'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1.3'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: A library to easily manage a Mongrel2 configuration database
|
95
|
+
email:
|
96
|
+
- arnaud@meuret.net
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- Guardfile
|
104
|
+
- LICENSE
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/m2config.rb
|
108
|
+
- lib/m2config/dir.rb
|
109
|
+
- lib/m2config/handler.rb
|
110
|
+
- lib/m2config/host.rb
|
111
|
+
- lib/m2config/proxy.rb
|
112
|
+
- lib/m2config/route.rb
|
113
|
+
- lib/m2config/schema.sql
|
114
|
+
- lib/m2config/server.rb
|
115
|
+
- lib/m2config/setting.rb
|
116
|
+
- lib/m2config/version.rb
|
117
|
+
- m2config.gemspec
|
118
|
+
- sample/full.rb
|
119
|
+
- spec/dir_spec.rb
|
120
|
+
- spec/env.rb
|
121
|
+
- spec/handler_spec.rb
|
122
|
+
- spec/host_spec.rb
|
123
|
+
- spec/m2config_spec.rb
|
124
|
+
- spec/proxy_spec.rb
|
125
|
+
- spec/route_spec.rb
|
126
|
+
- spec/server_spec.rb
|
127
|
+
- spec/setting_spec.rb
|
128
|
+
homepage: https://github.com/ameuret/m2config
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
hash: -327752419
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
segments:
|
151
|
+
- 0
|
152
|
+
hash: -327752419
|
153
|
+
requirements: []
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 1.8.25
|
156
|
+
signing_key:
|
157
|
+
specification_version: 3
|
158
|
+
summary: Manage your Mongrel2 configuration database using handy model classes that
|
159
|
+
map Servers, Hosts, Routes, Directories, Proxies, Handlers and Settings
|
160
|
+
test_files:
|
161
|
+
- spec/dir_spec.rb
|
162
|
+
- spec/env.rb
|
163
|
+
- spec/handler_spec.rb
|
164
|
+
- spec/host_spec.rb
|
165
|
+
- spec/m2config_spec.rb
|
166
|
+
- spec/proxy_spec.rb
|
167
|
+
- spec/route_spec.rb
|
168
|
+
- spec/server_spec.rb
|
169
|
+
- spec/setting_spec.rb
|