foreplay 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -2
- data/Rakefile +1 -1
- data/foreplay.gemspec +6 -6
- data/lib/foreplay/cli.rb +48 -48
- data/lib/foreplay/deploy.rb +361 -344
- data/lib/foreplay/setup.rb +33 -33
- data/lib/foreplay/utility.rb +3 -3
- data/lib/foreplay/version.rb +1 -1
- data/spec/lib/foreplay/deploy_spec.rb +130 -122
- data/spec/lib/foreplay/setup_spec.rb +13 -13
- data/spec/lib/foreplay/utility_spec.rb +28 -28
- data/spec/spec_helper.rb +2 -2
- metadata +2 -2
data/lib/foreplay/setup.rb
CHANGED
@@ -1,33 +1,33 @@
|
|
1
|
-
require 'thor/group'
|
2
|
-
|
3
|
-
module Foreplay
|
4
|
-
class Setup < Thor::Group
|
5
|
-
include Thor::Actions
|
6
|
-
|
7
|
-
class_option :name, :
|
8
|
-
class_option :repository, :
|
9
|
-
class_option :user, :
|
10
|
-
class_option :password
|
11
|
-
class_option :keyfile
|
12
|
-
class_option :private_key, :
|
13
|
-
class_option :port, :
|
14
|
-
class_option :path, :
|
15
|
-
class_option :servers, :
|
16
|
-
class_option :db_adapter, :
|
17
|
-
class_option :db_encoding, :
|
18
|
-
class_option :db_pool, :
|
19
|
-
class_option :db_name, :
|
20
|
-
class_option :db_host, :
|
21
|
-
class_option :db_user
|
22
|
-
class_option :db_password
|
23
|
-
class_option :resque_redis
|
24
|
-
|
25
|
-
def self.source_root
|
26
|
-
File.dirname(__FILE__)
|
27
|
-
end
|
28
|
-
|
29
|
-
def config
|
30
|
-
template('setup/foreplay.yml', 'config/foreplay.yml')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module Foreplay
|
4
|
+
class Setup < Thor::Group
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
class_option :name, aliases: '-n', default: File.basename(Dir.getwd)
|
8
|
+
class_option :repository, aliases: '-r'
|
9
|
+
class_option :user, aliases: '-u'
|
10
|
+
class_option :password
|
11
|
+
class_option :keyfile
|
12
|
+
class_option :private_key, aliases: '-k'
|
13
|
+
class_option :port, aliases: '-p', default: 50_000
|
14
|
+
class_option :path, aliases: '-f'
|
15
|
+
class_option :servers, aliases: '-s', type: :array
|
16
|
+
class_option :db_adapter, aliases: '-a', default: 'postgresql'
|
17
|
+
class_option :db_encoding, aliases: '-e', default: 'utf8'
|
18
|
+
class_option :db_pool, default: 5
|
19
|
+
class_option :db_name, aliases: '-d'
|
20
|
+
class_option :db_host, aliases: '-h'
|
21
|
+
class_option :db_user
|
22
|
+
class_option :db_password
|
23
|
+
class_option :resque_redis
|
24
|
+
|
25
|
+
def self.source_root
|
26
|
+
File.dirname(__FILE__)
|
27
|
+
end
|
28
|
+
|
29
|
+
def config
|
30
|
+
template('setup/foreplay.yml', 'config/foreplay.yml')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/foreplay/utility.rb
CHANGED
@@ -7,15 +7,15 @@ module Foreplay
|
|
7
7
|
# h1.supermerge(h2)
|
8
8
|
# #=> {:x=>{:y=>[4, 5, 6, 7, 8, 9]}, :z=>[7, 8, 9, "xyz"]}
|
9
9
|
def self.supermerge(hash, other_hash)
|
10
|
-
|
10
|
+
fail 'supermerge only works if you pass two hashes' unless hash.is_a?(Hash) && other_hash.is_a?(Hash)
|
11
11
|
|
12
12
|
new_hash = hash.deep_dup.with_indifferent_access
|
13
13
|
|
14
|
-
other_hash.each_pair do |k,v|
|
14
|
+
other_hash.each_pair do |k, v|
|
15
15
|
tv = new_hash[k]
|
16
16
|
|
17
17
|
if tv.is_a?(Hash) && v.is_a?(Hash)
|
18
|
-
new_hash[k] = Foreplay::Utility
|
18
|
+
new_hash[k] = Foreplay::Utility.supermerge(tv, v)
|
19
19
|
elsif tv.is_a?(Array) || v.is_a?(Array)
|
20
20
|
new_hash[k] = Array.wrap(tv) + Array.wrap(v)
|
21
21
|
else
|
data/lib/foreplay/version.rb
CHANGED
@@ -1,122 +1,130 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foreplay'
|
3
|
-
require 'net/ssh/shell'
|
4
|
-
|
5
|
-
describe Foreplay::Deploy do
|
6
|
-
let
|
7
|
-
let
|
8
|
-
let
|
9
|
-
let
|
10
|
-
|
11
|
-
before :each do
|
12
|
-
# Setup foreplay
|
13
|
-
`rm -f config/foreplay.yml`
|
14
|
-
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred --password trollope`
|
15
|
-
|
16
|
-
# Stub all the things
|
17
|
-
Net::SSH.stub(:start).and_yield(session)
|
18
|
-
session.stub(:shell).and_yield(shell)
|
19
|
-
shell.stub(:execute).and_return(process)
|
20
|
-
shell.stub(:wait!).and_return(false)
|
21
|
-
process.stub(:on_output).and_yield(process, "output message\n")
|
22
|
-
process.stub(:exit_status).and_return(0)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should complain on check if there's no config file" do
|
26
|
-
`rm -f config/foreplay.yml`
|
27
|
-
expect { Foreplay::Deploy.start([:check, 'production', '']) }
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
'
|
75
|
-
'
|
76
|
-
'
|
77
|
-
'
|
78
|
-
'echo "
|
79
|
-
'
|
80
|
-
'echo "
|
81
|
-
'echo "
|
82
|
-
'echo "
|
83
|
-
'echo "
|
84
|
-
'echo "
|
85
|
-
'
|
86
|
-
'
|
87
|
-
'
|
88
|
-
'
|
89
|
-
'
|
90
|
-
'echo
|
91
|
-
'
|
92
|
-
'
|
93
|
-
'
|
94
|
-
'sudo
|
95
|
-
'sudo
|
96
|
-
'sudo
|
97
|
-
'
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'foreplay'
|
3
|
+
require 'net/ssh/shell'
|
4
|
+
|
5
|
+
describe Foreplay::Deploy do
|
6
|
+
let(:ssh) { double(Net::SSH) }
|
7
|
+
let(:session) { double(Net::SSH::Connection::Session) }
|
8
|
+
let(:shell) { double(Net::SSH::Shell) }
|
9
|
+
let(:process) { double(Net::SSH::Shell::Process) }
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
# Setup foreplay
|
13
|
+
`rm -f config/foreplay.yml`
|
14
|
+
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred --password trollope`
|
15
|
+
|
16
|
+
# Stub all the things
|
17
|
+
Net::SSH.stub(:start).and_yield(session)
|
18
|
+
session.stub(:shell).and_yield(shell)
|
19
|
+
shell.stub(:execute).and_return(process)
|
20
|
+
shell.stub(:wait!).and_return(false)
|
21
|
+
process.stub(:on_output).and_yield(process, "output message\n")
|
22
|
+
process.stub(:exit_status).and_return(0)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should complain on check if there's no config file" do
|
26
|
+
`rm -f config/foreplay.yml`
|
27
|
+
expect { Foreplay::Deploy.start([:check, 'production', '']) }
|
28
|
+
.to raise_error(RuntimeError, /.*Please run foreplay setup or create the file manually.*/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should complain on deploy if there's no config file" do
|
32
|
+
`rm -f config/foreplay.yml`
|
33
|
+
expect { Foreplay::Deploy.start([:deploy, 'production', '']) }
|
34
|
+
.to raise_error(RuntimeError, /.*Please run foreplay setup or create the file manually.*/)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should complain if there are no authentication methods defined in the config file' do
|
38
|
+
`rm -f config/foreplay.yml`
|
39
|
+
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred --password ""`
|
40
|
+
expect { Foreplay::Deploy.start([:deploy, 'production', '']) }
|
41
|
+
.to raise_error(
|
42
|
+
RuntimeError,
|
43
|
+
/.*No authentication methods supplied. You must supply a private key, key file or password in the configuration file*/
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should complain if the private keyfile defined in the config file doesn't exist" do
|
48
|
+
`rm -f config/foreplay.yml`
|
49
|
+
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred --keyfile "/home/fred/no-such-file"`
|
50
|
+
expect { Foreplay::Deploy.start([:deploy, 'production', '']) }
|
51
|
+
.to raise_error(Errno::ENOENT, %r{.*No such file or directory @ rb_sysopen - /home/fred/no-such-file*})
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should terminate if a remote process exits with a non-zero status' do
|
55
|
+
process.stub(:exit_status).and_return(1)
|
56
|
+
expect { Foreplay::Deploy.start([:deploy, 'production', '']) }.to raise_error(RuntimeError, /.*output message*/)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should terminate if a connection can't be established with the remote server" do
|
60
|
+
Net::SSH.unstub(:start)
|
61
|
+
expect { Foreplay::Deploy.start([:deploy, 'production', '']) }
|
62
|
+
.to raise_error(RuntimeError, /.*There was a problem starting an ssh session on web.example.com*/)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should check the config' do
|
66
|
+
$stdout.should_receive(:puts).at_least(:once)
|
67
|
+
Foreplay::Deploy.start [:check, 'production', '']
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should deploy to the environment' do
|
71
|
+
Net::SSH.should_receive(:start).with('web.example.com', 'fred', verbose: :warn, port: 22, password: 'trollope').and_yield(session)
|
72
|
+
|
73
|
+
[
|
74
|
+
'mkdir -p apps/foreplay && cd apps/foreplay && rm -rf 50000 && git clone git@github.com:Xenapto/foreplay.git 50000',
|
75
|
+
'rvm rvmrc trust 50000',
|
76
|
+
'rvm rvmrc warning ignore 50000',
|
77
|
+
'cd 50000',
|
78
|
+
'if [ -f .ruby-version ] ; then rvm install `cat .ruby-version` ; else echo "No .ruby-version file found" ; fi',
|
79
|
+
'mkdir -p config',
|
80
|
+
'echo "RAILS_ENV=production" > .env',
|
81
|
+
'echo "concurrency: web=1,worker=0,scheduler=0" > .foreman',
|
82
|
+
'echo "app: foreplay-50000" >> .foreman',
|
83
|
+
'echo "port: 50000" >> .foreman',
|
84
|
+
'echo "user: fred" >> .foreman',
|
85
|
+
'echo "production:" > config/database.yml',
|
86
|
+
'echo " adapter: postgresql" >> config/database.yml',
|
87
|
+
'echo " encoding: utf8" >> config/database.yml',
|
88
|
+
'echo " database: TODO Put the database name here" >> config/database.yml',
|
89
|
+
'echo " pool: 5" >> config/database.yml',
|
90
|
+
'echo " host: TODO Put here the database host name" >> config/database.yml',
|
91
|
+
'echo " username: TODO Put here the database user" >> config/database.yml',
|
92
|
+
'echo " password: TODO Put here the database user\'s password" >> config/database.yml',
|
93
|
+
'bundle install --deployment --without development test',
|
94
|
+
'sudo ln -f `which foreman` /usr/bin/foreman || echo Using default version of foreman',
|
95
|
+
'sudo foreman export upstart /etc/init',
|
96
|
+
'sudo start foreplay-50000 || sudo restart foreplay-50000',
|
97
|
+
'mkdir -p .foreplay/foreplay && touch .foreplay/foreplay/current_port && cat .foreplay/foreplay/current_port',
|
98
|
+
'echo 50000 > $HOME/.foreplay/foreplay/current_port',
|
99
|
+
'sleep 60',
|
100
|
+
'sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 50000',
|
101
|
+
'sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 51000',
|
102
|
+
'sudo iptables-save > /etc/iptables/rules.v4',
|
103
|
+
'sudo iptables-save > /etc/iptables.up.rules',
|
104
|
+
'sudo iptables-save -c | egrep REDIRECT --color=never',
|
105
|
+
'sudo stop foreplay-51000 || echo \'No previous instance running\''
|
106
|
+
].each do |command|
|
107
|
+
shell.should_receive(:execute).with(command).and_return(process)
|
108
|
+
end
|
109
|
+
|
110
|
+
Foreplay::Deploy.start [:deploy, 'production', '']
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should use another port if there's already an installed instance" do
|
114
|
+
process.stub(:on_output).and_yield(process, "50000\n")
|
115
|
+
shell.should_receive(:execute).with('echo 51000 > $HOME/.foreplay/foreplay/current_port').and_return(process)
|
116
|
+
Foreplay::Deploy.start [:deploy, 'production', '']
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should use the private key provided in the config file' do
|
120
|
+
`rm -f config/foreplay.yml`
|
121
|
+
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred -k "top secret private key"`
|
122
|
+
Foreplay::Deploy.start([:deploy, 'production', ''])
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should add Redis details for Resque' do
|
126
|
+
`rm -f config/foreplay.yml`
|
127
|
+
`foreplay setup -r git@github.com:Xenapto/foreplay.git -s web.example.com -f apps/%a -u fred --resque-redis "redis://localhost:6379"`
|
128
|
+
Foreplay::Deploy.start([:deploy, 'production', ''])
|
129
|
+
end
|
130
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foreplay'
|
3
|
-
|
4
|
-
describe Foreplay::Setup do
|
5
|
-
before :each do
|
6
|
-
`rm -f config/foreplay.yml`
|
7
|
-
end
|
8
|
-
|
9
|
-
it
|
10
|
-
File.should_receive(:open)
|
11
|
-
Foreplay::Setup.start
|
12
|
-
end
|
13
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'foreplay'
|
3
|
+
|
4
|
+
describe Foreplay::Setup do
|
5
|
+
before :each do
|
6
|
+
`rm -f config/foreplay.yml`
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should create a config file' do
|
10
|
+
File.should_receive(:open)
|
11
|
+
Foreplay::Setup.start
|
12
|
+
end
|
13
|
+
end
|
@@ -1,28 +1,28 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foreplay'
|
3
|
-
|
4
|
-
describe Foreplay::Utility do
|
5
|
-
it
|
6
|
-
expect { Foreplay::Utility
|
7
|
-
end
|
8
|
-
|
9
|
-
it
|
10
|
-
expect(Foreplay::Utility
|
11
|
-
end
|
12
|
-
|
13
|
-
it
|
14
|
-
expect(Foreplay::Utility
|
15
|
-
end
|
16
|
-
|
17
|
-
it
|
18
|
-
expect(Foreplay::Utility
|
19
|
-
end
|
20
|
-
|
21
|
-
it
|
22
|
-
expect(Foreplay::Utility
|
23
|
-
end
|
24
|
-
|
25
|
-
it
|
26
|
-
expect(Foreplay::Utility
|
27
|
-
end
|
28
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'foreplay'
|
3
|
+
|
4
|
+
describe Foreplay::Utility do
|
5
|
+
it 'should complain unless two hashes are passed to it' do
|
6
|
+
expect { Foreplay::Utility.supermerge('x', 'y') }.to raise_error(RuntimeError)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should merge two simple hashes' do
|
10
|
+
expect(Foreplay::Utility.supermerge({ a: 'x' }, { b: 'y' })).to eq('a' => 'x', 'b' => 'y')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should merge two hashes both with arrays at the same key' do
|
14
|
+
expect(Foreplay::Utility.supermerge({ a: ['x'] }, { a: ['y'] })).to eq('a' => %w(x y))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should merge an array and a value at the same key' do
|
18
|
+
expect(Foreplay::Utility.supermerge({ a: 'x' }, { a: ['y'] })).to eq('a' => %w(x y))
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should replace a value at the same key' do
|
22
|
+
expect(Foreplay::Utility.supermerge({ a: 'x' }, { a: 'y' })).to eq('a' => 'y')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should merge two subhashes at the same key' do
|
26
|
+
expect(Foreplay::Utility.supermerge({ a: { b: 'x' } }, { a: { c: 'y' } })).to eq('a' => { 'b' => 'x', 'c' => 'y' })
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,11 +5,11 @@ SimpleCov.start
|
|
5
5
|
Coveralls.wear!('rails') if ENV['COVERALLS_REPO_TOKEN']
|
6
6
|
|
7
7
|
RSpec.configure do |config|
|
8
|
-
|
8
|
+
# Run specs in random order to surface order dependencies. If you find an
|
9
9
|
# order dependency and want to debug it, you can fix the order by providing
|
10
10
|
# the seed, which is printed after each run.
|
11
11
|
# --seed 1234
|
12
|
-
config.order =
|
12
|
+
config.order = 'random'
|
13
13
|
|
14
14
|
# Manually-added
|
15
15
|
config.color_enabled = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreplay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xenapto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|