engineyard 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,8 +5,9 @@ describe "ey web disable" do
5
5
 
6
6
  def command_to_run(opts)
7
7
  cmd = "web disable"
8
- cmd << " -e #{opts[:env]}" if opts[:env]
8
+ cmd << " -e #{opts[:environment]}" if opts[:environment]
9
9
  cmd << " -a #{opts[:app]}" if opts[:app]
10
+ cmd << " -c #{opts[:account]}" if opts[:account]
10
11
  cmd << " --verbose" if opts[:verbose]
11
12
  cmd
12
13
  end
@@ -15,7 +16,6 @@ describe "ey web disable" do
15
16
  @ssh_commands.should have_command_like(/engineyard-serverside.*deploy enable_maintenance_page.*--app #{scenario[:application]}/)
16
17
  end
17
18
 
18
- it_should_behave_like "it takes an environment name"
19
- it_should_behave_like "it takes an app name"
19
+ it_should_behave_like "it takes an environment name and an app name and an account name"
20
20
  it_should_behave_like "it invokes engineyard-serverside"
21
21
  end
@@ -5,8 +5,9 @@ describe "ey web enable" do
5
5
 
6
6
  def command_to_run(opts)
7
7
  cmd = "web enable"
8
- cmd << " -e #{opts[:env]}" if opts[:env]
8
+ cmd << " -e #{opts[:environment]}" if opts[:environment]
9
9
  cmd << " -a #{opts[:app]}" if opts[:app]
10
+ cmd << " -c #{opts[:account]}" if opts[:account]
10
11
  cmd << " --verbose" if opts[:verbose]
11
12
  cmd
12
13
  end
@@ -15,7 +16,6 @@ describe "ey web enable" do
15
16
  @ssh_commands.should have_command_like(/engineyard-serverside.*deploy disable_maintenance_page.*--app #{scenario[:application]}/)
16
17
  end
17
18
 
18
- it_should_behave_like "it takes an environment name"
19
- it_should_behave_like "it takes an app name"
19
+ it_should_behave_like "it takes an environment name and an app name and an account name"
20
20
  it_should_behave_like "it invokes engineyard-serverside"
21
21
  end
data/spec/spec_helper.rb CHANGED
@@ -29,6 +29,9 @@ require 'json'
29
29
  $LOAD_PATH.unshift(File.join(EY_ROOT, "lib"))
30
30
  require 'engineyard'
31
31
 
32
+ #autoload hax
33
+ EY::Error
34
+
32
35
  # Spec stuff
33
36
  require 'spec/autorun'
34
37
  require 'tmpdir'
@@ -39,7 +42,7 @@ support.each{|helper| require helper }
39
42
 
40
43
  Spec::Runner.configure do |config|
41
44
  config.include Spec::Helpers
42
- config.extend Spec::GitRepo
45
+ config.include Spec::GitRepo
43
46
  config.extend Spec::Helpers::SemanticNames
44
47
 
45
48
  config.before(:all) do
@@ -30,6 +30,8 @@ class FakeAwsm < Sinatra::Base
30
30
  Scenario::TwoApps
31
31
  when "one app, one environment"
32
32
  Scenario::LinkedApp
33
+ when "two accounts, two apps, two environments, ambiguous"
34
+ Scenario::MultipleAmbiguousAccounts
33
35
  when "one app, one environment, no instances"
34
36
  Scenario::LinkedAppNotRunning
35
37
  when "one app, one environment, app master red"
@@ -122,22 +124,31 @@ private
122
124
 
123
125
  class CloudMock
124
126
  def initialize(initial_conditions)
125
- @apps, @envs, @keys, @app_joins, @key_joins = [], [], [], [], []
127
+ @accounts, @apps, @envs, @keys, @app_joins, @key_joins = [], [], [], [], [], []
126
128
  @next_id = 1
127
129
 
130
+ initial_conditions.starting_accounts.each {|a| add_account(a) }
128
131
  initial_conditions.starting_apps.each {|a| add_app(a) }
129
132
  initial_conditions.starting_environments.each {|e| add_environment(e) }
130
133
  initial_conditions.starting_app_joins.each {|(app_id, env_id)| link_app(app_id, env_id) }
131
134
  end
132
135
 
136
+ def add_account(acc)
137
+ acc["id"] ||= next_id
138
+ @accounts << acc
139
+ acc
140
+ end
141
+
133
142
  def add_app(app)
134
143
  app["id"] ||= next_id
144
+ app["account"] ||= @accounts.first
135
145
  @apps << app
136
146
  app
137
147
  end
138
148
 
139
149
  def add_environment(env)
140
150
  env["id"] ||= next_id
151
+ env["account"] ||= @accounts.first
141
152
 
142
153
  unless env.has_key?("app_master")
143
154
  master = env["instances"].find{ |i| %w[solo app_master].include?(i["role"]) }
@@ -149,8 +160,11 @@ private
149
160
  end
150
161
 
151
162
  def link_app(app_id, env_id)
152
- @apps.find {|a| a["id"] == app_id } or raise "No such app id:#{app_id}"
153
- @envs.find {|e| e["id"] == env_id } or raise "No such environment id:#{env_id}"
163
+ app = @apps.find {|a| a["id"] == app_id } or raise "No such app id:#{app_id}"
164
+ env = @envs.find {|e| e["id"] == env_id } or raise "No such environment id:#{env_id}"
165
+ if app["account"]["id"] != env["account"]["id"]
166
+ raise "App #{app_id} in account #{app["account"]["id"]} cannot be attached to environment #{env_id} in account #{env["account"]["id"]}"
167
+ end
154
168
  @app_joins << [app_id, env_id]
155
169
  @app_joins.uniq!
156
170
  end
@@ -213,6 +227,7 @@ private
213
227
  self.git_remote = git_remote
214
228
  end
215
229
 
230
+ def starting_accounts() [{"name" => "main"}] end
216
231
  def starting_apps() [] end
217
232
  def starting_environments() [] end
218
233
  def starting_app_joins() [] end
@@ -298,6 +313,35 @@ private
298
313
 
299
314
  end # LinkedApp
300
315
 
316
+ class MultipleAmbiguousAccounts < LinkedApp
317
+ def starting_accounts
318
+ super + [{"name" => "account_2", "id" => 256}]
319
+ end
320
+
321
+ def starting_apps
322
+ apps = super
323
+ new_app = apps.first.dup
324
+ new_app["id"] += 1000
325
+ new_app["account"] = starting_accounts.last
326
+ apps + [new_app]
327
+ end
328
+
329
+ def starting_environments
330
+ envs = super
331
+ new_env = envs.first.dup
332
+ new_env["id"] += 1000
333
+ new_env["account"] = starting_accounts.last
334
+ envs + [new_env]
335
+ end
336
+
337
+ def starting_app_joins
338
+ joins = super
339
+ new_join = [joins.first[0] + 1000,
340
+ joins.first[1] + 1000]
341
+ joins + [new_join]
342
+ end
343
+ end
344
+
301
345
  class UnlinkedApp < Base
302
346
  def starting_apps
303
347
  [{
@@ -1,23 +1,36 @@
1
1
  module Spec
2
2
  module GitRepo
3
- def define_git_repo(name, &setup)
4
- # EY's ivars don't get cleared between examples, so we can keep
5
- # a git repo around longer (and thus make our tests faster)
6
- FakeFS.without { EY.define_git_repo(name, &setup) }
7
- end
3
+ module ClassMethods
8
4
 
9
- def use_git_repo(repo_name)
10
- before(:all) do
11
- FakeFS.without do
12
- @_original_wd ||= []
13
- @_original_wd << Dir.getwd
14
- Dir.chdir(EY.git_repo_dir(repo_name))
15
- end
5
+ def define_git_repo(name, &setup)
6
+ # EY's ivars don't get cleared between examples, so we can keep
7
+ # a git repo around longer (and thus make our tests faster)
8
+ FakeFS.without { EY.define_git_repo(name, &setup) }
16
9
  end
17
10
 
18
- after(:all) do
19
- FakeFS.without { Dir.chdir(@_original_wd.pop) }
11
+ def use_git_repo(repo_name)
12
+ before(:all) do
13
+ FakeFS.without do
14
+ @_original_wd ||= []
15
+ @_original_wd << Dir.getwd
16
+ Dir.chdir(EY.git_repo_dir(repo_name))
17
+ end
18
+ end
19
+
20
+ after(:all) do
21
+ FakeFS.without { Dir.chdir(@_original_wd.pop) }
22
+ end
20
23
  end
24
+
25
+ end # ClassMethods
26
+
27
+ def refresh_git_repo(name)
28
+ EY.refresh_git_repo(name)
21
29
  end
30
+
31
+ def self.included(other)
32
+ other.extend ClassMethods
33
+ end
34
+
22
35
  end
23
36
  end
@@ -146,6 +146,11 @@ module EY
146
146
  @git_repo_setup[name] = setup
147
147
  end
148
148
 
149
+ def refresh_git_repo(name)
150
+ @git_repo_dir_cache ||= {}
151
+ @git_repo_dir_cache.delete name
152
+ end
153
+
149
154
  def git_repo_dir(name)
150
155
  @git_repo_dir_cache ||= {}
151
156
  return @git_repo_dir_cache[name] if @git_repo_dir_cache.has_key?(name)
@@ -43,8 +43,63 @@ shared_examples_for "it requires an unambiguous git repo" do
43
43
  run_ey({}, {:expect_failure => true})
44
44
  @err.should =~ /ambiguous/
45
45
  @err.should =~ /specify one of the following environments/
46
- @err.should =~ /giblets/
47
- @err.should =~ /keycollector_production/
46
+ @err.should =~ /giblets \(main\)/
47
+ @err.should =~ /keycollector_production \(main\)/
48
+ end
49
+ end
50
+
51
+ shared_examples_for "it takes an environment name and an app name and an account name" do
52
+ it_should_behave_like "it takes an app name"
53
+ it_should_behave_like "it takes an environment name"
54
+
55
+ context "when multiple accounts with collaboration" do
56
+ before :all do
57
+ api_scenario "two accounts, two apps, two environments, ambiguous"
58
+ end
59
+
60
+ it "fails when the app and environment are ambiguous across accounts" do
61
+ run_ey({:environment => "giblets", :app => "rails232app", :ref => 'master'}, {:expect_failure => true})
62
+ @err.should match(/Multiple app deployments possible/i)
63
+ @err.should match(/ey \S+ --environment='giblets' --app='rails232app' --account='account_2'/i)
64
+ @err.should match(/ey \S+ --environment='giblets' --app='rails232app' --account='main'/i)
65
+ end
66
+
67
+ it "runs when specifying the account disambiguates the app to deploy" do
68
+ run_ey({:environment => "giblets", :app => "rails232app", :account => "main", :ref => 'master'})
69
+ verify_ran(make_scenario({
70
+ :environment => 'giblets',
71
+ :application => 'rails232app',
72
+ :master_hostname => 'app_master_hostname.compute-1.amazonaws.com',
73
+ :ssh_username => 'turkey',
74
+ }))
75
+ end
76
+ end
77
+ end
78
+
79
+ shared_examples_for "it takes an environment name and an account name" do
80
+ it_should_behave_like "it takes an environment name"
81
+
82
+ context "when multiple accounts with collaboration" do
83
+ before :all do
84
+ api_scenario "two accounts, two apps, two environments, ambiguous"
85
+ end
86
+
87
+ it "fails when the app and environment are ambiguous across accounts" do
88
+ run_ey({:environment => "giblets"}, {:expect_failure => true})
89
+ @err.should match(/multiple environments possible/i)
90
+ @err.should match(/ey \S+ --environment='giblets' --account='account_2'/i)
91
+ @err.should match(/ey \S+ --environment='giblets' --account='main'/i)
92
+ end
93
+
94
+ it "runs when specifying the account disambiguates the app to deploy" do
95
+ run_ey({:environment => "giblets", :account => "main"})
96
+ verify_ran(make_scenario({
97
+ :environment => 'giblets',
98
+ :application => 'rails232app',
99
+ :master_hostname => 'app_master_hostname.compute-1.amazonaws.com',
100
+ :ssh_username => 'turkey',
101
+ }))
102
+ end
48
103
  end
49
104
  end
50
105
 
@@ -53,7 +108,7 @@ shared_examples_for "it takes an environment name" do
53
108
 
54
109
  it "operates on the current environment by default" do
55
110
  api_scenario "one app, one environment"
56
- run_ey({:env => nil}, {:debug => true})
111
+ run_ey({:environment => nil}, {:debug => true})
57
112
  verify_ran(make_scenario({
58
113
  :environment => 'giblets',
59
114
  :application => 'rails232app',
@@ -64,23 +119,47 @@ shared_examples_for "it takes an environment name" do
64
119
 
65
120
  it "complains when you specify a nonexistent environment" do
66
121
  api_scenario "one app, one environment"
67
- run_ey({:env => 'typo-happens-here'}, {:expect_failure => true})
122
+ run_ey({:environment => 'typo-happens-here'}, {:expect_failure => true})
68
123
  @err.should match(/no environment named 'typo-happens-here'/i)
69
124
  end
70
125
 
126
+ context "outside a git repo" do
127
+ define_git_repo("not actually a git repo") do |git_dir|
128
+ # in case we screw up and are not in a freshly-generated test
129
+ # git repository, don't blow away the thing we're developing
130
+ system("rm -rf .git") if `git remote -v`.include?("path/to/repo.git")
131
+ git_dir.join("cookbooks").mkdir
132
+ end
133
+
134
+ use_git_repo("not actually a git repo")
135
+
136
+ before :all do
137
+ api_scenario "one app, one environment"
138
+ end
139
+
140
+ it "works (and does not complain about git remotes)" do
141
+ run_ey({:environment => 'giblets'}) unless @takes_app_name
142
+ end
143
+
144
+ end
145
+
71
146
  context "given a piece of the environment name" do
72
147
  before(:all) do
73
148
  api_scenario "one app, many similarly-named environments"
74
149
  end
75
150
 
76
151
  it "complains when the substring is ambiguous" do
77
- run_ey({:env => 'staging'}, {:expect_failure => true})
78
- @err.should match(/'staging' is ambiguous/)
152
+ run_ey({:environment => 'staging'}, {:expect_failure => true})
153
+ if @takes_app_name
154
+ @err.should match(/multiple app deployments possible/i)
155
+ else
156
+ @err.should match(/multiple environments possible/i)
157
+ end
79
158
  end
80
159
 
81
160
  it "works when the substring is unambiguous" do
82
161
  api_scenario "one app, many similarly-named environments"
83
- run_ey({:env => 'prod'}, {:debug => true})
162
+ run_ey({:environment => 'prod'}, {:debug => true})
84
163
  verify_ran(make_scenario({
85
164
  :environment => 'railsapp_production',
86
165
  :application => 'rails232app',
@@ -92,18 +171,19 @@ shared_examples_for "it takes an environment name" do
92
171
 
93
172
  it "complains when it can't guess the environment and its name isn't specified" do
94
173
  api_scenario "one app, one environment, not linked"
95
- run_ey({:env => nil}, {:expect_failure => true})
96
- @err.should =~ /single environment/i
174
+ run_ey({:environment => nil}, {:expect_failure => true})
175
+ @err.should match(/there is no application configured/i)
97
176
  end
98
177
  end
99
178
 
100
179
  shared_examples_for "it takes an app name" do
101
180
  include Spec::Helpers::SharedIntegrationTestUtils
181
+ before { @takes_app_name = true }
102
182
 
103
183
  it "allows you to specify a valid app" do
104
184
  api_scenario "one app, one environment"
105
185
  Dir.chdir(Dir.tmpdir) do
106
- run_ey({:env => 'giblets', :app => 'rails232app', :ref => 'master'}, {})
186
+ run_ey({:environment => 'giblets', :app => 'rails232app', :ref => 'master'}, {})
107
187
  verify_ran(make_scenario({
108
188
  :environment => 'giblets',
109
189
  :application => 'rails232app',
@@ -128,7 +208,7 @@ shared_examples_for "it takes an app name" do
128
208
 
129
209
  it "complains when you specify a nonexistant app" do
130
210
  api_scenario "one app, one environment"
131
- run_ey({:env => 'giblets', :app => 'P-time-SAT-solver', :ref => 'master'},
211
+ run_ey({:environment => 'giblets', :app => 'P-time-SAT-solver', :ref => 'master'},
132
212
  {:expect_failure => true})
133
213
  @err.should =~ /no app.*P-time-SAT-solver/i
134
214
  end
@@ -141,7 +221,7 @@ shared_examples_for "it invokes engineyard-serverside" do
141
221
  context "with arguments" do
142
222
  before(:all) do
143
223
  api_scenario "one app, one environment"
144
- run_ey({:env => 'giblets', :verbose => true})
224
+ run_ey({:environment => 'giblets', :verbose => true})
145
225
  end
146
226
 
147
227
  it "passes --verbose to engineyard-serverside" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: engineyard
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 1
10
- version: 1.3.1
9
+ - 2
10
+ version: 1.3.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - EY Cloud Team
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-20 00:00:00 -07:00
18
+ date: 2010-10-15 00:00:00 -07:00
19
19
  default_executable: ey
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,12 +24,12 @@ dependencies:
24
24
  requirements:
25
25
  - - ~>
26
26
  - !ruby/object:Gem::Version
27
- hash: 39
27
+ hash: 33
28
28
  segments:
29
29
  - 0
30
30
  - 14
31
- - 0
32
- version: 0.14.0
31
+ - 3
32
+ version: 0.14.3
33
33
  requirement: *id001
34
34
  type: :runtime
35
35
  name: thor
@@ -77,24 +77,10 @@ dependencies:
77
77
  version: "0"
78
78
  requirement: *id004
79
79
  type: :runtime
80
- name: ruby-termios
81
- prerelease: false
82
- - !ruby/object:Gem::Dependency
83
- version_requirements: &id005 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
92
- requirement: *id005
93
- type: :runtime
94
80
  name: json_pure
95
81
  prerelease: false
96
82
  - !ruby/object:Gem::Dependency
97
- version_requirements: &id006 !ruby/object:Gem::Requirement
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
98
84
  none: false
99
85
  requirements:
100
86
  - - ~>
@@ -105,23 +91,23 @@ dependencies:
105
91
  - 0
106
92
  - 4
107
93
  version: 0.0.4
108
- requirement: *id006
94
+ requirement: *id005
109
95
  type: :runtime
110
96
  name: escape
111
97
  prerelease: false
112
98
  - !ruby/object:Gem::Dependency
113
- version_requirements: &id007 !ruby/object:Gem::Requirement
99
+ version_requirements: &id006 !ruby/object:Gem::Requirement
114
100
  none: false
115
101
  requirements:
116
102
  - - "="
117
103
  - !ruby/object:Gem::Version
118
- hash: 29
104
+ hash: 17
119
105
  segments:
120
106
  - 1
121
107
  - 3
122
- - 3
123
- version: 1.3.3
124
- requirement: *id007
108
+ - 5
109
+ version: 1.3.5
110
+ requirement: *id006
125
111
  type: :runtime
126
112
  name: engineyard-serverside-adapter
127
113
  prerelease: false
@@ -147,6 +133,7 @@ files:
147
133
  - lib/engineyard/collection.rb
148
134
  - lib/engineyard/config.rb
149
135
  - lib/engineyard/error.rb
136
+ - lib/engineyard/model/account.rb
150
137
  - lib/engineyard/model/api_struct.rb
151
138
  - lib/engineyard/model/app.rb
152
139
  - lib/engineyard/model/environment.rb
@@ -154,6 +141,7 @@ files:
154
141
  - lib/engineyard/model/log.rb
155
142
  - lib/engineyard/model.rb
156
143
  - lib/engineyard/repo.rb
144
+ - lib/engineyard/resolver.rb
157
145
  - lib/engineyard/ruby_ext.rb
158
146
  - lib/engineyard/thor.rb
159
147
  - lib/engineyard/version.rb
@@ -170,6 +158,7 @@ files:
170
158
  - spec/engineyard/model/environment_spec.rb
171
159
  - spec/engineyard/model/instance_spec.rb
172
160
  - spec/engineyard/repo_spec.rb
161
+ - spec/engineyard/resolver_spec.rb
173
162
  - spec/engineyard_spec.rb
174
163
  - spec/ey/deploy_spec.rb
175
164
  - spec/ey/ey_spec.rb
@@ -235,6 +224,7 @@ test_files:
235
224
  - spec/engineyard/model/environment_spec.rb
236
225
  - spec/engineyard/model/instance_spec.rb
237
226
  - spec/engineyard/repo_spec.rb
227
+ - spec/engineyard/resolver_spec.rb
238
228
  - spec/engineyard_spec.rb
239
229
  - spec/ey/deploy_spec.rb
240
230
  - spec/ey/ey_spec.rb