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.
- data/lib/engineyard.rb +1 -17
- data/lib/engineyard/account.rb +13 -49
- data/lib/engineyard/account/app.rb +18 -0
- data/lib/engineyard/account/app_master.rb +12 -0
- data/lib/engineyard/account/environment.rb +31 -0
- data/lib/engineyard/account/log.rb +18 -0
- data/lib/engineyard/api.rb +4 -2
- data/lib/engineyard/cli.rb +34 -11
- data/lib/engineyard/cli/ui.rb +1 -1
- data/spec/engineyard/api_spec.rb +6 -6
- data/spec/engineyard/cli/api_spec.rb +1 -1
- data/spec/engineyard/config_spec.rb +9 -9
- data/spec/ey/deploy_spec.rb +40 -21
- data/spec/ey/logs_spec.rb +28 -0
- data/spec/spec_helper.rb +12 -13
- data/spec/support/fake_awsm.ru +251 -0
- data/spec/support/helpers.rb +50 -38
- data/spec/support/ruby_ext.rb +29 -0
- metadata +52 -102
- data/lib/vendor/thor.rb +0 -244
- data/lib/vendor/thor/actions.rb +0 -275
- data/lib/vendor/thor/actions/create_file.rb +0 -103
- data/lib/vendor/thor/actions/directory.rb +0 -91
- data/lib/vendor/thor/actions/empty_directory.rb +0 -134
- data/lib/vendor/thor/actions/file_manipulation.rb +0 -223
- data/lib/vendor/thor/actions/inject_into_file.rb +0 -104
- data/lib/vendor/thor/base.rb +0 -540
- data/lib/vendor/thor/core_ext/file_binary_read.rb +0 -9
- data/lib/vendor/thor/core_ext/hash_with_indifferent_access.rb +0 -75
- data/lib/vendor/thor/core_ext/ordered_hash.rb +0 -100
- data/lib/vendor/thor/error.rb +0 -30
- data/lib/vendor/thor/group.rb +0 -271
- data/lib/vendor/thor/invocation.rb +0 -180
- data/lib/vendor/thor/parser.rb +0 -4
- data/lib/vendor/thor/parser/argument.rb +0 -67
- data/lib/vendor/thor/parser/arguments.rb +0 -150
- data/lib/vendor/thor/parser/option.rb +0 -128
- data/lib/vendor/thor/parser/options.rb +0 -169
- data/lib/vendor/thor/rake_compat.rb +0 -66
- data/lib/vendor/thor/runner.rb +0 -314
- data/lib/vendor/thor/shell.rb +0 -83
- data/lib/vendor/thor/shell/basic.rb +0 -239
- data/lib/vendor/thor/shell/color.rb +0 -108
- data/lib/vendor/thor/task.rb +0 -102
- data/lib/vendor/thor/util.rb +0 -230
- 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.
|
3
|
+
require File.join(EY_ROOT, ".bundle/environment.rb")
|
3
4
|
rescue LoadError
|
4
|
-
|
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(
|
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
|
-
|
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
|
data/spec/support/helpers.rb
CHANGED
@@ -1,46 +1,58 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
20
|
-
|
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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|