vmc 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/lib/vmc.rb +2 -5
  2. data/lib/vmc/cli/app/apps.rb +4 -1
  3. data/lib/vmc/cli/app/push.rb +38 -221
  4. data/lib/vmc/cli/app/push/create.rb +125 -0
  5. data/lib/vmc/cli/app/push/interaction.rb +64 -0
  6. data/lib/vmc/cli/app/push/sync.rb +59 -0
  7. data/lib/vmc/cli/app/rename.rb +1 -1
  8. data/lib/vmc/cli/organization/base.rb +14 -0
  9. data/lib/vmc/cli/organization/create_org.rb +28 -0
  10. data/lib/vmc/cli/organization/delete_org.rb +65 -0
  11. data/lib/vmc/cli/organization/org.rb +46 -0
  12. data/lib/vmc/cli/organization/orgs.rb +35 -0
  13. data/lib/vmc/cli/organization/rename.rb +32 -0
  14. data/lib/vmc/cli/service/base.rb +8 -0
  15. data/lib/vmc/cli/service/binding.rb +66 -0
  16. data/lib/vmc/cli/service/create.rb +104 -0
  17. data/lib/vmc/cli/service/delete.rb +84 -0
  18. data/lib/vmc/cli/service/rename.rb +32 -0
  19. data/lib/vmc/cli/service/service.rb +45 -0
  20. data/lib/vmc/cli/service/services.rb +118 -0
  21. data/lib/vmc/cli/space/base.rb +21 -0
  22. data/lib/vmc/cli/space/create.rb +57 -0
  23. data/lib/vmc/cli/space/delete.rb +92 -0
  24. data/lib/vmc/cli/space/rename.rb +36 -0
  25. data/lib/vmc/cli/space/space.rb +67 -0
  26. data/lib/vmc/cli/space/spaces.rb +57 -0
  27. data/lib/vmc/cli/space/take.rb +18 -0
  28. data/lib/vmc/cli/start/base.rb +100 -0
  29. data/lib/vmc/cli/start/colors.rb +14 -0
  30. data/lib/vmc/cli/start/info.rb +124 -0
  31. data/lib/vmc/cli/start/login.rb +94 -0
  32. data/lib/vmc/cli/start/logout.rb +14 -0
  33. data/lib/vmc/cli/start/register.rb +38 -0
  34. data/lib/vmc/cli/start/target.rb +68 -0
  35. data/lib/vmc/cli/start/targets.rb +17 -0
  36. data/lib/vmc/version.rb +1 -1
  37. data/spec/factories/app_factory.rb +5 -0
  38. data/spec/factories/client_factory.rb +10 -1
  39. data/spec/factories/domain_factory.rb +2 -1
  40. data/spec/factories/factory.rb +1 -0
  41. data/spec/factories/framework_factory.rb +1 -0
  42. data/spec/factories/organization_factory.rb +18 -0
  43. data/spec/factories/route_factory.rb +1 -0
  44. data/spec/factories/runtime_factory.rb +10 -0
  45. data/spec/factories/service_binding_factory.rb +9 -0
  46. data/spec/factories/service_factory.rb +17 -0
  47. data/spec/factories/service_instance_factory.rb +10 -0
  48. data/spec/factories/service_plan_factory.rb +11 -0
  49. data/spec/factories/space_factory.rb +10 -0
  50. data/spec/support/interact_helpers.rb +7 -3
  51. data/spec/vmc/cli/app/push/create_spec.rb +450 -0
  52. data/spec/vmc/cli/app/push_spec.rb +303 -9
  53. data/spec/vmc/cli/app/rename_spec.rb +9 -4
  54. data/spec/vmc/cli/organization/rename_spec.rb +113 -0
  55. data/spec/vmc/cli/route/delete_route_spec.rb +2 -2
  56. data/spec/vmc/cli/service/rename_spec.rb +114 -0
  57. data/spec/vmc/cli/space/rename_spec.rb +114 -0
  58. metadata +109 -64
  59. data/lib/vmc/cli/organization.rb +0 -176
  60. data/lib/vmc/cli/service.rb +0 -387
  61. data/lib/vmc/cli/space.rb +0 -284
  62. data/lib/vmc/cli/start.rb +0 -432
  63. data/spec/assets/hello-sinatra/Gemfile.lock +0 -17
@@ -0,0 +1,14 @@
1
+ require "vmc/detect"
2
+ require "vmc/cli/start/base"
3
+
4
+ module VMC::Start
5
+ class Logout < Base
6
+ desc "Log out from the target"
7
+ group :start
8
+ def logout
9
+ with_progress("Logging out") do
10
+ remove_target_info
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require "vmc/detect"
2
+ require "vmc/cli/start/base"
3
+
4
+ module VMC::Start
5
+ class Register < Base
6
+ desc "Create a user and log in"
7
+ group :start, :hidden => true
8
+ input(:email, :argument => true, :desc => "Desired email") {
9
+ ask("Email")
10
+ }
11
+ input(:password, :desc => "Desired password") {
12
+ ask("Password", :echo => "*", :forget => true)
13
+ }
14
+ input(:verify, :desc => "Repeat password") {
15
+ ask("Confirm Password", :echo => "*", :forget => true)
16
+ }
17
+ input :login, :type => :boolean, :default => true,
18
+ :desc => "Automatically log in?"
19
+ def register
20
+ show_context
21
+
22
+ email = input[:email]
23
+ password = input[:password]
24
+
25
+ if !force? && password != input[:verify]
26
+ fail "Passwords do not match."
27
+ end
28
+
29
+ with_progress("Creating user") do
30
+ client.register(email, password)
31
+ end
32
+
33
+ if input[:login]
34
+ invoke :login, :username => email, :password => password
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,68 @@
1
+ require "vmc/detect"
2
+ require "vmc/cli/start/base"
3
+
4
+ module VMC::Start
5
+ class Target < Base
6
+ desc "Set or display the target cloud, organization, and space"
7
+ group :start
8
+ input :url, :argument => :optional, :desc => "Target URL to switch to"
9
+ input(:organization, :aliases => ["--org", "-o"],
10
+ :from_given => find_by_name("organization"),
11
+ :desc => "Organization") { |orgs|
12
+ ask("Organization", :choices => orgs, :display => proc(&:name))
13
+ }
14
+ input(:space, :alias => "-s",
15
+ :from_given => find_by_name("space"),
16
+ :desc => "Space") { |spaces|
17
+ ask("Space", :choices => spaces, :display => proc(&:name))
18
+ }
19
+ def target
20
+ if !input.given?(:url) && !input.given?(:organization) && !input.given?(:space)
21
+ display_target
22
+ display_org_and_space unless quiet?
23
+ return
24
+ end
25
+
26
+ if input.given?(:url)
27
+ target = sane_target_url(input[:url])
28
+ with_progress("Setting target to #{c(target, :name)}") do
29
+ client(target).info # check that it's valid before setting
30
+ set_target(target)
31
+ end
32
+ end
33
+
34
+ return unless v2? && client.logged_in?
35
+
36
+ if input.given?(:organization) || input.given?(:space)
37
+ info = target_info
38
+
39
+ select_org_and_space(input, info)
40
+
41
+ save_target_info(info)
42
+ end
43
+
44
+ return if quiet?
45
+
46
+ invalidate_client
47
+
48
+ line
49
+ display_target
50
+ display_org_and_space
51
+ end
52
+
53
+ private
54
+
55
+ def display_org_and_space
56
+ return unless v2?
57
+
58
+ if org = client.current_organization
59
+ line "organization: #{c(org.name, :name)}"
60
+ end
61
+
62
+ if space = client.current_space
63
+ line "space: #{c(space.name, :name)}"
64
+ end
65
+ rescue CFoundry::APIError
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ require "vmc/detect"
2
+ require "vmc/cli/start/base"
3
+
4
+ module VMC::Start
5
+ class Targets < Base
6
+ desc "List known targets."
7
+ group :start, :hidden => true
8
+ def targets
9
+ targets_info.each do |target, _|
10
+ line target
11
+ # TODO: print org/space
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+
data/lib/vmc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module VMC
2
- VERSION = "0.4.2".freeze
2
+ VERSION = "0.4.3".freeze
3
3
  end
@@ -1,6 +1,11 @@
1
1
  FactoryGirl.define do
2
2
  factory :app, :class => CFoundry::V2::App do
3
+ guid { FactoryGirl.generate(:guid) }
3
4
  name { FactoryGirl.generate(:random_string) }
5
+ memory 128
6
+ total_instances 0
7
+ production false
8
+ state "STOPPED"
4
9
 
5
10
  initialize_with do
6
11
  CFoundry::V2::App.new(nil, nil)
@@ -4,13 +4,22 @@ FactoryGirl.define do
4
4
  routes []
5
5
  apps []
6
6
  frameworks []
7
+ runtimes []
8
+ service_instances []
9
+ spaces []
10
+ organizations []
11
+ logged_in true
7
12
  end
8
13
 
9
14
  after_build do |client, evaluator|
10
- RR.stub(client).logged_in? { true }
15
+ RR.stub(client).logged_in? { evaluator.logged_in }
11
16
  RR.stub(client).routes { evaluator.routes }
12
17
  RR.stub(client).apps { evaluator.apps }
13
18
  RR.stub(client).frameworks { evaluator.frameworks }
19
+ RR.stub(client).runtimes { evaluator.runtimes }
20
+ RR.stub(client).service_instances { evaluator.service_instances }
21
+ RR.stub(client).spaces { evaluator.spaces }
22
+ RR.stub(client).organizations { evaluator.organizations }
14
23
  end
15
24
  end
16
25
  end
@@ -1,9 +1,10 @@
1
1
  FactoryGirl.define do
2
2
  factory :domain, :class => CFoundry::V2::Domain do
3
+ guid { FactoryGirl.generate(:guid) }
3
4
  name { FactoryGirl.generate(:random_string) }
4
5
 
5
6
  initialize_with do
6
7
  CFoundry::V2::Domain.new(nil, nil)
7
8
  end
8
9
  end
9
- end
10
+ end
@@ -1,3 +1,4 @@
1
1
  FactoryGirl.define do
2
2
  sequence(:random_string) {|n| "random_#{n}_string" }
3
+ sequence(:guid) {|n| "random_#{n}_guid" }
3
4
  end
@@ -1,5 +1,6 @@
1
1
  FactoryGirl.define do
2
2
  factory :framework, :class => CFoundry::V2::Framework do
3
+ guid { FactoryGirl.generate(:guid) }
3
4
  name { FactoryGirl.generate(:random_string) }
4
5
 
5
6
  initialize_with do
@@ -0,0 +1,18 @@
1
+ FactoryGirl.define do
2
+ factory :organization, :class => CFoundry::V2::Organization do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ name { FactoryGirl.generate(:random_string) }
5
+
6
+ ignore do
7
+ spaces []
8
+ end
9
+
10
+ initialize_with do
11
+ CFoundry::V2::Organization.new(nil, nil)
12
+ end
13
+
14
+ after_build do |org, evaluator|
15
+ RR.stub(org).spaces { evaluator.spaces }
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,6 @@
1
1
  FactoryGirl.define do
2
2
  factory :route, :class => CFoundry::V2::Route do
3
+ guid { FactoryGirl.generate(:guid) }
3
4
  host { FactoryGirl.generate(:random_string) }
4
5
  association :domain, :factory => :domain, :strategy => :build
5
6
 
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :runtime, :class => CFoundry::V2::Runtime do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ name { FactoryGirl.generate(:random_string) }
5
+
6
+ initialize_with do
7
+ CFoundry::V2::Runtime.new(nil, nil)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :service_binding, :class => CFoundry::V2::ServiceBinding do
3
+ guid { FactoryGirl.generate(:guid) }
4
+
5
+ initialize_with do
6
+ CFoundry::V2::ServiceBinding.new(nil, nil)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ FactoryGirl.define do
2
+ factory :service, :class => CFoundry::V2::Service do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ label "redis"
5
+ provider "core"
6
+ url "http://example.com"
7
+ description "small key-value store"
8
+ version "2.8"
9
+ info_url "http://cloudfoundry.com/redis"
10
+ active true
11
+
12
+ initialize_with do
13
+ CFoundry::V2::Service.new(nil, nil)
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :service_instance, :class => CFoundry::V2::ServiceInstance do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ name { FactoryGirl.generate(:random_string) }
5
+
6
+ initialize_with do
7
+ CFoundry::V2::ServiceInstance.new(nil, nil)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ FactoryGirl.define do
2
+ factory :service_plan, :class => CFoundry::V2::ServicePlan do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ name "D100"
5
+ description "Filibuster plan"
6
+
7
+ initialize_with do
8
+ CFoundry::V2::ServicePlan.new(nil, nil)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :space, :class => CFoundry::V2::Space do
3
+ guid { FactoryGirl.generate(:guid) }
4
+ name { FactoryGirl.generate(:random_string) }
5
+
6
+ initialize_with do
7
+ CFoundry::V2::Space.new(nil, nil)
8
+ end
9
+ end
10
+ end
@@ -1,13 +1,17 @@
1
1
  def stub_ask(*args, &block)
2
+ a_stub = nil
2
3
  any_instance_of VMC::CLI do |interactive|
3
- stub(interactive).ask(*args, &block)
4
+ a_stub = stub(interactive).ask(*args, &block)
4
5
  end
6
+ a_stub
5
7
  end
6
8
 
7
9
  def mock_ask(*args, &block)
10
+ a_mock = nil
8
11
  any_instance_of VMC::CLI do |interactive|
9
- mock(interactive).ask(*args, &block)
12
+ a_mock = mock(interactive).ask(*args, &block)
10
13
  end
14
+ a_mock
11
15
  end
12
16
 
13
17
  def dont_allow_ask(*args)
@@ -20,4 +24,4 @@ def mock_with_progress(message)
20
24
  any_instance_of VMC::CLI do |interactive|
21
25
  mock(interactive).with_progress(message) { |_, block| block.call }
22
26
  end
23
- end
27
+ end
@@ -0,0 +1,450 @@
1
+ require 'spec_helper'
2
+
3
+ describe VMC::App::Create do
4
+ let(:inputs) { {} }
5
+ let(:given) { {} }
6
+ let(:global) { { :color => false, :quiet => true } }
7
+
8
+ let(:frameworks) { FactoryGirl.build_list(:framework, 3) }
9
+ let(:framework) { frameworks.first }
10
+ let(:standalone) { FactoryGirl.build(:framework, :name => "standalone") }
11
+
12
+ let(:runtimes) { FactoryGirl.build_list(:runtime, 3) }
13
+ let(:runtime) { runtimes.first }
14
+
15
+ let(:service_instances) { FactoryGirl.build_list(:service_instance, 5) }
16
+
17
+ let(:client) do
18
+ FactoryGirl.build(
19
+ :client,
20
+ :frameworks => frameworks, :runtimes => runtimes,
21
+ :service_instances => service_instances)
22
+ end
23
+
24
+ before do
25
+ any_instance_of(VMC::CLI) do |cli|
26
+ stub(cli).client { client }
27
+ end
28
+ end
29
+
30
+ let(:create) do
31
+ create = VMC::App::Push.new
32
+ create.path = "somePath"
33
+ create.input = Mothership::Inputs.new(Mothership.commands[:push], create, inputs, given, global)
34
+ create
35
+ end
36
+
37
+ describe '#get_inputs' do
38
+ subject { create.get_inputs }
39
+
40
+ let(:inputs) do
41
+ { :name => "some-name",
42
+ :instances => 1,
43
+ :plan => "p100",
44
+ :framework => framework,
45
+ :runtime => runtime,
46
+ :memory => "1G"
47
+ }
48
+ end
49
+
50
+ context 'when all the inputs are given' do
51
+ its([:name]) { should eq "some-name" }
52
+ its([:total_instances]) { should eq 1 }
53
+ its([:space]) { should eq client.current_space }
54
+ its([:production]) { should eq true }
55
+ its([:framework]) { should eq framework }
56
+ its([:command]) { should eq nil }
57
+ its([:runtime]) { should eq runtime }
58
+ its([:memory]) { should eq 1024 }
59
+ end
60
+
61
+ context 'when certain inputs are not given' do
62
+ it 'should ask for the name' do
63
+ inputs.delete(:name)
64
+ mock_ask("Name") { "some-name" }
65
+ subject
66
+ end
67
+
68
+ it 'should ask for the total instances' do
69
+ inputs.delete(:instances)
70
+ mock_ask("Instances", anything) { 1 }
71
+ subject
72
+ end
73
+
74
+ it 'should ask for the framework' do
75
+ inputs.delete(:framework)
76
+ mock_ask('Framework', anything) do |_, options|
77
+ expect(options[:choices]).to eq frameworks.sort_by(&:name)
78
+ framework
79
+ end
80
+ subject
81
+ end
82
+
83
+ it 'should ask for the command if the framework is standalone' do
84
+ inputs[:framework] = standalone
85
+ mock_ask("Startup command") { "ruby main.rb" }
86
+ subject
87
+ end
88
+
89
+ it 'should ask for the runtime' do
90
+ inputs.delete(:runtime)
91
+ mock_ask('Runtime', anything) do |_, options|
92
+ expect(options[:choices]).to eq runtimes.sort_by(&:name)
93
+ runtime
94
+ end
95
+ subject
96
+ end
97
+
98
+ it 'should ask for the memory' do
99
+ inputs.delete(:memory)
100
+
101
+ memory_choices = %w(64M 128M 256M 512M 1G)
102
+ stub(create).memory_choices { memory_choices }
103
+
104
+ mock_ask('Memory Limit', anything) do |_, options|
105
+ expect(options[:choices]).to eq memory_choices
106
+ "1G"
107
+ end
108
+
109
+ subject
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#determine_framework' do
115
+ subject { create.determine_framework }
116
+
117
+ context 'when framework is given' do
118
+ let(:inputs) { { :framework => framework } }
119
+
120
+ it 'does not try to get the frameworks' do
121
+ any_instance_of(VMC::Detector) do |detector|
122
+ dont_allow(detector).detect_framework
123
+ dont_allow(detector).all_frameworks
124
+ end
125
+
126
+ dont_allow_ask
127
+ dont_allow(client).frameworks
128
+
129
+ subject
130
+ end
131
+
132
+ it { should eq framework }
133
+ end
134
+
135
+ context 'when framework is not given' do
136
+ context 'and a framework is detected' do
137
+ it "lists the detected framework and an 'other' option" do
138
+ any_instance_of(VMC::Detector) do |detector|
139
+ mock(detector).detect_framework { framework }
140
+ end
141
+
142
+ mock_ask('Framework', anything) do |_, options|
143
+ expect(options[:choices]).to eq [framework, :other] #frameworks.sort_by(&:name)
144
+ framework
145
+ end
146
+
147
+ subject
148
+ end
149
+ end
150
+
151
+ context 'and a framework is not detected' do
152
+ it "lists all available frameworks" do
153
+ any_instance_of(VMC::Detector) do |detector|
154
+ stub(detector).detect_framework
155
+ end
156
+
157
+ mock_ask('Framework', anything) do |_, options|
158
+ expect(options[:choices]).to eq frameworks.sort_by(&:name)
159
+ framework
160
+ end
161
+
162
+ subject
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '#detect_runtimes' do
169
+ subject { create.determine_runtime(framework) }
170
+
171
+ context 'when runtime is given' do
172
+ let(:inputs) { { :runtime => runtime } }
173
+
174
+ it 'does not try to get the runtime' do
175
+ any_instance_of(VMC::Detector) do |detector|
176
+ dont_allow(detector).detect_runtime
177
+ dont_allow(detector).all_runtimes
178
+ end
179
+
180
+ dont_allow_ask
181
+ dont_allow(client).runtimes
182
+
183
+ subject
184
+ end
185
+
186
+ it { should eq runtime }
187
+ end
188
+
189
+ context 'when runtime is not given' do
190
+ context 'and the framework is standalone' do
191
+ let(:framework) { standalone }
192
+
193
+ it "detects the runtime" do
194
+ any_instance_of(VMC::Detector) do |detector|
195
+ mock(detector).detect_runtimes { runtimes }
196
+ end
197
+
198
+ mock_ask('Runtime', anything) do |_, options|
199
+ expect(options[:choices]).to eq(runtimes.sort_by(&:name) + [:other])
200
+ runtime
201
+ end
202
+
203
+ subject
204
+ end
205
+ end
206
+
207
+ context 'and the framework is not standalone' do
208
+ it "gets the runtimes based on the framework" do
209
+ any_instance_of(VMC::Detector) do |detector|
210
+ mock(detector).runtimes(framework) { runtimes }
211
+ end
212
+
213
+ mock_ask('Runtime', anything) do |_, options|
214
+ expect(options[:choices]).to eq(runtimes.sort_by(&:name) + [:other])
215
+ runtime
216
+ end
217
+
218
+ subject
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ describe '#create_app' do
225
+ before { dont_allow_ask }
226
+
227
+ let(:app) { FactoryGirl.build(:app, :guid => nil) }
228
+
229
+ let(:attributes) do
230
+ { :name => "some-app",
231
+ :total_instances => 2,
232
+ :framework => framework,
233
+ :runtime => runtime,
234
+ :production => false,
235
+ :memory => 1024
236
+ }
237
+ end
238
+
239
+ before { stub(client).app { app } }
240
+
241
+ subject { create.create_app(attributes) }
242
+
243
+ it 'creates an app based on the resulting inputs' do
244
+ attributes.each do |key, val|
245
+ mock(app).__send__(:"#{key}=", val)
246
+ end
247
+
248
+ mock(create).filter(:create_app, app) { app }
249
+
250
+ mock(app).create!
251
+
252
+ subject
253
+ end
254
+ end
255
+
256
+ describe '#map_url' do
257
+ let(:app) { FactoryGirl.build(:app) }
258
+ let(:url_choices) { %W(#{app.name}.foo-cloud.com) }
259
+
260
+ before do
261
+ stub(create).url_choices { url_choices }
262
+ end
263
+
264
+ subject { create.map_url(app) }
265
+
266
+ it "maps a url" do
267
+ mock_ask('URL', anything) do |_, options|
268
+ expect(options[:choices]).to eq(url_choices + %w(none))
269
+ expect(options[:default]).to eq url_choices.first
270
+ url_choices.first
271
+ end
272
+
273
+ mock(create).invoke(:map, :app => app, :url => url_choices.first)
274
+
275
+ subject
276
+ end
277
+
278
+ context "when mapping fails" do
279
+ before do
280
+ mock_ask('URL', anything) { url_choices.first }
281
+
282
+ mock(create).invoke(:map, :app => app, :url => url_choices.first) do
283
+ raise CFoundry::RouteHostTaken.new(1234, "foo")
284
+ end
285
+ end
286
+
287
+ it "asks again" do
288
+ stub(create).line
289
+
290
+ mock_ask('URL', anything) { url_choices.first }
291
+
292
+ stub(create).invoke(:map, :app => app, :url => url_choices.first)
293
+
294
+ subject
295
+ end
296
+
297
+ it "reports the failure message" do
298
+ mock(create).line "foo"
299
+ mock(create).line
300
+
301
+ stub_ask('URL', anything) { url_choices.first }
302
+
303
+ stub(create).invoke(:map, :app => app, :url => url_choices.first)
304
+
305
+ subject
306
+ end
307
+ end
308
+ end
309
+
310
+ describe '#create_services' do
311
+ let(:app) { FactoryGirl.build(:app) }
312
+ subject { create.create_services(app) }
313
+
314
+ context 'when forcing' do
315
+ let(:inputs) { {:force => true} }
316
+
317
+ it "does not ask to create any services" do
318
+ dont_allow_ask("Create services for application?", anything)
319
+ subject
320
+ end
321
+
322
+ it "does not create any services" do
323
+ dont_allow(create).invoke(:create_service, anything)
324
+ subject
325
+ end
326
+ end
327
+
328
+ context 'when not forcing' do
329
+ let(:inputs) { { :force => false } }
330
+
331
+ it 'does not create the service if asked not to' do
332
+ mock_ask("Create services for application?", anything) { false }
333
+ dont_allow(create).invoke(:create_service, anything)
334
+
335
+ subject
336
+ end
337
+
338
+ it 'asks again to create a service' do
339
+ mock_ask("Create services for application?", anything) { true }
340
+ mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
341
+
342
+ mock_ask("Create another service?", :default => false) { true }
343
+ mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
344
+
345
+ mock_ask("Create another service?", :default => false) { true }
346
+ mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
347
+
348
+ mock_ask("Create another service?", :default => false) { false }
349
+ dont_allow(create).invoke(:create_service, anything).ordered
350
+
351
+ subject
352
+ end
353
+ end
354
+ end
355
+
356
+ describe '#bind_services' do
357
+ let(:app) { FactoryGirl.build(:app) }
358
+
359
+ subject { create.bind_services(app) }
360
+
361
+ context 'when forcing' do
362
+ let(:global) { { :force => true, :color => false, :quiet => true } }
363
+
364
+ it "does not ask to bind any services" do
365
+ dont_allow_ask("Bind other services to application?", anything)
366
+ subject
367
+ end
368
+
369
+ it "does not bind any services" do
370
+ dont_allow(create).invoke(:bind_service, anything)
371
+ subject
372
+ end
373
+ end
374
+
375
+ context 'when not forcing' do
376
+ it 'does not bind the service if asked not to' do
377
+ mock_ask("Bind other services to application?", anything) { false }
378
+ dont_allow(create).invoke(:bind_service, anything)
379
+
380
+ subject
381
+ end
382
+
383
+ it 'asks again to bind a service' do
384
+ bind_times = 3
385
+ call_count = 0
386
+
387
+ mock_ask("Bind other services to application?", anything) { true }
388
+
389
+ mock(create).invoke(:bind_service, :app => app).times(bind_times) do
390
+ call_count += 1
391
+ stub(app).services { service_instances.first(call_count) }
392
+ end
393
+
394
+ mock_ask("Bind another service?", anything).times(bind_times) do
395
+ call_count < bind_times
396
+ end
397
+
398
+ subject
399
+ end
400
+
401
+ it 'stops asking if there are no more services to bind' do
402
+ bind_times = service_instances.size
403
+ call_count = 0
404
+
405
+ mock_ask("Bind other services to application?", anything) { true }
406
+
407
+ mock(create).invoke(:bind_service, :app => app).times(bind_times) do
408
+ call_count += 1
409
+ stub(app).services { service_instances.first(call_count) }
410
+ end
411
+
412
+ mock_ask("Bind another service?", anything).times(bind_times - 1) { true }
413
+
414
+ subject
415
+ end
416
+
417
+ context 'when there are no services' do
418
+ let(:service_instances) { [] }
419
+
420
+ it 'does not ask to bind anything' do
421
+ dont_allow_ask
422
+ subject
423
+ end
424
+ end
425
+ end
426
+ end
427
+
428
+ describe '#start_app' do
429
+ let(:app) { FactoryGirl.build(:app) }
430
+ subject { create.start_app(app) }
431
+
432
+ context 'when the start flag is provided' do
433
+ let(:inputs) { {:start => true} }
434
+
435
+ it 'invokes the start command' do
436
+ mock(create).invoke(:start, :app => app)
437
+ subject
438
+ end
439
+ end
440
+
441
+ context 'when the start flag is not provided' do
442
+ let(:inputs) { {:start => false} }
443
+
444
+ it 'invokes the start command' do
445
+ dont_allow(create).invoke(:start, anything)
446
+ subject
447
+ end
448
+ end
449
+ end
450
+ end