vmc 0.4.2 → 0.4.3

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