rails-infrastructure 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.rdoc +80 -0
  8. data/Rakefile +7 -0
  9. data/examples/infrastructure/databases.yml +29 -0
  10. data/examples/infrastructure/environment.yml +2 -0
  11. data/examples/infrastructure/server.yml +9 -0
  12. data/examples/infrastructure/servers/unicorn.rb +69 -0
  13. data/examples/infrastructure/servers/unicorn.yml.erb +13 -0
  14. data/examples/infrastructure/version.yml +2 -0
  15. data/examples/infrastructure.yml +11 -0
  16. data/lib/infrastructure/configurable.rb +51 -0
  17. data/lib/infrastructure/configuration.rb +93 -0
  18. data/lib/infrastructure/constants.rb +5 -0
  19. data/lib/infrastructure/databases.rb +117 -0
  20. data/lib/infrastructure/environment.rb +16 -0
  21. data/lib/infrastructure/path.rb +7 -0
  22. data/lib/infrastructure/railtie.rb +68 -0
  23. data/lib/infrastructure/server.rb +7 -0
  24. data/lib/infrastructure/version.rb +23 -0
  25. data/lib/infrastructure.rb +25 -0
  26. data/lib/rails-infrastructure.rb +2 -0
  27. data/lib/tasks/databases.rake +148 -0
  28. data/lib/tasks/environment.rake +19 -0
  29. data/lib/tasks/server.rake +73 -0
  30. data/lib/tasks/version.rake +23 -0
  31. data/rails-infrastructure.gemspec +28 -0
  32. data/test/infrastructure/configurable_test.rb +94 -0
  33. data/test/infrastructure/configuration_test.yml.erb +5 -0
  34. data/test/infrastructure/database_test.rb +108 -0
  35. data/test/infrastructure/environment_test.rb +23 -0
  36. data/test/infrastructure/paths_test.rb +9 -0
  37. data/test/infrastructure/server_test.rb +9 -0
  38. data/test/infrastructure/version_test.rb +23 -0
  39. data/test/infrastructure_test.rb +26 -0
  40. data/test/test_helper.rb +2 -0
  41. metadata +163 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae39560352b96bff043a01081b3f177ef773939a
4
+ data.tar.gz: c047a2e92b7238608c753f7854bac01fcba115e6
5
+ SHA512:
6
+ metadata.gz: 78f4f9ee3fedc2482bc7ac0f5aca68d8896c75785b837a3187559681cffdbb1d9b27c7d2ffe6e0e4c4f8a45b12448e942fdccc9455fd708992d05955909bf85b
7
+ data.tar.gz: c3f63bece8638110c4045238aef75ec528fb710c113b9d7c3bd0f5f325023e8e2b9711084193122fe75fb17f7e943a9948aeacf2b7b590e36417221e52c53d9a
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ infrastructure
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails-infrastructure.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Griffith Chaffee
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,80 @@
1
+ = Rails::Infrastructure
2
+
3
+ This gem provides several much needed enhancements to the rails framework
4
+
5
+ 1. Multi database support and management
6
+ 2. Environment management
7
+ 3. Version managment
8
+ 4. Path managment
9
+ 5. Server management
10
+ 6. Useful configuration module mixin
11
+ 7. Rails configuration constant
12
+
13
+ = Getting Started
14
+
15
+ # Gemfile
16
+ gem 'rails-infrastructure'
17
+
18
+ Copy examples into config directory
19
+
20
+ # example layout
21
+ config/infrastructure.yml
22
+ config/infrastructure/version.yml
23
+ config/infrastructure/environment.yml
24
+ config/infrastructure/server.yml
25
+ config/infrastructure/servers/unicorn.yml.erb
26
+ ...
27
+
28
+ == Muli Database Support
29
+
30
+ Infrastructure::Databases
31
+
32
+ This class provides all the required functions for connecting and working with multiple databases through ActiveRecord. There several rake tasks preconfigured to replace their rails countarparts.
33
+
34
+ rake database:create[id] # Create database if it does not exist
35
+ rake database:drop[id,force] # Drop database if exists
36
+ rake database:migrate[id,version] # Migrate database
37
+ rake database:reset[id,force] # Drop, create, then migrate database
38
+ rake database:reset:seed[force] # Reset then seed database
39
+ rake database:rollback[id,version] # Rollback database
40
+ rake database:seed[id] # Seed database
41
+ rake databases:create # Create all databases that dont exist
42
+ rake databases:drop[force] # Drop all databases that exist
43
+ rake databases:migrate[version] # Migrate all databases
44
+ rake databases:reset[force] # Drop, create, migrate all databases
45
+ rake databases:reset:seed[force] # Reset then seed all databases
46
+ rake databases:rollback[version] # Rollback all databases
47
+ rake databases:seed[force] # Seed all databases
48
+
49
+ == Environment Management
50
+
51
+ Infrastructure::Environment
52
+
53
+ rake environment:current # display current environment
54
+ rake environment:development # Change to development environment
55
+ rake environment:production # Change to production environment
56
+ rake environment:test # Change to test environment
57
+
58
+ == Version Management
59
+
60
+ Infrastructure::Version
61
+
62
+ rake version:bump:major # Bump major version
63
+ rake version:bump:minor # Bump minor version
64
+ rake version:bump:tiny # Bump tiny version
65
+ rake version:current # display current version
66
+
67
+ == Server Management
68
+
69
+ Infrastructure::Server
70
+
71
+ rake server:unicorn:kill # Kill unicorn server
72
+ rake server:unicorn:restart # Restart unicorn server
73
+ rake server:unicorn:start # Start unicorn server
74
+ rake server:unicorn:stop # Stop unicorn server
75
+ rake server:unicorn:tail # Tail unicorn server log file
76
+
77
+ == Path Management
78
+
79
+ Infrastructure::Path
80
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ end
@@ -0,0 +1,29 @@
1
+ ---
2
+ system:
3
+ database: postgres
4
+
5
+ defaults:
6
+ adapter: postgresql
7
+ encoding: unicode
8
+ username: root
9
+ password: toor
10
+ pool: 5
11
+ host: localhost
12
+
13
+ test:
14
+ defaults:
15
+ id: test
16
+ test: {}
17
+
18
+ development:
19
+ defaults:
20
+ id: dev1
21
+ dev1: {}
22
+ dev2: {}
23
+
24
+ production:
25
+ defaults:
26
+ id: demo
27
+ demo: {}
28
+ best: {}
29
+ other: {}
@@ -0,0 +1,2 @@
1
+ ---
2
+ environment: development
@@ -0,0 +1,9 @@
1
+ ---
2
+ defaults:
3
+ daemonize: true
4
+ port: 8080
5
+ interface: 0.0.0.0
6
+ kill_signal: TERM
7
+
8
+ servers:
9
+ - unicorn
@@ -0,0 +1,69 @@
1
+ require File.expand_path('../../../application', __FILE__)
2
+
3
+ config = Inf.server.unicorn
4
+
5
+ # workers
6
+ worker_processes config.workers
7
+
8
+ # worker response timeout
9
+ timeout config.timeout
10
+
11
+ # iisten on interface
12
+ listen "#{config.interface}:#{config.port}", backlog: config.backlog
13
+ # listen on socket
14
+ listen config.socket_file, backlog: config.backlog
15
+ # pid file
16
+ pid config.pid_file
17
+
18
+ # logs
19
+ stderr_path = config.log_file
20
+ stdout_path = config.log_file
21
+ logger = Logger.new config.log_file
22
+ logger logger
23
+
24
+ # general
25
+ check_client_connection false
26
+ preload_app true
27
+
28
+ if GC.respond_to?(:copy_on_write_friendly=)
29
+ GC.copy_on_write_friendly = true
30
+ end
31
+
32
+ before_fork do |server, worker|
33
+ ActiveRecord::Base.connection.disconnect!
34
+ old_pid_file = config.pid_file + '.oldbin'
35
+ if File.exists? old_pid_file
36
+ begin
37
+ Process.kill 'QUIT', File.read(old_pid_file).strip.to_i
38
+ rescue Errno::ENOENT, Errno::ESRCH
39
+ end
40
+ end
41
+ end
42
+
43
+ after_fork do |server, worker|
44
+ ActiveRecord::Base.establish_connection
45
+ begin
46
+ uid, gid = Process.euid, Process.egid
47
+ user config.user, config.group
48
+ target_uid = Etc.getpwnam(config.user).uid
49
+ target_gid = Etc.getgrnam(config.group).gid
50
+ worker.tmp.chown target_uid, target_gid
51
+ if uid != target_uid || gid != target_gid
52
+ Process.initgroups config.user, target_gid
53
+ Process::GID.change_privilege target_gid
54
+ Process::UID.change_privilege target_uid
55
+ end
56
+ rescue ArgumentError => error
57
+ if error.message.include? "can't find user"
58
+ unless Rails.env.production?
59
+ logger.info { "Could not change to user/group #{config.user}:#{config.group} but ignoring because environment is not production" }
60
+ else
61
+ logger.fatal { "Could not change to user/group #{config.user}:#{config.group}" }
62
+ Process.kill 'QUIT', server.pid.to_i
63
+ end
64
+ else
65
+ logger.fatal { "#{error.class}: #{error.message}\n" + error.backtrace.join("\n") }
66
+ Process.kill 'QUIT', server.pid.to_i
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ ---
2
+ config_file: <%= Inf.path.rails.infrastructure_servers_dir + '/unicorn.rb' %>
3
+ socket_file: <%= Inf.path.rails.tmp_sockets_dir + '/unicorn.sock' %>
4
+ pid_file: <%= Inf.path.rails.tmp_pids_dir + '/unicorn.pid' %>
5
+ log_file: <%= Inf.path.rails.log_dir + "/unicorn.#{Inf.environment.to_s}.log" %>
6
+ workers: <%= Inf.environment.production? ? 16 : 4 %>
7
+ user: unicorn
8
+ group: unicorn
9
+ timeout: 15
10
+ backlog: 1024
11
+ stop: kill
12
+ stop_signal: QUIT
13
+ start: unicorn_rails -c <%= Inf.path.rails.infrastructure_servers_dir + '/unicorn.rb' %> -D
@@ -0,0 +1,2 @@
1
+ ---
2
+ version: 2.1.3
@@ -0,0 +1,11 @@
1
+ ---
2
+ domain: my-domain.com
3
+ fruits:
4
+ - Apple
5
+ - Blueberry
6
+ - Grape
7
+ regex:
8
+ key: /\A[a-z0-9][a-z0-9_]+[a-z0-9]\z/
9
+ validation:
10
+ format:
11
+ message: is not in the correct format
@@ -0,0 +1,51 @@
1
+ class Infrastructure
2
+ module Configurable
3
+
4
+ def self.included(base)
5
+ base.extend Forwardable
6
+ base.send :def_delegators, :configuration, :assign, :fetch, :configure, :each
7
+ base.send :def_delegators, :configuration, :load_config, :load_config_if_exists, :save_config
8
+ end
9
+
10
+ def configuration
11
+ @configuration ||= Configuration.new self
12
+ end
13
+
14
+ def callback(key, *params, &block)
15
+ callbacks[key] << block if block
16
+ callbacks[key] += Array(params)
17
+ end
18
+
19
+ def callbacks
20
+ @callbacks ||= {
21
+ before_configure: [],
22
+ after_configure: [],
23
+ before_assignment: [
24
+ -> (key, value) { configuration_accessor key unless respond_to? key }
25
+ ],
26
+ after_assignment: []
27
+ }
28
+ end
29
+
30
+ def configuration_accessor(key)
31
+ self.class.send(:define_method, key) { configuration.send(key) }
32
+ end
33
+
34
+ def before_assignment(*params)
35
+ callbacks[:before_assignment].each { |block| block.call *params }
36
+ end
37
+
38
+ def after_assignment(*params)
39
+ callbacks[:after_assignment].each { |block| block.call *params }
40
+ end
41
+
42
+ def before_configure(*params)
43
+ callbacks[:before_configure].each { |block| block.call *params }
44
+ end
45
+
46
+ def after_configure(*params)
47
+ callbacks[:after_configure].each { |block| block.call *params }
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,93 @@
1
+ class Infrastructure
2
+ class Configuration
3
+ attr_reader :attributes
4
+
5
+ def initialize(base, config = {})
6
+ @base = base
7
+ @attributes = Hash.new
8
+ assign config
9
+ end
10
+
11
+ def configure(&block)
12
+ raise "configure expects a block" unless block
13
+ before_configure
14
+ instance_eval &block
15
+ after_configure
16
+ end
17
+
18
+ def config
19
+ self
20
+ end
21
+
22
+ def load_config_if_exists(path_to_config_file, &block)
23
+ if File.exists? path_to_config_file
24
+ load_config path_to_config_file, &block
25
+ end
26
+ end
27
+
28
+ def load_config(path_to_config_file, &block)
29
+ assign YAML.load(ERB.new(File.read(path_to_config_file)).result)
30
+ block.call if block
31
+ end
32
+
33
+ def save_config(path_to_config_file)
34
+ File.open(path_to_config_file, 'w') do |file|
35
+ file.write to_h(stringify_keys: true).to_yaml
36
+ end
37
+ end
38
+
39
+ def to_h(params = {})
40
+ attributes = @attributes.dup
41
+ if params[:stringify_keys]
42
+ attributes.keys.each { |key| attributes[key.to_s] = attributes.delete(key) unless key.is_a?(String) }
43
+ attributes.each { |key, value| attributes[key] = value.to_h(params) if value.is_a? Configuration }
44
+ else
45
+ attributes.each { |key, value| attributes[key] = value.to_h(params) if value.is_a? Configuration }
46
+ end
47
+ end
48
+
49
+ def fetch(key)
50
+ @attributes[key.to_sym]
51
+ end
52
+
53
+ def before_configure(*params)
54
+ @base.before_configure *params
55
+ end
56
+
57
+ def after_configure(*params)
58
+ @base.after_configure *params
59
+ end
60
+
61
+ def before_assignment(*params)
62
+ @base.before_assignment *params
63
+ end
64
+
65
+ def after_assignment(*params)
66
+ @base.after_assignment *params
67
+ end
68
+
69
+ def assign(key, value = nil)
70
+ if key.is_a?(Hash)
71
+ key.each { |k,v| assign k, v }
72
+ else
73
+ key = key.to_sym
74
+ before_assignment key, value
75
+ @attributes[key] = value.is_a?(Hash) ? Configuration.new(self, value) : value
76
+ after_assignment key, value
77
+ end
78
+ end
79
+
80
+ def method_missing(method, *params, &block)
81
+ if @attributes.keys.include? method
82
+ fetch method
83
+ elsif method.to_s.end_with? '='
84
+ assign method.to_s[0..-2], params.first
85
+ elsif @attributes.respond_to? method
86
+ @attributes.send method, *params, &block
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ end
93
+ end