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.
@@ -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