m2config 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :dev do
6
+ gem 'guard'
7
+ gem 'rb-inotify'
8
+ gem 'rspec'
9
+ gem 'guard-rspec'
10
+ gem "libnotify"
11
+ end
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"
@@ -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,15 @@
1
+ module M2Config
2
+ class Proxy < Sequel::Model(:proxy)
3
+ plugin :validation_helpers
4
+
5
+ def initialize( fields )
6
+ super(fields, false)
7
+ save
8
+ end
9
+
10
+ def type
11
+ "proxy"
12
+ end
13
+
14
+ end
15
+ 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
@@ -0,0 +1,3 @@
1
+ module M2Config
2
+ VERSION = "0.1.0"
3
+ 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,8 @@
1
+ require "bundler/setup"
2
+ require "m2config" # rspec automatically adds ./lib to LOAD_PATH
3
+ require "sqlite3"
4
+ require "pp"
5
+
6
+ DEFAULT_DB_NAME = "config.sqlite"
7
+ CUSTOM_DB_NAME = "custom.sqlite"
8
+ EXISTING_DB_NAME = "empty.sqlite"
@@ -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
+
@@ -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
@@ -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
@@ -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