engineyard 0.8.2 → 0.9.0
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/api.rb +0 -10
- data/lib/engineyard/collection.rb +2 -0
- data/lib/engineyard/collection/abstract.rb +43 -0
- data/lib/engineyard/collection/apps.rb +8 -0
- data/lib/engineyard/collection/environments.rb +3 -30
- data/lib/engineyard/error.rb +14 -4
- data/lib/engineyard/model/app.rb +4 -0
- data/lib/engineyard/model/environment.rb +1 -1
- data/lib/engineyard/model/instance.rb +7 -1
- data/lib/engineyard/repo.rb +3 -1
- data/lib/engineyard/thor.rb +5 -1
- data/lib/engineyard/version.rb +1 -1
- data/spec/engineyard/collection/apps.rb +14 -0
- data/spec/engineyard/collection/environments.rb +4 -65
- data/spec/engineyard/model/instance_spec.rb +32 -0
- data/spec/support/shared_behavior.rb +61 -3
- metadata +8 -4
data/lib/engineyard/api.rb
CHANGED
@@ -38,19 +38,9 @@ module EY
|
|
38
38
|
app_for_repo(repo) || raise(NoAppError.new(repo))
|
39
39
|
end
|
40
40
|
|
41
|
-
def fetch_app(name)
|
42
|
-
apps.find{|a| a.name == name}
|
43
|
-
end
|
44
|
-
|
45
|
-
def fetch_app!(name)
|
46
|
-
return unless name
|
47
|
-
fetch_app(name) || raise(InvalidAppError.new(name))
|
48
|
-
end
|
49
|
-
|
50
41
|
class InvalidCredentials < EY::Error; end
|
51
42
|
class RequestFailed < EY::Error; end
|
52
43
|
|
53
|
-
|
54
44
|
def self.request(path, opts={})
|
55
45
|
require 'rest_client'
|
56
46
|
require 'json'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'engineyard/error'
|
2
|
+
|
3
|
+
module EY
|
4
|
+
module Collection
|
5
|
+
class Abstract < Array
|
6
|
+
|
7
|
+
def named(name)
|
8
|
+
find {|x| x.name == name }
|
9
|
+
end
|
10
|
+
|
11
|
+
def match_one(name_part)
|
12
|
+
named(name_part) || find_by_unambiguous_substring(name_part)
|
13
|
+
end
|
14
|
+
|
15
|
+
def match_one!(name_part)
|
16
|
+
match_one(name_part) or raise invalid_error(name_part)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def find_by_unambiguous_substring(name_part)
|
22
|
+
candidates = find_all{|e| e.name[name_part] }
|
23
|
+
if candidates.size > 1
|
24
|
+
raise ambiguous_error(name_part, candidates.map {|e| e.name})
|
25
|
+
end
|
26
|
+
candidates.first
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
attr_accessor :invalid_error, :ambiguous_error
|
31
|
+
end
|
32
|
+
|
33
|
+
def invalid_error(*args, &blk)
|
34
|
+
self.class.invalid_error.new(*args, &blk)
|
35
|
+
end
|
36
|
+
|
37
|
+
def ambiguous_error(*args, &blk)
|
38
|
+
self.class.ambiguous_error.new(*args, &blk)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,35 +1,8 @@
|
|
1
|
-
require 'engineyard/error'
|
2
|
-
|
3
1
|
module EY
|
4
2
|
module Collection
|
5
|
-
class Environments <
|
6
|
-
|
7
|
-
|
8
|
-
find {|e| e.name == name}
|
9
|
-
end
|
10
|
-
|
11
|
-
def named!(name)
|
12
|
-
named(name) or raise EnvironmentError,
|
13
|
-
"Environment '#{name}' can't be found\nYou can create it at #{EY.config.endpoint}"
|
14
|
-
end
|
15
|
-
|
16
|
-
def match_one(name_part)
|
17
|
-
named(name_part) || find_by_unambiguous_substring(name_part)
|
18
|
-
end
|
19
|
-
|
20
|
-
def match_one!(name_part)
|
21
|
-
match_one(name_part) or raise NoEnvironmentError.new(name_part)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
def find_by_unambiguous_substring(name_part)
|
26
|
-
candidates = find_all{|e| e.name[name_part] }
|
27
|
-
if candidates.size > 1
|
28
|
-
raise AmbiguousEnvironmentName.new(name_part, candidates.map {|e| e.name})
|
29
|
-
end
|
30
|
-
candidates.first
|
31
|
-
end
|
32
|
-
|
3
|
+
class Environments < Abstract
|
4
|
+
self.invalid_error = NoEnvironmentError
|
5
|
+
self.ambiguous_error = AmbiguousEnvironmentName
|
33
6
|
end
|
34
7
|
end
|
35
8
|
end
|
data/lib/engineyard/error.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module EY
|
2
|
-
class Error < RuntimeError
|
2
|
+
class Error < RuntimeError
|
3
|
+
def ambiguous(type, name, matches)
|
4
|
+
pretty_names = matches.map {|x| "'#{x}'"}.join(', ')
|
5
|
+
"The name '#{name}' is ambiguous; it matches all of the following #{type} names: #{pretty_names}.\n" +
|
6
|
+
"Please use a longer, unambiguous substring or the entire #{type} name."
|
7
|
+
end
|
8
|
+
end
|
3
9
|
|
4
10
|
class NoRemotesError < EY::Error
|
5
11
|
def initialize(path)
|
@@ -23,6 +29,12 @@ module EY
|
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
32
|
+
class AmbiguousAppName < EY::Error
|
33
|
+
def initialize(name, matches)
|
34
|
+
super ambiguous("app", name, matches)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
26
38
|
class NoAppMaster < EY::Error
|
27
39
|
def initialize(env_name)
|
28
40
|
super "The environment '#{env_name}' does not have a master instance."
|
@@ -40,9 +52,7 @@ module EY
|
|
40
52
|
|
41
53
|
class AmbiguousEnvironmentName < EY::EnvironmentError
|
42
54
|
def initialize(name, matches)
|
43
|
-
|
44
|
-
super "The name '#{name}' is ambiguous; it matches all of the following environment names: #{pretty_names}.\n" +
|
45
|
-
"Please use a longer, unambiguous substring or the entire environment name."
|
55
|
+
super ambiguous("environment", name, matches)
|
46
56
|
end
|
47
57
|
end
|
48
58
|
|
data/lib/engineyard/model/app.rb
CHANGED
@@ -56,6 +56,10 @@ module EY
|
|
56
56
|
end
|
57
57
|
|
58
58
|
|
59
|
+
def has_app_code?
|
60
|
+
!["db_master", "db_slave"].include?(role.to_s)
|
61
|
+
end
|
62
|
+
|
59
63
|
def ensure_eysd_present
|
60
64
|
case ey_deploy_check
|
61
65
|
when :ssh_failed
|
@@ -110,7 +114,9 @@ module EY
|
|
110
114
|
|
111
115
|
def invoke_eysd_deploy(deploy_args, verbose=false)
|
112
116
|
start = [eysd_path, "_#{EYSD_VERSION}_", 'deploy']
|
113
|
-
instance_args = environment.instances.
|
117
|
+
instance_args = environment.instances.find_all do |inst|
|
118
|
+
inst.has_app_code?
|
119
|
+
end.inject(['--instances']) do |command, inst|
|
114
120
|
instance_tuple = [inst.public_hostname, inst.role]
|
115
121
|
instance_tuple << inst.name if inst.name
|
116
122
|
|
data/lib/engineyard/repo.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'escape'
|
2
|
+
|
1
3
|
module EY
|
2
4
|
class Repo
|
3
5
|
|
@@ -19,7 +21,7 @@ module EY
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def urls
|
22
|
-
lines = `git config -f #{@path}/.git/config --get-regexp 'remote.*.url'`.split(/\n/)
|
24
|
+
lines = `git config -f #{Escape.shell_command(@path)}/.git/config --get-regexp 'remote.*.url'`.split(/\n/)
|
23
25
|
raise NoRemotesError.new(@path) if lines.empty?
|
24
26
|
lines.map { |c| c.split.last }
|
25
27
|
end
|
data/lib/engineyard/thor.rb
CHANGED
@@ -102,7 +102,11 @@ module EY
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def fetch_app(app_name = nil)
|
105
|
-
|
105
|
+
if app_name
|
106
|
+
api.apps.match_one!(app_name)
|
107
|
+
else
|
108
|
+
api.app_for_repo!(repo)
|
109
|
+
end
|
106
110
|
end
|
107
111
|
|
108
112
|
def get_apps(all_apps = false)
|
data/lib/engineyard/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Collection::Apps do
|
4
|
+
before do
|
5
|
+
@collection_class = EY::Collection::Apps
|
6
|
+
@collection = @collection_class.new([
|
7
|
+
EY::Model::App.from_hash("id" => 1234, "name" => "app_production"),
|
8
|
+
EY::Model::App.from_hash("id" => 4321, "name" => "app_staging"),
|
9
|
+
EY::Model::App.from_hash("id" => 8765, "name" => "bigapp_staging"),
|
10
|
+
])
|
11
|
+
end
|
12
|
+
|
13
|
+
it_should_behave_like "model collections"
|
14
|
+
end
|
@@ -1,75 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe EY::Collection::Environments do
|
4
|
-
before
|
5
|
-
@
|
4
|
+
before do
|
5
|
+
@collection_class = EY::Collection::Environments
|
6
|
+
@collection = @collection_class.new([
|
6
7
|
EY::Model::Environment.from_hash("id" => 1234, "name" => "app_production"),
|
7
8
|
EY::Model::Environment.from_hash("id" => 4321, "name" => "app_staging"),
|
8
9
|
EY::Model::Environment.from_hash("id" => 8765, "name" => "bigapp_staging"),
|
9
10
|
])
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
it "works when given an unambiguous substring" do
|
14
|
-
@envs.match_one("prod").name.should == "app_production"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "raises an error when given an ambiguous substring" do
|
18
|
-
lambda {
|
19
|
-
@envs.match_one("staging")
|
20
|
-
}.should raise_error(EY::AmbiguousEnvironmentName)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "returns an exact match if one exists" do
|
24
|
-
@envs.match_one("app_staging").name.should == "app_staging"
|
25
|
-
end
|
26
|
-
|
27
|
-
it "returns nil when it can't find anything" do
|
28
|
-
@envs.match_one("dev-and-production").should be_nil
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "#match_one!" do
|
33
|
-
it "works when given an unambiguous substring" do
|
34
|
-
@envs.match_one!("prod").name.should == "app_production"
|
35
|
-
end
|
36
|
-
|
37
|
-
it "raises an error when given an ambiguous substring" do
|
38
|
-
lambda {
|
39
|
-
@envs.match_one!("staging")
|
40
|
-
}.should raise_error(EY::AmbiguousEnvironmentName)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "returns an exact match if one exists" do
|
44
|
-
@envs.match_one!("app_staging").name.should == "app_staging"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "raises an error when it can't find anything" do
|
48
|
-
lambda {
|
49
|
-
@envs.match_one!("dev-and-production")
|
50
|
-
}.should raise_error(EY::EnvironmentError)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "#named" do
|
55
|
-
it "finds the environment with the matching name" do
|
56
|
-
@envs.named("app_staging").id.should == 4321
|
57
|
-
end
|
58
|
-
|
59
|
-
it "returns nil when no name matches" do
|
60
|
-
@envs.named("something else").should be_nil
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "#named!" do
|
65
|
-
it "finds the environment with the matching name" do
|
66
|
-
@envs.named!("app_staging").id.should == 4321
|
67
|
-
end
|
68
|
-
|
69
|
-
it "raises an error when no name matches" do
|
70
|
-
lambda {
|
71
|
-
@envs.named!("something else")
|
72
|
-
}.should raise_error(EY::EnvironmentError)
|
73
|
-
end
|
74
|
-
end
|
13
|
+
it_should_behave_like "model collections"
|
75
14
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "EY::Model::Instance#has_app_code?" do
|
4
|
+
|
5
|
+
def have_app_code
|
6
|
+
simple_matcher("has app code") { |given| given.has_app_code? }
|
7
|
+
end
|
8
|
+
|
9
|
+
it "is true for solos" do
|
10
|
+
EY::Model::Instance.from_hash("role" => "solo").should have_app_code
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is true for app masters" do
|
14
|
+
EY::Model::Instance.from_hash("role" => "app_master").should have_app_code
|
15
|
+
end
|
16
|
+
|
17
|
+
it "is true for app slaves" do
|
18
|
+
EY::Model::Instance.from_hash("role" => "app").should have_app_code
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is true for utilities" do
|
22
|
+
EY::Model::Instance.from_hash("role" => "util").should have_app_code
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is false for DB masters" do
|
26
|
+
EY::Model::Instance.from_hash("role" => "db_master").should_not have_app_code
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is false for DB slaves" do
|
30
|
+
EY::Model::Instance.from_hash("role" => "db_slave").should_not have_app_code
|
31
|
+
end
|
32
|
+
end
|
@@ -126,17 +126,21 @@ shared_examples_for "it invokes eysd" do
|
|
126
126
|
it "passes along instance information to eysd" do
|
127
127
|
instance_args = [
|
128
128
|
Regexp.quote("ec2-174-129-198-124.compute-1.amazonaws.com,app_master"),
|
129
|
-
Regexp.quote("ec2-174-129-142-53.compute-1.amazonaws.com,db_master"),
|
130
129
|
Regexp.quote("ec2-72-44-46-66.compute-1.amazonaws.com,app"),
|
131
130
|
Regexp.quote("ec2-184-73-116-228.compute-1.amazonaws.com,util,fluffy"),
|
132
131
|
]
|
133
132
|
|
134
|
-
|
133
|
+
db_instance = Regexp.quote("ec2-174-129-142-53.compute-1.amazonaws.com,db_master")
|
134
|
+
|
135
|
+
# apps + utilities are all mentioned
|
135
136
|
instance_args.each do |i|
|
136
137
|
@ssh_commands.last.should =~ /#{i}/
|
137
138
|
end
|
138
139
|
|
139
|
-
#
|
140
|
+
# but not database instances
|
141
|
+
@ssh_commands.last.should_not =~ /#{db_instance}/
|
142
|
+
|
143
|
+
# and it's all after the option '--instances'
|
140
144
|
@ssh_commands.last.should match(/--instances (#{instance_args.join('|')})/)
|
141
145
|
end
|
142
146
|
|
@@ -186,5 +190,59 @@ shared_examples_for "it invokes eysd" do
|
|
186
190
|
ver = Regexp.quote(EY::Model::Instance::EYSD_VERSION)
|
187
191
|
@ssh_commands.should have_command_like(/eysd _#{ver}_ deploy/)
|
188
192
|
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
shared_examples_for "model collections" do
|
197
|
+
describe "#match_one" do
|
198
|
+
it "works when given an unambiguous substring" do
|
199
|
+
@collection.match_one("prod").name.should == "app_production"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "raises an error when given an ambiguous substring" do
|
203
|
+
lambda {
|
204
|
+
@collection.match_one("staging")
|
205
|
+
}.should raise_error(@collection_class.ambiguous_error)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "returns an exact match if one exists" do
|
209
|
+
@collection.match_one("app_staging").name.should == "app_staging"
|
210
|
+
end
|
211
|
+
|
212
|
+
it "returns nil when it can't find anything" do
|
213
|
+
@collection.match_one("dev-and-production").should be_nil
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "#match_one!" do
|
218
|
+
it "works when given an unambiguous substring" do
|
219
|
+
@collection.match_one!("prod").name.should == "app_production"
|
220
|
+
end
|
221
|
+
|
222
|
+
it "raises an error when given an ambiguous substring" do
|
223
|
+
lambda {
|
224
|
+
@collection.match_one!("staging")
|
225
|
+
}.should raise_error(@collection_class.ambiguous_error)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "returns an exact match if one exists" do
|
229
|
+
@collection.match_one!("app_staging").name.should == "app_staging"
|
230
|
+
end
|
231
|
+
|
232
|
+
it "raises an error when it can't find anything" do
|
233
|
+
lambda {
|
234
|
+
@collection.match_one!("dev-and-production")
|
235
|
+
}.should raise_error(@collection_class.invalid_error)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "#named" do
|
240
|
+
it "finds matching by name" do
|
241
|
+
@collection.named("app_staging").name.should == "app_staging"
|
242
|
+
end
|
243
|
+
|
244
|
+
it "returns nil when no name matches" do
|
245
|
+
@collection.named("something else").should be_nil
|
246
|
+
end
|
189
247
|
end
|
190
248
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 9
|
8
|
+
- 0
|
9
|
+
version: 0.9.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- EY Cloud Team
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-07-07 00:00:00 -07:00
|
18
18
|
default_executable: ey
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -114,6 +114,8 @@ files:
|
|
114
114
|
- lib/engineyard/cli/ui.rb
|
115
115
|
- lib/engineyard/cli/web.rb
|
116
116
|
- lib/engineyard/cli.rb
|
117
|
+
- lib/engineyard/collection/abstract.rb
|
118
|
+
- lib/engineyard/collection/apps.rb
|
117
119
|
- lib/engineyard/collection/environments.rb
|
118
120
|
- lib/engineyard/collection.rb
|
119
121
|
- lib/engineyard/config.rb
|
@@ -192,10 +194,12 @@ test_files:
|
|
192
194
|
- spec/engineyard/api_spec.rb
|
193
195
|
- spec/engineyard/cli/api_spec.rb
|
194
196
|
- spec/engineyard/cli_spec.rb
|
197
|
+
- spec/engineyard/collection/apps.rb
|
195
198
|
- spec/engineyard/collection/environments.rb
|
196
199
|
- spec/engineyard/config_spec.rb
|
197
200
|
- spec/engineyard/model/api_struct_spec.rb
|
198
201
|
- spec/engineyard/model/environment_spec.rb
|
202
|
+
- spec/engineyard/model/instance_spec.rb
|
199
203
|
- spec/engineyard/repo_spec.rb
|
200
204
|
- spec/engineyard_spec.rb
|
201
205
|
- spec/ey/deploy_spec.rb
|