engineyard 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  module EY
2
- class Account
2
+ module Model
3
3
  class Log < ApiStruct.new(:id, :role, :main, :custom)
4
4
  def instance_name
5
5
  "#{role} #{id}"
@@ -15,9 +15,9 @@ module EY
15
15
  end
16
16
 
17
17
  def urls
18
- `git config -f #{@path}/.git/config --get-regexp 'remote.*.url'`.split(/\n/).map do |c|
19
- c.split.last
20
- end
18
+ lines = `git config -f #{@path}/.git/config --get-regexp 'remote.*.url'`.split(/\n/)
19
+ raise NoRemotesError.new(@path) if lines.empty?
20
+ lines.map { |c| c.split.last }
21
21
  end
22
22
 
23
23
  end # Repo
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe EY::Account::ApiStruct do
4
- class Foo < EY::Account::ApiStruct.new(:fruit); end
5
- class FooWithAccount < EY::Account::ApiStruct.new(:fruit, :account); end
3
+ describe EY::Model::ApiStruct do
4
+ class Foo < EY::Model::ApiStruct.new(:fruit, :veggie); end
6
5
 
7
6
  it "acts like a normal struct" do
8
7
  f = Foo.new("banana")
@@ -28,10 +27,15 @@ describe EY::Account::ApiStruct do
28
27
  f.should == [Foo.new("banana")]
29
28
  end
30
29
 
31
- it "handles an account as the second argument" do
32
- f = FooWithAccount.from_array([:fruit => "banana"], "account")
33
- f.should == [FooWithAccount.new("banana", "account")]
30
+ it "handles a common-arguments hash as the second argument" do
31
+ foos = Foo.from_array(
32
+ [{:fruit => "banana"}, {:fruit => 'apple'}],
33
+ :veggie => 'kale')
34
+ foos.should == [
35
+ Foo.new("banana", "kale"),
36
+ Foo.new("apple", "kale"),
37
+ ]
34
38
  end
35
39
  end
36
40
 
37
- end
41
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe "EY::Model::Environment#rebuild" do
4
+ it_should_behave_like "it has an api"
5
+
6
+ it "hits the rebuild action in the API" do
7
+ env = EY::Model::Environment.from_hash({
8
+ "id" => 46534,
9
+ "api" => @api,
10
+ })
11
+
12
+ FakeWeb.register_uri(:put,
13
+ "https://cloud.engineyard.com/api/v2/environments/#{env.id}/rebuild",
14
+ :body => {}.to_json)
15
+
16
+ env.rebuild
17
+
18
+ FakeWeb.should have_requested(:put, "https://cloud.engineyard.com/api/v2/environments/#{env.id}/rebuild")
19
+ end
20
+ end
21
+
22
+ describe "EY::Model::Environment#instances" do
23
+ it_should_behave_like "it has an api"
24
+
25
+ it "returns instances" do
26
+ env = EY::Model::Environment.from_hash({
27
+ "id" => 10291,
28
+ "api" => @api,
29
+ })
30
+
31
+ instance_data = {
32
+ "id" => "1",
33
+ "role" => "app_master",
34
+ "amazon_id" => "i-likebeer",
35
+ "public_hostname" => "banana_master"
36
+ }
37
+ FakeWeb.register_uri(:get,
38
+ "https://cloud.engineyard.com/api/v2/environments/#{env.id}/instances",
39
+ :body => {"instances" => [instance_data]}.to_json)
40
+
41
+
42
+ env.should have(1).instances
43
+ env.instances.first.should == EY::Model::Instance.from_hash(instance_data.merge(:environment => env))
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe "EY::Model::Instance's script for checking ey-deploy's version" do
4
+
5
+ def fake_out_no_ey_deploy
6
+ Gem.should_receive(:source_index).and_return(Gem::SourceIndex.new)
7
+ end
8
+
9
+ def fake_out_installed_ey_deploy_version(version)
10
+ net_sftp_gem = Gem::Specification.new do |s|
11
+ s.authors = ["Jamis Buck"]
12
+ s.autorequire = "net/sftp"
13
+ s.date = Time.utc(2008, 2, 24)
14
+ s.email = "jamis@jamisbuck.org"
15
+ s.files = ["doc/faq",
16
+ # snip
17
+ "test/protocol/tc_driver.rb"]
18
+ s.homepage = "http://net-ssh.rubyforge.org/sftp"
19
+ s.name = "net-sftp"
20
+ s.require_paths = ["lib"]
21
+ s.rubygems_version = "1.3.5"
22
+ s.specification_version = 2
23
+ s.summary = "Net::SFTP is a pure-Ruby implementation of the SFTP client protocol."
24
+ s.test_files = ["test/ALL-TESTS.rb"]
25
+ s.version = Gem::Version.new("1.1.1")
26
+ end
27
+
28
+ ey_deploy_gem = Gem::Specification.new do |s|
29
+ s.name = 'ey-deploy'
30
+ s.authors = ["EY Cloud Team"]
31
+ s.date = Time.utc(2010, 1, 2)
32
+ s.files = ['lib/engineyard/ey-deploy.rb'] # or something
33
+ s.specification_version = 2
34
+ s.version = Gem::Version.new(version)
35
+ end
36
+
37
+ fake_source_index = Gem::SourceIndex.new(
38
+ 'net-sftp-1.1.1' => net_sftp_gem,
39
+ "ey-deploy-#{version}" => ey_deploy_gem
40
+ )
41
+ Gem.should_receive(:source_index).and_return(fake_source_index)
42
+ end
43
+
44
+ def script_exit_status
45
+ eval EY::Model::Instance::CHECK_SCRIPT
46
+ rescue SystemExit => e
47
+ return e.status
48
+ end
49
+
50
+ it "exits 104 if the ey-deploy gem is not installed" do
51
+ fake_out_no_ey_deploy
52
+ script_exit_status.should == 104
53
+ end
54
+
55
+ it "exits 70 if the installed ey-deploy is too old" do
56
+ fake_out_installed_ey_deploy_version('0.0.1')
57
+ script_exit_status.should == 70
58
+ end
59
+
60
+ it "exits 17 if the installed ey-deploy is too new" do
61
+ fake_out_installed_ey_deploy_version('1000.0.0')
62
+ script_exit_status.should == 17
63
+ end
64
+
65
+ it "exits 0 if the version number is correct" do
66
+ correct_version = EY::Model::Instance::EYSD_VERSION.gsub(/[^\d\.]/, '')
67
+ fake_out_installed_ey_deploy_version(correct_version)
68
+ script_exit_status.should == 0
69
+ end
70
+ end
@@ -26,26 +26,29 @@ describe EY::Repo do
26
26
  it "returns the urls of the remotes" do
27
27
  origin_url = "git://github.com/engineyard/engineyard.git"
28
28
  other_url = "git@github.com:engineyard/engineyard.git"
29
- set_url origin_url
30
- set_url other_url, "other"
29
+ set_url origin_url, "origin"
30
+ set_url other_url, "other"
31
31
  @r.urls.should include(origin_url)
32
32
  @r.urls.should include(other_url)
33
33
  end
34
34
 
35
- it "returns nil if there is no origin remote" do
36
- set_url nil
37
- @r.urls.should be_empty
35
+ it "raises EY::NoRemotesError if there is no origin remote" do
36
+ clear_urls
37
+ lambda { @r.urls }.should raise_error(EY::NoRemotesError)
38
38
  end
39
39
 
40
- def set_url(url, remote="origin")
41
- @config_path = @path+"config"
42
- # This has to all shell out because FakeFS is enabled
43
- if url
44
- system("mkdir -p #{@path} && cd #{@path} && git init -q")
45
- system("git config -f #{@config_path} remote.#{remote}.url #{url}")
46
- else
47
- system("rm -rf #{@config_path}")
48
- end
40
+ def config_path
41
+ @path+"config"
42
+ end
43
+
44
+ # This has to all shell out because FakeFS is enabled
45
+ def set_url(url, remote)
46
+ system("mkdir -p #{@path} && cd #{@path} && git init -q")
47
+ system("git config -f #{config_path} remote.#{remote}.url #{url}")
48
+ end
49
+
50
+ def clear_urls
51
+ system("rm -rf #{config_path}")
49
52
  end
50
53
  end # url
51
54
 
@@ -1,38 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "ey deploy" do
4
- # like the "an integration test" setup, but without the ~/.eyrc file
5
- # so we can test creating it
6
- before(:all) do
7
- FakeFS.deactivate!
8
- ENV['EYRC'] = "/tmp/eyrc"
9
- ENV['CLOUD_URL'] = EY.fake_awsm
10
- FakeWeb.allow_net_connect = true
11
- end
3
+ describe "ey deploy without an eyrc file" do
12
4
 
13
- after(:all) do
14
- ENV['CLOUD_URL'] = nil
15
- FakeFS.activate!
16
- FakeWeb.allow_net_connect = false
5
+ it_should_behave_like "an integration test without an eyrc file"
6
+
7
+ before(:each) do
8
+ FileUtils.rm_rf(ENV['EYRC'])
9
+ api_scenario "one app, one environment"
17
10
  end
18
11
 
19
- describe "without an eyrc file" do
20
- before(:each) do
21
- FileUtils.rm_rf(ENV['EYRC'])
22
- api_scenario "one app, one environment"
12
+ it "prompts for authentication before continuing" do
13
+ ey("deploy", :hide_err => true) do |input|
14
+ input.puts("test@test.test")
15
+ input.puts("test")
23
16
  end
24
17
 
25
- it "prompts for authentication before continuing" do
26
- ey("deploy", :hide_err => true) do |input|
27
- input.puts("test@test.test")
28
- input.puts("test")
29
- end
30
-
31
- @out.should include("We need to fetch your API token, please login")
32
- @out.should include("Email:")
33
- @out.should include("Password:")
34
- @ssh_commands.should_not be_empty
35
- end
18
+ @out.should include("We need to fetch your API token, please login")
19
+ @out.should include("Email:")
20
+ @out.should include("Password:")
21
+ @ssh_commands.should_not be_empty
36
22
  end
37
23
  end
38
24
 
@@ -42,25 +28,25 @@ describe "ey deploy" do
42
28
  context "with invalid input" do
43
29
  it "complains when there is no app" do
44
30
  api_scenario "empty"
45
- ey "deploy", :hide_err => true, :expect_failure => true
31
+ ey "deploy", :expect_failure => true
46
32
  @err.should include(%|no application configured|)
47
33
  end
48
34
 
49
35
  it "complains when you specify a nonexistent environment" do
50
36
  api_scenario "one app, one environment"
51
- ey "deploy typo-happens-here master", :hide_err => true, :expect_failure => true
37
+ ey "deploy typo-happens-here master", :expect_failure => true
52
38
  @err.should match(/no environment named 'typo-happens-here'/i)
53
39
  end
54
40
 
55
41
  it "complains when the specified environment does not contain the app" do
56
42
  api_scenario "one app, one environment, not linked"
57
- ey "deploy giblets master", :hide_err => true, :expect_failure => true
43
+ ey "deploy giblets master", :expect_failure => true
58
44
  @err.should match(/doesn't run this application/i)
59
45
  end
60
46
 
61
47
  it "complains when environment is ambiguous" do
62
48
  api_scenario "one app, two environments"
63
- ey "deploy", :hide_err => true, :expect_failure => true
49
+ ey "deploy", :expect_failure => true
64
50
  @err.should match(/was called incorrectly/i)
65
51
  end
66
52
  end
@@ -85,7 +71,7 @@ describe "ey deploy" do
85
71
  it "defaults to 'rake db:migrate'" do
86
72
  ey "deploy"
87
73
  @ssh_commands.last.should =~ /eysd deploy/
88
- @ssh_commands.last.should =~ /--migrate='rake db:migrate'/
74
+ @ssh_commands.last.should =~ /--migrate 'rake db:migrate'/
89
75
  end
90
76
 
91
77
  it "can be disabled with --no-migrate" do
@@ -98,12 +84,6 @@ describe "ey deploy" do
98
84
  ey "deploy --no-migrate giblets master"
99
85
  @ssh_commands.last.should_not =~ /--migrate/
100
86
  end
101
-
102
- it "can be disabled with --no-migrate" do
103
- ey "deploy --no-migrate"
104
- @ssh_commands.last.should =~ /eysd deploy/
105
- @ssh_commands.last.should_not =~ /--migrate/
106
- end
107
87
  end
108
88
 
109
89
  context "choosing something to deploy" do
@@ -127,6 +107,8 @@ describe "ey deploy" do
127
107
  [
128
108
  # initial repo setup
129
109
  'git init >/dev/null 2>&1',
110
+ 'git config user.email deploy@spec.test',
111
+ 'git config user.name "Deploy Spec"',
130
112
  'git remote add origin "user@git.host/path/to/repo.git"',
131
113
 
132
114
  # we'll have one commit on master
@@ -171,6 +153,22 @@ describe "ey deploy" do
171
153
  end
172
154
  end
173
155
 
156
+ context "when there is extra configuration" do
157
+ before(:all) do
158
+ write_yaml({"environments" => {"giblets" => {"bert" => "ernie"}}},
159
+ File.join(@local_git_dir, "ey.yml"))
160
+ end
161
+
162
+ after(:all) do
163
+ File.unlink(File.join(@local_git_dir, "ey.yml"))
164
+ end
165
+
166
+ it "gets passed along to eysd" do
167
+ ey "deploy"
168
+ @ssh_commands.last.should =~ /--config '\{\"bert\":\"ernie\"\}'/
169
+ end
170
+ end
171
+
174
172
  context "with a configured default branch" do
175
173
  before(:all) do
176
174
  write_yaml({"environments" => {"giblets" => {"branch" => "master"}}},
@@ -187,7 +185,7 @@ describe "ey deploy" do
187
185
  end
188
186
 
189
187
  it "complains about a non-default branch without --force" do
190
- ey "deploy giblets current-branch", :hide_err => true, :expect_failure => true
188
+ ey "deploy giblets current-branch", :expect_failure => true
191
189
  @err.should =~ /deploy branch is set to "master"/
192
190
  end
193
191
 
@@ -198,25 +196,77 @@ describe "ey deploy" do
198
196
  end
199
197
  end
200
198
 
199
+ context "specifying an environment" do
200
+ before(:all) do
201
+ api_scenario "one app, many similarly-named environments"
202
+ end
203
+
204
+ it "lets you choose by unambiguous substring" do
205
+ ey "deploy prod"
206
+ @out.should match(/Running deploy for 'railsapp_production'/)
207
+ end
208
+
209
+ it "lets you choose by complete name even if the complete name is ambiguous" do
210
+ ey "deploy railsapp_staging"
211
+ @out.should match(/Running deploy for 'railsapp_staging'/)
212
+ end
213
+
214
+ it "complains when given an ambiguous substring" do
215
+ # NB: there's railsapp_staging and railsapp_staging_2
216
+ ey "deploy staging", :hide_err => true, :expect_failure => true
217
+ @err.should match(/'staging' is ambiguous/)
218
+ end
219
+ end
220
+
201
221
  context "eysd install" do
202
222
  before(:all) do
203
223
  api_scenario "one app, one environment"
204
224
  end
205
225
 
206
- after(:all) do
226
+ before(:each) do
227
+ ENV.delete "NO_SSH"
228
+ end
229
+
230
+ after(:each) do
207
231
  ENV['NO_SSH'] = "true"
208
232
  end
209
233
 
210
- it "installs eysd if 'eysd check' fails" do
211
- ENV.delete('NO_SSH')
212
- fake_ssh_no_eysd = "#!/usr/bin/env ruby\n exit!(127) if ARGV.last =~ /eysd check/"
234
+ def exiting_ssh(exit_code)
235
+ "#!/usr/bin/env ruby\n exit!(#{exit_code}) if ARGV.to_s =~ /Base64.decode64/"
236
+ end
237
+
238
+ it "raises an error if SSH fails" do
239
+ ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(255)}, :expect_failure => true
240
+ @err.should =~ /SSH connection to \S+ failed/
241
+ end
213
242
 
214
- ey "deploy", :prepend_to_path => {'ssh' => fake_ssh_no_eysd}
243
+ it "installs ey-deploy if it's missing" do
244
+ ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(104)}
215
245
 
216
246
  gem_install_command = @ssh_commands.find do |command|
217
247
  command =~ /gem install ey-deploy/
218
248
  end
219
249
  gem_install_command.should =~ %r{/usr/local/ey_resin/ruby/bin/gem install}
220
250
  end
251
+
252
+ it "upgrades ey-deploy if it's too old" do
253
+ ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(70)}
254
+ @ssh_commands.should have_command_like(/gem uninstall -a -x ey-deploy/)
255
+ @ssh_commands.should have_command_like(/gem install ey-deploy/)
256
+ end
257
+
258
+ it "raises an error if ey-deploy is too new" do
259
+ ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(17)}, :expect_failure => true
260
+ @ssh_commands.should_not have_command_like(/gem install ey-deploy/)
261
+ @ssh_commands.should_not have_command_like(/eysd deploy/)
262
+ @err.should match(/too new/i)
263
+ end
264
+
265
+ it "does not change ey-deploy if its version is satisfactory" do
266
+ ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(0)}
267
+ @ssh_commands.should_not have_command_like(/gem install ey-deploy/)
268
+ @ssh_commands.should_not have_command_like(/gem uninstall.* ey-deploy/)
269
+ @ssh_commands.should have_command_like(/eysd deploy/)
270
+ end
221
271
  end
222
272
  end
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "ey environments" do
4
+
4
5
  it_should_behave_like "an integration test"
5
6
 
6
7
  before(:all) do
@@ -10,7 +11,16 @@ describe "ey environments" do
10
11
  it "lists the environments your app is in" do
11
12
  ey "environments"
12
13
  @out.should =~ /giblets/
13
- @out.should =~ /ham/
14
+ @out.should =~ /bakon/
15
+ end
16
+
17
+ it "reports failure to find a git repo when not in one" do
18
+ api_git_remote('dontcare')
19
+ Dir.chdir("/tmp") do
20
+ ey "environments", :expect_failure => true
21
+ @err.should =~ /fatal: No git remotes found in .*\/tmp/
22
+ @out.should_not =~ /no application configured/
23
+ end
14
24
  end
15
25
 
16
26
  end