ors 0.0.1

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.
data/.autotest ADDED
@@ -0,0 +1,3 @@
1
+ Autotest.add_hook(:initialize) do |autotest|
2
+ autotest.add_mapping(%r{^lib/ors/.*\.rb$}) { autotest.files_matching %r{^spec/.*\.rb} }
3
+ end
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.swp
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler"
2
+
3
+ Bundler::GemHelper.install_tasks
data/bin/ors ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + "/../lib")
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) and (not $LOAD_PATH.include? lib)
5
+
6
+ require "ors"
7
+
8
+ ORS::Command.run ARGV
@@ -0,0 +1,40 @@
1
+ require "ors/commands/base"
2
+ Dir[File.join File.dirname(__FILE__), "commands", "*.rb"].each { |c| require c }
3
+
4
+ module ORS
5
+
6
+ class Command
7
+
8
+ module ClassMethods
9
+
10
+ include ORS::Commands
11
+
12
+ def run args
13
+ command, *options = args
14
+ klass = command.to_s.capitalize
15
+
16
+ if available_commands.include? klass
17
+ ORS::Config.parse_options options
18
+
19
+ if ORS::Config.valid_options?
20
+ Base.run ORS::Commands.const_get(klass)
21
+ else
22
+ Base.run Help
23
+ end
24
+ else
25
+ Base.run Help
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def available_commands
32
+ ORS::Commands.constants.map {|klass| klass.to_s }
33
+ end
34
+
35
+ end
36
+ extend ClassMethods
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,18 @@
1
+ module ORS::Commands
2
+ class Base
3
+ include ORS::Helpers
4
+
5
+ module ClassMethods
6
+ def run klass
7
+ klass.new.execute
8
+ end
9
+ end
10
+ extend ClassMethods
11
+
12
+ def run klass
13
+ self.class.run klass
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,24 @@
1
+ module ORS::Commands
2
+ class Console < Base
3
+ def execute
4
+ execute_command console_server,
5
+ %(source ~/.rvm/scripts/rvm),
6
+ %(cd #{deploy_directory}),
7
+ %(if [ -f script/rails ]; then bundle exec rails console #{environment}; else ./script/console #{environment}; fi),
8
+ :exec => true
9
+ end
10
+
11
+ def help
12
+ puts <<-END
13
+ Usage: ./ors console [environment=production] [options]
14
+
15
+ === Description
16
+ Replaces current process and runs rails console.
17
+
18
+ === Options
19
+ --pretend (or -p) Don't execute anything, just show me what you're going to do
20
+ --no-gateway (or -ng) Don't use a gateway (if you're inside the firewall)
21
+ END
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module ORS::Commands
2
+
3
+ class Deploy < Base
4
+
5
+ def execute
6
+ info "deploying #{name} #{environment}..."
7
+
8
+ [Update, Migrate, Restart].each {|command| run command }
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,32 @@
1
+ module ORS::Commands
2
+
3
+ class Help < Base
4
+
5
+ def execute
6
+ puts <<-END
7
+ Usage: ./ors <action> [environment=production] [options]
8
+
9
+ === Actions
10
+ help You're looking at it
11
+ console Bring up a console on the production servers
12
+ logs Show the last few log entries from the production servers
13
+ deploy Update the code, run the migrations, and restart unicorn
14
+ setup Sets up the default environment on the servers
15
+ update Updates the code on all servers
16
+ migrate Runs the migrations on the migration server
17
+ start Starts up unicorn on the app servers
18
+ stop Stops unicorn on the app servers
19
+ restart Retarts unicorn on the app servers
20
+
21
+ === Environments
22
+ Must be one of: production demo staging
23
+ Defaults to production.
24
+
25
+ === Options
26
+ --pretend (or -p) Don't execute anything, just show me what you're going to do (default: false)
27
+ --no-gateway (or -ng) Don't use a gateway (if you're inside the firewall) (default: true)
28
+ END
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module ORS::Commands
2
+ class Logs < Base
3
+
4
+ def execute
5
+ all_logs = app_servers.map do |server|
6
+ [
7
+ server,
8
+ execute_command(server,
9
+ %(cd #{deploy_directory}),
10
+ %(tail -n #{log_lines} log/#{environment}.log),
11
+ :capture => true)
12
+ ]
13
+ end
14
+
15
+ puts ORS::LogUnifier.new(all_logs).unify unless pretending
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module ORS::Commands
2
+
3
+ class Migrate < Base
4
+
5
+ def execute
6
+ info "migrating #{name} #{environment}..."
7
+
8
+ run_migrations migration_server
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ module ORS::Commands
2
+
3
+ class Restart < Base
4
+
5
+ def execute
6
+ info "restarting #{name} #{environment}..."
7
+
8
+ execute_in_parallel(app_servers) {|server| restart_server server }
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,18 @@
1
+ module ORS::Commands
2
+
3
+ class Setup < Base
4
+
5
+ def execute
6
+ info "setting up #{name} #{environment}..."
7
+
8
+ execute_in_parallel(all_servers) {|server| setup_repo server }
9
+ execute_in_parallel(ruby_servers) {|server| setup_ruby server }
10
+
11
+ execute_command migration_server, %(source ~/.rvm/scripts/rvm),
12
+ %(cd #{deploy_directory}),
13
+ %(RAILS_ENV=#{environment} rake db:create)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,13 @@
1
+ module ORS::Commands
2
+
3
+ class Start < Base
4
+
5
+ def execute
6
+ info "starting #{name} #{environment}..."
7
+
8
+ execute_in_parallel(app_servers) {|server| start_server server }
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,13 @@
1
+ module ORS::Commands
2
+
3
+ class Stop < Base
4
+
5
+ def execute
6
+ info "stopping #{name} #{environment}..."
7
+
8
+ execute_in_parallel(app_servers) {|server| stop_server server }
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ module ORS::Commands
2
+
3
+ class Update < Base
4
+
5
+ def execute
6
+ info "updating #{name} #{environment}..."
7
+
8
+ execute_in_parallel(all_servers) {|server| update_code server }
9
+ execute_in_parallel(ruby_servers) {|server| bundle_install server }
10
+ end
11
+
12
+ end
13
+
14
+ end
data/lib/ors/config.rb ADDED
@@ -0,0 +1,97 @@
1
+ module ORS
2
+ module Config
3
+
4
+ mattr_accessor :name, :environment, :use_gateway, :pretending, :log_lines
5
+
6
+ self.environment = "production"
7
+ self.pretending = false
8
+ self.use_gateway = true
9
+ self.log_lines = 100
10
+
11
+ module ModuleMethods
12
+
13
+ def parse_options options
14
+ self.name = name_from_git
15
+ self.environment = options.shift unless options.empty? or options.first.match(/^-/)
16
+
17
+ options.each do |option|
18
+ case option
19
+ when "-p", "--pretend" then self.pretending = true
20
+ when "-ng", "--no-gateway" then self.use_gateway = false
21
+ end
22
+ end
23
+ end
24
+
25
+ def valid_options?
26
+ name.to_s.size > 0 and valid_environments.include?(environment)
27
+ end
28
+
29
+ def valid_environments
30
+ %w(production demo staging)
31
+ end
32
+
33
+ private
34
+
35
+ def name_from_git
36
+ git.config["remote.origin.url"].gsub /.*?:(.*?).git/, '\1'
37
+ end
38
+
39
+ def git
40
+ @git ||= Git.open(Dir.pwd)
41
+ end
42
+
43
+ end
44
+ extend ModuleMethods
45
+
46
+ def gateway
47
+ "deploy-gateway"
48
+ end
49
+
50
+ def deploy_user
51
+ "deployer"
52
+ end
53
+
54
+ def repo
55
+ "ors_git"
56
+ end
57
+
58
+ def base_path
59
+ "/var/www"
60
+ end
61
+
62
+ def web_servers
63
+ %w(koala)
64
+ end
65
+
66
+ def app_servers
67
+ %w(eel jellyfish squid)
68
+ end
69
+
70
+ def migration_server
71
+ "tuna"
72
+ end
73
+
74
+ def console_server
75
+ "tuna"
76
+ end
77
+
78
+ def ruby_servers
79
+ app_servers + [migration_server]
80
+ end
81
+
82
+ def all_servers
83
+ web_servers + app_servers + [migration_server]
84
+ end
85
+
86
+ def deploy_directory
87
+ directory = File.join base_path, name
88
+
89
+ if environment == "production"
90
+ directory
91
+ else
92
+ "#{directory}_#{environment}"
93
+ end
94
+ end
95
+
96
+ end
97
+ end
@@ -0,0 +1,53 @@
1
+ # copied from activesupport
2
+ class Module
3
+ def mattr_reader(*syms)
4
+ syms.each do |sym|
5
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
6
+ @@#{sym} = nil unless defined? @@#{sym}
7
+
8
+ def self.#{sym}
9
+ @@#{sym}
10
+ end
11
+ EOS
12
+
13
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
14
+ def #{sym}
15
+ @@#{sym}
16
+ end
17
+ EOS
18
+ end
19
+ end
20
+
21
+ def mattr_writer(*syms)
22
+ syms.each do |sym|
23
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
24
+ def self.#{sym}=(obj)
25
+ @@#{sym} = obj
26
+ end
27
+ EOS
28
+
29
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
30
+ def #{sym}=(obj)
31
+ @@#{sym} = obj
32
+ end
33
+ EOS
34
+ end
35
+ end
36
+
37
+ # Extends the module object with module and instance accessors for class attributes,
38
+ # just like the native attr* accessors for instance attributes.
39
+ #
40
+ # module AppConfiguration
41
+ # mattr_accessor :google_api_key
42
+ # self.google_api_key = "123456789"
43
+ #
44
+ # mattr_accessor :paypal_url
45
+ # self.paypal_url = "www.sandbox.paypal.com"
46
+ # end
47
+ #
48
+ # AppConfiguration.google_api_key = "overriding the api key!"
49
+ def mattr_accessor(*syms)
50
+ mattr_reader(*syms)
51
+ mattr_writer(*syms)
52
+ end
53
+ end
@@ -0,0 +1,137 @@
1
+ module ORS
2
+ module Helpers
3
+
4
+ include Config
5
+
6
+ def setup_repo server
7
+ info "[#{server}] installing codebase..."
8
+
9
+ execute_command server, %(cd #{base_path}),
10
+ %(rm -rf #{deploy_directory}),
11
+ %(git clone #{REPO}:#{name} #{deploy_directory}),
12
+ %(mkdir -p #{deploy_directory}/tmp/pids),
13
+ %(mkdir -p #{deploy_directory}/log)
14
+ end
15
+
16
+ def setup_ruby server
17
+ info "[#{server}] installing ruby and gems..."
18
+
19
+ execute_command server, %(source ~/.rvm/scripts/rvm),
20
+ %(cd #{deploy_directory}),
21
+ %(gem install rubygems-update),
22
+ %(gem update --system),
23
+ %(gem install bundler),
24
+ %(bundle install --without development test osx > bundler.log)
25
+ end
26
+
27
+ def update_code server
28
+ info "[#{server}] updating codebase..."
29
+
30
+ execute_command server, %(cd #{deploy_directory}),
31
+ %(git fetch),
32
+ %(git checkout -q -f origin/#{environment}),
33
+ %(git reset --hard)
34
+ end
35
+
36
+ def bundle_install server
37
+ info "[#{server}] installing bundle..."
38
+
39
+ execute_command server, %(source ~/.rvm/scripts/rvm),
40
+ %(cd #{deploy_directory}),
41
+ %(bundle install --without development test osx > bundler.log)
42
+ end
43
+
44
+ def start_server server
45
+ info "[#{server}] starting unicorn..."
46
+
47
+ execute_command server, %(source ~/.rvm/scripts/rvm),
48
+ %(cd #{deploy_directory}),
49
+ %(bundle exec #{unicorn} -c config/unicorn.rb -D -E #{environment})
50
+ end
51
+
52
+ def stop_server server
53
+ info "[#{server}] stopping unicorn..."
54
+
55
+ execute_command server, %(cd #{deploy_directory}),
56
+ %(kill \\`cat tmp/pids/unicorn.pid\\`)
57
+ end
58
+
59
+ def restart_server server
60
+ info "[#{server}] restarting unicorn..."
61
+
62
+ execute_command server, %(cd #{deploy_directory}),
63
+ %(kill -USR2 \\`cat tmp/pids/unicorn.pid\\`)
64
+ end
65
+
66
+ def run_migrations server
67
+ info "[#{server}] running migrations..."
68
+
69
+ execute_command server, %(cd #{deploy_directory}),
70
+ %(RAILS_ENV=#{environment} rake db:migrate db:seed)
71
+ end
72
+
73
+ def execute_in_parallel servers
74
+ servers.map do |server|
75
+ Thread.new(server) do |server|
76
+ yield server
77
+ end
78
+ end.map {|thread| thread.join }
79
+ end
80
+
81
+ # options = {:exec => ?, :capture => ?}
82
+ def execute_command server, *command_array
83
+ options = {:exec => false, :capture => false}
84
+ options.merge!(command_array.pop) if command_array.last.is_a?(Hash)
85
+
86
+ command = build_command(server, command_array, options)
87
+
88
+ if pretending
89
+ info("[#{server}] #{command}")
90
+ else
91
+ if options[:exec]
92
+ exec command
93
+ else
94
+ results = `#{command}`
95
+ if options[:capture]
96
+ return results
97
+ else
98
+ results.split("\n").each do |result|
99
+ info("[#{server}] #{result}")
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def build_command server, *commands_and_maybe_options
107
+ return "" if commands_and_maybe_options.empty?
108
+
109
+ if commands_and_maybe_options.last.is_a?(Hash)
110
+ options = commands_and_maybe_options.pop
111
+ command_array = commands_and_maybe_options
112
+ else
113
+ command_array = commands_and_maybe_options
114
+ options = {}
115
+ end
116
+
117
+ commands = command_array.join " && "
118
+ psuedo_tty = options[:exec] ? '-t ' : ''
119
+
120
+ if use_gateway
121
+ %(ssh #{psuedo_tty}#{gateway} 'ssh #{psuedo_tty}#{deploy_user}@#{server} "#{commands}"')
122
+ else
123
+ %(ssh #{psuedo_tty}#{deploy_user}@#{server} "#{commands}")
124
+ end
125
+ end
126
+
127
+ def info message
128
+ STDOUT.puts message
129
+ end
130
+
131
+ def fatal message
132
+ info message
133
+ exit 1
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,61 @@
1
+ module ORS
2
+
3
+ class LogUnifier
4
+
5
+ attr_reader :logs, :pretty_adjust
6
+
7
+ def initialize logs
8
+ @pretty_adjust = 0
9
+
10
+ @logs = logs.inject(Hash.new) do |hash, (server, log_rows)|
11
+ @pretty_adjust = [@pretty_adjust, server.length].max
12
+ hash[server] = log_rows
13
+ hash
14
+ end
15
+ end
16
+
17
+ def unify
18
+ group_by_entry.
19
+ select {|entry| entry[:timestamp].size == 14 }.
20
+ sort_by {|entry| entry[:timestamp] }.
21
+ map do |entry|
22
+ entry[:lines].
23
+ map {|line| ["[#{entry[:server]}]".ljust(pretty_adjust + 3), line].join }.
24
+ join "\n"
25
+ end.
26
+ flatten.
27
+ join("\n\n\n")
28
+ end
29
+
30
+ private
31
+
32
+ def group_by_entry
33
+ entries = Array.new
34
+
35
+ logs.each do |server, log_rows|
36
+ entry = {:lines => Array.new, :server => server}
37
+
38
+ log_rows.split(/\n/).each do |line|
39
+ if line == ""
40
+ unless entry[:lines].empty?
41
+ entries << entry
42
+ entry = {:lines => Array.new, :server => server}
43
+ end
44
+ else
45
+ if entry[:lines].empty?
46
+ entry[:timestamp] = line.gsub(/^(?:Processing|Started).*?(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*$/, '\1').gsub(/\D/, '')
47
+ end
48
+
49
+ entry[:lines] << line
50
+ end
51
+ end
52
+
53
+ entries << entry
54
+ end
55
+
56
+ entries
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,3 @@
1
+ module ORS
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ors.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "rubygems"
2
+ require "git"
3
+
4
+ require "ors/core_ext"
5
+ require "ors/log_unifier"
6
+ require "ors/config"
7
+ require "ors/helpers"
8
+ require "ors/command"
data/ors.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ors/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ors"
7
+ s.version = ORS::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jason Dew and John Long"]
10
+ s.email = ["jason.dew@ors.sc.gov and john.long@ors.sc.gov"]
11
+ s.homepage = ""
12
+ s.summary = %q{Heroku-like deployment utilities for ORS}
13
+ s.description = %q{Heroku-like deployment utilities for ORS}
14
+
15
+ s.rubyforge_project = "ors"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "git"
23
+
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "rr"
26
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Command do
4
+
5
+ subject { ORS::Command }
6
+
7
+ context ".run" do
8
+
9
+ it "should execute help when the command is help" do
10
+ mock(ORS::Commands::Help).new { mock!.execute.subject }
11
+ subject.run ["help"]
12
+ end
13
+
14
+ it "should execute help when no command is given" do
15
+ mock(ORS::Commands::Help).new { mock!.execute.subject }
16
+ subject.run []
17
+ end
18
+
19
+ it "should execute help when an unknown command is given" do
20
+ mock(ORS::Commands::Help).new { mock!.execute.subject }
21
+ subject.run ["as0d9fja0s9djf"]
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Commands::Base do
4
+
5
+ context ".run" do
6
+
7
+ it "should instantiate the command and call #execute on it" do
8
+ klass = mock!.new { mock!.execute.subject }.subject
9
+ ORS::Commands::Base.run klass
10
+ end
11
+
12
+ end
13
+
14
+ context "#run" do
15
+ it "should call the class method" do
16
+ mock(ORS::Commands::Base).run("Foo")
17
+ subject.run "Foo"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Commands::Console do
4
+
5
+ context "#run" do
6
+ it "should set pretending to true and call exec" do
7
+ stub(subject).name {'abc/growhealthy'}
8
+ stub(subject).environment {'production'}
9
+ mock(subject).execute_command(is_a(String), is_a(String), is_a(String), is_a(String), is_a(Hash)).returns("command")
10
+ subject.execute
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Commands::Deploy do
4
+
5
+ context "#execute" do
6
+
7
+ it "should call update, migrate, then restart" do
8
+ mock(subject).info /deploying/
9
+
10
+ mock(subject).run(ORS::Commands::Update)
11
+ mock(subject).run(ORS::Commands::Migrate)
12
+ mock(subject).run(ORS::Commands::Restart)
13
+
14
+ subject.execute
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Commands::Help do
4
+
5
+ context "#run" do
6
+
7
+ it "should display the help documentation" do
8
+ mock(subject).puts is_a(String)
9
+ subject.execute
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Commands::Logs do
4
+
5
+ context "#execute" do
6
+ it "should get logs from all of the app servers and then unify them" do
7
+ mock(subject).pretending { false }
8
+ mock(subject).app_servers { mock!.map { :logs }.subject }
9
+ mock(ORS::LogUnifier).new(:logs) { mock!.unify { :output }.subject }
10
+ mock(subject).puts(:output)
11
+
12
+ subject.execute
13
+ end
14
+
15
+ it "should not call the LogUnifier if pretending" do
16
+ mock(subject).pretending { true }
17
+ mock(subject).app_servers { mock!.map { :logs }.subject }
18
+ mock(ORS::LogUnifier).new(:logs).never
19
+
20
+ subject.execute
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,99 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Config do
4
+
5
+ subject { class Foo; include ORS::Config; end; Foo.new }
6
+
7
+ context ".parse_options" do
8
+ it("should default pretend to false") { subject.pretending.should be_false }
9
+ it("should default use_gateway to true") { subject.use_gateway.should be_true }
10
+
11
+ it "should set the environment when it is given" do
12
+ ORS::Config.parse_options %w(foobar -p)
13
+ subject.environment.should == "foobar"
14
+ end
15
+
16
+ it "should set pretend to true if -p is given" do
17
+ ORS::Config.pretending = false
18
+ ORS::Config.parse_options %w(-p)
19
+
20
+ subject.pretending.should be_true
21
+ end
22
+
23
+ it "should set pretend to true if --pretend is given" do
24
+ ORS::Config.pretending = false
25
+ ORS::Config.parse_options %w(--pretend)
26
+
27
+ subject.pretending.should be_true
28
+ end
29
+
30
+ it "should set use_gateway to false if -ng is given" do
31
+ ORS::Config.use_gateway = true
32
+ ORS::Config.parse_options %w(-ng)
33
+
34
+ subject.use_gateway.should be_false
35
+ end
36
+
37
+ it "should set use_gateway to false if --no-gateway is given" do
38
+ ORS::Config.use_gateway = true
39
+ ORS::Config.parse_options %w(--no-gateway)
40
+
41
+ subject.use_gateway.should be_false
42
+ end
43
+ end
44
+
45
+ context ".valid_options?" do
46
+
47
+ it "should be true when there is a name and valid environment" do
48
+ subject.name = "foo"
49
+ subject.environment = "production"
50
+
51
+ ORS::Config.valid_options?.should be_true
52
+ end
53
+
54
+ it "should be false when there is a name but an invalid environment" do
55
+ subject.name = "foo"
56
+ subject.environment = "-p"
57
+
58
+ ORS::Config.valid_options?.should be_false
59
+ end
60
+
61
+ it "should be false when there is a valid environment but a blank name" do
62
+ subject.name = ""
63
+ subject.environment = "production"
64
+
65
+ ORS::Config.valid_options?.should be_false
66
+ end
67
+
68
+ end
69
+
70
+ context "#all_servers" do
71
+ it "should return all servers" do
72
+ subject.all_servers.should == (subject.web_servers + subject.app_servers + [subject.migration_server])
73
+ end
74
+ end
75
+
76
+ context "config permanence" do
77
+ before do
78
+ class ORS::OtherConfig; include ORS::Config; end
79
+ @other_config = ORS::OtherConfig.new
80
+
81
+ class ORS::ConfigTest; include ORS::Config; end
82
+ @some_config = ORS::ConfigTest.new
83
+ end
84
+
85
+ %w(use_gateway pretending).each do |accessor|
86
+ it "should allow you to set #{accessor}" do
87
+ ORS::Config.should respond_to("#{accessor}")
88
+ end
89
+
90
+ it "should know if its #{accessor} across classes" do
91
+ ORS::Config.send("#{accessor}=", true)
92
+
93
+ @some_config.send(accessor).should == true
94
+ @other_config.send(accessor).should == true
95
+ end
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,68 @@
1
+ require "spec_helper"
2
+
3
+ describe ORS::Helpers do
4
+
5
+ subject { class ORS::HelperTest; include ORS::Helpers; end; ORS::HelperTest.new }
6
+
7
+ context "#execute_command" do
8
+ before do
9
+ stub(subject).info(is_a(String)).returns "message"
10
+ stub(subject).build_command.returns "command"
11
+ stub(subject).`(is_a(String)) {'output'} # ` # syntax highlighting
12
+ end
13
+
14
+ context "without options" do
15
+ it "should not fail" do
16
+ lambda {subject.execute_command("server", "command1", "command2")}.should_not raise_error
17
+ end
18
+
19
+ it "should not run exec" do
20
+ dont_allow(subject).exec(is_a(String))
21
+ subject.execute_command("server", "command1", "command2")
22
+ end
23
+ end
24
+
25
+ context "with options" do
26
+ it "should run exec with exec option" do
27
+ mock(subject).exec(is_a(String)) { "return" }
28
+ subject.execute_command("server", "command1", "command2", :exec => true)
29
+ end
30
+
31
+ it "should not put results into stdout when capturing" do
32
+ dont_allow(subject).info(is_a(String))
33
+ subject.execute_command("server", "command1", "command2", :capture => true)
34
+ end
35
+ end
36
+ end
37
+
38
+ context "#build_command" do
39
+
40
+ it "should return a blank string given no commands" do
41
+ subject.build_command("server").should == ""
42
+ end
43
+
44
+ context "with gateway" do
45
+ before { mock(subject).use_gateway.returns(true) }
46
+
47
+ it "should build the command" do
48
+ subject.build_command("server", %(cd /tmp)).should == %(ssh deploy-gateway 'ssh deployer@server "cd /tmp"')
49
+ end
50
+
51
+ it "should build the command with psuedo tty" do
52
+ subject.build_command("server", %(cd /tmp), :exec => true).should == %(ssh -t deploy-gateway 'ssh -t deployer@server "cd /tmp"')
53
+ end
54
+ end
55
+
56
+ context "without gateway" do
57
+ before { mock(subject).use_gateway.returns(false) }
58
+
59
+ it "should build the command" do
60
+ subject.build_command("server", %(cd /tmp)).should == %(ssh deployer@server "cd /tmp")
61
+ end
62
+
63
+ it "should build the command with psuedo tty" do
64
+ subject.build_command("server", %(cd /tmp), :exec => true).should == %(ssh -t deployer@server "cd /tmp")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,101 @@
1
+ require "spec_helper"
2
+
3
+ module ORS
4
+ describe LogUnifier do
5
+
6
+ context "#unify" do
7
+
8
+ it "should return the logs if there is only one server" do
9
+ logs = <<-END
10
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
11
+ Processing by ReviewsController#index as HTML
12
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
13
+
14
+
15
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
16
+ Processing by ReviewsController#index as HTML
17
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
18
+ END
19
+
20
+ logs_with_server = <<-END
21
+ [server] Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
22
+ [server] Processing by ReviewsController#index as HTML
23
+ [server] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
24
+
25
+
26
+ [server] Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
27
+ [server] Processing by ReviewsController#index as HTML
28
+ [server] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
29
+ END
30
+
31
+ unifier = LogUnifier.new [["server", logs]]
32
+ unifier.unify.should == logs_with_server.chomp
33
+ end
34
+
35
+ it "should intertwine log entires by date if there are multiple servers" do
36
+ server_1_logs = <<-END
37
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
38
+
39
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
40
+ Processing by ReviewsController#index as HTML
41
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
42
+
43
+
44
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:58:33 -0500
45
+ Processing by ReviewsController#index as HTML
46
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
47
+ END
48
+
49
+ server_2_logs = <<-END
50
+ Processing by ReviewsController#index as HTML
51
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
52
+
53
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:49:33 -0500
54
+ Processing by ReviewsController#index as HTML
55
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
56
+
57
+
58
+ Started GET "/" for 10.203.228.96 at 2011-02-02 08:52:33 -0500
59
+ Processing by ReviewsController#index as HTML
60
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
61
+
62
+
63
+ Started GET "/" for 10.203.228.96 at 2011-02-03 05:00:33 -0500
64
+ Processing by ReviewsController#index as HTML
65
+ Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
66
+ END
67
+
68
+ answer = <<-END
69
+ [server1] Started GET "/" for 10.203.228.96 at 2011-02-02 08:48:33 -0500
70
+ [server1] Processing by ReviewsController#index as HTML
71
+ [server1] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
72
+
73
+
74
+ [server2] Started GET "/" for 10.203.228.96 at 2011-02-02 08:49:33 -0500
75
+ [server2] Processing by ReviewsController#index as HTML
76
+ [server2] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
77
+
78
+
79
+ [server2] Started GET "/" for 10.203.228.96 at 2011-02-02 08:52:33 -0500
80
+ [server2] Processing by ReviewsController#index as HTML
81
+ [server2] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
82
+
83
+
84
+ [server1] Started GET "/" for 10.203.228.96 at 2011-02-02 08:58:33 -0500
85
+ [server1] Processing by ReviewsController#index as HTML
86
+ [server1] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
87
+
88
+
89
+ [server2] Started GET "/" for 10.203.228.96 at 2011-02-03 05:00:33 -0500
90
+ [server2] Processing by ReviewsController#index as HTML
91
+ [server2] Completed 200 OK in 41ms (Views: 3.6ms | ActiveRecord: 31.6ms)
92
+ END
93
+
94
+ unifier = LogUnifier.new([["server1", server_1_logs], ["server2", server_2_logs]])
95
+ unifier.unify.should == answer.chomp
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.expand_path("../../lib/ors", __FILE__))
2
+
3
+ Dir[File.expand_path("spec/support/**/*.rb", __FILE__)].each {|f| require f}
4
+
5
+ RSpec.configure do |config|
6
+ config.mock_with :rr
7
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ors
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jason Dew and John Long
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-03 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: git
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rr
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ description: Heroku-like deployment utilities for ORS
64
+ email:
65
+ - jason.dew@ors.sc.gov and john.long@ors.sc.gov
66
+ executables:
67
+ - ors
68
+ extensions: []
69
+
70
+ extra_rdoc_files: []
71
+
72
+ files:
73
+ - .autotest
74
+ - .gitignore
75
+ - .rspec
76
+ - Gemfile
77
+ - Rakefile
78
+ - bin/ors
79
+ - lib/ors.rb
80
+ - lib/ors/command.rb
81
+ - lib/ors/commands/base.rb
82
+ - lib/ors/commands/console.rb
83
+ - lib/ors/commands/deploy.rb
84
+ - lib/ors/commands/help.rb
85
+ - lib/ors/commands/logs.rb
86
+ - lib/ors/commands/migrate.rb
87
+ - lib/ors/commands/restart.rb
88
+ - lib/ors/commands/setup.rb
89
+ - lib/ors/commands/start.rb
90
+ - lib/ors/commands/stop.rb
91
+ - lib/ors/commands/update.rb
92
+ - lib/ors/config.rb
93
+ - lib/ors/core_ext.rb
94
+ - lib/ors/helpers.rb
95
+ - lib/ors/log_unifier.rb
96
+ - lib/ors/version.rb
97
+ - ors.gemspec
98
+ - spec/ors/command_spec.rb
99
+ - spec/ors/commands/base_spec.rb
100
+ - spec/ors/commands/console_spec.rb
101
+ - spec/ors/commands/deploy_spec.rb
102
+ - spec/ors/commands/help_spec.rb
103
+ - spec/ors/commands/logs_spec.rb
104
+ - spec/ors/config_spec.rb
105
+ - spec/ors/helpers_spec.rb
106
+ - spec/ors/log_unifier_spec.rb
107
+ - spec/spec_helper.rb
108
+ has_rdoc: true
109
+ homepage: ""
110
+ licenses: []
111
+
112
+ post_install_message:
113
+ rdoc_options: []
114
+
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ requirements: []
136
+
137
+ rubyforge_project: ors
138
+ rubygems_version: 1.5.0
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: Heroku-like deployment utilities for ORS
142
+ test_files:
143
+ - spec/ors/command_spec.rb
144
+ - spec/ors/commands/base_spec.rb
145
+ - spec/ors/commands/console_spec.rb
146
+ - spec/ors/commands/deploy_spec.rb
147
+ - spec/ors/commands/help_spec.rb
148
+ - spec/ors/commands/logs_spec.rb
149
+ - spec/ors/config_spec.rb
150
+ - spec/ors/helpers_spec.rb
151
+ - spec/ors/log_unifier_spec.rb
152
+ - spec/spec_helper.rb