engineyard 1.3.13 → 1.3.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  require 'escape'
2
- require 'open4'
2
+ require 'net/ssh'
3
3
 
4
4
  module EY
5
5
  module Model
@@ -74,20 +74,47 @@ module EY
74
74
  def ssh(remote_command, verbose, &block)
75
75
  raise(ArgumentError, "Block required!") unless block
76
76
 
77
- raw_cmd = %w[ssh -o StrictHostKeyChecking=no]
78
- raw_cmd << '-q' unless verbose
79
- raw_cmd << "#{environment.username}@#{hostname}"
80
- raw_cmd << remote_command
81
-
82
- cmd = Escape.shell_command(raw_cmd)
77
+ exit_code = nil
78
+ cmd = Escape.shell_command(['bash', '-lc', remote_command])
83
79
  EY.ui.debug(cmd)
84
80
  puts cmd if verbose
85
81
  if ENV["NO_SSH"]
86
82
  block.call("NO_SSH is set. No output.")
87
83
  true
88
84
  else
89
- status = Open4.spawn(cmd, :out => block, :err => block, :quiet => true)
90
- status.success?
85
+ begin
86
+ Net::SSH.start(hostname, environment.username, :paranoid => false) do |net_ssh|
87
+ net_ssh.open_channel do |channel|
88
+ channel.exec cmd do |_, success|
89
+ unless success
90
+ block.call "Remote command execution failed"
91
+ return false
92
+ end
93
+
94
+ channel.on_data do |_, data|
95
+ block.call data
96
+ end
97
+
98
+ channel.on_extended_data do |_, _, data|
99
+ block.call data
100
+ end
101
+
102
+ channel.on_request("exit-status") do |_, data|
103
+ exit_code = data.read_long
104
+ end
105
+
106
+ channel.on_request("exit-signal") do |_, data|
107
+ exit_code = 255
108
+ end
109
+ end
110
+ end
111
+
112
+ net_ssh.loop
113
+ end
114
+ exit_code.zero?
115
+ rescue Net::SSH::AuthenticationFailed
116
+ raise EY::Error, "Authentication Failed: Please add your environment's ssh key with: ssh-add path/to/key"
117
+ end
91
118
  end
92
119
  end
93
120
 
@@ -1,3 +1,3 @@
1
1
  module EY
2
- VERSION = '1.3.13'
2
+ VERSION = '1.3.14'
3
3
  end
@@ -53,25 +53,25 @@ describe "ey deploy" do
53
53
  context "with invalid input" do
54
54
  it "complains when there is no app" do
55
55
  api_scenario "empty"
56
- ey "deploy", :expect_failure => true
56
+ fast_failing_ey ["deploy"]
57
57
  @err.should include(%|no application configured|)
58
58
  end
59
59
 
60
60
  it "complains when the specified environment does not contain the app" do
61
61
  api_scenario "one app, one environment, not linked"
62
- ey "deploy -e giblets -r master", :expect_failure => true
62
+ fast_failing_ey %w[deploy -e giblets -r master]
63
63
  @err.should match(/there is no application configured/i)
64
64
  end
65
65
 
66
66
  it "complains when environment is not specified and app is in >1 environment" do
67
67
  api_scenario "one app, many environments"
68
- ey "deploy", :expect_failure => true
68
+ fast_failing_ey %w[deploy]
69
69
  @err.should match(/multiple app deployments possible/i)
70
70
  end
71
71
 
72
72
  it "complains when the app master is in a non-running state" do
73
73
  api_scenario "one app, one environment, app master red"
74
- ey "deploy --environment giblets --ref master", :expect_failure => true
74
+ fast_failing_ey %w[deploy --environment giblets --ref master]
75
75
  @err.should_not match(/No running instances/i)
76
76
  @err.should match(/running.*\(green\)/)
77
77
  end
@@ -83,24 +83,24 @@ describe "ey deploy" do
83
83
  end
84
84
 
85
85
  it "finds engineyard-serverside despite its being buried in the filesystem" do
86
- ey "deploy"
86
+ fast_ey %w[deploy]
87
87
  @ssh_commands.last.should =~ %r{/usr/local/ey_resin/ruby/bin/engineyard-serverside}
88
88
  end
89
89
 
90
90
  it "defaults to 'rake db:migrate'" do
91
- ey "deploy"
91
+ fast_ey %w[deploy]
92
92
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
93
93
  @ssh_commands.last.should =~ /--migrate 'rake db:migrate --trace'/
94
94
  end
95
95
 
96
96
  it "can be disabled with --no-migrate" do
97
- ey "deploy --no-migrate"
97
+ fast_ey %w[deploy --no-migrate]
98
98
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
99
99
  @ssh_commands.last.should_not =~ /--migrate/
100
100
  end
101
101
 
102
102
  it "uses the default when --migrate is specified with no value" do
103
- ey "deploy --migrate"
103
+ fast_ey %w[deploy --migrate]
104
104
  @ssh_commands.last.should match(/--migrate 'rake db:migrate --trace'/)
105
105
  end
106
106
 
@@ -111,7 +111,7 @@ describe "ey deploy" do
111
111
  after { File.unlink 'ey.yml' }
112
112
 
113
113
  it "migrates with the custom command by default" do
114
- ey "deploy"
114
+ fast_ey %w[deploy]
115
115
  @ssh_commands.last.should =~ /--migrate 'thor fancy:migrate'/
116
116
  end
117
117
  end
@@ -121,18 +121,18 @@ describe "ey deploy" do
121
121
  after { File.unlink 'ey.yml' }
122
122
 
123
123
  it "does not migrate by default" do
124
- ey "deploy"
124
+ fast_ey %w[deploy]
125
125
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
126
126
  @ssh_commands.last.should_not =~ /--migrate/
127
127
  end
128
128
 
129
129
  it "can be turned back on with --migrate" do
130
- ey "deploy --migrate 'rake fancy:migrate'"
130
+ fast_ey ["deploy", "--migrate", "rake fancy:migrate"]
131
131
  @ssh_commands.last.should =~ /--migrate 'rake fancy:migrate'/
132
132
  end
133
133
 
134
134
  it "migrates with the default when --migrate is specified with no value" do
135
- ey "deploy --migrate"
135
+ fast_ey %w[deploy --migrate]
136
136
  @ssh_commands.last.should match(/--migrate 'rake db:migrate --trace'/)
137
137
  end
138
138
  end
@@ -142,7 +142,7 @@ describe "ey deploy" do
142
142
  after { File.unlink 'ey.yml' }
143
143
 
144
144
  it "migrates with the default" do
145
- ey "deploy"
145
+ fast_ey %w[deploy]
146
146
  @ssh_commands.last.should match(/--migrate 'rake db:migrate --trace'/)
147
147
  end
148
148
  end
@@ -155,12 +155,12 @@ describe "ey deploy" do
155
155
  after { File.unlink 'ey.yml' }
156
156
 
157
157
  it "does not migrate by default" do
158
- ey "deploy"
158
+ fast_ey %w[deploy]
159
159
  @ssh_commands.last.should_not match(/--migrate/)
160
160
  end
161
161
 
162
162
  it "migrates with the custom command when --migrate is specified with no value" do
163
- ey "deploy --migrate"
163
+ fast_ey %w[deploy --migrate]
164
164
  @ssh_commands.last.should match(/--migrate 'thor fancy:migrate'/)
165
165
  end
166
166
  end
@@ -172,7 +172,7 @@ describe "ey deploy" do
172
172
  end
173
173
 
174
174
  it "passes the framework environment" do
175
- ey "deploy"
175
+ fast_ey %w[deploy]
176
176
  @ssh_commands.last.should match(/--framework-env production/)
177
177
  end
178
178
  end
@@ -199,27 +199,27 @@ describe "ey deploy" do
199
199
 
200
200
  context "without a configured default branch" do
201
201
  it "defaults to the checked-out local branch" do
202
- ey "deploy"
202
+ fast_ey %w[deploy]
203
203
  @ssh_commands.last.should =~ /--ref resolved-current-branch/
204
204
  end
205
205
 
206
206
  it "deploys another branch if given" do
207
- ey "deploy --ref master"
207
+ fast_ey %w[deploy --ref master]
208
208
  @ssh_commands.last.should =~ /--ref resolved-master/
209
209
  end
210
210
 
211
211
  it "deploys a tag if given" do
212
- ey "deploy --ref v1"
212
+ fast_ey %w[deploy --ref v1]
213
213
  @ssh_commands.last.should =~ /--ref resolved-v1/
214
214
  end
215
215
 
216
216
  it "allows using --branch to specify a branch" do
217
- ey "deploy --branch master"
217
+ fast_ey %w[deploy --branch master]
218
218
  @ssh_commands.last.should match(/--ref resolved-master/)
219
219
  end
220
220
 
221
221
  it "allows using --tag to specify the tag" do
222
- ey "deploy --tag v1"
222
+ fast_ey %w[deploy --tag v1]
223
223
  @ssh_commands.last.should match(/--ref resolved-v1/)
224
224
  end
225
225
  end
@@ -234,7 +234,7 @@ describe "ey deploy" do
234
234
  end
235
235
 
236
236
  it "gets passed along to engineyard-serverside" do
237
- ey "deploy"
237
+ fast_ey %w[deploy]
238
238
  @ssh_commands.last.should =~ /--config '\{\"bert\":\"ernie\"\}'/
239
239
  end
240
240
  end
@@ -249,17 +249,17 @@ describe "ey deploy" do
249
249
  end
250
250
 
251
251
  it "deploys the default branch by default" do
252
- ey "deploy"
252
+ fast_ey %w[deploy]
253
253
  @ssh_commands.last.should =~ /--ref resolved-master/
254
254
  end
255
255
 
256
256
  it "complains about a non-default branch without --ignore-default_branch" do
257
- ey "deploy -r current-branch", :expect_failure => true
257
+ fast_failing_ey %w[deploy -r current-branch]
258
258
  @err.should =~ /deploy branch is set to "master"/
259
259
  end
260
260
 
261
261
  it "deploys a non-default branch with --ignore-default-branch" do
262
- ey "deploy -r current-branch --ignore-default-branch"
262
+ fast_ey %w[deploy -r current-branch --ignore-default-branch]
263
263
  @ssh_commands.last.should =~ /--ref resolved-current-branch/
264
264
  end
265
265
  end
@@ -271,7 +271,7 @@ describe "ey deploy" do
271
271
  end
272
272
 
273
273
  it "lets you choose by complete name even if the complete name is ambiguous" do
274
- ey "deploy --environment railsapp_staging"
274
+ fast_ey %w[deploy --environment railsapp_staging]
275
275
  @out.should match(/Beginning deploy for.*'railsapp_staging'/)
276
276
  end
277
277
  end
@@ -304,7 +304,7 @@ describe "ey deploy" do
304
304
  after { File.unlink("ey.yml") }
305
305
 
306
306
  it "overrides what's in ey.yml" do
307
- ey "deploy --extra-deploy-hook-options beer:esb"
307
+ fast_ey %w[deploy --extra-deploy-hook-options beer:esb]
308
308
  extra_deploy_hook_options['beer'].should == 'esb'
309
309
  end
310
310
  end
@@ -325,14 +325,14 @@ describe "ey deploy" do
325
325
  end
326
326
 
327
327
  it "allows you to specify an app when not in a directory" do
328
- ey "deploy --app rails232app --ref master"
328
+ fast_ey %w[deploy --app rails232app --ref master]
329
329
  @ssh_commands.last.should match(/--app rails232app/)
330
330
  @ssh_commands.last.should match(/--ref resolved-master/)
331
331
  end
332
332
 
333
333
  it "requires that you specify a ref when specifying the application" do
334
334
  Dir.chdir(File.expand_path("~")) do
335
- ey "deploy --app rails232app", :expect_failure => true
335
+ fast_failing_ey %w[deploy --app rails232app]
336
336
  @err.should match(/you must also specify the ref to deploy/)
337
337
  end
338
338
  end
@@ -343,7 +343,7 @@ describe "ey deploy" do
343
343
 
344
344
  before(:all) do
345
345
  api_scenario "one app, one environment", "user@git.host:path/to/repo.git"
346
- ey "deploy"
346
+ fast_ey ["deploy"]
347
347
  @deploy_command = @ssh_commands.find {|c| c =~ /engineyard-serverside.*deploy/ }
348
348
  end
349
349
 
@@ -1,6 +1,9 @@
1
+ require 'engineyard/cli'
2
+
1
3
  require 'realweb'
2
- require "rest_client"
4
+ require 'rest_client'
3
5
  require 'open4'
6
+ require 'stringio'
4
7
 
5
8
  module Spec
6
9
  module Helpers
@@ -16,6 +19,56 @@ module Spec
16
19
  NonzeroExitStatus = Class.new(UnexpectedExit)
17
20
  ZeroExitStatus = Class.new(UnexpectedExit)
18
21
 
22
+ def fast_ey(args)
23
+ err, out = StringIO.new, StringIO.new
24
+ capture_stderr_into(err) do
25
+ capture_stdout_into(out) do
26
+ with_env('DEBUG' => 'true') do
27
+ EY::CLI.start(args)
28
+ end
29
+ end
30
+ end
31
+ ensure
32
+ @err, @out = err.string, out.string
33
+ @raw_ssh_commands, @ssh_commands = extract_ssh_commands(@out)
34
+ end
35
+
36
+ def fast_failing_ey(*args)
37
+ begin
38
+ fast_ey(*args)
39
+ raise ZeroExitStatus
40
+ rescue SystemExit => exit_status
41
+ # SystemExit typically indicates a bogus command, which we
42
+ # here in expected-to-fail land are entirely happy with.
43
+ nil
44
+ rescue EY::Error => e
45
+ more_err, more_out = StringIO.new, StringIO.new
46
+
47
+ capture_stderr_into(more_err) do
48
+ capture_stdout_into(more_out) do
49
+ EY.ui.print_exception(e)
50
+ end
51
+ end
52
+
53
+ @err << more_err.string
54
+ @out << more_out.string
55
+ end
56
+ end
57
+
58
+ def capture_stderr_into(stream)
59
+ $stderr = stream
60
+ yield
61
+ ensure
62
+ $stderr = STDERR
63
+ end
64
+
65
+ def capture_stdout_into(stream)
66
+ $stdout = stream
67
+ yield
68
+ ensure
69
+ $stdout = STDOUT
70
+ end
71
+
19
72
  def ey(cmd = nil, options = {}, &block)
20
73
  hide_err = options.has_key?(:hide_err) ? options[:hide_err] : options[:expect_failure]
21
74
  path_prepends = options[:prepend_to_path]
@@ -54,14 +107,26 @@ module Spec
54
107
  end
55
108
  end
56
109
 
57
- @raw_ssh_commands = @out.split(/\n/).find_all do |line|
58
- line =~ /^ssh/
110
+ @raw_ssh_commands, @ssh_commands = extract_ssh_commands(@out)
111
+
112
+ puts @err unless @err.empty? || hide_err
113
+ @out
114
+ end
115
+
116
+ def extract_ssh_commands(output)
117
+ raw_ssh_commands = @out.split(/\n/).find_all do |line|
118
+ line =~ /^bash -lc/ || line =~ /^ssh/
59
119
  end
60
120
 
61
- @ssh_commands = @raw_ssh_commands.map do |cmd|
121
+ ssh_commands = raw_ssh_commands.map do |cmd|
62
122
  # Strip off everything up to and including user@host, leaving
63
123
  # just the command that the remote system would run
64
- ssh_prefix_removed = cmd.gsub(/^.*?\w+@\S*\s*/, '')
124
+ #
125
+ # XXX: this is a really icky icky.
126
+ # engineyard gem was written as if shelling out to run serverside
127
+ # and running an ssh command will always be the same. This is a nasty
128
+ # hack to get it working with Net::SSH for now so we can repair 1.9.2.
129
+ ssh_prefix_removed = cmd.gsub(/^bash -lc /, '').gsub(/^ssh .*?\w+@\S*\s*/, '')
65
130
 
66
131
  # Its arguments have been double-escaped: one layer is to get
67
132
  # them through our local shell and into ssh, and the other
@@ -72,8 +137,7 @@ module Spec
72
137
  `echo #{just_the_remote_command}`.strip
73
138
  end
74
139
 
75
- puts @err unless @err.empty? || hide_err
76
- @out
140
+ [raw_ssh_commands, ssh_commands]
77
141
  end
78
142
 
79
143
  def api_scenario(scenario, remote = "user@git.host:path/to/repo.git")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: engineyard
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 13
10
- version: 1.3.13
9
+ - 14
10
+ version: 1.3.14
11
11
  platform: ruby
12
12
  authors:
13
13
  - EY Cloud Team
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-10 00:00:00 -08:00
18
+ date: 2011-01-11 00:00:00 -08:00
19
19
  default_executable: ey
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -118,14 +118,14 @@ dependencies:
118
118
  requirements:
119
119
  - - ~>
120
120
  - !ruby/object:Gem::Version
121
- hash: 21
121
+ hash: 33
122
122
  segments:
123
- - 1
123
+ - 2
124
124
  - 0
125
- - 1
126
- version: 1.0.1
125
+ - 23
126
+ version: 2.0.23
127
127
  requirement: *id007
128
- name: open4
128
+ name: net-ssh
129
129
  prerelease: false
130
130
  type: :runtime
131
131
  description: This gem allows you to deploy your rails application to the Engine Yard cloud directly from the command line.