engineyard 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'
@@ -1,5 +1,7 @@
1
1
  module EY
2
2
  module Collection
3
+ autoload :Abstract, 'engineyard/collection/abstract'
3
4
  autoload :Environments, 'engineyard/collection/environments'
5
+ autoload :Apps, 'engineyard/collection/apps'
4
6
  end
5
7
  end
@@ -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
@@ -0,0 +1,8 @@
1
+ module EY
2
+ module Collection
3
+ class Apps < Abstract
4
+ self.invalid_error = InvalidAppError
5
+ self.ambiguous_error = AmbiguousAppName
6
+ end
7
+ end
8
+ end
@@ -1,35 +1,8 @@
1
- require 'engineyard/error'
2
-
3
1
  module EY
4
2
  module Collection
5
- class Environments < Array
6
-
7
- def named(name)
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
@@ -1,5 +1,11 @@
1
1
  module EY
2
- class Error < RuntimeError; end
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
- pretty_names = matches.map {|x| "'#{x}'"}.join(', ')
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
 
@@ -8,6 +8,10 @@ module EY
8
8
  end
9
9
  end
10
10
 
11
+ def self.from_array(*)
12
+ Collection::Apps[*super]
13
+ end
14
+
11
15
  def sole_environment
12
16
  if environments.size == 1
13
17
  environments.first
@@ -13,7 +13,7 @@ module EY
13
13
  end
14
14
  end
15
15
 
16
- def self.from_array(array, extras={})
16
+ def self.from_array(*)
17
17
  Collection::Environments[*super]
18
18
  end
19
19
 
@@ -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.inject(['--instances']) do |command, inst|
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
 
@@ -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
@@ -102,7 +102,11 @@ module EY
102
102
  end
103
103
 
104
104
  def fetch_app(app_name = nil)
105
- api.fetch_app!(app_name) || api.app_for_repo!(repo)
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)
@@ -1,3 +1,3 @@
1
1
  module EY
2
- VERSION = '0.8.2'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -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(:each) do
5
- @envs = described_class.new([
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
- describe "#match_one" do
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
- # they should all be mentioned
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
- # after the option '--instances'
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
8
- - 2
9
- version: 0.8.2
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-06-30 00:00:00 -07:00
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