elzar 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +46 -83
  5. data/README.md +19 -17
  6. data/USAGE.md +257 -0
  7. data/bin/elzar +94 -0
  8. data/chef/site-cookbooks/ruby/metadata.rb +3 -1
  9. data/chef/site-cookbooks/ruby/recipes/default.rb +1 -0
  10. data/chef/site-cookbooks/ruby/recipes/path.rb +17 -0
  11. data/elzar.gemspec +4 -0
  12. data/lib/elzar.rb +5 -1
  13. data/lib/elzar/assistant.rb +82 -70
  14. data/lib/elzar/aws_config.rb +46 -0
  15. data/lib/elzar/cli.rb +143 -0
  16. data/lib/elzar/compute.rb +52 -0
  17. data/lib/elzar/core_ext/hash.rb +18 -0
  18. data/lib/elzar/fog.rb +53 -0
  19. data/lib/elzar/ssh_key_locator.rb +37 -0
  20. data/lib/elzar/templates/Gemfile +4 -4
  21. data/lib/elzar/templates/Vagrantfile.erb +1 -1
  22. data/lib/elzar/templates/aws_config.private.yml +13 -0
  23. data/lib/elzar/templates/aws_config.yml +6 -0
  24. data/lib/elzar/templates/data_bags/deploy/authorized_keys.json +4 -5
  25. data/lib/elzar/templates/dna/rails.json +15 -0
  26. data/lib/elzar/templates/gitignore +1 -0
  27. data/lib/elzar/version.rb +1 -1
  28. data/script/ci_nightly +14 -0
  29. data/spec/fixtures/rails_integration_template/add_root_user.rb +9 -0
  30. data/spec/fixtures/rails_integration_template/database.yml +7 -0
  31. data/spec/fixtures/rails_integration_template/deploy.rb +11 -0
  32. data/spec/fixtures/rails_integration_template/template.rb +22 -0
  33. data/spec/integration/rails_spec.rb +190 -0
  34. data/spec/lib/elzar/assistant_spec.rb +30 -0
  35. data/spec/lib/elzar/aws_config_spec.rb +84 -0
  36. data/spec/lib/elzar/ssh_key_locator_spec.rb +51 -0
  37. data/spec/spec_helper.rb +11 -0
  38. data/spec/support/shell_interaction_helpers.rb +33 -0
  39. metadata +107 -7
  40. data/lib/elzar/chef_dna.rb +0 -48
  41. data/lib/elzar/templates/dna.json +0 -25
  42. data/spec/chef_dna_spec.rb +0 -58
@@ -0,0 +1,52 @@
1
+ require 'elzar/fog'
2
+ require 'slushy'
3
+ require 'yaml'
4
+
5
+ module Elzar
6
+ module Compute
7
+ def self.provision_and_bootstrap!(instance_name, aws_config)
8
+ instance_id, instance_ip = provision(instance_name, aws_config)
9
+ bootstrap(instance_id, aws_config)
10
+
11
+ [instance_id, instance_ip]
12
+ end
13
+
14
+ def self.provision(name, aws_config)
15
+ config = aws_config['server']['creation_config']
16
+ config['tags'] = {'Name' => name}
17
+
18
+ slushy_instance = Slushy::Instance.launch(fog_connection(aws_config), config)
19
+ [slushy_instance.instance_id, slushy_instance.server.public_ip_address]
20
+ end
21
+
22
+ def self.bootstrap(instance_id, aws_config)
23
+ slushy_instance = slushy_instance_for(instance_id, aws_config)
24
+ slushy_instance.bootstrap
25
+ end
26
+
27
+ def self.converge!(instance_id, aws_config)
28
+ tmpdir = Elzar.merge_and_create_temp_directory File.expand_path('provision/')
29
+ slushy_instance = slushy_instance_for(instance_id, aws_config)
30
+ slushy_instance.converge tmpdir
31
+
32
+ [slushy_instance.instance_id, slushy_instance.server.public_ip_address]
33
+ end
34
+
35
+ def self.destroy!(instance_id, aws_config)
36
+ slushy_instance = slushy_instance_for(instance_id, aws_config)
37
+ slushy_instance.terminate
38
+ end
39
+
40
+ private
41
+
42
+ def self.fog_connection(aws_config)
43
+ @fog_connection ||= Fog::Compute.new(aws_config['aws_credentials'].merge(:provider => 'AWS'))
44
+ end
45
+
46
+ def self.slushy_instance_for(instance_id, aws_config)
47
+ Slushy::Instance.new(fog_connection(aws_config), instance_id).tap do |s|
48
+ s.server.private_key = aws_config['server']['private_key']
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ module HashDeepMergeExt
2
+
3
+ # Implementation pulled from ActiveSupport
4
+ def deep_merge(other_hash)
5
+ dup.deep_merge!(other_hash)
6
+ end
7
+
8
+ def deep_merge!(other_hash)
9
+ other_hash.each_pair do |k,v|
10
+ tv = self[k]
11
+ self[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v
12
+ end
13
+ self
14
+ end
15
+
16
+ end
17
+
18
+ Hash.send(:include, HashDeepMergeExt) unless Hash.new.respond_to?(:deep_merge)
@@ -0,0 +1,53 @@
1
+ require 'fog'
2
+ require 'fog/core/ssh'
3
+
4
+ # Monkey-patch Fog 1.3.1 to stream SSH output
5
+ # (in real time) to stdout.
6
+ class Fog::SSH::Real
7
+ def run(commands)
8
+ commands = [*commands]
9
+ results = []
10
+ begin
11
+ Net::SSH.start(@address, @username, @options) do |ssh|
12
+ commands.each do |command|
13
+ result = Fog::SSH::Result.new(command)
14
+ ssh.open_channel do |ssh_channel|
15
+ ssh_channel.request_pty
16
+ ssh_channel.exec(command) do |channel, success|
17
+ unless success
18
+ raise "Could not execute command: #{command.inspect}"
19
+ end
20
+
21
+ channel.on_data do |ch, data|
22
+ result.stdout << data
23
+ puts data
24
+ end
25
+
26
+ channel.on_extended_data do |ch, type, data|
27
+ next unless type == 1
28
+ result.stderr << data
29
+ puts data
30
+ end
31
+
32
+ channel.on_request('exit-status') do |ch, data|
33
+ result.status = data.read_long
34
+ end
35
+
36
+ channel.on_request('exit-signal') do |ch, data|
37
+ result.status = 255
38
+ end
39
+ end
40
+ end
41
+ ssh.loop
42
+ results << result
43
+ end
44
+ end
45
+ rescue Net::SSH::HostKeyMismatch => exception
46
+ exception.remember_host!
47
+ sleep 0.2
48
+ retry
49
+ end
50
+ results
51
+ end
52
+ end
53
+
@@ -0,0 +1,37 @@
1
+ module Elzar
2
+ module SshKeyLocator
3
+
4
+ class << self
5
+ def default_key_file_paths
6
+ %w[id_dsa.pub id_ecdsa.pub id_rsa.pub].map do |base_filename|
7
+ File.expand_path("~/.ssh/#{base_filename}")
8
+ end
9
+ end
10
+
11
+ def find_keys(candidate_key_file_paths = default_key_file_paths)
12
+ local_keys = find_local_keys(candidate_key_file_paths)
13
+ local_keys.empty? ? find_agent_keys : local_keys
14
+ end
15
+
16
+ def find_local_keys(candidate_key_file_paths = default_key_file_paths)
17
+ first_existing_file = candidate_key_file_paths.find { |p| File.exist?(p) }
18
+ return [] unless first_existing_file
19
+
20
+ file_content = File.read(first_existing_file)
21
+ split_keys(file_content)
22
+ end
23
+
24
+ def find_agent_keys
25
+ keys = split_keys(`ssh-add -L`)
26
+ $?.success? ? keys : []
27
+ end
28
+
29
+ private
30
+
31
+ def split_keys(s)
32
+ s.split("\n").reject { |k| k.strip.empty? }
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -5,8 +5,8 @@ group "development" do
5
5
  gem "json", "1.5.2"
6
6
 
7
7
  gem "elzar"
8
- gem "vagrant", "0.8.7"
9
- gem "chef", "0.10.8"
10
- gem "knife-solo", "0.0.4"
11
- gem "knife-github-cookbooks", :git => "git://github.com/sumbach/knife-github-cookbooks.git"
8
+ gem "vagrant", "1.0.5"
9
+ gem "chef", "10.14.4"
10
+ gem "knife-solo", "0.0.14"
11
+ gem "knife-github-cookbooks", "~> 0.1.7"
12
12
  end
@@ -5,7 +5,7 @@ Vagrant::Config.run do |config|
5
5
  config.vm.box = "lucid64"
6
6
  config.vm.box_url = "http://files.vagrantup.com/lucid64.box"
7
7
  config.vm.host_name = <%= @vm_host_name.inspect %>
8
- config.vm.network "172.25.5.5"
8
+ config.vm.network :hostonly, "172.25.5.5"
9
9
  config.vm.provision :shell, :path => "upgrade-chef.sh"
10
10
  config.vm.provision :chef_solo do |chef|
11
11
  chef.cookbooks_path = <%= @cookbooks_path.inspect %>
@@ -0,0 +1,13 @@
1
+ # !!! DO NOT add this file to source control !!!
2
+ #
3
+ # Settings in this file override settings in aws_config.yml
4
+ aws_credentials:
5
+ aws_access_key_id: <your aws access key id>
6
+ aws_secret_access_key: <your aws secret access key>
7
+
8
+ server:
9
+ private_key: |
10
+ -----BEGIN RSA PRIVATE KEY-----
11
+ Include the RSA private key here. This should correspond to the keypair indicated
12
+ by server[:creation_config][:key_name] in aws_config.yml.
13
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,6 @@
1
+ server:
2
+ creation_config:
3
+ flavor_id: <instance type, e.g. 'm1.large'>
4
+ image_id: <AMI to bootstrap with; must be some Ubuntu server image; e.g., "ami-fd589594" for Ubuntu 11.04>
5
+ groups: <security group to place the new deployment in, e.g. "default">
6
+ key_name: <name of the public/private keypair to start instance with>
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "id":"authorized_keys",
3
3
  "keys": [
4
- "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzqe0G9iGh9QoCdBVYmaTIxZU0cZP15uiXtLUsOf+BAjniNy2tX6fM+9+Mwmz76sqPlpL/ai/eVKg/WlmjtZErInTUdEu5IGoNqORLtwxGtu4u0tl/bByIEeYInHqlFlQnyEFeSEcWwW9JKWC7jL3Wh4M8FZrrGIQ7yd+XF4Q3vUpL+MZThs3/+VSoGvqcPbRGHoLtlgjwsjobXI6ckj839SkT0zVPuIoUl7zxlD4FRH95Hv60fjVIFU3D2aeOJrLkqHFogGjrXG47AIjgw5Xb1cwTUA0zQQ1Lq5TF038smXEyvySPOAuPPTnBC11TuzADdEuI0zFmjSu2RYi4/TfZw== alex.redington@thinkrelevance.com",
5
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/aJwkhY3lpj6f62mpsy+fZ1lS90jF2cSTkX/bmjXrBO4yyFQsPFzsZhe6kdKkJGsVocppS8TZujzwL2vnhH4zfIIDIEwl9F9bqBznTwuwP0BcPIEJTEc7YVds2ocjR73A9YHHZxV7IfzYnYVunEmPtvPCSdQn+xq3V1bzY9tJJzXu/9DI0qxjTQAWB5nPfqyGwNnn2pcfNeZQquXMRHQnEyncpGq936vrYemwr25MlGNGzvhq0vQM8Qo5PSqh7XwSHR31aTsyL6RDF9nMOqHvqRsF+MKrsZSCYhjZ9ebuSRjdiDeWGNeYA8+zJJiirjJYwN6qxIGQ1AAkNrqZfKzV russolsen@thinkrelevance.com",
6
- "ssh-dss AAAAB3NzaC1kc3MAAACBAJCaIm17djv5DOGA0amRQTibubORv0mVCDnhkT/rYOIEAXr9S+s3JqrWqC9Q9++wFxVvuTr7rJArktoPQJXuAZfk9yH1Yyd2dhzMM/jHnw/TYKOnYj6mn4ygwARm9oZkuBI9AV81ICBtZPdBwPAH4vpOoY8FtKCCaiKrJdOCJfSPAAAAFQDlOSP4ehJY3w65d5GDEMftZ2va/wAAAIAUwmNmhG4W8LNv+ONsvJ/+GY2OumSJt72uzjcFRx9OLFzMgTG5YqQNuCbosA5SXvRS4w1F2+gPW/Tsdh9D3CElqOq3slMY+1JuDWznDK3byDe5sHQz8OOpjBtxFdn+bZJHTXercVpfIqjxR+903/zjYUT2tgv8kyZu44thn8+wRAAAAIBCoJqTsZwwErIH+RnX+LIETPYkKMt664CYb9mnNDj5a6hV/JX+ThiFdDd4YBUTVQkyNTQasJgOfZyauDT0BQJiEIiag1guvRtLhYH3PEId3vMsMGfv5349v2UqVr9g01CnbOL+yGc/Akxcw58/5QZe45S3A7hDbgUGsEBTNEuGaQ== sam@thinkrelevance.com",
7
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/kJu5qUgbtVqYdxxN0LvZMJ5//JRno7bgnQ8ZB6dAouyE13GaiJ3jl61xCdKIOe6FL9/x2C379fcj2MUXiq/iIH4bllgn9owux7TucE4bKmMm2DxwDH/A2kvES3V+7LznvSSyhUJTSIVII2gQdeSaeE1DrJDNJJv/riXvmP6BI1AaLJnfE82Ym7XuYeLqvz1f6pCwxCZipuxjqr8HNBL3MfVN4Dw2xxya5AwAiR5Za93fVmszXBoyGo+BaUTTjdGzb4ghGOHjgp7rdLWbRoVcyXWntXq0jQ/Jkdg0dUVvFgLA88/IjyKvstmI1SrKK6SlwCWLSjAESpX3xRG2FNhp gabriel.horner@gmail.com"
8
- ]
4
+ "TODO: Add your public SSH keys for the provisioned server here",
5
+ "TODO: Add your public SSH keys for the provisioned server here",
6
+ "TODO: Add your public SSH keys for the provisioned server here"
7
+ ]
9
8
  }
@@ -0,0 +1,15 @@
1
+ {
2
+ "run_list":["role[plumbing]", "role[postgres_database]", "ruby", "passenger", "rails_app", "ruby::path"],
3
+ "passenger": {
4
+ "version": "3.0.11",
5
+ "root_path": "/opt/relevance-ruby/lib/ruby/gems/1.9.1/gems/passenger-3.0.11",
6
+ "module_path": "/opt/relevance-ruby/lib/ruby/gems/1.9.1/gems/passenger-3.0.11/ext/apache2/mod_passenger.so"
7
+ },
8
+ "ruby": {
9
+ "version": "1.9.3-p194",
10
+ "url": "http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz"
11
+ },
12
+ "rails_app": {
13
+ "name": "TODO: Replace with the name of your Rails app"
14
+ }
15
+ }
@@ -0,0 +1 @@
1
+ aws_config.private.yml
@@ -1,3 +1,3 @@
1
1
  module Elzar
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ source "$HOME/.rvm/scripts/rvm"
4
+ export CI_RUBY_VERSION="ruby-1.9.3-p194"
5
+ export CI_GEMSET=elzar_nightly
6
+
7
+ # Tests and app are all running in CI_GEMSET
8
+ export NO_RVM=true
9
+
10
+ rvm use "$CI_RUBY_VERSION@$CI_GEMSET"
11
+ gem install bundler
12
+ bundle install
13
+
14
+ bundle exec rspec --tag ci
@@ -0,0 +1,9 @@
1
+ class AddRootUser < ActiveRecord::Migration
2
+ def up
3
+ User.find_or_create_by_username! 'root'
4
+ end
5
+
6
+ def down
7
+ raise ActiveRecord::IrreversibleMigration
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ production:
2
+ adapter: postgresql
3
+ encoding: unicode
4
+ database: elzar_nightly_app_production
5
+ pool: 5
6
+ username: deploy
7
+ password: d3pl0y-p0stgr3s
@@ -0,0 +1,11 @@
1
+ require 'bundler/capistrano'
2
+ require 'capistrano/relevance/all'
3
+
4
+ set :application, "elzar_nightly_app"
5
+ set :repository, "/tmp/elzar_nightly_app" # TODO Find a way not to duplicate this path here and inside the spec. Pass as env arg?
6
+
7
+ set(:server_ip) { ENV['SERVER_IP'] || raise("You must supply SERVER_IP") }
8
+
9
+ role :web, server_ip
10
+ role :app, server_ip
11
+ role :db, server_ip, :primary => true
@@ -0,0 +1,22 @@
1
+ TemplateRoot = File.expand_path '..', __FILE__
2
+
3
+ gem 'capistrano', :group => 'deployment', :git => 'git://github.com/capistrano/capistrano', :ref => 'b31e2f5'
4
+ gem 'capistrano-relevance', :group => 'deployment'
5
+
6
+ gem 'therubyracer', :group => 'assets', :platforms => :ruby
7
+
8
+ run 'bundle install'
9
+ run 'bundle exec capify .'
10
+
11
+ remove_file File.join('config', 'deploy.rb')
12
+ copy_file File.join(TemplateRoot, 'deploy.rb'), File.join('config', 'deploy.rb')
13
+
14
+ run 'rails generate scaffold user username:string'
15
+
16
+ next_migration_timestamp = (Time.now + 1)
17
+ migration_filename = next_migration_timestamp.utc.strftime("%Y%m%d%H%M%S") + '_add_root_user.rb'
18
+ copy_file File.join(TemplateRoot, 'add_root_user.rb'), File.join('db', 'migrate', migration_filename)
19
+
20
+ git :init
21
+ git :add => "."
22
+ git :commit => "-a -m 'Initial commit'"
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+ require 'json'
4
+
5
+ describe "Rails integration", :ci => true do
6
+ let(:rails_app) { 'elzar_nightly_app' }
7
+ let(:path_to_rails_app) { File.join '/tmp', rails_app }
8
+ let(:server_name) { "Elzar Nightly (rails) - #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}" }
9
+ let(:aws_config_dir) { ENV['AWS_CONFIG_DIR'] || raise('You must set AWS_CONFIG_DIR to run the integration tests') }
10
+ let(:instance_info) { { :id => nil, :ip => nil } }
11
+
12
+ ######################################################################
13
+ # Command line helpers
14
+ ######################################################################
15
+
16
+ # wrapper around system
17
+ def shell(cmd)
18
+ puts "Executing #{cmd}..."
19
+ Bundler.clean_system(cmd)
20
+ abort "Command '#{cmd}' failed" unless $?.success?
21
+ end
22
+
23
+ def elzar(args)
24
+ puts "Running `elzar #{args}`"
25
+
26
+ super
27
+
28
+ raise "Error running `elzar #{args}`. Failed with: #{stderr}" unless process.exitstatus == 0
29
+ end
30
+
31
+ def rake(cmd)
32
+ sh "bundle exec rake #{cmd}"
33
+ end
34
+
35
+ def in_rails_app(&block)
36
+ pwd = FileUtils.pwd
37
+ FileUtils.cd path_to_rails_app
38
+ yield
39
+ ensure
40
+ FileUtils.cd pwd
41
+ end
42
+
43
+ ######################################################################
44
+ # Rails app helpers
45
+ ######################################################################
46
+
47
+ def create_new_rails_app
48
+ shell "gem install rails"
49
+ FileUtils.rm_rf(path_to_rails_app)
50
+ rails_template = File.expand_path('../../fixtures/rails_integration_template/template.rb', __FILE__)
51
+ shell %Q{rails new "#{path_to_rails_app}" -d postgresql -m "#{rails_template}"}
52
+ end
53
+
54
+ def configure_elzar
55
+ in_rails_app do
56
+ rewrite_json('provision/dna.json') do |dna|
57
+ dna['rails_app']['name'] = rails_app
58
+ end
59
+ end
60
+ end
61
+
62
+ def rewrite_json(path_to_json, &block)
63
+ json = JSON.parse File.read(path_to_json)
64
+ yield json
65
+ File.open(path_to_json, 'w') { |f| f << JSON.generate(json) }
66
+ end
67
+
68
+ ######################################################################
69
+ # AWS helpers
70
+ ######################################################################
71
+
72
+ def aws_config
73
+ @aws_config ||= Elzar::AwsConfig.load_configs(aws_config_dir)
74
+ end
75
+
76
+ def fog
77
+ @fog ||= Fog::Compute.new(aws_config['aws_credentials'].merge(:provider => 'AWS'))
78
+ end
79
+
80
+ def server(instance_id)
81
+ fog.servers.get(instance_id).tap do |s|
82
+ s.private_key = aws_config['server']['private_key']
83
+ end
84
+ end
85
+
86
+ def ssh(server, cmd)
87
+ job = nil
88
+ capture_stdout { job = server.ssh(cmd).first }
89
+ job
90
+ end
91
+
92
+ def put_database_config_on_server(server)
93
+ shared_path = "/var/www/apps/#{rails_app}/shared/config"
94
+ path_to_db_config = File.expand_path('../../fixtures/rails_integration_template/database.yml', __FILE__)
95
+ server.scp path_to_db_config, "/home/ubuntu/database.yml"
96
+
97
+ ssh server, "sudo mkdir -p #{shared_path}"
98
+ ssh server, "sudo mv ~/database.yml #{shared_path}/database.yml"
99
+ ssh server, "sudo chown -R deploy:deploy #{shared_path}"
100
+ end
101
+
102
+ def destroy_instance(instance_id)
103
+ in_rails_app do
104
+ elzar "destroy \"#{instance_id}\" --aws_config_dir=#{aws_config_dir}"
105
+ end
106
+ end
107
+
108
+ def capture_instance_details(output)
109
+ id = output.match(/Instance ID: (.+)$/i)[1]
110
+ ip = output.match(/Instance IP: (.+)$/i)[1]
111
+ [id, ip]
112
+ end
113
+
114
+ ######################################################################
115
+ # Assertion helpers
116
+ ######################################################################
117
+
118
+ # Returns true if the command gives zero exit status, false for non zero exit status.
119
+ def execute_local_command(cmd)
120
+ Bundler.clean_system(cmd)
121
+ end
122
+
123
+ # Returns true if the command gives zero exit status, false for non zero exit status.
124
+ def execute_remote_command(server, cmd)
125
+ ssh(server, cmd).status == 0
126
+ end
127
+
128
+ def assert_state_after_init
129
+ in_rails_app do
130
+ execute_local_command('ls provision > /dev/null').should == true
131
+ execute_local_command('grep -q rails provision/dna.json').should == true
132
+ end
133
+ end
134
+
135
+ def assert_state_after_preheat(server)
136
+ execute_remote_command(server, 'gem list | grep chef').should == true
137
+ end
138
+
139
+ def assert_state_after_cook(server)
140
+ execute_remote_command(server, '/opt/relevance-ruby/bin/ruby -v | grep 1\.9\.3').should == true
141
+ execute_remote_command(server, 'sudo service postgresql status').should == true
142
+ execute_remote_command(server, 'sudo service nginx status').should == true
143
+ execute_remote_command(server, 'ls /home/deploy').should == true
144
+ end
145
+
146
+ def assert_state_after_deploy(server_ip)
147
+ execute_local_command(%Q{curl -sL -w '%{http_code}' #{server_ip} -o /dev/null | grep 200}).should == true
148
+ execute_local_command(%Q{curl -s #{server_ip}/users.json | grep '"username":"root"'}).should == true
149
+ end
150
+
151
+ it 'works' do
152
+ create_new_rails_app
153
+
154
+ in_rails_app do
155
+ elzar "init --dna=rails"
156
+ end
157
+
158
+ assert_state_after_init
159
+
160
+ in_rails_app do
161
+ configure_elzar
162
+ elzar %Q{preheat "#{server_name}" --aws_config_dir=#{aws_config_dir}}
163
+ instance_info[:id], instance_info[:ip] = capture_instance_details(stdout)
164
+ end
165
+
166
+ instance_info[:id].should_not == nil
167
+ instance_info[:ip].should_not == nil
168
+ server = server(instance_info[:id])
169
+
170
+ assert_state_after_preheat(server)
171
+
172
+ in_rails_app do
173
+ elzar "cook \"#{instance_info[:id]}\" --aws_config_dir=#{aws_config_dir}"
174
+ end
175
+
176
+ assert_state_after_cook(server)
177
+
178
+ in_rails_app do
179
+ shell %Q{SERVER_IP="#{instance_info[:ip]}" cap deploy:setup}
180
+ put_database_config_on_server(server)
181
+ shell %Q{SERVER_IP="#{instance_info[:ip]}" cap deploy}
182
+ end
183
+
184
+ assert_state_after_deploy(instance_info[:ip])
185
+ end
186
+
187
+ after(:each) do
188
+ destroy_instance(instance_info[:id]) if instance_info[:id]
189
+ end
190
+ end