relevance_rails 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,7 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ watch(%r{^spec/support/.+\.rb$}) { "spec" }
7
+ end
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 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.
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
- = conn = ActiveRecord::Base.connection
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 "No ssh keys were found! Check ssh-add -L and your keys_git_url config."
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 fetch_elzar
43
- git :remote => 'add -f elzar git://github.com/relevance/elzar.git'
44
- git :merge => '-s ours --no-commit elzar/master'
45
- git :"read-tree" => '--prefix=provision/ -u elzar/master'
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
- create_file('provision/.rvmrc', File.read(rvmrc), :force => true)
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/data_bags/deploy/authorized_keys.json'
75
- git :add => 'provision/Vagrantfile'
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
- local_keys = `ssh-add -L`.split("\n")
110
- local_keys = [] unless $?.success?
111
- (local_keys + RelevanceRails::PublicKeyFetcher.public_keys).uniq
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
- gem 'haml', '~> 3.1.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.6.0'
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
- class AptInstallError < StandardError
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
- server = provision_ec2_instances(name)
14
- wait_for_ssh server
15
- run_commands server
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
- server = fog_connection.servers.get(instance_id)
22
- server.stop
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
- server = fog_connection.servers.get(instance_id)
31
- server.destroy
32
- server.wait_for { state == "terminated" }
33
- puts "Removing config/ec2_instance.txt..."
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
- server = fog_connection.servers.get(instance_id)
40
- puts server.reload.dns_name
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('config/ec2_instance.txt').chomp
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
- server = fog_connection.servers.create(config['server']['creation_config'])
60
- fog_connection.tags.create(:key => 'Name',
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
- server
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? user_git_url
7
- git_url = File.read user_git_url
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 '--version'
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 app_name
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 '--relevance-dev'
70
- rubygem = "#{ENV['rvm_path']}/gems/#{current_gemset}/cache/relevance_rails-#{RelevanceRails::VERSION}.gem"
71
- child_env.run('gem', 'install', rubygem)
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
- abort "Unable to install relevance_rails into the new gemset" if result.exit_status != 0
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)
@@ -1,3 +1,3 @@
1
1
  module RelevanceRails
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,7 +1,6 @@
1
1
  require "relevance_rails/version"
2
2
  require "relevance_rails/public_key_fetcher"
3
- require "relevance_rails/chef_dna"
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
@@ -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.add_development_dependency 'pry'
27
+ s.add_runtime_dependency 'elzar', '~> 0.1.0'
28
+
35
29
  s.add_development_dependency 'capybara'
36
- s.add_development_dependency 'rspec'
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 "ruby-1.9.2@relevance_rails"
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=postgresql --relevance-dev
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 "ruby-1.9.2@$RAILS_APP"
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
- builtin cd $RAILS_APP
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 :environment_name => '1.9.3@default'
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
- ** Better error handling when the aws.yml is not present
19
- ** On an uncaught exception, destroy the ec2 instances (?)
20
- ** RelevanceRails::Provision.wait_for_ssh intermittently hangs
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.1.2
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-04-19 00:00:00.000000000 Z
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: fog
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.3.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.3.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: pry
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: capybara
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/lib/provision_config_generator_spec.rb
176
- - spec/lib/provision_spec.rb
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: relevance_rails
200
- rubygems_version: 1.8.21
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,6 +0,0 @@
1
- {
2
- "id":"authorized_keys",
3
- "keys": [
4
- <%= authorized_keys.join(",\n") %>
5
- ]
6
- }
@@ -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
@@ -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