af 0.3.22 → 0.5.0.beta.1
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.
- checksums.yaml +14 -6
- data/LICENSE +1277 -24
- data/Rakefile +24 -87
- data/bin/af +7 -2
- data/lib/af/version.rb +3 -0
- data/lib/vmc.rb +7 -2
- data/lib/vmc/cli.rb +475 -0
- data/lib/vmc/cli/app/app.rb +45 -0
- data/lib/vmc/cli/app/apps.rb +105 -0
- data/lib/vmc/cli/app/base.rb +82 -0
- data/lib/vmc/cli/app/crashes.rb +46 -0
- data/lib/vmc/cli/app/delete.rb +95 -0
- data/lib/vmc/cli/app/deprecated.rb +11 -0
- data/lib/vmc/cli/app/env.rb +78 -0
- data/lib/vmc/cli/app/files.rb +137 -0
- data/lib/vmc/cli/app/health.rb +26 -0
- data/lib/vmc/cli/app/instances.rb +53 -0
- data/lib/vmc/cli/app/logs.rb +76 -0
- data/lib/vmc/cli/app/push.rb +107 -0
- data/lib/vmc/cli/app/push/create.rb +150 -0
- data/lib/vmc/cli/app/push/interactions.rb +100 -0
- data/lib/vmc/cli/app/push/sync.rb +64 -0
- data/lib/vmc/cli/app/rename.rb +39 -0
- data/lib/vmc/cli/app/restart.rb +20 -0
- data/lib/vmc/cli/app/scale.rb +71 -0
- data/lib/vmc/cli/app/start.rb +93 -0
- data/lib/vmc/cli/app/stats.rb +67 -0
- data/lib/vmc/cli/app/stop.rb +27 -0
- data/lib/vmc/cli/domain/base.rb +12 -0
- data/lib/vmc/cli/domain/domains.rb +40 -0
- data/lib/vmc/cli/domain/map.rb +55 -0
- data/lib/vmc/cli/domain/unmap.rb +56 -0
- data/lib/vmc/cli/help.rb +16 -0
- data/lib/vmc/cli/interactive.rb +105 -0
- data/lib/vmc/cli/organization/base.rb +14 -0
- data/lib/vmc/cli/organization/create.rb +32 -0
- data/lib/vmc/cli/organization/delete.rb +73 -0
- data/lib/vmc/cli/organization/org.rb +45 -0
- data/lib/vmc/cli/organization/orgs.rb +35 -0
- data/lib/vmc/cli/organization/rename.rb +36 -0
- data/lib/vmc/cli/route/base.rb +12 -0
- data/lib/vmc/cli/route/map.rb +80 -0
- data/lib/vmc/cli/route/routes.rb +26 -0
- data/lib/vmc/cli/route/unmap.rb +94 -0
- data/lib/vmc/cli/service/base.rb +8 -0
- data/lib/vmc/cli/service/bind.rb +44 -0
- data/lib/vmc/cli/service/create.rb +126 -0
- data/lib/vmc/cli/service/delete.rb +86 -0
- data/lib/vmc/cli/service/rename.rb +35 -0
- data/lib/vmc/cli/service/service.rb +42 -0
- data/lib/vmc/cli/service/services.rb +115 -0
- data/lib/vmc/cli/service/unbind.rb +38 -0
- data/lib/vmc/cli/space/base.rb +21 -0
- data/lib/vmc/cli/space/create.rb +56 -0
- data/lib/vmc/cli/space/delete.rb +95 -0
- data/lib/vmc/cli/space/rename.rb +39 -0
- data/lib/vmc/cli/space/space.rb +64 -0
- data/lib/vmc/cli/space/spaces.rb +55 -0
- data/lib/vmc/cli/space/take.rb +16 -0
- data/lib/vmc/cli/start/base.rb +80 -0
- data/lib/vmc/cli/start/colors.rb +13 -0
- data/lib/vmc/cli/start/info.rb +122 -0
- data/lib/vmc/cli/start/login.rb +92 -0
- data/lib/vmc/cli/start/logout.rb +13 -0
- data/lib/vmc/cli/start/target.rb +64 -0
- data/lib/vmc/cli/start/target_interactions.rb +37 -0
- data/lib/vmc/cli/start/targets.rb +16 -0
- data/lib/vmc/cli/user/base.rb +29 -0
- data/lib/vmc/cli/user/create.rb +39 -0
- data/lib/vmc/cli/user/delete.rb +25 -0
- data/lib/vmc/cli/user/passwd.rb +50 -0
- data/lib/vmc/cli/user/register.rb +42 -0
- data/lib/vmc/cli/user/users.rb +32 -0
- data/lib/vmc/constants.rb +13 -0
- data/lib/vmc/detect.rb +134 -0
- data/lib/vmc/errors.rb +17 -0
- data/lib/vmc/plugin.rb +56 -0
- data/lib/vmc/spacing.rb +89 -0
- data/lib/vmc/spec_helper.rb +1 -0
- data/lib/vmc/test_support.rb +4 -0
- data/lib/vmc/test_support/command_helper.rb +32 -0
- data/lib/vmc/test_support/common_input_examples.rb +14 -0
- data/lib/vmc/test_support/fake_home_dir.rb +16 -0
- data/lib/vmc/test_support/interact_helper.rb +29 -0
- data/lib/vmc/version.rb +3 -0
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/features/new_user_flow_spec.rb +71 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/vmc/cli/app/base_spec.rb +17 -0
- data/spec/vmc/cli/app/delete_spec.rb +188 -0
- data/spec/vmc/cli/app/instances_spec.rb +65 -0
- data/spec/vmc/cli/app/push/create_spec.rb +571 -0
- data/spec/vmc/cli/app/push_spec.rb +369 -0
- data/spec/vmc/cli/app/rename_spec.rb +104 -0
- data/spec/vmc/cli/app/scale_spec.rb +81 -0
- data/spec/vmc/cli/app/stats_spec.rb +62 -0
- data/spec/vmc/cli/domain/map_spec.rb +140 -0
- data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
- data/spec/vmc/cli/organization/orgs_spec.rb +108 -0
- data/spec/vmc/cli/organization/rename_spec.rb +113 -0
- data/spec/vmc/cli/route/map_spec.rb +138 -0
- data/spec/vmc/cli/route/unmap_spec.rb +215 -0
- data/spec/vmc/cli/service/bind_spec.rb +25 -0
- data/spec/vmc/cli/service/delete_spec.rb +22 -0
- data/spec/vmc/cli/service/rename_spec.rb +105 -0
- data/spec/vmc/cli/service/service_spec.rb +23 -0
- data/spec/vmc/cli/service/unbind_spec.rb +25 -0
- data/spec/vmc/cli/space/rename_spec.rb +102 -0
- data/spec/vmc/cli/space/spaces_spec.rb +104 -0
- data/spec/vmc/cli/start/info_spec.rb +153 -0
- data/spec/vmc/cli/start/login_spec.rb +71 -0
- data/spec/vmc/cli/user/create_spec.rb +54 -0
- data/spec/vmc/cli/user/passwd_spec.rb +102 -0
- data/spec/vmc/cli/user/register_spec.rb +148 -0
- data/spec/vmc/cli_spec.rb +448 -0
- data/spec/vmc/detect_spec.rb +54 -0
- metadata +231 -124
- data/README.md +0 -155
- data/caldecott_helper/Gemfile +0 -10
- data/caldecott_helper/Gemfile.lock +0 -48
- data/caldecott_helper/server.rb +0 -43
- data/config/clients.yml +0 -17
- data/config/micro/offline.conf +0 -2
- data/config/micro/paths.yml +0 -22
- data/config/micro/refresh_ip.rb +0 -20
- data/lib/cli.rb +0 -48
- data/lib/cli/commands/admin.rb +0 -81
- data/lib/cli/commands/apps.rb +0 -1358
- data/lib/cli/commands/base.rb +0 -233
- data/lib/cli/commands/manifest.rb +0 -56
- data/lib/cli/commands/micro.rb +0 -115
- data/lib/cli/commands/misc.rb +0 -147
- data/lib/cli/commands/services.rb +0 -217
- data/lib/cli/commands/user.rb +0 -70
- data/lib/cli/config.rb +0 -176
- data/lib/cli/console_helper.rb +0 -163
- data/lib/cli/core_ext.rb +0 -122
- data/lib/cli/errors.rb +0 -19
- data/lib/cli/file_helper.rb +0 -123
- data/lib/cli/frameworks.rb +0 -265
- data/lib/cli/manifest_helper.rb +0 -316
- data/lib/cli/runner.rb +0 -633
- data/lib/cli/services_helper.rb +0 -104
- data/lib/cli/tunnel_helper.rb +0 -336
- data/lib/cli/usage.rb +0 -129
- data/lib/cli/version.rb +0 -7
- data/lib/cli/zip_util.rb +0 -102
- data/lib/vmc/client.rb +0 -574
- data/lib/vmc/const.rb +0 -27
- data/lib/vmc/micro.rb +0 -56
- data/lib/vmc/micro/switcher/base.rb +0 -97
- data/lib/vmc/micro/switcher/darwin.rb +0 -19
- data/lib/vmc/micro/switcher/dummy.rb +0 -15
- data/lib/vmc/micro/switcher/linux.rb +0 -16
- data/lib/vmc/micro/switcher/windows.rb +0 -31
- data/lib/vmc/micro/vmrun.rb +0 -158
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
|
|
4
|
+
describe VMC::App::Stats do
|
|
5
|
+
let(:global) { { :color => false } }
|
|
6
|
+
let(:inputs) { {:app => apps[0]} }
|
|
7
|
+
let(:given) { {} }
|
|
8
|
+
let(:client) { fake_client(:apps => apps) }
|
|
9
|
+
let(:apps) { [fake(:app, :name => "basic_app")] }
|
|
10
|
+
let(:time) { Time.local(2012,11,1,2,30)}
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
any_instance_of(VMC::CLI) do |cli|
|
|
14
|
+
stub(cli).client { client }
|
|
15
|
+
stub(cli).precondition { nil }
|
|
16
|
+
end
|
|
17
|
+
stub(client).base.stub!.instances(anything) do
|
|
18
|
+
{
|
|
19
|
+
"12" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
|
20
|
+
"1" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
|
|
21
|
+
"2" => {:state => "STARTED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"}
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
subject do
|
|
27
|
+
capture_output do
|
|
28
|
+
Mothership.new.invoke(:instances, inputs, given, global)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'metadata' do
|
|
33
|
+
let(:command) { Mothership.commands[:instances] }
|
|
34
|
+
|
|
35
|
+
describe 'command' do
|
|
36
|
+
subject { command }
|
|
37
|
+
its(:description) { should eq "List an app's instances" }
|
|
38
|
+
it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
include_examples 'inputs must have descriptions'
|
|
42
|
+
|
|
43
|
+
describe 'arguments' do
|
|
44
|
+
subject { command.arguments }
|
|
45
|
+
it 'has no arguments' do
|
|
46
|
+
should eq([{:type=>:splat, :value=>nil, :name=>:apps}])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'prints out the instances in the correct order' do
|
|
52
|
+
subject
|
|
53
|
+
expect(stdout.string).to match /.*instance \#1.*instance \#2.*instance \#12.*/m
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'prints out one of the instances correctly' do
|
|
57
|
+
subject
|
|
58
|
+
expect(stdout.string).to include <<-OUT.strip_heredoc
|
|
59
|
+
instance #2: started
|
|
60
|
+
started: #{time.strftime("%F %r")}
|
|
61
|
+
debugger: port bar at foo
|
|
62
|
+
console: port qux at baz
|
|
63
|
+
OUT
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,571 @@
|
|
|
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) { fake_list(:framework, 3) }
|
|
9
|
+
let(:framework) { buildpack }
|
|
10
|
+
let(:buildpack) { fake(:framework, :name => "buildpack") }
|
|
11
|
+
let(:standalone) { fake(:framework, :name => "standalone") }
|
|
12
|
+
|
|
13
|
+
let(:runtimes) { fake_list(:runtime, 3) }
|
|
14
|
+
let(:runtime) { runtimes.first }
|
|
15
|
+
|
|
16
|
+
let(:service_instances) { fake_list(:service_instance, 5) }
|
|
17
|
+
|
|
18
|
+
let(:client) do
|
|
19
|
+
fake_client(
|
|
20
|
+
:frameworks => frameworks,
|
|
21
|
+
:runtimes => runtimes,
|
|
22
|
+
:service_instances => service_instances)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
any_instance_of(VMC::CLI) do |cli|
|
|
27
|
+
stub(cli).client { client }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
let(:create) do
|
|
32
|
+
command = Mothership.commands[:push]
|
|
33
|
+
create = VMC::App::Push.new(command)
|
|
34
|
+
create.path = "some-path"
|
|
35
|
+
create.input = Mothership::Inputs.new(command, create, inputs, given, global)
|
|
36
|
+
create.extend VMC::App::PushInteractions
|
|
37
|
+
create
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe '#get_inputs' do
|
|
41
|
+
subject { create.get_inputs }
|
|
42
|
+
|
|
43
|
+
let(:inputs) do
|
|
44
|
+
{ :name => "some-name",
|
|
45
|
+
:instances => 1,
|
|
46
|
+
:plan => "p100",
|
|
47
|
+
:framework => framework,
|
|
48
|
+
:runtime => runtime,
|
|
49
|
+
:memory => "1G",
|
|
50
|
+
:command => "ruby main.rb",
|
|
51
|
+
:buildpack => "git://example.com"
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'when all the inputs are given' do
|
|
56
|
+
its([:name]) { should eq "some-name" }
|
|
57
|
+
its([:total_instances]) { should eq 1 }
|
|
58
|
+
its([:space]) { should eq client.current_space }
|
|
59
|
+
its([:production]) { should eq true }
|
|
60
|
+
its([:framework]) { should eq framework }
|
|
61
|
+
its([:command]) { should eq "ruby main.rb" }
|
|
62
|
+
its([:runtime]) { should eq runtime }
|
|
63
|
+
its([:memory]) { should eq 1024 }
|
|
64
|
+
its([:buildpack]) { should eq "git://example.com" }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'when certain inputs are not given' do
|
|
68
|
+
it 'should ask for the name' do
|
|
69
|
+
inputs.delete(:name)
|
|
70
|
+
mock_ask("Name") { "some-name" }
|
|
71
|
+
subject
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should ask for the total instances' do
|
|
75
|
+
inputs.delete(:instances)
|
|
76
|
+
mock_ask("Instances", anything) { 1 }
|
|
77
|
+
subject
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should ask for the framework' do
|
|
81
|
+
inputs.delete(:framework)
|
|
82
|
+
mock_ask('Framework', anything) do |_, options|
|
|
83
|
+
expect(options[:choices]).to eq frameworks.sort_by(&:name)
|
|
84
|
+
framework
|
|
85
|
+
end
|
|
86
|
+
subject
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'when the command is not given' do
|
|
90
|
+
before { inputs.delete(:command) }
|
|
91
|
+
|
|
92
|
+
shared_examples 'an app that can have a custom start command' do
|
|
93
|
+
it 'should ask if there is a custom start command' do
|
|
94
|
+
mock_ask("Use custom startup command?", :default => false) { false }
|
|
95
|
+
subject
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context 'when the user answers "yes" to the custom start command' do
|
|
99
|
+
before { stub_ask("Use custom startup command?", :default => false) { true } }
|
|
100
|
+
|
|
101
|
+
it 'should ask for the startup command' do
|
|
102
|
+
mock_ask("Startup command") { "foo bar.com" }
|
|
103
|
+
subject[:command].should eq "foo bar.com"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'when the user answers "no" to the custom start command' do
|
|
108
|
+
before { stub_ask("Use custom startup command?", :default => false) { false } }
|
|
109
|
+
|
|
110
|
+
it 'should not ask for the startup command' do
|
|
111
|
+
dont_allow_ask("Startup command")
|
|
112
|
+
subject
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'when the framework is "buildpack"' do
|
|
118
|
+
let(:framework) { buildpack }
|
|
119
|
+
|
|
120
|
+
include_examples 'an app that can have a custom start command'
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'when the framework is "standalone"' do
|
|
124
|
+
let(:framework) { standalone }
|
|
125
|
+
|
|
126
|
+
include_examples 'an app that can have a custom start command'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context 'when the framework is neither "buildpack" nor "standalone"' do
|
|
130
|
+
let(:framework) { fake(:framework, :name => "java") }
|
|
131
|
+
|
|
132
|
+
it 'does not ask if there is a custom start command' do
|
|
133
|
+
dont_allow_ask("Startup command")
|
|
134
|
+
subject
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'should ask for the runtime' do
|
|
140
|
+
inputs.delete(:runtime)
|
|
141
|
+
mock_ask('Runtime', anything) do |_, options|
|
|
142
|
+
expect(options[:choices]).to eq runtimes.sort_by(&:name)
|
|
143
|
+
runtime
|
|
144
|
+
end
|
|
145
|
+
subject
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'should ask for the memory' do
|
|
149
|
+
inputs.delete(:memory)
|
|
150
|
+
|
|
151
|
+
memory_choices = %w(64M 128M 256M 512M 1G)
|
|
152
|
+
stub(create).memory_choices { memory_choices }
|
|
153
|
+
|
|
154
|
+
mock_ask('Memory Limit', anything) do |_, options|
|
|
155
|
+
expect(options[:choices]).to eq memory_choices
|
|
156
|
+
"1G"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
subject
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
describe '#determine_framework' do
|
|
165
|
+
subject { create.determine_framework }
|
|
166
|
+
|
|
167
|
+
context 'when framework is given' do
|
|
168
|
+
let(:inputs) { { :framework => framework } }
|
|
169
|
+
|
|
170
|
+
it 'does not try to get the frameworks' do
|
|
171
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
172
|
+
dont_allow(detector).detect_framework
|
|
173
|
+
dont_allow(detector).all_frameworks
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
dont_allow_ask
|
|
177
|
+
dont_allow(client).frameworks
|
|
178
|
+
|
|
179
|
+
subject
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it { should eq framework }
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'when framework is not given' do
|
|
186
|
+
context 'and a framework is detected' do
|
|
187
|
+
it "lists the detected framework and an 'other' option" do
|
|
188
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
189
|
+
mock(detector).detect_framework { framework }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
mock_ask('Framework', anything) do |_, options|
|
|
193
|
+
expect(options[:choices]).to eq [framework, :other] #frameworks.sort_by(&:name)
|
|
194
|
+
framework
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
subject
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context 'and a framework is not detected' do
|
|
202
|
+
it "lists all available frameworks" do
|
|
203
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
204
|
+
stub(detector).detect_framework
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
mock_ask('Framework', anything) do |_, options|
|
|
208
|
+
expect(options[:choices]).to eq frameworks.sort_by(&:name)
|
|
209
|
+
framework
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
subject
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
describe '#detect_runtimes' do
|
|
219
|
+
subject { create.determine_runtime(framework) }
|
|
220
|
+
|
|
221
|
+
context 'when runtime is given' do
|
|
222
|
+
let(:inputs) { { :runtime => runtime } }
|
|
223
|
+
|
|
224
|
+
it 'does not try to get the runtime' do
|
|
225
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
226
|
+
dont_allow(detector).detect_runtime
|
|
227
|
+
dont_allow(detector).all_runtimes
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
dont_allow_ask
|
|
231
|
+
dont_allow(client).runtimes
|
|
232
|
+
|
|
233
|
+
subject
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it { should eq runtime }
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
context 'when runtime is not given' do
|
|
240
|
+
context 'and the framework is standalone' do
|
|
241
|
+
let(:framework) { standalone }
|
|
242
|
+
|
|
243
|
+
it "detects the runtime" do
|
|
244
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
245
|
+
mock(detector).detect_runtimes { runtimes }
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
mock_ask('Runtime', anything) do |_, options|
|
|
249
|
+
expect(options[:choices]).to eq(runtimes.sort_by(&:name) + [:other])
|
|
250
|
+
runtime
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
subject
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context 'and the framework is not standalone' do
|
|
258
|
+
it "gets the runtimes based on the framework" do
|
|
259
|
+
any_instance_of(VMC::Detector) do |detector|
|
|
260
|
+
mock(detector).runtimes(framework) { runtimes }
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
mock_ask('Runtime', anything) do |_, options|
|
|
264
|
+
expect(options[:choices]).to eq(runtimes.sort_by(&:name) + [:other])
|
|
265
|
+
runtime
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
subject
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe '#create_app' do
|
|
275
|
+
before { dont_allow_ask }
|
|
276
|
+
|
|
277
|
+
let(:app) { fake(:app, :guid => nil) }
|
|
278
|
+
|
|
279
|
+
let(:attributes) do
|
|
280
|
+
{ :name => "some-app",
|
|
281
|
+
:total_instances => 2,
|
|
282
|
+
:framework => framework,
|
|
283
|
+
:runtime => runtime,
|
|
284
|
+
:production => false,
|
|
285
|
+
:memory => 1024,
|
|
286
|
+
:buildpack => "git://example.com"
|
|
287
|
+
}
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
before { stub(client).app { app } }
|
|
291
|
+
|
|
292
|
+
subject { create.create_app(attributes) }
|
|
293
|
+
|
|
294
|
+
it 'creates an app based on the resulting inputs' do
|
|
295
|
+
mock(create).filter(:create_app, app) { app }
|
|
296
|
+
|
|
297
|
+
mock(app).create!
|
|
298
|
+
|
|
299
|
+
subject
|
|
300
|
+
|
|
301
|
+
attributes.each do |key, val|
|
|
302
|
+
expect(app.send(key)).to eq val
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
context "with an invalid buildpack" do
|
|
307
|
+
before do
|
|
308
|
+
stub(app).create! do
|
|
309
|
+
raise CFoundry::MessageParseError.new(
|
|
310
|
+
"Request invalid due to parse error: Field: buildpack, Error: Value git@github.com:cloudfoundry/heroku-buildpack-ruby.git doesn't match regexp String /GIT_URL_REGEX/",
|
|
311
|
+
1001)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "fails and prints a pretty message" do
|
|
316
|
+
stub(create).line(anything)
|
|
317
|
+
expect { subject }.to raise_error(
|
|
318
|
+
VMC::UserError, "Buildpack must be a public git repository URI.")
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
describe '#map_url' do
|
|
324
|
+
let(:app) { fake(:app, :space => space) }
|
|
325
|
+
let(:space) { fake(:space, :domains => domains) }
|
|
326
|
+
let(:domains) { [fake(:domain, :name => "foo.com")] }
|
|
327
|
+
let(:hosts) { [app.name] }
|
|
328
|
+
|
|
329
|
+
subject { create.map_route(app) }
|
|
330
|
+
|
|
331
|
+
it "asks for a subdomain with 'none' as an option" do
|
|
332
|
+
mock_ask('Subdomain', anything) do |_, options|
|
|
333
|
+
expect(options[:choices]).to eq(hosts + %w(none))
|
|
334
|
+
expect(options[:default]).to eq hosts.first
|
|
335
|
+
hosts.first
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
stub_ask("Domain", anything) { domains.first }
|
|
339
|
+
|
|
340
|
+
stub(create).invoke
|
|
341
|
+
|
|
342
|
+
subject
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "asks for a domain with 'none' as an option" do
|
|
346
|
+
stub_ask("Subdomain", anything) { hosts.first }
|
|
347
|
+
|
|
348
|
+
mock_ask('Domain', anything) do |_, options|
|
|
349
|
+
expect(options[:choices]).to eq(domains + %w(none))
|
|
350
|
+
expect(options[:default]).to eq domains.first
|
|
351
|
+
domains.first
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
stub(create).invoke
|
|
355
|
+
|
|
356
|
+
subject
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "maps the host and domain after both are given" do
|
|
360
|
+
stub_ask('Subdomain', anything) { hosts.first }
|
|
361
|
+
stub_ask('Domain', anything) { domains.first }
|
|
362
|
+
|
|
363
|
+
mock(create).invoke(:map,
|
|
364
|
+
:app => app, :host => hosts.first,
|
|
365
|
+
:domain => domains.first)
|
|
366
|
+
|
|
367
|
+
subject
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context "when 'none' is given as the host" do
|
|
371
|
+
context "and a domain is provided afterwards" do
|
|
372
|
+
it "invokes 'map' with an empty host" do
|
|
373
|
+
mock_ask('Subdomain', anything) { "none" }
|
|
374
|
+
stub_ask('Domain', anything) { domains.first }
|
|
375
|
+
|
|
376
|
+
mock(create).invoke(:map,
|
|
377
|
+
:host => "", :domain => domains.first, :app => app)
|
|
378
|
+
|
|
379
|
+
subject
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context "when 'none' is given as the domain" do
|
|
385
|
+
it "does not perform any mapping" do
|
|
386
|
+
stub_ask('Subdomain', anything) { "foo" }
|
|
387
|
+
mock_ask('Domain', anything) { "none" }
|
|
388
|
+
|
|
389
|
+
dont_allow(create).invoke(:map, anything)
|
|
390
|
+
|
|
391
|
+
subject
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
context "when mapping fails" do
|
|
396
|
+
before do
|
|
397
|
+
mock_ask('Subdomain', anything) { "foo" }
|
|
398
|
+
mock_ask('Domain', anything) { domains.first }
|
|
399
|
+
|
|
400
|
+
mock(create).invoke(:map,
|
|
401
|
+
:host => "foo", :domain => domains.first, :app => app) do
|
|
402
|
+
raise CFoundry::RouteHostTaken.new("foo", 1234)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
it "asks again" do
|
|
407
|
+
stub(create).line
|
|
408
|
+
|
|
409
|
+
mock_ask('Subdomain', anything) { hosts.first }
|
|
410
|
+
mock_ask('Domain', anything) { domains.first }
|
|
411
|
+
|
|
412
|
+
stub(create).invoke
|
|
413
|
+
|
|
414
|
+
subject
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
it "reports the failure message" do
|
|
418
|
+
mock(create).line "foo"
|
|
419
|
+
mock(create).line
|
|
420
|
+
|
|
421
|
+
stub_ask('Subdomain', anything) { hosts.first }
|
|
422
|
+
stub_ask('Domain', anything) { domains.first }
|
|
423
|
+
|
|
424
|
+
stub(create).invoke
|
|
425
|
+
|
|
426
|
+
subject
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
describe '#create_services' do
|
|
432
|
+
let(:app) { fake(:app) }
|
|
433
|
+
subject { create.create_services(app) }
|
|
434
|
+
|
|
435
|
+
context 'when forcing' do
|
|
436
|
+
let(:inputs) { {:force => true} }
|
|
437
|
+
|
|
438
|
+
it "does not ask to create any services" do
|
|
439
|
+
dont_allow_ask("Create services for application?", anything)
|
|
440
|
+
subject
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it "does not create any services" do
|
|
444
|
+
dont_allow(create).invoke(:create_service, anything)
|
|
445
|
+
subject
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
context 'when not forcing' do
|
|
450
|
+
let(:inputs) { { :force => false } }
|
|
451
|
+
|
|
452
|
+
it 'does not create the service if asked not to' do
|
|
453
|
+
mock_ask("Create services for application?", anything) { false }
|
|
454
|
+
dont_allow(create).invoke(:create_service, anything)
|
|
455
|
+
|
|
456
|
+
subject
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it 'asks again to create a service' do
|
|
460
|
+
mock_ask("Create services for application?", anything) { true }
|
|
461
|
+
mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
|
|
462
|
+
|
|
463
|
+
mock_ask("Create another service?", :default => false) { true }
|
|
464
|
+
mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
|
|
465
|
+
|
|
466
|
+
mock_ask("Create another service?", :default => false) { true }
|
|
467
|
+
mock(create).invoke(:create_service, { :app => app }, :plan => :interact).ordered
|
|
468
|
+
|
|
469
|
+
mock_ask("Create another service?", :default => false) { false }
|
|
470
|
+
dont_allow(create).invoke(:create_service, anything).ordered
|
|
471
|
+
|
|
472
|
+
subject
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
describe '#bind_services' do
|
|
478
|
+
let(:app) { fake(:app) }
|
|
479
|
+
|
|
480
|
+
subject { create.bind_services(app) }
|
|
481
|
+
|
|
482
|
+
context 'when forcing' do
|
|
483
|
+
let(:global) { { :force => true, :color => false, :quiet => true } }
|
|
484
|
+
|
|
485
|
+
it "does not ask to bind any services" do
|
|
486
|
+
dont_allow_ask("Bind other services to application?", anything)
|
|
487
|
+
subject
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
it "does not bind any services" do
|
|
491
|
+
dont_allow(create).invoke(:bind_service, anything)
|
|
492
|
+
subject
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
context 'when not forcing' do
|
|
497
|
+
it 'does not bind the service if asked not to' do
|
|
498
|
+
mock_ask("Bind other services to application?", anything) { false }
|
|
499
|
+
dont_allow(create).invoke(:bind_service, anything)
|
|
500
|
+
|
|
501
|
+
subject
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
it 'asks again to bind a service' do
|
|
505
|
+
bind_times = 3
|
|
506
|
+
call_count = 0
|
|
507
|
+
|
|
508
|
+
mock_ask("Bind other services to application?", anything) { true }
|
|
509
|
+
|
|
510
|
+
mock(create).invoke(:bind_service, :app => app).times(bind_times) do
|
|
511
|
+
call_count += 1
|
|
512
|
+
stub(app).services { service_instances.first(call_count) }
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
mock_ask("Bind another service?", anything).times(bind_times) do
|
|
516
|
+
call_count < bind_times
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
subject
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it 'stops asking if there are no more services to bind' do
|
|
523
|
+
bind_times = service_instances.size
|
|
524
|
+
call_count = 0
|
|
525
|
+
|
|
526
|
+
mock_ask("Bind other services to application?", anything) { true }
|
|
527
|
+
|
|
528
|
+
mock(create).invoke(:bind_service, :app => app).times(bind_times) do
|
|
529
|
+
call_count += 1
|
|
530
|
+
stub(app).services { service_instances.first(call_count) }
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
mock_ask("Bind another service?", anything).times(bind_times - 1) { true }
|
|
534
|
+
|
|
535
|
+
subject
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
context 'when there are no services' do
|
|
539
|
+
let(:service_instances) { [] }
|
|
540
|
+
|
|
541
|
+
it 'does not ask to bind anything' do
|
|
542
|
+
dont_allow_ask
|
|
543
|
+
subject
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
describe '#start_app' do
|
|
550
|
+
let(:app) { fake(:app) }
|
|
551
|
+
subject { create.start_app(app) }
|
|
552
|
+
|
|
553
|
+
context 'when the start flag is provided' do
|
|
554
|
+
let(:inputs) { {:start => true} }
|
|
555
|
+
|
|
556
|
+
it 'invokes the start command' do
|
|
557
|
+
mock(create).invoke(:start, :app => app)
|
|
558
|
+
subject
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
context 'when the start flag is not provided' do
|
|
563
|
+
let(:inputs) { {:start => false} }
|
|
564
|
+
|
|
565
|
+
it 'invokes the start command' do
|
|
566
|
+
dont_allow(create).invoke(:start, anything)
|
|
567
|
+
subject
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
end
|