relevance_rails 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +11 -0
- data/Guardfile +7 -0
- data/Rakefile +8 -0
- data/USAGE.md +5 -4
- data/lib/generators/fixtures/fixtures_generator.rb +1 -2
- data/lib/generators/provision_config/provision_config_generator.rb +39 -31
- data/lib/generators/relevance_file/templates/Gemfile.erb +5 -2
- data/lib/relevance_rails/provision.rb +35 -108
- data/lib/relevance_rails/public_key_fetcher.rb +2 -2
- data/lib/relevance_rails/runner.rb +14 -10
- data/lib/relevance_rails/version.rb +1 -1
- data/lib/relevance_rails.rb +1 -2
- data/relevance_rails.gemspec +8 -11
- data/script/ci +6 -2
- data/script/ci_nightly +23 -7
- data/script/elzar_nightly +33 -0
- data/spec/elzar_recipes_spec.rb +88 -0
- data/spec/lib/generators/provision_config/provision_config_generator_spec.rb +116 -0
- data/spec/lib/{runner_spec.rb → relevance_rails/runner_spec.rb} +2 -3
- data/spec/spec_helper.rb +1 -0
- data/techdebt.md +7 -9
- metadata +94 -19
- data/lib/generators/provision_config/templates/authorized_keys.json.erb +0 -6
- data/lib/relevance_rails/chef_dna.rb +0 -34
- data/spec/lib/provision_config_generator_spec.rb +0 -26
- data/spec/lib/provision_spec.rb +0 -68
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
*v0.2.0*
|
2
|
+
|
3
|
+
* Depend on slushy for provisioning
|
4
|
+
* Depend on elzar as a gem
|
5
|
+
** elzar's chef recipes stay in elzar
|
6
|
+
** relevance_rails has no knowledge of elzar's recipe internals
|
7
|
+
* Search for local ssh public keys before querying ssh-agent
|
8
|
+
* Improved UX around retrying failed commands
|
9
|
+
* Fix fixtures generator
|
10
|
+
* Generated Rails app depends on haml <= 3.1.4 due to haml 3.1.5 bug
|
11
|
+
|
1
12
|
*v0.1.2*
|
2
13
|
|
3
14
|
* add streaming output from chef convergence using a fog monkeypatch
|
data/Guardfile
ADDED
data/Rakefile
CHANGED
@@ -9,3 +9,11 @@ task :acceptance do
|
|
9
9
|
ENV["ACCEPTANCE"] = "true"
|
10
10
|
Rake::Task[:spec].invoke
|
11
11
|
end
|
12
|
+
|
13
|
+
# Do not run using bundle exec!
|
14
|
+
# FakeFS causes issues when bundler injects it into the require chain.
|
15
|
+
desc 'Run the elzar nightly specs'
|
16
|
+
RSpec::Core::RakeTask.new :elzar_nightly do |t|
|
17
|
+
t.pattern = 'spec/elzar_recipes_spec.rb'
|
18
|
+
t.rspec_opts = '-t ci'
|
19
|
+
end
|
data/USAGE.md
CHANGED
@@ -13,10 +13,11 @@ $ rails g provision_config postgresql
|
|
13
13
|
Configuring bundled ssh keys
|
14
14
|
----------------------------
|
15
15
|
|
16
|
-
By default, relevance_rails bundles
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
By default, relevance_rails bundles one of your local keys (~/.ssh/id_rsa.pub, ~/.ssh/id_dsa.pub, or
|
17
|
+
~/.ssh/id_ecdsa.pub) with your instance. If none are found it bundles all your keys from `ssh-add
|
18
|
+
-L`. For bundling additional keys, you can create a ~/.relevance_rails/keys_git_url file and point it
|
19
|
+
to a git repo that has additional keys. Keys in that git repo should exist as top level *.pub files.
|
20
|
+
You *MUST* have at least one key to provision.
|
20
21
|
|
21
22
|
Provisioning on EC2
|
22
23
|
-------------------
|
@@ -11,8 +11,7 @@ STR
|
|
11
11
|
%h1 WELCOME HOME
|
12
12
|
STR
|
13
13
|
create_file "app/views/relevance_rails/db.html.haml", <<-STR
|
14
|
-
|
15
|
-
= results = conn.execute("select 4200+42 as advanced_math")
|
14
|
+
- results = ActiveRecord::Base.connection.select_all("select 4200+42 as advanced_math")
|
16
15
|
%h1.advanced_math= results.first["advanced_math"]
|
17
16
|
STR
|
18
17
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'relevance_rails'
|
2
|
+
require 'tempfile'
|
2
3
|
require 'rails/generators'
|
4
|
+
require 'elzar'
|
3
5
|
|
4
6
|
class ProvisionConfigGenerator < Rails::Generators::Base
|
5
7
|
include RelevanceRails::GeneratorOverrides
|
@@ -27,7 +29,14 @@ class ProvisionConfigGenerator < Rails::Generators::Base
|
|
27
29
|
|
28
30
|
def check_authorized_keys
|
29
31
|
if (@authorized_keys = fetch_keys).empty?
|
30
|
-
abort
|
32
|
+
abort <<-EOF
|
33
|
+
No SSH public keys were found!
|
34
|
+
|
35
|
+
To ensure you have remote access to your servers, an SSH public key must be available from at least one of these sources:
|
36
|
+
- local file (~/.ssh/id_rsa.pub, ~/.ssh/id_dsa.pub, or ~/.ssh/id_ecdsa.pub)
|
37
|
+
- ssh-agent (by running `ssh-add -L`)
|
38
|
+
- public keys git repo (URL to repo specified in ~/.relevance_rails/key_git_url)
|
39
|
+
EOF
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|
@@ -39,42 +48,23 @@ class ProvisionConfigGenerator < Rails::Generators::Base
|
|
39
48
|
git :commit => '-m "Add Capistrano files"'
|
40
49
|
end
|
41
50
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
gsub_file 'provision/Vagrantfile', /config\.vm\.host_name(\s+)= .*$/,
|
47
|
-
"config.vm.host_name\\1= '#{name.gsub('_','-')}.local'"
|
48
|
-
end
|
49
|
-
|
50
|
-
def create_authorized_key_data_bag
|
51
|
-
@authorized_keys.map! {|key| "\"#{key}\""}
|
52
|
-
template('authorized_keys.json.erb', 'provision/data_bags/deploy/authorized_keys.json', {:force => true})
|
53
|
-
end
|
54
|
-
|
55
|
-
def create_dna_json
|
56
|
-
path = File.expand_path('provision/dna.json', destination_root)
|
57
|
-
json = JSON.parse File.binread(path)
|
58
|
-
json['rails_app']['name'] = name
|
59
|
-
RelevanceRails::ChefDNA.gene_splice(json,database)
|
60
|
-
create_file('provision/dna.json', JSON.generate(json), {:force => true})
|
51
|
+
def create_provision_directory
|
52
|
+
Elzar.create_provision_directory Rails.root.join('provision'),
|
53
|
+
:ruby_version => RelevanceRails.ruby_version, :database => database,
|
54
|
+
:authorized_keys => @authorized_keys, :app_name => name
|
61
55
|
end
|
62
56
|
|
63
57
|
def create_rvmrc
|
64
58
|
if File.exists?(rvmrc = Rails.root.join('.rvmrc'))
|
65
|
-
|
66
|
-
git :add => 'provision/.rvmrc'
|
59
|
+
copy_file(rvmrc, 'provision/.rvmrc', :force => true)
|
67
60
|
else
|
68
61
|
remove_file 'provision/.rvmrc'
|
69
|
-
git :rm => 'provision/.rvmrc'
|
70
62
|
end
|
71
63
|
end
|
72
64
|
|
73
65
|
def commit_changes
|
74
|
-
git :add => 'provision/
|
75
|
-
git :
|
76
|
-
git :add => 'provision/dna.json'
|
77
|
-
git :commit => '-m "Merge Elzar as our provision subdirectory"'
|
66
|
+
git :add => 'provision/'
|
67
|
+
git :commit => "-m 'Provision directory auto-created by elzar #{Elzar::VERSION}'"
|
78
68
|
end
|
79
69
|
|
80
70
|
private
|
@@ -104,10 +94,28 @@ class ProvisionConfigGenerator < Rails::Generators::Base
|
|
104
94
|
git :add => destination
|
105
95
|
end
|
106
96
|
|
107
|
-
|
108
97
|
def fetch_keys
|
109
|
-
|
110
|
-
|
111
|
-
|
98
|
+
keys = local_keys
|
99
|
+
keys = ssh_agent_keys if keys.empty?
|
100
|
+
keys += RelevanceRails::PublicKeyFetcher.public_keys
|
101
|
+
keys.uniq
|
102
|
+
end
|
103
|
+
|
104
|
+
def local_keys
|
105
|
+
key_files = [
|
106
|
+
File.expand_path("~/.ssh/id_dsa.pub"),
|
107
|
+
File.expand_path("~/.ssh/id_ecdsa.pub"),
|
108
|
+
File.expand_path("~/.ssh/id_rsa.pub"),
|
109
|
+
]
|
110
|
+
key_files.select { |p| File.exist?(p) }.take(1).map { |p| split_keys(File.read(p)) }.flatten(1)
|
111
|
+
end
|
112
|
+
|
113
|
+
def ssh_agent_keys
|
114
|
+
keys = split_keys(`ssh-add -L`)
|
115
|
+
$?.success? ? keys : []
|
116
|
+
end
|
117
|
+
|
118
|
+
def split_keys(s)
|
119
|
+
s.split("\n").reject { |k| k.blank? }
|
112
120
|
end
|
113
121
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
3
|
gem 'rails', '~> 3.2.2'
|
4
|
-
|
4
|
+
# Avoiding 3.1.5 which has a bug with aliasing
|
5
|
+
# AbstractController::Rendering#render_to_body
|
6
|
+
# https://github.com/haml/haml/issues/519
|
7
|
+
gem 'haml', '>= 3.1.0', '<= 3.1.4'
|
5
8
|
gem 'configatron', '~> 2.8.3'
|
6
9
|
gem 'airbrake', '~> 3.0.4'
|
7
10
|
gem 'factory_girl_rails', '~> 1.2.0'
|
@@ -29,7 +32,7 @@ end
|
|
29
32
|
group "development", "test" do
|
30
33
|
gem 'capybara', '~> 1.1.1'
|
31
34
|
gem 'selenium-webdriver', '~> 2.5.0'
|
32
|
-
gem 'rspec-rails', '~> 2.
|
35
|
+
gem 'rspec-rails', '~> 2.9.0'
|
33
36
|
gem 'mocha', '~> 0.9.12'
|
34
37
|
gem 'guard-rspec', '~> 0.5.0', :require => false
|
35
38
|
gem 'growl', '~> 1.0.3', :require => false
|
@@ -1,49 +1,59 @@
|
|
1
1
|
require 'fog'
|
2
2
|
require 'thor'
|
3
|
-
require 'timeout'
|
4
3
|
require 'relevance_rails/fog_ext/ssh'
|
4
|
+
require 'slushy'
|
5
|
+
require 'elzar'
|
5
6
|
|
6
7
|
module RelevanceRails
|
7
8
|
module Provision
|
8
|
-
|
9
|
-
end
|
9
|
+
CONFIG_FILE = 'config/ec2_instance.txt'
|
10
10
|
|
11
11
|
def self.create_ec2(name = nil)
|
12
12
|
abort "Please provide a $NAME" unless name
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
slushy = provision_ec2_instances(name)
|
14
|
+
slushy.bootstrap
|
15
|
+
tmpdir = Elzar.merge_and_create_temp_directory Rails.root.join('provision')
|
16
|
+
slushy.converge tmpdir
|
17
|
+
server = slushy.server
|
18
|
+
puts "Server Instance: #{server.id}"
|
19
|
+
puts "Server IP: #{server.public_ip_address}"
|
20
|
+
server
|
16
21
|
end
|
17
22
|
|
18
23
|
def self.stop_ec2
|
19
|
-
return unless ENV["FORCE"] == "true" || Thor::Shell::Basic.new.yes?("Are you sure you want to shut down EC2 instance #{instance_id}?")
|
24
|
+
return unless (ENV["FORCE"] == "true") || Thor::Shell::Basic.new.yes?("Are you sure you want to shut down EC2 instance #{instance_id}?")
|
20
25
|
puts "Shutting down EC2 instance #{instance_id}..."
|
21
|
-
|
22
|
-
|
23
|
-
server.wait_for { state == "stopped" }
|
26
|
+
slushy = Slushy::Instance.new(fog_connection, instance_id)
|
27
|
+
slushy.stop
|
24
28
|
puts "Done!"
|
25
29
|
end
|
26
30
|
|
27
31
|
def self.destroy_ec2
|
28
|
-
return unless ENV["FORCE"] == "true" || Thor::Shell::Basic.new.yes?("Are you sure you want to destroy EC2 instance #{instance_id}?")
|
32
|
+
return unless (ENV["FORCE"] == "true") || Thor::Shell::Basic.new.yes?("Are you sure you want to destroy EC2 instance #{instance_id}?")
|
29
33
|
puts "Destroying EC2 instance #{instance_id}..."
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
File.delete('config/ec2_instance.txt')
|
34
|
+
slushy = Slushy::Instance.new(fog_connection, instance_id)
|
35
|
+
slushy.terminate
|
36
|
+
puts "Removing #{CONFIG_FILE}..."
|
37
|
+
File.delete(CONFIG_FILE)
|
35
38
|
puts "Done!"
|
36
39
|
end
|
37
40
|
|
38
41
|
def self.current_dns
|
39
|
-
|
40
|
-
|
42
|
+
puts current_server.reload.dns_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.current_server
|
46
|
+
fog_connection.servers.get(instance_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.private_key
|
50
|
+
config['server']['private_key']
|
41
51
|
end
|
42
52
|
|
43
53
|
private
|
44
54
|
|
45
55
|
def self.instance_id
|
46
|
-
@instance_id ||= File.read(
|
56
|
+
@instance_id ||= File.read(CONFIG_FILE).chomp
|
47
57
|
end
|
48
58
|
|
49
59
|
def self.config
|
@@ -56,97 +66,14 @@ module RelevanceRails
|
|
56
66
|
|
57
67
|
def self.provision_ec2_instances(name)
|
58
68
|
puts "Provisioning an instance..."
|
59
|
-
|
60
|
-
|
61
|
-
:value => "#{name}",
|
62
|
-
:resource_id => server.id)
|
63
|
-
server.private_key = config['server']['private_key']
|
64
|
-
|
65
|
-
File.open("config/ec2_instance.txt", "w") do |f|
|
66
|
-
f.puts(server.id)
|
67
|
-
end
|
69
|
+
conf = config['server']['creation_config']
|
70
|
+
conf['tags'] = {'Name' => name}
|
68
71
|
|
72
|
+
slushy = Slushy::Instance.launch(fog_connection, conf)
|
73
|
+
slushy.server.private_key = private_key
|
74
|
+
File.open(CONFIG_FILE, "w") { |f| f.puts(slushy.server.id) }
|
69
75
|
puts "Provisioned!"
|
70
|
-
|
76
|
+
slushy
|
71
77
|
end
|
72
|
-
|
73
|
-
def self.run_commands(server)
|
74
|
-
apt_installs(server)
|
75
|
-
puts "Installing chef..."
|
76
|
-
run_command(server, 'sudo gem install chef --no-ri --no-rdoc --version 0.10.8')
|
77
|
-
puts "Copying chef resources from provision directory..."
|
78
|
-
server.scp("#{Rails.root.join('provision')}/", '/tmp/chef-solo', :recursive => true)
|
79
|
-
puts "Converging server, this may take a while (10-20 minutes)"
|
80
|
-
run_command(server, 'cd /tmp/chef-solo && sudo /var/lib/gems/1.8/bin/chef-solo -c solo.rb -j dna.json')
|
81
|
-
|
82
|
-
puts "Server Instance: #{server.id}"
|
83
|
-
puts "Server IP: #{server.public_ip_address}"
|
84
|
-
server
|
85
|
-
end
|
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
|
-
|
124
|
-
def self.run_command(server, command)
|
125
|
-
jobs = server.ssh(command)
|
126
|
-
exit 1 unless jobs_succeeded?(jobs)
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.wait_for_ssh(server)
|
130
|
-
puts "Waiting for ssh connectivity..."
|
131
|
-
server.wait_for { ready? }
|
132
|
-
retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], "Connecting to Amazon refused. Retrying...") do
|
133
|
-
sleep 10
|
134
|
-
Timeout.timeout(60) { server.ssh('ls') }
|
135
|
-
end
|
136
|
-
puts "Server up and listening for SSH!"
|
137
|
-
end
|
138
|
-
|
139
|
-
def self.jobs_succeeded?(jobs)
|
140
|
-
return true if jobs.all? { |job| job.status == 0 }
|
141
|
-
jobs.each do |job|
|
142
|
-
puts "----------------------"
|
143
|
-
puts "Command '#{job.command}'"
|
144
|
-
puts "STDOUT: #{job.stdout}"
|
145
|
-
puts "STDERR: #{job.stderr}"
|
146
|
-
puts "----------------------"
|
147
|
-
end
|
148
|
-
false
|
149
|
-
end
|
150
|
-
|
151
78
|
end
|
152
79
|
end
|
@@ -3,8 +3,8 @@ require 'tmpdir'
|
|
3
3
|
module RelevanceRails::PublicKeyFetcher
|
4
4
|
def self.public_keys
|
5
5
|
pubkeys = []
|
6
|
-
return pubkeys unless File.exist?
|
7
|
-
git_url = File.read
|
6
|
+
return pubkeys unless File.exist?(user_git_url)
|
7
|
+
git_url = File.read(user_git_url)
|
8
8
|
return pubkeys unless git_url =~ /\/(.*)\.git/
|
9
9
|
repo_name = $1
|
10
10
|
Dir.mktmpdir('public_keys') { |dir|
|
@@ -3,17 +3,17 @@ require 'relevance_rails'
|
|
3
3
|
module RelevanceRails
|
4
4
|
class Runner
|
5
5
|
def self.start(argv=ARGV)
|
6
|
-
if argv.empty? || argv[0] == '--help' || argv[0] == '-h'
|
6
|
+
if argv.empty? || (argv[0] == '--help') || (argv[0] == '-h')
|
7
7
|
print_help
|
8
|
-
elsif argv.delete
|
8
|
+
elsif argv.delete('--version')
|
9
9
|
puts "RelevanceRails #{RelevanceRails::VERSION}"
|
10
10
|
elsif argv[0] == 'new'
|
11
11
|
add_default_options! argv
|
12
|
-
if ENV['rvm_path'].nil?
|
12
|
+
if ENV['rvm_path'].nil? || ENV['NO_RVM']
|
13
13
|
exec 'rails', *argv
|
14
14
|
else
|
15
15
|
app_name = argv[1]
|
16
|
-
env = setup_rvm
|
16
|
+
env = setup_rvm(app_name)
|
17
17
|
|
18
18
|
new_rvm_string = "#{env.environment_name.split('@')[0]}@#{app_name}"
|
19
19
|
install_relevance_rails argv, new_rvm_string, env.environment_name
|
@@ -54,9 +54,7 @@ STR
|
|
54
54
|
# in 1.12.0, so you don't use this trick anymore.
|
55
55
|
$LOAD_PATH.unshift "#{ENV['rvm_path']}/lib"
|
56
56
|
end
|
57
|
-
|
58
57
|
require 'rvm'
|
59
|
-
|
60
58
|
env = RVM::Environment.current
|
61
59
|
env.gemset_create(app_name)
|
62
60
|
env
|
@@ -66,13 +64,19 @@ STR
|
|
66
64
|
child_env = RVM::Environment.new(new_rvm_string)
|
67
65
|
puts "Installing relevance_rails into the app's gemset..."
|
68
66
|
|
69
|
-
result = if argv.delete
|
70
|
-
|
71
|
-
|
67
|
+
result = if argv.delete('--relevance-dev')
|
68
|
+
gem_dir = "#{ENV['rvm_path']}/gems/#{current_gemset}/cache"
|
69
|
+
require 'elzar'
|
70
|
+
child_env.run('gem', 'install', "#{gem_dir}/elzar-#{Elzar::VERSION}.gem")
|
71
|
+
child_env.run('gem', 'install', "#{gem_dir}/relevance_rails-#{RelevanceRails::VERSION}.gem")
|
72
72
|
else
|
73
73
|
child_env.run('gem', 'install', 'relevance_rails', '-v', RelevanceRails::VERSION)
|
74
74
|
end
|
75
|
-
|
75
|
+
if result.exit_status != 0
|
76
|
+
abort "Unable to install relevance_rails into the new gemset. " +
|
77
|
+
"\nExit code: #{result.exit_status}" +
|
78
|
+
"\nFailed with:\n#{result.stderr}"
|
79
|
+
end
|
76
80
|
end
|
77
81
|
|
78
82
|
def self.add_default_options!(argv)
|
data/lib/relevance_rails.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "relevance_rails/version"
|
2
2
|
require "relevance_rails/public_key_fetcher"
|
3
|
-
require
|
4
|
-
require 'relevance_rails/railtie' if defined? Rails
|
3
|
+
require 'relevance_rails/railtie' if defined?(Rails)
|
5
4
|
require 'relevance_rails/generator_overrides'
|
6
5
|
|
7
6
|
module RelevanceRails
|
data/relevance_rails.gemspec
CHANGED
@@ -8,31 +8,28 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.homepage = "http://github.com/relevance/relevance_rails"
|
9
9
|
s.authors = ["Alex Redington"]
|
10
10
|
s.email = ["alex.redington@thinkrelevance.com"]
|
11
|
-
s.homepage = ""
|
12
11
|
s.summary = %q{Rails 3 Relevance style, with all infrastructure bits automated away.}
|
13
12
|
s.description = %q{A Rails 3 wrapper which forces template use and includes a plethora of generators for standard Relevance bits.}
|
14
13
|
|
15
|
-
s.rubyforge_project = "relevance_rails"
|
16
|
-
|
17
14
|
s.files = `git ls-files`.split("\n")
|
18
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
-
s.require_paths = ["lib"]
|
21
17
|
|
22
|
-
s.bindir = 'bin'
|
23
18
|
s.executables = ['relevance_rails']
|
24
19
|
|
25
|
-
# specify any dependencies here; for example:
|
26
|
-
s.add_runtime_dependency 'rails', '~> 3.2'
|
27
|
-
|
28
20
|
# be aware that we're monkey-patching fog in fog_ext/ssh.rb;
|
29
21
|
# if we update fog, that monkey-patch might need to be
|
30
22
|
# revisited
|
31
23
|
s.add_runtime_dependency 'fog', '1.3.1'
|
32
|
-
|
24
|
+
s.add_runtime_dependency 'rails', '~> 3.2'
|
25
|
+
s.add_runtime_dependency 'slushy', '~> 0.1.1'
|
33
26
|
s.add_runtime_dependency 'thor', '~> 0.14.6'
|
34
|
-
s.
|
27
|
+
s.add_runtime_dependency 'elzar', '~> 0.1.0'
|
28
|
+
|
35
29
|
s.add_development_dependency 'capybara'
|
36
|
-
s.add_development_dependency '
|
30
|
+
s.add_development_dependency 'fakefs'
|
31
|
+
s.add_development_dependency 'guard-rspec'
|
32
|
+
s.add_development_dependency 'pry'
|
37
33
|
s.add_development_dependency 'rake', '~> 0.9.2.2'
|
34
|
+
s.add_development_dependency 'rspec'
|
38
35
|
end
|
data/script/ci
CHANGED
@@ -25,9 +25,13 @@ function files_must_NOT_exist {
|
|
25
25
|
RAILS_APP="app_for_ci"
|
26
26
|
TARGET_HOST="placeholder.example.com"
|
27
27
|
|
28
|
+
# Set overrideable defaults
|
29
|
+
: ${CI_DATABASE:="postgresql"}
|
30
|
+
: ${CI_RUBY_VERSION:="ruby-1.9.2"}
|
31
|
+
|
28
32
|
# Setup RVM
|
29
33
|
source "$HOME/.rvm/scripts/rvm"
|
30
|
-
rvm use "
|
34
|
+
rvm use "$CI_RUBY_VERSION@relevance_rails"
|
31
35
|
echo "RVM is now using:` rvm current`"
|
32
36
|
|
33
37
|
# exit if any statement fails;
|
@@ -50,7 +54,7 @@ rvm --force gemset delete $RAILS_APP
|
|
50
54
|
set -e
|
51
55
|
echo "Done"
|
52
56
|
|
53
|
-
relevance_rails new $RAILS_APP --database
|
57
|
+
relevance_rails new $RAILS_APP --database=$CI_DATABASE --relevance-dev
|
54
58
|
|
55
59
|
# NOTE: this does NOT change the RVM gemset; we set it manually below
|
56
60
|
builtin cd $RAILS_APP
|
data/script/ci_nightly
CHANGED
@@ -13,36 +13,53 @@ function stop_server_and_exit {
|
|
13
13
|
echo "Stopping newly-created server..."
|
14
14
|
bundle exec rake provision:stop FORCE=true --trace
|
15
15
|
echo "Done."
|
16
|
+
else
|
17
|
+
echo "No server to stop (i.e. can't find config/ec2_instance.txt)."
|
16
18
|
fi
|
17
19
|
|
18
20
|
echo "BUILD FAILED"
|
19
21
|
exit 1
|
20
22
|
}
|
21
23
|
|
24
|
+
function cd_rails_app {
|
25
|
+
builtin cd $RAILS_APP
|
26
|
+
rvm gemset use $RAILS_APP
|
27
|
+
}
|
28
|
+
|
22
29
|
echo "RVM is now using:` rvm current`"
|
23
30
|
|
31
|
+
if [ -z $CI_RUBY_VERSION ]; then
|
32
|
+
echo 'You must specify $CI_RUBY_VERSION!'
|
33
|
+
exit 1
|
34
|
+
fi
|
35
|
+
|
36
|
+
if [ -z $CI_DATABASE ]; then
|
37
|
+
echo 'You must specify $CI_DATABASE!'
|
38
|
+
exit 1
|
39
|
+
fi
|
40
|
+
|
24
41
|
set -e
|
25
42
|
./script/ci
|
26
43
|
set +e
|
27
44
|
|
28
45
|
source "$HOME/.rvm/scripts/rvm"
|
29
|
-
rvm use "
|
46
|
+
rvm use "$CI_RUBY_VERSION@$RAILS_APP"
|
30
47
|
echo "RVM is now using:` rvm current`"
|
31
48
|
|
32
49
|
builtin cd $RAILS_APP
|
33
|
-
|
50
|
+
|
34
51
|
echo "Provisioning an EC2 instance..."
|
35
52
|
rm -f $EC2_MEMENTO_FILE
|
36
53
|
server_name="Nightly Build Testing - `date "+%Y-%m-%d %H:%M:%S"` "
|
37
54
|
bundle exec rake --trace provision:ec2 NAME="$server_name"
|
38
55
|
[ $? -ne 0 ] && stop_server_and_exit
|
39
56
|
echo "Done!"
|
40
|
-
|
57
|
+
|
41
58
|
echo "Determine the EC2 instance's DNS name..."
|
42
59
|
TARGET_HOST=`bundle exec rake provision:current_dns`
|
43
60
|
[ $? -ne 0 ] && stop_server_and_exit
|
44
61
|
echo "Done."
|
45
|
-
|
62
|
+
|
46
63
|
echo "Generating relevance_rails deployment scripts..."
|
47
64
|
./script/rails generate deployment staging $TARGET_HOST --force
|
48
65
|
[ $? -ne 0 ] && stop_server_and_exit
|
@@ -67,11 +84,10 @@ echo "RVM is now using:` rvm current`"
|
|
67
84
|
|
68
85
|
echo "Running the acceptance tests against our newly-created server..."
|
69
86
|
ACCEPTANCE_HOST=$TARGET_HOST rake acceptance --trace
|
70
|
-
[ $? -ne 0 ] && stop_server_and_exit
|
87
|
+
[ $? -ne 0 ] && cd_rails_app && stop_server_and_exit
|
71
88
|
echo "Done."
|
72
89
|
|
73
|
-
|
74
|
-
rvm gemset use $RAILS_APP
|
90
|
+
cd_rails_app
|
75
91
|
|
76
92
|
echo "Terminating our newly-created server..."
|
77
93
|
bundle exec rake provision:destroy FORCE=true --trace
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
RAILS_APP="elzar_nightly_app"
|
4
|
+
EC2_MEMENTO_FILE="config/ec2_instance.txt"
|
5
|
+
|
6
|
+
function stop_server_and_exit {
|
7
|
+
if [ -f $EC2_MEMENTO_FILE ]; then
|
8
|
+
echo "Stopping newly-created server..."
|
9
|
+
bundle exec rake provision:stop FORCE=true --trace
|
10
|
+
else
|
11
|
+
echo "No server to stop (i.e. can't find config/ec2_instance.txt)."
|
12
|
+
fi
|
13
|
+
|
14
|
+
echo "BUILD FAILED"
|
15
|
+
exit 1
|
16
|
+
}
|
17
|
+
|
18
|
+
source "$HOME/.rvm/scripts/rvm"
|
19
|
+
export CI_GEMSET=elzar_nightly
|
20
|
+
# Tests and app are all running in CI_GEMSET
|
21
|
+
export NO_RVM=true
|
22
|
+
|
23
|
+
rvm use "$CI_RUBY_VERSION@$CI_GEMSET"
|
24
|
+
gem install bundler
|
25
|
+
bundle install
|
26
|
+
|
27
|
+
# DO NOT bundle exec rake - fakefs activation borks everything
|
28
|
+
rake elzar_nightly
|
29
|
+
|
30
|
+
[ $? -ne 0 ] && builtin cd $RAILS_APP && stop_server_and_exit
|
31
|
+
|
32
|
+
builtin cd $RAILS_APP
|
33
|
+
bundle exec rake provision:destroy FORCE=true --trace
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'relevance_rails/provision'
|
4
|
+
|
5
|
+
describe "Elzar recipes", :ci => true do
|
6
|
+
let(:rails_app) { ENV['RAILS_APP'] || 'elzar_nightly_app' }
|
7
|
+
let(:server_name) { "Elzar Nightly (#{database} / #{ruby_version}) - #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}" }
|
8
|
+
let(:database) { ENV['CI_DATABASE'] || 'mysql' }
|
9
|
+
let(:database_cmd) { { 'mysql' => 'mysql', 'postgresql' => 'psql'}[database] }
|
10
|
+
let(:ruby_version) { ENV['CI_RUBY_VERSION'] || 'ruby-1.9.3-p125' }
|
11
|
+
let(:ruby_bin_path) {
|
12
|
+
ruby_version.start_with?('ree-') ? '/opt/ruby-enterprise/bin' : '/opt/relevance-ruby/bin'
|
13
|
+
}
|
14
|
+
let(:gemset) { ENV['CI_GEMSET'] || 'elzar_nightly' }
|
15
|
+
|
16
|
+
# wrapper around system
|
17
|
+
def shell(cmd)
|
18
|
+
puts "Executing #{cmd}..."
|
19
|
+
system(cmd)
|
20
|
+
abort "Command '#{cmd}' failed" unless $?.success?
|
21
|
+
end
|
22
|
+
|
23
|
+
def sh(cmd)
|
24
|
+
shell "#{ruby_version}@#{gemset} -S #{cmd}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def rake(cmd)
|
28
|
+
sh "bundle exec rake #{cmd}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# New app is created in current gemset
|
32
|
+
def create_new_app
|
33
|
+
rake 'install --trace'
|
34
|
+
FileUtils.rm_rf(rails_app)
|
35
|
+
sh "relevance_rails new #{rails_app} --database=#{database} --relevance-dev"
|
36
|
+
end
|
37
|
+
|
38
|
+
def ssh(cmd)
|
39
|
+
server = RelevanceRails::Provision.current_server
|
40
|
+
server.username = 'relevance'
|
41
|
+
server.private_key = RelevanceRails::Provision.private_key
|
42
|
+
job = nil
|
43
|
+
capture_stdout { job = server.ssh(cmd).first }
|
44
|
+
job
|
45
|
+
end
|
46
|
+
|
47
|
+
def command_succeeds(cmd)
|
48
|
+
ssh(cmd).status.should == 0
|
49
|
+
end
|
50
|
+
|
51
|
+
before(:all) do
|
52
|
+
create_new_app
|
53
|
+
Dir.chdir rails_app
|
54
|
+
rake %[provision:ec2 NAME="#{server_name}" --trace]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "installs the right ruby" do
|
58
|
+
job = ssh "#{ruby_bin_path}/ruby -v"
|
59
|
+
if ruby_version.start_with?('ree-')
|
60
|
+
job.stdout.include?("Ruby Enterprise Edition").should be_true
|
61
|
+
else
|
62
|
+
version_number = ruby_version.sub(/^ruby/, '').tr('-', '')
|
63
|
+
job.stdout.start_with?("ruby #{version_number}").should be_true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "installs the correct database" do
|
68
|
+
command_succeeds("#{database_cmd} --version")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "creates a deploy user" do
|
72
|
+
command_succeeds("ls /home/deploy")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "creates nginx and configures it" do
|
76
|
+
# TODO: get nginx version from elzar
|
77
|
+
command_succeeds "/opt/nginx-1.0.10/sbin/nginx -h"
|
78
|
+
command_succeeds "ls /etc/nginx/nginx.conf"
|
79
|
+
command_succeeds "ls /etc/init.d/nginx"
|
80
|
+
command_succeeds "ls /etc/nginx/sites-enabled/#{rails_app}"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "installs passenger gem and configures it" do
|
84
|
+
command_succeeds "#{ruby_bin_path}/gem list passenger$ |grep passenger -q"
|
85
|
+
command_succeeds "ls /etc/nginx/conf.d/passenger.conf"
|
86
|
+
command_succeeds %[grep -q "passenger_ruby #{ruby_bin_path}/ruby;" /etc/nginx/conf.d/passenger.conf]
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'fakefs/spec_helpers'
|
4
|
+
require 'generators/provision_config/provision_config_generator'
|
5
|
+
|
6
|
+
describe ProvisionConfigGenerator do
|
7
|
+
subject { ProvisionConfigGenerator.new(["name"]) }
|
8
|
+
|
9
|
+
describe "#local_keys" do
|
10
|
+
include FakeFS::SpecHelpers
|
11
|
+
|
12
|
+
def write_fixture(path, contents)
|
13
|
+
FileUtils.mkdir_p(File.dirname(path))
|
14
|
+
File.open(path, "w") { |f| f.write(contents) }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the contents of id_rsa.pub when it exists" do
|
18
|
+
write_fixture(File.expand_path("~/.ssh/id_rsa.pub"), "RSA-public-key")
|
19
|
+
subject.send(:local_keys).should == ["RSA-public-key"]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the contents of id_dsa.pub when it exists" do
|
23
|
+
write_fixture(File.expand_path("~/.ssh/id_dsa.pub"), "DSA-public-key")
|
24
|
+
subject.send(:local_keys).should == ["DSA-public-key"]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns the contents of id_ecdsa.pub when it exists" do
|
28
|
+
write_fixture(File.expand_path("~/.ssh/id_ecdsa.pub"), "ECDSA-public-key")
|
29
|
+
subject.send(:local_keys).should == ["ECDSA-public-key"]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns the contents of id_dsa.pub when both id_dsa.pub and id_rsa.pub exist" do
|
33
|
+
write_fixture(File.expand_path("~/.ssh/id_dsa.pub"), "DSA-public-key")
|
34
|
+
write_fixture(File.expand_path("~/.ssh/id_rsa.pub"), "RSA-public-key")
|
35
|
+
subject.send(:local_keys).should == ["DSA-public-key"]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "ignores trailing newlines" do
|
39
|
+
write_fixture(File.expand_path("~/.ssh/id_rsa.pub"), "RSA-public-key\n\n")
|
40
|
+
subject.send(:local_keys).should == ["RSA-public-key"]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "ignores blank lines" do
|
44
|
+
write_fixture(File.expand_path("~/.ssh/id_rsa.pub"), "\n\nRSA-public-key\n\n\n")
|
45
|
+
subject.send(:local_keys).should == ["RSA-public-key"]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#ssh_agent_keys" do
|
50
|
+
it "retrieves keys from ssh agent" do
|
51
|
+
subject.should_receive("`").with("ssh-add -L") do
|
52
|
+
system("true")
|
53
|
+
"my-public-key\nanother-public-key"
|
54
|
+
end
|
55
|
+
subject.send(:ssh_agent_keys).should == ["my-public-key", "another-public-key"]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "ignores output from ssh-add when execution fails" do
|
59
|
+
subject.stub("`") do
|
60
|
+
system("false")
|
61
|
+
# Actual message that comes back from failed call
|
62
|
+
"The agent has no entities"
|
63
|
+
end
|
64
|
+
subject.send(:ssh_agent_keys).should == []
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#fetch_keys" do
|
69
|
+
it "returns local keys when they exist" do
|
70
|
+
subject.stub(:local_keys).and_return(["key-from-local-file"])
|
71
|
+
subject.stub(:ssh_agent_keys).and_return(["key-from-ssh-agent"])
|
72
|
+
RelevanceRails::PublicKeyFetcher.stub(:public_keys).and_return([])
|
73
|
+
subject.send(:fetch_keys).should == ["key-from-local-file"]
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns keys from ssh agent when local keys do NOT exist" do
|
77
|
+
subject.stub(:local_keys).and_return([])
|
78
|
+
subject.stub(:ssh_agent_keys).and_return(["key-from-ssh-agent"])
|
79
|
+
RelevanceRails::PublicKeyFetcher.stub(:public_keys).and_return([])
|
80
|
+
subject.send(:fetch_keys).should == ["key-from-ssh-agent"]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "combines local keys with those from PublicKeyFetcher" do
|
84
|
+
subject.stub(:local_keys).and_return(["key-from-local-file"])
|
85
|
+
RelevanceRails::PublicKeyFetcher.stub(:public_keys).and_return(["key-from-git-repo"])
|
86
|
+
subject.send(:fetch_keys).should == ["key-from-local-file", "key-from-git-repo"]
|
87
|
+
end
|
88
|
+
|
89
|
+
it "combines ssh agent keys with those from PublicKeyFetcher" do
|
90
|
+
subject.stub(:local_keys).and_return([])
|
91
|
+
subject.stub(:ssh_agent_keys).and_return(["key-from-ssh-agent"])
|
92
|
+
RelevanceRails::PublicKeyFetcher.stub(:public_keys).and_return(["key-from-git-repo"])
|
93
|
+
subject.send(:fetch_keys).should == ["key-from-ssh-agent", "key-from-git-repo"]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "excludes duplicate keys" do
|
97
|
+
subject.stub(:local_keys).and_return(["key-1", "key-2", "key-1"])
|
98
|
+
RelevanceRails::PublicKeyFetcher.stub(:public_keys).and_return(["key-3", "key-2", "key-3"])
|
99
|
+
subject.send(:fetch_keys).should == ["key-1", "key-2", "key-3"]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#check_authorized_keys" do
|
104
|
+
it "aborts if no ssh-keys are found" do
|
105
|
+
subject.stub(:fetch_keys).and_return([])
|
106
|
+
should_abort_with(/^No SSH public keys were found!/) do
|
107
|
+
subject.check_authorized_keys
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "doesn't abort if ssh-keys are found" do
|
112
|
+
subject.should_receive(:fetch_keys).and_return(['ssh-rsa ZZZZ'])
|
113
|
+
expect { subject.check_authorized_keys }.to_not raise_error
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -15,10 +15,9 @@ describe RelevanceRails::Runner do
|
|
15
15
|
it "new calls exec" do
|
16
16
|
RelevanceRails::Runner.should_receive(:exec).with(anything,
|
17
17
|
'-S', 'rails', 'new', 'the_app', '-m',
|
18
|
-
File.expand_path(File.dirname(__FILE__)
|
19
|
-
"/../../lib/relevance_rails/relevance_rails_template.rb"))
|
18
|
+
File.expand_path("../../../lib/relevance_rails/relevance_rails_template.rb", File.dirname(__FILE__)))
|
20
19
|
RelevanceRails::Runner.should_receive(:install_relevance_rails)
|
21
|
-
env = mock
|
20
|
+
env = mock(:environment_name => '1.9.3@default')
|
22
21
|
RelevanceRails::Runner.should_receive(:setup_rvm).and_return(env)
|
23
22
|
start('new', 'the_app')
|
24
23
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -44,6 +44,7 @@ RSpec.configure do |config|
|
|
44
44
|
config.include TestHelpers
|
45
45
|
config.filter_run :focused => true
|
46
46
|
config.filter_run_excluding :acceptance => true
|
47
|
+
config.filter_run_excluding :ci => true
|
47
48
|
config.filter_run_excluding :disabled => true
|
48
49
|
config.run_all_when_everything_filtered = true
|
49
50
|
end
|
data/techdebt.md
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
* TECHDEBT BY COMPONENT *
|
2
2
|
|
3
3
|
* GENERAL
|
4
|
-
** remove heredocs, replace by erb templates
|
5
4
|
** move all general configuration to a ~/.relevance_rails.yml file (AWS stuff, keys git repo stuff)
|
6
|
-
** cleaner rvm version detection - intermittenly picks up no version
|
7
5
|
** intermittent mysql::server failures (mysql server not up yet) on `vagrant up`. Attempt fix in site_cookbooks
|
8
|
-
** intermittent setup failure - apt-get update fails with 404s or ruby not found
|
9
6
|
** when generating an app with --database=postgresql, provision_config
|
10
7
|
generator intermittently fails at the beginning with different gem not found
|
11
8
|
errors. Generating the app more than once or inspecting the problem solves it
|
12
9
|
** provision_config generator intermittently can't detect current working directory which breaks
|
13
10
|
git commands. Current solution of sprinkling Dir.chdir is a bandaid at best.
|
14
|
-
|
15
|
-
* Provisioning an instance
|
16
|
-
** Don't hardcode path to chef binstub, caused by ubuntu installing weirdness
|
17
11
|
** Make the deployment generator idempotent
|
18
|
-
**
|
19
|
-
|
20
|
-
|
12
|
+
** Have pg and mysql recipes depend on a unified gem install method. This method would call
|
13
|
+
gem_package for mri and ree_gem for ree. When this is done, we can add --dont-install-useful-gems
|
14
|
+
back to the ree installer.
|
15
|
+
** Upgrade to haml > 3.1.5 once AbstractController::Rendering#render_to_body bug is resolved
|
16
|
+
** bundle exec rake elzar_nightly breaks due to fakefs being activated early in require chain.
|
17
|
+
Calling the rake task works fine locally and on CI. Attempting to not require fakefs in the
|
18
|
+
Gemfile didn't work.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relevance_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.3.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - '='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.3.1
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rails
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,21 +44,21 @@ dependencies:
|
|
28
44
|
- !ruby/object:Gem::Version
|
29
45
|
version: '3.2'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
47
|
+
name: slushy
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
33
49
|
none: false
|
34
50
|
requirements:
|
35
|
-
- -
|
51
|
+
- - ~>
|
36
52
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
53
|
+
version: 0.1.1
|
38
54
|
type: :runtime
|
39
55
|
prerelease: false
|
40
56
|
version_requirements: !ruby/object:Gem::Requirement
|
41
57
|
none: false
|
42
58
|
requirements:
|
43
|
-
- -
|
59
|
+
- - ~>
|
44
60
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
61
|
+
version: 0.1.1
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: thor
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,7 +76,23 @@ dependencies:
|
|
60
76
|
- !ruby/object:Gem::Version
|
61
77
|
version: 0.14.6
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
79
|
+
name: elzar
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.1.0
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.1.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: capybara
|
64
96
|
requirement: !ruby/object:Gem::Requirement
|
65
97
|
none: false
|
66
98
|
requirements:
|
@@ -76,7 +108,7 @@ dependencies:
|
|
76
108
|
- !ruby/object:Gem::Version
|
77
109
|
version: '0'
|
78
110
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
111
|
+
name: fakefs
|
80
112
|
requirement: !ruby/object:Gem::Requirement
|
81
113
|
none: false
|
82
114
|
requirements:
|
@@ -92,7 +124,23 @@ dependencies:
|
|
92
124
|
- !ruby/object:Gem::Version
|
93
125
|
version: '0'
|
94
126
|
- !ruby/object:Gem::Dependency
|
95
|
-
name: rspec
|
127
|
+
name: guard-rspec
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: pry
|
96
144
|
requirement: !ruby/object:Gem::Requirement
|
97
145
|
none: false
|
98
146
|
requirements:
|
@@ -123,6 +171,22 @@ dependencies:
|
|
123
171
|
- - ~>
|
124
172
|
- !ruby/object:Gem::Version
|
125
173
|
version: 0.9.2.2
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: rspec
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
126
190
|
description: A Rails 3 wrapper which forces template use and includes a plethora of
|
127
191
|
generators for standard Relevance bits.
|
128
192
|
email:
|
@@ -137,6 +201,7 @@ files:
|
|
137
201
|
- .travis.yml
|
138
202
|
- CHANGELOG.md
|
139
203
|
- Gemfile
|
204
|
+
- Guardfile
|
140
205
|
- README.md
|
141
206
|
- Rakefile
|
142
207
|
- USAGE.md
|
@@ -146,7 +211,6 @@ files:
|
|
146
211
|
- lib/generators/fixtures/fixtures_generator.rb
|
147
212
|
- lib/generators/provision_config/provision_config_generator.rb
|
148
213
|
- lib/generators/provision_config/templates/Capfile
|
149
|
-
- lib/generators/provision_config/templates/authorized_keys.json.erb
|
150
214
|
- lib/generators/provision_config/templates/deploy.rb.erb
|
151
215
|
- lib/generators/provision_config/templates/recipes_deploy.rb
|
152
216
|
- lib/generators/provision_config/templates/vagrant.rb
|
@@ -158,7 +222,6 @@ files:
|
|
158
222
|
- lib/generators/relevance_file/templates/database.example.yml.postgresql.erb
|
159
223
|
- lib/generators/relevance_file/templates/spec_helper.rb
|
160
224
|
- lib/relevance_rails.rb
|
161
|
-
- lib/relevance_rails/chef_dna.rb
|
162
225
|
- lib/relevance_rails/fog_ext/ssh.rb
|
163
226
|
- lib/relevance_rails/generator_overrides.rb
|
164
227
|
- lib/relevance_rails/provision.rb
|
@@ -171,13 +234,14 @@ files:
|
|
171
234
|
- relevance_rails.gemspec
|
172
235
|
- script/ci
|
173
236
|
- script/ci_nightly
|
237
|
+
- script/elzar_nightly
|
174
238
|
- spec/acceptance_spec.rb
|
175
|
-
- spec/
|
176
|
-
- spec/lib/
|
177
|
-
- spec/lib/runner_spec.rb
|
239
|
+
- spec/elzar_recipes_spec.rb
|
240
|
+
- spec/lib/generators/provision_config/provision_config_generator_spec.rb
|
241
|
+
- spec/lib/relevance_rails/runner_spec.rb
|
178
242
|
- spec/spec_helper.rb
|
179
243
|
- techdebt.md
|
180
|
-
homepage:
|
244
|
+
homepage: http://github.com/relevance/relevance_rails
|
181
245
|
licenses: []
|
182
246
|
post_install_message:
|
183
247
|
rdoc_options: []
|
@@ -189,16 +253,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
189
253
|
- - ! '>='
|
190
254
|
- !ruby/object:Gem::Version
|
191
255
|
version: '0'
|
256
|
+
segments:
|
257
|
+
- 0
|
258
|
+
hash: 3573380774667230504
|
192
259
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
260
|
none: false
|
194
261
|
requirements:
|
195
262
|
- - ! '>='
|
196
263
|
- !ruby/object:Gem::Version
|
197
264
|
version: '0'
|
265
|
+
segments:
|
266
|
+
- 0
|
267
|
+
hash: 3573380774667230504
|
198
268
|
requirements: []
|
199
|
-
rubyforge_project:
|
200
|
-
rubygems_version: 1.8.
|
269
|
+
rubyforge_project:
|
270
|
+
rubygems_version: 1.8.24
|
201
271
|
signing_key:
|
202
272
|
specification_version: 3
|
203
273
|
summary: Rails 3 Relevance style, with all infrastructure bits automated away.
|
204
|
-
test_files:
|
274
|
+
test_files:
|
275
|
+
- spec/acceptance_spec.rb
|
276
|
+
- spec/elzar_recipes_spec.rb
|
277
|
+
- spec/lib/generators/provision_config/provision_config_generator_spec.rb
|
278
|
+
- spec/lib/relevance_rails/runner_spec.rb
|
279
|
+
- spec/spec_helper.rb
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module RelevanceRails::ChefDNA
|
2
|
-
def self.gene_splice(json, database)
|
3
|
-
set_ruby(json)
|
4
|
-
set_database(json, database)
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.set_database(json, database)
|
8
|
-
if database == 'postgresql'
|
9
|
-
db_index = json['run_list'].find_index { |e| e == 'mysql::server' || e == 'role[postgres_database]'}
|
10
|
-
json['run_list'][db_index] = 'role[postgres_database]'
|
11
|
-
elsif database.nil? || database == 'mysql'
|
12
|
-
db_index = json['run_list'].find_index { |e| e == 'mysql::server' || e == 'role[postgres_database]'}
|
13
|
-
json['run_list'][db_index] = 'mysql::server'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.set_ruby(json)
|
18
|
-
if RelevanceRails.ruby_version =~ /^ree-(.*)/i
|
19
|
-
json['ruby_enterprise']['version'] = $1
|
20
|
-
json['ruby_enterprise']['url'] = "http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise-#{$1}"
|
21
|
-
appstack_index = json['run_list'].find_index {|e| e[/^role\[.*_appstack\]$/] }
|
22
|
-
json['run_list'][appstack_index] = 'role[enterprise_appstack]'
|
23
|
-
elsif RelevanceRails.ruby_version =~ /^ruby-(.*)/i
|
24
|
-
full_version = $1
|
25
|
-
json['ruby']['version'] = full_version
|
26
|
-
major_version = full_version[/(\d\.\d).*/, 1]
|
27
|
-
json['ruby']['url'] = "http://ftp.ruby-lang.org/pub/ruby/#{major_version}/ruby-#{full_version}.tar.gz"
|
28
|
-
appstack_index = json['run_list'].find_index {|e| e[/^role\[.*_appstack\]$/] }
|
29
|
-
json['run_list'][appstack_index] = 'role[ruby_appstack]'
|
30
|
-
else
|
31
|
-
raise "Your ruby is NOT SUPPORTED. Please use ree or ruby."
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'generators/provision_config/provision_config_generator'
|
3
|
-
|
4
|
-
describe ProvisionConfigGenerator do
|
5
|
-
context '#check_authorized_keys' do
|
6
|
-
subject { ProvisionConfigGenerator.new(['name']) }
|
7
|
-
|
8
|
-
it "aborts if no ssh-keys are found" do
|
9
|
-
subject.should_receive(:`).and_return do
|
10
|
-
system('exit 1')
|
11
|
-
# Actual message that comes back from failed call
|
12
|
-
'The agent has no entities'
|
13
|
-
end
|
14
|
-
RelevanceRails::PublicKeyFetcher.should_receive(:public_keys).and_return([])
|
15
|
-
|
16
|
-
should_abort_with(/^No ssh keys were found!/) do
|
17
|
-
subject.check_authorized_keys
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
it "doesn't abort if ssh-keys are found" do
|
22
|
-
subject.should_receive(:fetch_keys).and_return(['ssh-rsa ZZZZ'])
|
23
|
-
expect { subject.check_authorized_keys }.to_not raise_error
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/spec/lib/provision_spec.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'relevance_rails/provision'
|
3
|
-
|
4
|
-
describe RelevanceRails::Provision do
|
5
|
-
def job(options={})
|
6
|
-
options = {:stdout => '', :stderr => '', :status => 0}.update options
|
7
|
-
mock(options)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe '.run_commands' do
|
11
|
-
it "fails fast if a command fails" do
|
12
|
-
server = mock(:ssh => [job(:status => 1, :command => 'exit 1', :stderr => 'FAIL WHALE')])
|
13
|
-
capture_stdout do
|
14
|
-
expect do
|
15
|
-
RelevanceRails::Provision.run_commands server
|
16
|
-
end.to raise_error SystemExit
|
17
|
-
end.should =~ /STDERR: FAIL WHALE/
|
18
|
-
end
|
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
|
68
|
-
end
|