relevance_rails 0.1.1.alpha → 0.1.2
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/CHANGELOG.md +7 -0
- data/README.md +4 -59
- data/USAGE.md +64 -0
- data/lib/generators/provision_config/provision_config_generator.rb +6 -0
- data/lib/generators/relevance_file/templates/Gemfile.erb +5 -5
- data/lib/generators/relevance_file/templates/README.markdown.erb +3 -28
- data/lib/relevance_rails/fog_ext/ssh.rb +53 -0
- data/lib/relevance_rails/provision.rb +48 -24
- data/lib/relevance_rails/runner.rb +33 -2
- data/lib/relevance_rails/version.rb +1 -1
- data/lib/tasks/provision.rake +4 -2
- data/relevance_rails.gemspec +6 -1
- data/script/ci +10 -20
- data/spec/lib/provision_spec.rb +54 -2
- metadata +11 -9
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -24,73 +24,18 @@ $ gem install relevance_rails
|
|
|
24
24
|
$ relevance_rails new <your new project>
|
|
25
25
|
````
|
|
26
26
|
|
|
27
|
-
For existing projects, first add to your Gemfile:
|
|
27
|
+
For existing projects, please note we *only* support Rails 3.2 and higher! To add to an existing project, first add to your Gemfile:
|
|
28
28
|
|
|
29
29
|
group :development, :test do
|
|
30
30
|
gem 'relevance_rails'
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
After a `bundle install`, pull in our chef recipes into provision/:
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
$ rails g provision_config
|
|
38
|
-
# if using postgresql
|
|
39
|
-
$ rails g provision_config postgresql
|
|
40
|
-
```
|
|
34
|
+
Using relevance_rails
|
|
35
|
+
---------------------
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
----------------------------
|
|
37
|
+
[See USAGE](https://github.com/relevance/relevance_rails/blob/master/USAGE.md)
|
|
44
38
|
|
|
45
|
-
By default, relevance_rails bundles all your keys from `ssh-add -L` with your instance. For bundling
|
|
46
|
-
additional keys, you can create a ~/.relevance_rails/keys_git_url file and point it to a git repo that
|
|
47
|
-
has additional keys. Keys in that git repo should exist as top level *.pub files. You *MUST* have at
|
|
48
|
-
least one key to provision.
|
|
49
|
-
|
|
50
|
-
Provisioning on EC2
|
|
51
|
-
-------------------
|
|
52
|
-
|
|
53
|
-
First create an aws config in ~/.relevance\_rails/aws\_config.yml.
|
|
54
|
-
An example config looks like this:
|
|
55
|
-
|
|
56
|
-
```yaml
|
|
57
|
-
aws_credentials:
|
|
58
|
-
:aws_access_key_id: <your aws access key id>
|
|
59
|
-
:aws_secret_access_key: <your aws secret access key>
|
|
60
|
-
|
|
61
|
-
server:
|
|
62
|
-
creation_config:
|
|
63
|
-
:flavor_id: <instance type, e.g. 'm1.large'>
|
|
64
|
-
:image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
|
|
65
|
-
:groups: <security group to place the new deployment in, e.g. "default">
|
|
66
|
-
:key_name: <name of the public/private keypair to start instance with>
|
|
67
|
-
private_key: |
|
|
68
|
-
-----BEGIN RSA PRIVATE KEY-----
|
|
69
|
-
Include the RSA private key here. This should correspond to the keypair indicated
|
|
70
|
-
by :key_name above.
|
|
71
|
-
-----END RSA PRIVATE KEY-----
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Now just provision your instance:
|
|
75
|
-
|
|
76
|
-
```sh
|
|
77
|
-
$ rake provision:ec2_and_generate NAME=qa
|
|
78
|
-
$ cap qa deploy:setup deploy
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Provisioning with Vagrant
|
|
82
|
-
-------------------------
|
|
83
|
-
|
|
84
|
-
From your app's root directory:
|
|
85
|
-
|
|
86
|
-
```sh
|
|
87
|
-
$ cd provision
|
|
88
|
-
# pull in vagrant and chef
|
|
89
|
-
$ bundle install
|
|
90
|
-
$ vagrant up
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Vagrant instance should be up at 172.25.5.5.
|
|
94
39
|
|
|
95
40
|
Supported Ruby Versions
|
|
96
41
|
-----------------------
|
data/USAGE.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Setup Chef
|
|
2
|
+
----------
|
|
3
|
+
|
|
4
|
+
To setup chef recipes in provision/:
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
# defaults to mysql
|
|
8
|
+
$ rails g provision_config
|
|
9
|
+
# if using postgresql
|
|
10
|
+
$ rails g provision_config postgresql
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Configuring bundled ssh keys
|
|
14
|
+
----------------------------
|
|
15
|
+
|
|
16
|
+
By default, relevance_rails bundles all your keys from `ssh-add -L` with your instance. For bundling
|
|
17
|
+
additional keys, you can create a ~/.relevance_rails/keys_git_url file and point it to a git repo that
|
|
18
|
+
has additional keys. Keys in that git repo should exist as top level *.pub files. You *MUST* have at
|
|
19
|
+
least one key to provision.
|
|
20
|
+
|
|
21
|
+
Provisioning on EC2
|
|
22
|
+
-------------------
|
|
23
|
+
|
|
24
|
+
First create an aws config in ~/.relevance\_rails/aws\_config.yml.
|
|
25
|
+
An example config looks like this:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
aws_credentials:
|
|
29
|
+
:aws_access_key_id: <your aws access key id>
|
|
30
|
+
:aws_secret_access_key: <your aws secret access key>
|
|
31
|
+
|
|
32
|
+
server:
|
|
33
|
+
creation_config:
|
|
34
|
+
:flavor_id: <instance type, e.g. 'm1.large'>
|
|
35
|
+
:image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
|
|
36
|
+
:groups: <security group to place the new deployment in, e.g. "default">
|
|
37
|
+
:key_name: <name of the public/private keypair to start instance with>
|
|
38
|
+
private_key: |
|
|
39
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
40
|
+
Include the RSA private key here. This should correspond to the keypair indicated
|
|
41
|
+
by :key_name above.
|
|
42
|
+
-----END RSA PRIVATE KEY-----
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Now just provision your instance:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
$ rake provision:ec2_and_generate NAME=qa
|
|
49
|
+
$ cap qa deploy:setup deploy
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Provisioning with Vagrant
|
|
53
|
+
-------------------------
|
|
54
|
+
|
|
55
|
+
From your app's root directory:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
$ cd provision
|
|
59
|
+
# pull in vagrant and chef
|
|
60
|
+
$ bundle install
|
|
61
|
+
$ vagrant up
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Vagrant instance should be up at 172.25.5.5.
|
|
@@ -19,6 +19,12 @@ class ProvisionConfigGenerator < Rails::Generators::Base
|
|
|
19
19
|
Dir.chdir(destination_root)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def check_git_status
|
|
23
|
+
unless `git status`[/working directory clean/]
|
|
24
|
+
abort "Your git repository is dirty. Clean up before reinvoking this command."
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
def check_authorized_keys
|
|
23
29
|
if (@authorized_keys = fetch_keys).empty?
|
|
24
30
|
abort "No ssh keys were found! Check ssh-add -L and your keys_git_url config."
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
source :rubygems
|
|
2
2
|
|
|
3
|
-
gem 'rails', '3.2.2'
|
|
4
|
-
gem 'haml', '3.1.4'
|
|
5
|
-
gem 'configatron', '2.8.3'
|
|
3
|
+
gem 'rails', '~> 3.2.2'
|
|
4
|
+
gem 'haml', '~> 3.1.4'
|
|
5
|
+
gem 'configatron', '~> 2.8.3'
|
|
6
6
|
gem 'airbrake', '~> 3.0.4'
|
|
7
|
-
gem 'factory_girl_rails', '1.2.0'
|
|
8
|
-
gem 'jquery-rails', '1.0.14'
|
|
7
|
+
gem 'factory_girl_rails', '~> 1.2.0'
|
|
8
|
+
gem 'jquery-rails', '~> 1.0.14'
|
|
9
9
|
gem 'therubyracer'
|
|
10
10
|
<%- if database == 'mysql' -%>
|
|
11
11
|
gem 'mysql2', '~> 0.3.11'
|
|
@@ -5,32 +5,7 @@
|
|
|
5
5
|
gem install bundler
|
|
6
6
|
[TODO other setup commands here]
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Using relevance_rails
|
|
9
|
+
---------------------
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
An example config looks like this:
|
|
12
|
-
|
|
13
|
-
```yaml
|
|
14
|
-
aws_credentials:
|
|
15
|
-
:aws_access_key_id: <your aws access key id>
|
|
16
|
-
:aws_secret_access_key: <your aws secret access key>
|
|
17
|
-
|
|
18
|
-
server:
|
|
19
|
-
creation_config:
|
|
20
|
-
:flavor_id: <instance type, e.g. 'm1.large'>
|
|
21
|
-
:image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
|
|
22
|
-
:groups: <security group to place the new deployment in, e.g. "default">
|
|
23
|
-
:key_name: <name of the public/private keypair to start instance with>
|
|
24
|
-
private_key: |
|
|
25
|
-
-----BEGIN RSA PRIVATE KEY-----
|
|
26
|
-
Include the RSA private key here. This should correspond to the keypair indicated
|
|
27
|
-
by :key_name above.
|
|
28
|
-
-----END RSA PRIVATE KEY-----
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Now just provision your instance:
|
|
32
|
-
|
|
33
|
-
```sh
|
|
34
|
-
$ rails g deployment qa
|
|
35
|
-
$ cap qa deploy:setup deploy
|
|
36
|
-
```
|
|
11
|
+
[See USAGE](https://github.com/relevance/relevance_rails/blob/master/USAGE.md)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'fog'
|
|
2
|
+
require 'fog/core/ssh'
|
|
3
|
+
|
|
4
|
+
# Monkey-patch Fog 1.3.1 to stream SSH output
|
|
5
|
+
# (in real time) to stdout.
|
|
6
|
+
class Fog::SSH::Real
|
|
7
|
+
def run(commands)
|
|
8
|
+
commands = [*commands]
|
|
9
|
+
results = []
|
|
10
|
+
begin
|
|
11
|
+
Net::SSH.start(@address, @username, @options) do |ssh|
|
|
12
|
+
commands.each do |command|
|
|
13
|
+
result = Fog::SSH::Result.new(command)
|
|
14
|
+
ssh.open_channel do |ssh_channel|
|
|
15
|
+
ssh_channel.request_pty
|
|
16
|
+
ssh_channel.exec(command) do |channel, success|
|
|
17
|
+
unless success
|
|
18
|
+
raise "Could not execute command: #{command.inspect}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
channel.on_data do |ch, data|
|
|
22
|
+
result.stdout << data
|
|
23
|
+
puts data
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
channel.on_extended_data do |ch, type, data|
|
|
27
|
+
next unless type == 1
|
|
28
|
+
result.stderr << data
|
|
29
|
+
puts data
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
channel.on_request('exit-status') do |ch, data|
|
|
33
|
+
result.status = data.read_long
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
channel.on_request('exit-signal') do |ch, data|
|
|
37
|
+
result.status = 255
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
ssh.loop
|
|
42
|
+
results << result
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
rescue Net::SSH::HostKeyMismatch => exception
|
|
46
|
+
exception.remember_host!
|
|
47
|
+
sleep 0.2
|
|
48
|
+
retry
|
|
49
|
+
end
|
|
50
|
+
results
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
require 'fog'
|
|
2
2
|
require 'thor'
|
|
3
3
|
require 'timeout'
|
|
4
|
+
require 'relevance_rails/fog_ext/ssh'
|
|
4
5
|
|
|
5
6
|
module RelevanceRails
|
|
6
7
|
module Provision
|
|
8
|
+
class AptInstallError < StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
def self.create_ec2(name = nil)
|
|
8
12
|
abort "Please provide a $NAME" unless name
|
|
9
13
|
server = provision_ec2_instances(name)
|
|
@@ -54,10 +58,10 @@ module RelevanceRails
|
|
|
54
58
|
puts "Provisioning an instance..."
|
|
55
59
|
server = fog_connection.servers.create(config['server']['creation_config'])
|
|
56
60
|
fog_connection.tags.create(:key => 'Name',
|
|
57
|
-
:value => "#{
|
|
61
|
+
:value => "#{name}",
|
|
58
62
|
:resource_id => server.id)
|
|
59
63
|
server.private_key = config['server']['private_key']
|
|
60
|
-
|
|
64
|
+
|
|
61
65
|
File.open("config/ec2_instance.txt", "w") do |f|
|
|
62
66
|
f.puts(server.id)
|
|
63
67
|
end
|
|
@@ -65,17 +69,12 @@ module RelevanceRails
|
|
|
65
69
|
puts "Provisioned!"
|
|
66
70
|
server
|
|
67
71
|
end
|
|
68
|
-
|
|
72
|
+
|
|
69
73
|
def self.run_commands(server)
|
|
70
|
-
|
|
71
|
-
run_command(server, 'sudo apt-get update')
|
|
72
|
-
puts "Installing ruby..."
|
|
73
|
-
run_command(server, 'sudo apt-get -y install ruby')
|
|
74
|
-
puts "Installing rubygems..."
|
|
75
|
-
run_command(server, 'sudo apt-get -y install rubygems1.8')
|
|
74
|
+
apt_installs(server)
|
|
76
75
|
puts "Installing chef..."
|
|
77
76
|
run_command(server, 'sudo gem install chef --no-ri --no-rdoc --version 0.10.8')
|
|
78
|
-
puts "Copying chef resources from provision directory
|
|
77
|
+
puts "Copying chef resources from provision directory..."
|
|
79
78
|
server.scp("#{Rails.root.join('provision')}/", '/tmp/chef-solo', :recursive => true)
|
|
80
79
|
puts "Converging server, this may take a while (10-20 minutes)"
|
|
81
80
|
run_command(server, 'cd /tmp/chef-solo && sudo /var/lib/gems/1.8/bin/chef-solo -c solo.rb -j dna.json')
|
|
@@ -85,6 +84,43 @@ module RelevanceRails
|
|
|
85
84
|
server
|
|
86
85
|
end
|
|
87
86
|
|
|
87
|
+
def self.retry_block(times, errors, failure)
|
|
88
|
+
succeeded = false
|
|
89
|
+
attempts = 0
|
|
90
|
+
last_error = nil
|
|
91
|
+
until succeeded || attempts > times-1
|
|
92
|
+
begin
|
|
93
|
+
retval = yield
|
|
94
|
+
succeeded = true
|
|
95
|
+
rescue *errors => e
|
|
96
|
+
puts failure
|
|
97
|
+
attempts +=1
|
|
98
|
+
last_error = e
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
if succeeded
|
|
102
|
+
return retval
|
|
103
|
+
else
|
|
104
|
+
exit 1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.apt_installs(server)
|
|
109
|
+
retry_block(3, [AptInstallError], "Apt-cache came from corrupt mirror, retrying update...") do
|
|
110
|
+
puts "Updating apt cache..."
|
|
111
|
+
run_apt_command(server, 'sudo apt-get update')
|
|
112
|
+
puts "Installing ruby..."
|
|
113
|
+
run_apt_command(server, 'sudo apt-get -y install ruby')
|
|
114
|
+
puts "Installing rubygems..."
|
|
115
|
+
run_apt_command(server, 'sudo apt-get -y install rubygems1.8')
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.run_apt_command(server, command)
|
|
120
|
+
jobs = server.ssh(command)
|
|
121
|
+
raise AptInstallError unless jobs_succeeded?(jobs)
|
|
122
|
+
end
|
|
123
|
+
|
|
88
124
|
def self.run_command(server, command)
|
|
89
125
|
jobs = server.ssh(command)
|
|
90
126
|
exit 1 unless jobs_succeeded?(jobs)
|
|
@@ -93,22 +129,10 @@ module RelevanceRails
|
|
|
93
129
|
def self.wait_for_ssh(server)
|
|
94
130
|
puts "Waiting for ssh connectivity..."
|
|
95
131
|
server.wait_for { ready? }
|
|
96
|
-
|
|
97
|
-
attempts = 0
|
|
98
|
-
last_error = nil
|
|
99
|
-
until succeeded || attempts > 4
|
|
132
|
+
retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], "Connecting to Amazon refused. Retrying...") do
|
|
100
133
|
sleep 10
|
|
101
|
-
|
|
102
|
-
# Should be checked for compatability across rubies
|
|
103
|
-
Timeout.timeout(60) { server.ssh('ls') }
|
|
104
|
-
succeeded = true
|
|
105
|
-
rescue Errno::ECONNREFUSED, Timeout::Error => e
|
|
106
|
-
puts "Connecting to Amazon refused. Attempt #{attempts+1}..."
|
|
107
|
-
attempts += 1
|
|
108
|
-
last_error = e
|
|
109
|
-
end
|
|
134
|
+
Timeout.timeout(60) { server.ssh('ls') }
|
|
110
135
|
end
|
|
111
|
-
raise last_error unless succeeded
|
|
112
136
|
puts "Server up and listening for SSH!"
|
|
113
137
|
end
|
|
114
138
|
|
|
@@ -3,7 +3,9 @@ require 'relevance_rails'
|
|
|
3
3
|
module RelevanceRails
|
|
4
4
|
class Runner
|
|
5
5
|
def self.start(argv=ARGV)
|
|
6
|
-
if argv.
|
|
6
|
+
if argv.empty? || argv[0] == '--help' || argv[0] == '-h'
|
|
7
|
+
print_help
|
|
8
|
+
elsif argv.delete '--version'
|
|
7
9
|
puts "RelevanceRails #{RelevanceRails::VERSION}"
|
|
8
10
|
elsif argv[0] == 'new'
|
|
9
11
|
add_default_options! argv
|
|
@@ -22,8 +24,37 @@ module RelevanceRails
|
|
|
22
24
|
|
|
23
25
|
private
|
|
24
26
|
|
|
27
|
+
def self.print_help
|
|
28
|
+
puts <<-STR
|
|
29
|
+
Usage: relevance_rails new APP [OPTIONS]
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
|
|
33
|
+
-d, --database <database>: Generate dependencies, configuration, and deployments
|
|
34
|
+
for database, only supports mysql (default) and
|
|
35
|
+
postgresql
|
|
36
|
+
|
|
37
|
+
When invoked in an RVM shell, the new project and newly provisioned servers will
|
|
38
|
+
inherit the current ruby. The new project will get its own gemset.
|
|
39
|
+
|
|
40
|
+
When invoked in other contexts, newly provisioned servers will attempt to
|
|
41
|
+
install a ruby which matches the ruby executing the relevance_rails process.
|
|
42
|
+
STR
|
|
43
|
+
end
|
|
44
|
+
|
|
25
45
|
def self.setup_rvm(app_name)
|
|
26
|
-
|
|
46
|
+
rvm_version = Gem::Version.new(`rvm --version`[/rvm (\d\.\d+\.\d+)/, 1].to_s)
|
|
47
|
+
|
|
48
|
+
if rvm_version < Gem::Version.new('1.10.2')
|
|
49
|
+
abort "Rvm version 1.10.2 or greater is required. Run 'rvm get stable'"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if rvm_version < Gem::Version.new('1.12.0')
|
|
53
|
+
# RVM's ruby drivers were factored out into a gem
|
|
54
|
+
# in 1.12.0, so you don't use this trick anymore.
|
|
55
|
+
$LOAD_PATH.unshift "#{ENV['rvm_path']}/lib"
|
|
56
|
+
end
|
|
57
|
+
|
|
27
58
|
require 'rvm'
|
|
28
59
|
|
|
29
60
|
env = RVM::Environment.current
|
data/lib/tasks/provision.rake
CHANGED
|
@@ -3,13 +3,15 @@ require 'relevance_rails/provision'
|
|
|
3
3
|
namespace :provision do
|
|
4
4
|
desc 'Provision a deployable EC2 instance and generate Capistrano config'
|
|
5
5
|
task :ec2_and_generate do
|
|
6
|
-
|
|
6
|
+
server_name = "#{Rails.application.class.parent_name} #{ENV['NAME']}"
|
|
7
|
+
server = RelevanceRails::Provision.create_ec2(server_name)
|
|
7
8
|
system('rails', 'generate', 'deployment', ENV['NAME'], server.public_ip_address)
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
desc 'Provision a deployable EC2 instance'
|
|
11
12
|
task :ec2 do
|
|
12
|
-
|
|
13
|
+
server_name = "#{Rails.application.class.parent_name} #{ENV['NAME']}"
|
|
14
|
+
RelevanceRails::Provision.create_ec2(server_name)
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
desc 'Stop your previously-provisioned EC2 instance'
|
data/relevance_rails.gemspec
CHANGED
|
@@ -24,7 +24,12 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
|
|
25
25
|
# specify any dependencies here; for example:
|
|
26
26
|
s.add_runtime_dependency 'rails', '~> 3.2'
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
# be aware that we're monkey-patching fog in fog_ext/ssh.rb;
|
|
29
|
+
# if we update fog, that monkey-patch might need to be
|
|
30
|
+
# revisited
|
|
31
|
+
s.add_runtime_dependency 'fog', '1.3.1'
|
|
32
|
+
|
|
28
33
|
s.add_runtime_dependency 'thor', '~> 0.14.6'
|
|
29
34
|
s.add_development_dependency 'pry'
|
|
30
35
|
s.add_development_dependency 'capybara'
|
data/script/ci
CHANGED
|
@@ -40,35 +40,25 @@ bundle exec rake spec
|
|
|
40
40
|
|
|
41
41
|
echo "Building new relevance_rails gem..."
|
|
42
42
|
rm -Rf relevance_rails-*.gem
|
|
43
|
-
|
|
43
|
+
rake install --trace
|
|
44
44
|
echo "Done"
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# NOTE: RVM 1.x doesn't work with "set -e", so you have to unset/set it.
|
|
46
|
+
echo "Ensure we remove any old app directory or gemset..."
|
|
47
|
+
rm -Rf ./$RAILS_APP
|
|
49
48
|
set +e
|
|
50
49
|
rvm --force gemset delete $RAILS_APP
|
|
51
|
-
rvm gemset create $RAILS_APP
|
|
52
|
-
rvm gemset use $RAILS_APP
|
|
53
|
-
echo "RVM is now using:` rvm current`"
|
|
54
50
|
set -e
|
|
51
|
+
echo "Done"
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
echo "Removing old relevance_rails gem..."
|
|
58
|
-
gem uninstall --verbose --all --executables relevance_rails
|
|
59
|
-
echo "Done"
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
echo "Installing relevance_rails gem into $RAILS_APP gemset..."
|
|
63
|
-
gem install relevance_rails-*.gem
|
|
64
|
-
echo "Done."
|
|
65
|
-
|
|
66
|
-
rm -Rf ./$RAILS_APP
|
|
67
|
-
relevance_rails new $RAILS_APP --database=postgresql
|
|
53
|
+
relevance_rails new $RAILS_APP --database=postgresql --relevance-dev
|
|
68
54
|
|
|
69
|
-
# NOTE: this does NOT change the RVM gemset; we set it manually
|
|
55
|
+
# NOTE: this does NOT change the RVM gemset; we set it manually below
|
|
70
56
|
builtin cd $RAILS_APP
|
|
57
|
+
|
|
58
|
+
set +e
|
|
59
|
+
rvm gemset use $RAILS_APP
|
|
71
60
|
echo "RVM is now using:` rvm current`"
|
|
61
|
+
set -e
|
|
72
62
|
|
|
73
63
|
files_must_NOT_exist public/index.html
|
|
74
64
|
files_must_exist config/database.yml provision/dna.json config/deploy.rb config/deploy/recipes/deploy.rb
|
data/spec/lib/provision_spec.rb
CHANGED
|
@@ -2,10 +2,14 @@ require 'spec_helper'
|
|
|
2
2
|
require 'relevance_rails/provision'
|
|
3
3
|
|
|
4
4
|
describe RelevanceRails::Provision do
|
|
5
|
+
def job(options={})
|
|
6
|
+
options = {:stdout => '', :stderr => '', :status => 0}.update options
|
|
7
|
+
mock(options)
|
|
8
|
+
end
|
|
9
|
+
|
|
5
10
|
describe '.run_commands' do
|
|
6
11
|
it "fails fast if a command fails" do
|
|
7
|
-
|
|
8
|
-
server = mock(:ssh => [job])
|
|
12
|
+
server = mock(:ssh => [job(:status => 1, :command => 'exit 1', :stderr => 'FAIL WHALE')])
|
|
9
13
|
capture_stdout do
|
|
10
14
|
expect do
|
|
11
15
|
RelevanceRails::Provision.run_commands server
|
|
@@ -13,4 +17,52 @@ describe RelevanceRails::Provision do
|
|
|
13
17
|
end.should =~ /STDERR: FAIL WHALE/
|
|
14
18
|
end
|
|
15
19
|
end
|
|
20
|
+
|
|
21
|
+
describe '.wait_for_ssh' do
|
|
22
|
+
|
|
23
|
+
let(:server) { mock("server") }
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
server.should_receive(:wait_for).ordered.and_return(true)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'retries if the first attempt fails' do
|
|
30
|
+
server.should_receive(:ssh).ordered.and_raise(Errno::ECONNREFUSED)
|
|
31
|
+
server.should_receive(:ssh).ordered.and_return([job(:command => 'echo')])
|
|
32
|
+
RelevanceRails::Provision.should_receive(:sleep).twice.with(10).and_return(10)
|
|
33
|
+
expect do
|
|
34
|
+
capture_stdout { RelevanceRails::Provision.wait_for_ssh(server) }
|
|
35
|
+
end.to_not raise_error
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'retries up to five times, then fails' do
|
|
39
|
+
server.should_receive(:ssh).ordered.exactly(5).times.and_raise(Errno::ECONNREFUSED)
|
|
40
|
+
RelevanceRails::Provision.should_receive(:sleep).exactly(5).times.with(10).and_return(10)
|
|
41
|
+
expect do
|
|
42
|
+
capture_stdout { RelevanceRails::Provision.wait_for_ssh(server) }
|
|
43
|
+
end.to raise_error SystemExit
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '.apt_installs' do
|
|
48
|
+
it 'retries if the first attempt fails' do
|
|
49
|
+
server = mock("server")
|
|
50
|
+
server.should_receive(:ssh).ordered.with('sudo apt-get update').and_return([job(:command => 'sudo apt-get update')])
|
|
51
|
+
server.should_receive(:ssh).ordered.with('sudo apt-get -y install ruby').and_return([job(:status => 1, :command => 'sudo apt-get -y install ruby')])
|
|
52
|
+
server.should_receive(:ssh).ordered.with('sudo apt-get update').and_return([job(:command => 'sudo apt-get update')])
|
|
53
|
+
server.should_receive(:ssh).ordered.with('sudo apt-get -y install ruby').and_return([job(:command => 'sudo apt-get -y install ruby')])
|
|
54
|
+
server.should_receive(:ssh).ordered.with('sudo apt-get -y install rubygems1.8').and_return([job(:command => 'sudo apt-get -y install rubygems1.8')])
|
|
55
|
+
expect do
|
|
56
|
+
capture_stdout { RelevanceRails::Provision.apt_installs(server) }
|
|
57
|
+
end.to_not raise_error
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'tries twice, then fails' do
|
|
61
|
+
server = mock("server")
|
|
62
|
+
server.should_receive(:ssh).exactly(3).with('sudo apt-get update').and_return([job(:status => 1, :command => 'sudo apt-get update')])
|
|
63
|
+
expect do
|
|
64
|
+
capture_stdout { RelevanceRails::Provision.apt_installs(server) }
|
|
65
|
+
end.to raise_error SystemExit
|
|
66
|
+
end
|
|
67
|
+
end
|
|
16
68
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: relevance_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.1.2
|
|
5
|
+
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Alex Redington
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-04-
|
|
12
|
+
date: 2012-04-19 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rails
|
|
@@ -32,17 +32,17 @@ dependencies:
|
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
33
33
|
none: false
|
|
34
34
|
requirements:
|
|
35
|
-
- -
|
|
35
|
+
- - '='
|
|
36
36
|
- !ruby/object:Gem::Version
|
|
37
|
-
version: 1.3.
|
|
37
|
+
version: 1.3.1
|
|
38
38
|
type: :runtime
|
|
39
39
|
prerelease: false
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
41
|
none: false
|
|
42
42
|
requirements:
|
|
43
|
-
- -
|
|
43
|
+
- - '='
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: 1.3.
|
|
45
|
+
version: 1.3.1
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
47
|
name: thor
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -139,6 +139,7 @@ files:
|
|
|
139
139
|
- Gemfile
|
|
140
140
|
- README.md
|
|
141
141
|
- Rakefile
|
|
142
|
+
- USAGE.md
|
|
142
143
|
- aws_config.example.yml
|
|
143
144
|
- bin/relevance_rails
|
|
144
145
|
- lib/generators/deployment/deployment_generator.rb
|
|
@@ -158,6 +159,7 @@ files:
|
|
|
158
159
|
- lib/generators/relevance_file/templates/spec_helper.rb
|
|
159
160
|
- lib/relevance_rails.rb
|
|
160
161
|
- lib/relevance_rails/chef_dna.rb
|
|
162
|
+
- lib/relevance_rails/fog_ext/ssh.rb
|
|
161
163
|
- lib/relevance_rails/generator_overrides.rb
|
|
162
164
|
- lib/relevance_rails/provision.rb
|
|
163
165
|
- lib/relevance_rails/public_key_fetcher.rb
|
|
@@ -190,9 +192,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
190
192
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
193
|
none: false
|
|
192
194
|
requirements:
|
|
193
|
-
- - ! '
|
|
195
|
+
- - ! '>='
|
|
194
196
|
- !ruby/object:Gem::Version
|
|
195
|
-
version:
|
|
197
|
+
version: '0'
|
|
196
198
|
requirements: []
|
|
197
199
|
rubyforge_project: relevance_rails
|
|
198
200
|
rubygems_version: 1.8.21
|