ors 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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