engineyard 0.2.9 → 0.2.10

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.
Files changed (46) hide show
  1. data/lib/engineyard.rb +1 -17
  2. data/lib/engineyard/account.rb +13 -49
  3. data/lib/engineyard/account/app.rb +18 -0
  4. data/lib/engineyard/account/app_master.rb +12 -0
  5. data/lib/engineyard/account/environment.rb +31 -0
  6. data/lib/engineyard/account/log.rb +18 -0
  7. data/lib/engineyard/api.rb +4 -2
  8. data/lib/engineyard/cli.rb +34 -11
  9. data/lib/engineyard/cli/ui.rb +1 -1
  10. data/spec/engineyard/api_spec.rb +6 -6
  11. data/spec/engineyard/cli/api_spec.rb +1 -1
  12. data/spec/engineyard/config_spec.rb +9 -9
  13. data/spec/ey/deploy_spec.rb +40 -21
  14. data/spec/ey/logs_spec.rb +28 -0
  15. data/spec/spec_helper.rb +12 -13
  16. data/spec/support/fake_awsm.ru +251 -0
  17. data/spec/support/helpers.rb +50 -38
  18. data/spec/support/ruby_ext.rb +29 -0
  19. metadata +52 -102
  20. data/lib/vendor/thor.rb +0 -244
  21. data/lib/vendor/thor/actions.rb +0 -275
  22. data/lib/vendor/thor/actions/create_file.rb +0 -103
  23. data/lib/vendor/thor/actions/directory.rb +0 -91
  24. data/lib/vendor/thor/actions/empty_directory.rb +0 -134
  25. data/lib/vendor/thor/actions/file_manipulation.rb +0 -223
  26. data/lib/vendor/thor/actions/inject_into_file.rb +0 -104
  27. data/lib/vendor/thor/base.rb +0 -540
  28. data/lib/vendor/thor/core_ext/file_binary_read.rb +0 -9
  29. data/lib/vendor/thor/core_ext/hash_with_indifferent_access.rb +0 -75
  30. data/lib/vendor/thor/core_ext/ordered_hash.rb +0 -100
  31. data/lib/vendor/thor/error.rb +0 -30
  32. data/lib/vendor/thor/group.rb +0 -271
  33. data/lib/vendor/thor/invocation.rb +0 -180
  34. data/lib/vendor/thor/parser.rb +0 -4
  35. data/lib/vendor/thor/parser/argument.rb +0 -67
  36. data/lib/vendor/thor/parser/arguments.rb +0 -150
  37. data/lib/vendor/thor/parser/option.rb +0 -128
  38. data/lib/vendor/thor/parser/options.rb +0 -169
  39. data/lib/vendor/thor/rake_compat.rb +0 -66
  40. data/lib/vendor/thor/runner.rb +0 -314
  41. data/lib/vendor/thor/shell.rb +0 -83
  42. data/lib/vendor/thor/shell/basic.rb +0 -239
  43. data/lib/vendor/thor/shell/color.rb +0 -108
  44. data/lib/vendor/thor/task.rb +0 -102
  45. data/lib/vendor/thor/util.rb +0 -230
  46. data/lib/vendor/thor/version.rb +0 -3
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ey logs" do
4
+ before(:all) do
5
+ ENV['CLOUD_URL'] = EY.fake_awsm
6
+ FakeWeb.allow_net_connect = true
7
+
8
+ FakeFS.deactivate!
9
+ ENV['EYRC'] = "/tmp/eyrc"
10
+ token = { ENV['CLOUD_URL'] => {
11
+ "api_token" => "f81a1706ddaeb148cfb6235ddecfc1cf"} }
12
+ File.open(ENV['EYRC'], "w"){|f| YAML.dump(token, f) }
13
+ end
14
+
15
+ after(:all) do
16
+ ENV['CLOUD_URL'] = nil
17
+ FakeFS.activate!
18
+ FakeWeb.allow_net_connect = false
19
+ end
20
+
21
+ it "runs when environment is known" do
22
+ api_scenario "one app, one environment"
23
+ ey "logs giblets"
24
+ @out.should match(/MAIN LOG OUTPUT/)
25
+ @out.should match(/CUSTOM LOG OUTPUT/)
26
+ @err.should be_empty
27
+ end
28
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,9 @@
1
+ EY_ROOT = File.expand_path("../..", __FILE__)
1
2
  begin
2
- require File.expand_path('../../.bundle/environment', __FILE__)
3
+ require File.join(EY_ROOT, ".bundle/environment.rb")
3
4
  rescue LoadError
4
- require "rubygems"; require "bundler"; Bundler.setup
5
+ puts "Can't load bundler environment. You need to run `bundle lock`."
6
+ exit
5
7
  end
6
8
 
7
9
  # Bundled gems
@@ -9,15 +11,20 @@ require 'fakeweb'
9
11
  require 'fakefs/safe'
10
12
 
11
13
  # Engineyard gem
12
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.join(EY_ROOT, "lib"))
13
15
  require 'engineyard'
14
16
 
15
17
  # Spec stuff
16
18
  require 'spec/autorun'
17
- require 'support/helpers'
18
19
  require 'yaml'
20
+ support = Dir[File.join(EY_ROOT,'/spec/support/*.rb')]
21
+ support.each{|helper| require helper }
22
+
23
+ EY.start_fake_awsm
19
24
 
20
25
  Spec::Runner.configure do |config|
26
+ config.include Spec::Helpers
27
+
21
28
  config.before(:all) do
22
29
  FakeWeb.allow_net_connect = false
23
30
  FakeFS.activate!
@@ -26,15 +33,7 @@ Spec::Runner.configure do |config|
26
33
  end
27
34
 
28
35
  config.before(:each) do
29
- EY.config = nil
30
36
  FakeFS::FileSystem.clear
31
- end
32
-
33
- def load_config(file="ey.yml")
34
- YAML.load_file(File.expand_path(file))
35
- end
36
-
37
- def write_config(data, file = "ey.yml")
38
- File.open(file, "w"){|f| YAML.dump(data, f) }
37
+ EY.instance_eval{ @config = nil }
39
38
  end
40
39
  end
@@ -0,0 +1,251 @@
1
+ require 'rubygems'
2
+ require 'sinatra/base'
3
+ require 'json'
4
+
5
+ class FakeAwsm < Sinatra::Base
6
+
7
+ def initialize(*_)
8
+ super
9
+ # the class var is because the object passed to #run is #dup-ed on
10
+ # every request. It makes sense; you hardly ever want to keep
11
+ # state in your application object (accidentally or otherwise),
12
+ # but in this situation that's exactly what we want to do.
13
+ @@scenario = Scenario::Empty # have to start somewhere
14
+ end
15
+
16
+ before { content_type "application/json" }
17
+
18
+ get "/" do
19
+ content_type :html
20
+ "OMG"
21
+ end
22
+
23
+ put "/scenario" do
24
+ new_scenario = case params[:scenario]
25
+ when "empty"
26
+ Scenario::Empty
27
+ when "one app, one environment, not linked"
28
+ Scenario::UnlinkedApp
29
+ when "one app, one environment"
30
+ Scenario::LinkedApp
31
+ when "one app, two environments"
32
+ Scenario::OneAppTwoEnvs
33
+ end
34
+ if new_scenario
35
+ @@scenario = new_scenario
36
+ {"ok" => "true"}.to_json
37
+ else
38
+ status(400)
39
+ {"ok" => "false", "message" => "wtf is the #{params[:scenario]} scenario?"}.to_json
40
+ end
41
+ end
42
+
43
+ get "/api/v2/apps" do
44
+ {"apps" => @@scenario.apps}.to_json
45
+ end
46
+
47
+ get "/api/v2/environments" do
48
+ {"environments" => @@scenario.environments}.to_json
49
+ end
50
+
51
+ get "/api/v2/environments/:env_id/logs" do
52
+ {"logs" => @@scenario.logs(params[:env_id])}.to_json
53
+ end
54
+
55
+ post "/api/v2/authenticate" do
56
+ if valid_user?
57
+ {"api_token" => "deadbeef", "ok" => true}.to_json
58
+ else
59
+ status(401)
60
+ {"ok" => false}.to_json
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def valid_user?
67
+ params[:email] == "test@test.test" &&
68
+ params[:password] == "test"
69
+ end
70
+
71
+ module FindableGitRemote
72
+ # Since we have to find something in `git remote -v` that
73
+ # corresponds to an app in cloud.ey in order to do anything, we
74
+ # simulate this by faking out the API to have whatever git
75
+ # remote we'll find anyway.
76
+ def git_remote
77
+ remotes = []
78
+ `git remote -v`.each_line do |line|
79
+ parts = line.split(/\t/)
80
+ # the remote will look like
81
+ # "git@github.com:engineyard/engineyard.git (fetch)\n"
82
+ # so we need to chop it up a bit
83
+ remotes << parts[1].gsub(/\s.*$/, "") if parts[1]
84
+ end
85
+ remotes.first
86
+ end
87
+ end
88
+
89
+ module Scenario
90
+ class Empty
91
+ def self.apps
92
+ []
93
+ end
94
+
95
+ def self.environments
96
+ []
97
+ end
98
+ end
99
+
100
+ class UnlinkedApp
101
+ extend FindableGitRemote
102
+
103
+ def self.apps
104
+ [{
105
+ "name" => "rails232app",
106
+ "environments" => [],
107
+ "repository_uri" => git_remote}]
108
+ end
109
+
110
+ def self.environments
111
+ [{
112
+ "ssh_username" => "turkey",
113
+ "instances" => [{
114
+ "public_hostname" => "174.129.198.124",
115
+ "status" => "running",
116
+ "id" => 27220}],
117
+ "name" => "giblets",
118
+ "apps" => [],
119
+ "instances_count" => 1,
120
+ "stack_name" => "nginx_mongrel",
121
+ "id" => 200,
122
+ "app_master" => {
123
+ "public_hostname" => "174.129.198.124",
124
+ "status" => "running",
125
+ "id" => 27220}}]
126
+ end
127
+ end
128
+
129
+ class LinkedApp
130
+ extend FindableGitRemote
131
+
132
+ def self.apps
133
+ [{"name" => "rails232app",
134
+ "environments" => [{"ssh_username" => "turkey",
135
+ "instances" => [{"public_hostname" => "174.129.198.124",
136
+ "status" => "running",
137
+ "id" => 27220}],
138
+ "name" => "giblets",
139
+ "apps" => [{"name" => "rails232app",
140
+ "repository_uri" => git_remote}],
141
+ "instances_count" => 1,
142
+ "stack_name" => "nginx_mongrel",
143
+ "id" => 200,
144
+ "app_master" => {"public_hostname" => "174.129.198.124",
145
+ "status" => "running",
146
+ "id" => 27220}}],
147
+ "repository_uri" => git_remote}]
148
+ end
149
+
150
+ def self.environments
151
+ [{
152
+ "ssh_username" => "turkey",
153
+ "instances" => [{
154
+ "public_hostname" => "174.129.198.124",
155
+ "status" => "running",
156
+ "id" => 27220}],
157
+ "name" => "giblets",
158
+ "apps" => [{
159
+ "name" => "rails232app",
160
+ "repository_uri" => git_remote}],
161
+ "instances_count" => 1,
162
+ "stack_name" => "nginx_mongrel",
163
+ "id" => 200,
164
+ "app_master" => {
165
+ "public_hostname" => "174.129.198.124",
166
+ "status" => "running",
167
+ "id" => 27220}}]
168
+ end
169
+
170
+ def self.logs(env_id)
171
+ [{
172
+ "id" => env_id,
173
+ "role" => "app_master",
174
+ "main" => "MAIN LOG OUTPUT",
175
+ "custom" => "CUSTOM LOG OUTPUT"
176
+ }]
177
+ end
178
+ end
179
+
180
+ class OneAppTwoEnvs
181
+ extend FindableGitRemote
182
+
183
+ def self.apps
184
+ apps = [{
185
+ "name" => "rails232app",
186
+ "repository_uri" => git_remote
187
+ }]
188
+
189
+ [{"name" => "rails232app",
190
+ "environments" => [{
191
+ "ssh_username" => "turkey",
192
+ "instances" => [{"public_hostname" => "174.129.198.124",
193
+ "status" => "running",
194
+ "id" => 27220}],
195
+ "name" => "giblets",
196
+ "apps" => apps,
197
+ "instances_count" => 1,
198
+ "stack_name" => "nginx_mongrel",
199
+ "id" => 200,
200
+ "app_master" => {"public_hostname" => "174.129.198.124",
201
+ "status" => "running",
202
+ "id" => 27220}
203
+ }, {
204
+ "ssh_username" => "ham",
205
+ "instances" => [],
206
+ "name" => "bakon",
207
+ "apps" => apps,
208
+ "instances_count" => 0,
209
+ "stack_name" => "nginx_passenger",
210
+ "id" => 8371,
211
+ "app_master" => nil,
212
+ }],
213
+ "repository_uri" => git_remote}]
214
+ end
215
+
216
+ def self.environments
217
+ [{
218
+ "ssh_username" => "turkey",
219
+ "instances" => [{
220
+ "public_hostname" => "174.129.198.124",
221
+ "status" => "running",
222
+ "id" => 27220}],
223
+ "name" => "giblets",
224
+ "apps" => [{
225
+ "name" => "rails232app",
226
+ "repository_uri" => git_remote}],
227
+ "instances_count" => 1,
228
+ "stack_name" => "nginx_mongrel",
229
+ "id" => 200,
230
+ "app_master" => {
231
+ "public_hostname" => "174.129.198.124",
232
+ "status" => "running",
233
+ "id" => 27220}
234
+ }, {
235
+ "ssh_username" => "ham",
236
+ "instances" => [],
237
+ "name" => "bakon",
238
+ "apps" => [{
239
+ "name" => "rails232app",
240
+ "repository_uri" => git_remote}],
241
+ "instances_count" => 0,
242
+ "stack_name" => "nginx_passenger",
243
+ "id" => 8371,
244
+ "app_master" => nil,
245
+ }]
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ run FakeAwsm.new
@@ -1,46 +1,58 @@
1
- module Kernel
2
- def capture_stdio(input = nil, &block)
3
- require 'stringio'
4
- org_stdin, $stdin = $stdin, StringIO.new(input) if input
5
- org_stdout, $stdout = $stdout, StringIO.new
6
- yield
7
- return @out = $stdout.string
8
- ensure
9
- $stdout = org_stdout
10
- $stdin = org_stdin
11
- end
12
- alias capture_stdout capture_stdio
13
- end
1
+ require 'ey_merkin'
2
+ require "rest_client"
3
+
4
+ module Spec
5
+ module Helpers
6
+ def ey(cmd = nil, options = {})
7
+ require "open3"
8
+ hide_err = options.delete(:hide_err)
9
+ ENV['DEBUG'] = options.delete(:debug)
10
+
11
+ args = options.map { |k,v| "--#{k} #{v}"}.join(" ")
12
+ eybin = File.expand_path('../bundled_ey', __FILE__)
13
+
14
+ @in, @out, @err = Open3.popen3("#{eybin} #{cmd} #{args}")
15
+
16
+ yield @in if block_given?
17
+ @err = @err.read_available_bytes
18
+ @out = @out.read_available_bytes
19
+ @ssh_commands = @out.split(/\n/).find_all do |line|
20
+ line =~ /^ssh/
21
+ end.map do |line|
22
+ line.sub(/^.*?\"/, '').sub(/\"$/, '')
23
+ end
24
+
25
+ puts @err unless @err.empty? || hide_err
26
+ @out
27
+ end
14
28
 
15
- class IO
16
- def read_available_bytes(chunk_size = 1024, select_timeout = 5)
17
- buffer = []
29
+ def api_scenario(scenario)
30
+ response = ::RestClient.put(EY.fake_awsm + '/scenario', {"scenario" => scenario}, {})
31
+ raise "Setting scenario failed: #{response.inspect}" unless response.code == 200
32
+ end
18
33
 
19
- while self.class.select([self], nil, nil, select_timeout)
20
- begin
21
- buffer << self.readpartial(chunk_size)
22
- rescue(EOFError)
23
- break
24
- end
34
+ def read_yaml(file="ey.yml")
35
+ YAML.load_file(File.expand_path(file))
25
36
  end
26
37
 
27
- return buffer.join
38
+ def write_yaml(data, file = "ey.yml")
39
+ File.open(file, "w"){|f| YAML.dump(data, f) }
40
+ end
28
41
  end
29
42
  end
30
43
 
31
- def ey(cmd = nil, options = {})
32
- require "open3"
33
- hide_err = options.delete(:hide_err)
34
-
35
- args = options.map { |k,v| "--#{k} #{v}"}.join(" ")
36
- eybin = File.expand_path('../bundled_ey', __FILE__)
37
-
38
- @in, @out, @err = Open3.popen3("#{eybin} #{cmd} #{args}")
39
-
40
- yield @in if block_given?
41
- @err = @err.read_available_bytes
42
- @out = @out.read_available_bytes
43
-
44
- puts @err unless @err.empty? || hide_err
45
- @out
44
+ module EY
45
+ class << self
46
+ def fake_awsm
47
+ @fake_awsm ||= begin
48
+ unless system("ruby -c spec/support/fake_awsm.ru > /dev/null")
49
+ raise SyntaxError, "There is a syntax error in fake_awsm.ru! fix it!"
50
+ end
51
+ config_ru = File.join(EY_ROOT, "spec/support/fake_awsm.ru")
52
+ @server = EY::Merkin.start_server(config_ru)
53
+ "http://localhost:#{@server.port}"
54
+ end
55
+ end
56
+ alias_method :start_fake_awsm, :fake_awsm
57
+ end
46
58
  end
@@ -0,0 +1,29 @@
1
+ module Kernel
2
+ def capture_stdio(input = nil, &block)
3
+ require 'stringio'
4
+ org_stdin, $stdin = $stdin, StringIO.new(input) if input
5
+ org_stdout, $stdout = $stdout, StringIO.new
6
+ yield
7
+ return @out = $stdout.string
8
+ ensure
9
+ $stdout = org_stdout
10
+ $stdin = org_stdin
11
+ end
12
+ alias capture_stdout capture_stdio
13
+ end
14
+
15
+ class IO
16
+ def read_available_bytes(chunk_size = 1024, select_timeout = 5)
17
+ buffer = []
18
+
19
+ while self.class.select([self], nil, nil, select_timeout)
20
+ begin
21
+ buffer << self.readpartial(chunk_size)
22
+ rescue(EOFError)
23
+ break
24
+ end
25
+ end
26
+
27
+ return buffer.join
28
+ end
29
+ end