vmc 0.4.0.beta.20 → 0.4.0.beta.21
Sign up to get free protection for your applications and to get access to all the features.
- data/vmc-ng/Rakefile +41 -5
- data/vmc-ng/lib/vmc/cli/app.rb +7 -3
- data/vmc-ng/lib/vmc/cli/start.rb +111 -72
- data/vmc-ng/lib/vmc/cli.rb +63 -15
- data/vmc-ng/lib/vmc/version.rb +1 -1
- data/vmc-ng/spec/Rakefile +14 -0
- data/vmc-ng/spec/app/apps_spec.rb +75 -0
- data/vmc-ng/spec/helpers.rb +103 -0
- data/vmc-ng/spec/start/target_spec.rb +34 -0
- metadata +42 -10
data/vmc-ng/Rakefile
CHANGED
@@ -1,11 +1,47 @@
|
|
1
|
-
require "
|
1
|
+
require "rake"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
end
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
require "vmc/version"
|
6
5
|
|
7
6
|
task :default => :spec
|
8
7
|
|
9
|
-
|
8
|
+
desc "Run specs"
|
9
|
+
task :spec => ["bundler:install", "test:spec"]
|
10
|
+
|
11
|
+
desc "Run integration tests"
|
12
|
+
task :test => ["bundler:install", "test:integration"]
|
13
|
+
|
14
|
+
task :build do
|
15
|
+
sh "gem build vmc.gemspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :install => :build do
|
19
|
+
sh "gem install --local vmc-#{VMC::VERSION}"
|
20
|
+
end
|
21
|
+
|
22
|
+
task :uninstall do
|
23
|
+
sh "gem uninstall vmc"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :reinstall => [:uninstall, :install]
|
27
|
+
|
28
|
+
task :release => :build do
|
29
|
+
sh "gem push vmc-#{VMC::VERSION}.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace "bundler" do
|
33
|
+
desc "Install gems"
|
34
|
+
task "install" do
|
35
|
+
sh("bundle install")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace "test" do
|
40
|
+
task "spec" do |t|
|
41
|
+
# nothing
|
42
|
+
end
|
10
43
|
|
44
|
+
task "integration" do |t|
|
45
|
+
sh("cd spec && bundle exec rake spec")
|
46
|
+
end
|
11
47
|
end
|
data/vmc-ng/lib/vmc/cli/app.rb
CHANGED
@@ -43,13 +43,17 @@ module VMC
|
|
43
43
|
|
44
44
|
desc "List your applications"
|
45
45
|
group :apps
|
46
|
+
input :space, :desc => "Show apps in given space",
|
47
|
+
:from_given => proc { |name|
|
48
|
+
client.space_by_name(name) || \
|
49
|
+
fail("Unknown space '#{name}'")
|
50
|
+
}
|
46
51
|
input :name, :desc => "Filter by name regexp"
|
47
52
|
input :runtime, :desc => "Filter by runtime regexp"
|
48
53
|
input :framework, :desc => "Filter by framework regexp"
|
49
54
|
input :url, :desc => "Filter by url regexp"
|
50
55
|
def apps(input)
|
51
|
-
if
|
52
|
-
space = client.current_space
|
56
|
+
if space = input[:space] || client.current_space
|
53
57
|
apps =
|
54
58
|
with_progress("Getting applications in #{c(space.name, :name)}") do
|
55
59
|
space.apps
|
@@ -146,7 +150,7 @@ module VMC
|
|
146
150
|
|
147
151
|
app = client.app
|
148
152
|
app.name = name
|
149
|
-
app.space = client.current_space if
|
153
|
+
app.space = client.current_space if client.current_space
|
150
154
|
app.total_instances = input[:instances]
|
151
155
|
|
152
156
|
detector = Detector.new(client, path)
|
data/vmc-ng/lib/vmc/cli/start.rb
CHANGED
@@ -9,6 +9,19 @@ module VMC
|
|
9
9
|
@@displayed_target
|
10
10
|
end
|
11
11
|
|
12
|
+
|
13
|
+
# These commands don't require authentication.
|
14
|
+
def precondition; end
|
15
|
+
|
16
|
+
|
17
|
+
def self.find_by_name(what)
|
18
|
+
proc { |name, choices|
|
19
|
+
choices.find { |c| c.name == name } ||
|
20
|
+
fail("Unknown #{what} '#{name}'")
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
|
12
25
|
desc "Display information on the current target, user, etc."
|
13
26
|
group :start
|
14
27
|
input :runtimes, :type => :boolean,
|
@@ -57,7 +70,7 @@ module VMC
|
|
57
70
|
|
58
71
|
if user = client.current_user
|
59
72
|
puts ""
|
60
|
-
puts "user: #{b(user.email || user.
|
73
|
+
puts "user: #{b(user.email || user.guid)}"
|
61
74
|
end
|
62
75
|
end
|
63
76
|
|
@@ -104,21 +117,25 @@ module VMC
|
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
107
|
-
|
108
120
|
desc "Set or display the current target cloud"
|
109
121
|
group :start
|
110
122
|
input :url, :argument => :optional,
|
111
123
|
:desc => "Target URL to switch to"
|
124
|
+
input(:interactive, :alias => "-i", :type => :boolean,
|
125
|
+
:desc => "Interactively select organization/space")
|
112
126
|
input(:organization, :aliases => ["--org", "-o"],
|
113
|
-
:
|
114
|
-
|
127
|
+
:from_given => find_by_name("organization"),
|
128
|
+
:desc => "Organization") { |orgs|
|
129
|
+
ask("Organization", :choices => orgs, :display => proc(&:name))
|
115
130
|
}
|
116
|
-
input(:space, :alias => "-s",
|
117
|
-
|
131
|
+
input(:space, :alias => "-s",
|
132
|
+
:from_given => find_by_name("space"),
|
133
|
+
:desc => "Space") { |spaces|
|
134
|
+
ask("Space", :choices => spaces, :display => proc(&:name))
|
118
135
|
}
|
119
136
|
def target(input)
|
120
|
-
if !input
|
121
|
-
!input.given?(:space)
|
137
|
+
if !input[:interactive] && !input.given?(:url) &&
|
138
|
+
!input.given?(:organization) && !input.given?(:space)
|
122
139
|
display_target
|
123
140
|
return
|
124
141
|
end
|
@@ -130,22 +147,22 @@ module VMC
|
|
130
147
|
set_target(target)
|
131
148
|
end
|
132
149
|
|
133
|
-
|
150
|
+
unless quiet?
|
151
|
+
puts ""
|
152
|
+
display_org_and_space
|
153
|
+
end
|
134
154
|
end
|
135
155
|
|
136
|
-
return unless v2?
|
137
|
-
|
138
|
-
unless client.logged_in?
|
139
|
-
puts "" unless quiet?
|
140
|
-
invoke :login
|
141
|
-
@client = nil
|
142
|
-
end
|
156
|
+
return unless v2? && client.logged_in?
|
143
157
|
|
144
|
-
|
158
|
+
if input[:interactive] || input.given?(:organization) ||
|
159
|
+
input.given?(:space)
|
160
|
+
info = target_info
|
145
161
|
|
146
|
-
|
162
|
+
select_org_and_space(input, info)
|
147
163
|
|
148
|
-
|
164
|
+
save_target_info(info)
|
165
|
+
end
|
149
166
|
end
|
150
167
|
|
151
168
|
|
@@ -159,34 +176,22 @@ module VMC
|
|
159
176
|
end
|
160
177
|
|
161
178
|
|
162
|
-
def ask_prompt(type, label)
|
163
|
-
if type == "password"
|
164
|
-
options = { :echo => "*", :forget => true }
|
165
|
-
else
|
166
|
-
options = {}
|
167
|
-
end
|
168
|
-
|
169
|
-
ask(label, options)
|
170
|
-
end
|
171
|
-
|
172
|
-
def ask_prompts(credentials, prompts)
|
173
|
-
prompts.each do |name, meta|
|
174
|
-
type, label = meta
|
175
|
-
credentials[name] ||= ask_prompt(type, label)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
179
|
desc "Authenticate with the target"
|
180
180
|
group :start
|
181
181
|
input :username, :alias => "--email", :argument => :optional,
|
182
182
|
:desc => "Account email"
|
183
183
|
input :password, :desc => "Account password"
|
184
|
+
input(:interactive, :alias => "-i", :type => :boolean,
|
185
|
+
:desc => "Interactively select organization/space")
|
184
186
|
input(:organization, :aliases => ["--org", "-o"],
|
185
|
-
:
|
186
|
-
|
187
|
+
:from_given => find_by_name("organization"),
|
188
|
+
:desc => "Organization") { |orgs|
|
189
|
+
ask("Organization", :choices => orgs, :display => proc(&:name))
|
187
190
|
}
|
188
|
-
input(:space, :alias => "-s",
|
189
|
-
|
191
|
+
input(:space, :alias => "-s",
|
192
|
+
:from_given => find_by_name("space"),
|
193
|
+
:desc => "Space") { |spaces|
|
194
|
+
ask("Space", :choices => spaces, :display => proc(&:name))
|
190
195
|
}
|
191
196
|
def login(input)
|
192
197
|
display_target unless quiet?
|
@@ -228,9 +233,14 @@ module VMC
|
|
228
233
|
end
|
229
234
|
end
|
230
235
|
|
231
|
-
select_org_and_space(input, info) if v2?
|
232
|
-
|
233
236
|
save_target_info(info)
|
237
|
+
invalidate_client
|
238
|
+
|
239
|
+
if v2?
|
240
|
+
puts "" if input[:interactive]
|
241
|
+
select_org_and_space(input, info)
|
242
|
+
save_target_info(info)
|
243
|
+
end
|
234
244
|
ensure
|
235
245
|
exit_status 1 if not authenticated
|
236
246
|
end
|
@@ -288,18 +298,31 @@ module VMC
|
|
288
298
|
|
289
299
|
private
|
290
300
|
|
301
|
+
def ask_prompt(type, label)
|
302
|
+
if type == "password"
|
303
|
+
options = { :echo => "*", :forget => true }
|
304
|
+
else
|
305
|
+
options = {}
|
306
|
+
end
|
307
|
+
|
308
|
+
ask(label, options)
|
309
|
+
end
|
310
|
+
|
311
|
+
def ask_prompts(credentials, prompts)
|
312
|
+
prompts.each do |name, meta|
|
313
|
+
type, label = meta
|
314
|
+
credentials[name] ||= ask_prompt(type, label)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
291
318
|
def display_target
|
292
|
-
return if
|
319
|
+
return if displayed_target?
|
293
320
|
|
294
321
|
if quiet?
|
295
322
|
puts client.target
|
296
323
|
else
|
297
|
-
puts "
|
298
|
-
|
299
|
-
if v2? && client.current_organization && client.current_space
|
300
|
-
puts "Organization: #{c(client.current_organization.name, :name)}"
|
301
|
-
puts "Space: #{c(client.current_space.name, :name)}"
|
302
|
-
end
|
324
|
+
puts "target: #{c(client.target, :name)}"
|
325
|
+
display_org_and_space
|
303
326
|
end
|
304
327
|
|
305
328
|
puts ""
|
@@ -307,6 +330,19 @@ module VMC
|
|
307
330
|
@@displayed_target = true
|
308
331
|
end
|
309
332
|
|
333
|
+
def display_org_and_space
|
334
|
+
return unless v2?
|
335
|
+
|
336
|
+
if org = client.current_organization
|
337
|
+
puts "organization: #{c(org.name, :name)}"
|
338
|
+
end
|
339
|
+
|
340
|
+
if space = client.current_space
|
341
|
+
puts "space: #{c(space.name, :name)}"
|
342
|
+
end
|
343
|
+
rescue CFoundry::APIError
|
344
|
+
end
|
345
|
+
|
310
346
|
def display_runtime(r)
|
311
347
|
if quiet?
|
312
348
|
puts r.name
|
@@ -346,56 +382,59 @@ module VMC
|
|
346
382
|
end
|
347
383
|
end
|
348
384
|
|
349
|
-
def org_valid?(
|
350
|
-
return false unless
|
351
|
-
client.organization(
|
385
|
+
def org_valid?(guid, user = client.current_user)
|
386
|
+
return false unless guid
|
387
|
+
client.organization(guid).users.include? user
|
352
388
|
rescue CFoundry::APIError
|
353
389
|
false
|
354
390
|
end
|
355
391
|
|
356
|
-
def space_valid?(
|
357
|
-
return false unless
|
358
|
-
client.space(
|
392
|
+
def space_valid?(guid, user = client.current_user)
|
393
|
+
return false unless guid
|
394
|
+
client.space(guid).developers.include? user
|
359
395
|
rescue CFoundry::APIError
|
360
396
|
false
|
361
397
|
end
|
362
398
|
|
363
399
|
def select_org_and_space(input, info)
|
364
|
-
|
400
|
+
changed_org = false
|
401
|
+
|
402
|
+
if input[:interactive] || input.given?(:organization) || \
|
403
|
+
!org_valid?(info[:organization])
|
365
404
|
orgs = client.organizations
|
366
405
|
fail "No organizations!" if orgs.empty?
|
367
406
|
|
368
|
-
if orgs.size == 1 && !input.given?(:organization)
|
407
|
+
if !input[:interactive] && orgs.size == 1 && !input.given?(:organization)
|
369
408
|
org = orgs.first
|
370
409
|
else
|
371
|
-
|
372
|
-
org = orgs.find { |o| o.name == org_name }
|
373
|
-
fail "Unknown organization '#{org_name}'" unless org
|
410
|
+
org = input[:organization, orgs.sort_by(&:name)]
|
374
411
|
end
|
375
412
|
|
376
|
-
|
413
|
+
with_progress("Switching to organization #{c(org.name, :name)}") do
|
414
|
+
info[:organization] = org.guid
|
415
|
+
changed_org = true
|
416
|
+
end
|
377
417
|
else
|
378
418
|
org = client.current_organization
|
379
419
|
end
|
380
420
|
|
381
|
-
# switching org
|
382
|
-
if input
|
383
|
-
|
384
|
-
spaces =
|
385
|
-
s.organization.id == org.id
|
386
|
-
end
|
421
|
+
# switching org means switching space
|
422
|
+
if input[:interactive] || changed_org || input.given?(:space) || \
|
423
|
+
!space_valid?(info[:space])
|
424
|
+
spaces = org.spaces
|
387
425
|
|
388
426
|
fail "No spaces!" if spaces.empty?
|
389
427
|
|
390
|
-
if spaces.size == 1 && !input.given?(:space)
|
428
|
+
if !input[:interactive] && spaces.size == 1 && !input.given?(:space)
|
391
429
|
space = spaces.first
|
392
430
|
else
|
393
|
-
|
394
|
-
space = spaces.
|
395
|
-
fail "Unknown space '#{space_name}'" unless space
|
431
|
+
puts "" if changed_org
|
432
|
+
space = input[:space, spaces.sort_by(&:name)]
|
396
433
|
end
|
397
434
|
|
398
|
-
|
435
|
+
with_progress("Switching to space #{c(space.name, :name)}") do
|
436
|
+
info[:space] = space.guid
|
437
|
+
end
|
399
438
|
end
|
400
439
|
end
|
401
440
|
end
|
data/vmc-ng/lib/vmc/cli.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require "yaml"
|
2
|
+
require "socket"
|
3
|
+
require "net/http"
|
2
4
|
|
3
5
|
require "mothership"
|
4
6
|
require "mothership/pretty"
|
@@ -62,10 +64,27 @@ module VMC
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
67
|
+
def precondition
|
68
|
+
unless client.logged_in?
|
69
|
+
fail "Please log in with 'vmc login'."
|
70
|
+
end
|
71
|
+
|
72
|
+
return unless v2?
|
73
|
+
|
74
|
+
unless client.current_organization
|
75
|
+
fail "Please select an organization with 'vmc target -i'."
|
76
|
+
end
|
77
|
+
|
78
|
+
unless client.current_space
|
79
|
+
fail "Please select a space with 'vmc target -i'."
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
65
83
|
def execute(cmd, argv)
|
66
84
|
if option(:help)
|
67
85
|
invoke :help, :command => cmd.name.to_s
|
68
86
|
else
|
87
|
+
cmd.context.new.precondition if cmd.context <= CLI
|
69
88
|
super
|
70
89
|
end
|
71
90
|
rescue Interrupt
|
@@ -82,18 +101,27 @@ module VMC
|
|
82
101
|
puts c("Not authenticated! Try logging in:", :warning)
|
83
102
|
|
84
103
|
invoke :login
|
85
|
-
@client = nil
|
86
104
|
|
87
105
|
retry
|
88
106
|
end
|
89
107
|
|
108
|
+
log_error(e)
|
109
|
+
|
90
110
|
err "Denied: #{e.description}"
|
111
|
+
|
91
112
|
rescue Exception => e
|
113
|
+
ensure_config_dir
|
114
|
+
|
115
|
+
log_error(e)
|
116
|
+
|
92
117
|
msg = e.class.name
|
93
118
|
msg << ": #{e}" unless e.to_s.empty?
|
94
119
|
err msg
|
120
|
+
end
|
95
121
|
|
96
|
-
|
122
|
+
def log_error(e)
|
123
|
+
msg = e.class.name
|
124
|
+
msg << ": #{e}" unless e.to_s.empty?
|
97
125
|
|
98
126
|
File.open(File.expand_path(VMC::CRASH_FILE), "w") do |f|
|
99
127
|
f.puts "Time of crash:"
|
@@ -125,14 +153,14 @@ module VMC
|
|
125
153
|
option(:color)
|
126
154
|
end
|
127
155
|
|
128
|
-
def err(msg,
|
156
|
+
def err(msg, status = 1)
|
129
157
|
if quiet?
|
130
158
|
$stderr.puts(msg)
|
131
159
|
else
|
132
160
|
puts c(msg, :error)
|
133
161
|
end
|
134
162
|
|
135
|
-
exit_status
|
163
|
+
exit_status status
|
136
164
|
end
|
137
165
|
|
138
166
|
def fail(msg)
|
@@ -141,7 +169,12 @@ module VMC
|
|
141
169
|
|
142
170
|
def sane_target_url(url)
|
143
171
|
unless url =~ /^https?:\/\//
|
144
|
-
|
172
|
+
begin
|
173
|
+
TCPSocket.new(url, Net::HTTP.https_default_port)
|
174
|
+
url = "https://#{url}"
|
175
|
+
rescue SocketError, Timeout::Error
|
176
|
+
url = "http://#{url}"
|
177
|
+
end
|
145
178
|
end
|
146
179
|
|
147
180
|
url.gsub(/\/$/, "")
|
@@ -180,7 +213,7 @@ module VMC
|
|
180
213
|
f.write(sane_target_url(url))
|
181
214
|
end
|
182
215
|
|
183
|
-
|
216
|
+
invalidate_client
|
184
217
|
end
|
185
218
|
|
186
219
|
def targets_info
|
@@ -221,7 +254,7 @@ module VMC
|
|
221
254
|
end
|
222
255
|
|
223
256
|
def remove_target_info
|
224
|
-
ts =
|
257
|
+
ts = targets_info
|
225
258
|
ts.delete client_target
|
226
259
|
save_targets(ts)
|
227
260
|
end
|
@@ -234,12 +267,17 @@ module VMC
|
|
234
267
|
client.is_a?(CFoundry::V2::Client)
|
235
268
|
end
|
236
269
|
|
270
|
+
def invalidate_client
|
271
|
+
@@client = nil
|
272
|
+
client
|
273
|
+
end
|
274
|
+
|
237
275
|
def client
|
238
|
-
return
|
276
|
+
return @@client if defined?(@@client) && @@client
|
239
277
|
|
240
278
|
info = target_info
|
241
279
|
|
242
|
-
|
280
|
+
@@client =
|
243
281
|
case info[:version]
|
244
282
|
when 2
|
245
283
|
CFoundry::V2::Client.new(client_target, info[:token])
|
@@ -249,11 +287,11 @@ module VMC
|
|
249
287
|
CFoundry::Client.new(client_target, info[:token])
|
250
288
|
end
|
251
289
|
|
252
|
-
|
253
|
-
|
290
|
+
@@client.proxy = option(:proxy)
|
291
|
+
@@client.trace = option(:trace)
|
254
292
|
|
255
293
|
info[:version] ||=
|
256
|
-
case
|
294
|
+
case @@client
|
257
295
|
when CFoundry::V2::Client
|
258
296
|
2
|
259
297
|
else
|
@@ -261,16 +299,26 @@ module VMC
|
|
261
299
|
end
|
262
300
|
|
263
301
|
if org = info[:organization]
|
264
|
-
|
302
|
+
@@client.current_organization = @@client.organization(org)
|
265
303
|
end
|
266
304
|
|
267
305
|
if space = info[:space]
|
268
|
-
|
306
|
+
@@client.current_space = @@client.space(space)
|
269
307
|
end
|
270
308
|
|
271
309
|
save_target_info(info)
|
272
310
|
|
273
|
-
|
311
|
+
@@client
|
312
|
+
end
|
313
|
+
|
314
|
+
class << self
|
315
|
+
def client
|
316
|
+
@@client
|
317
|
+
end
|
318
|
+
|
319
|
+
def client=(c)
|
320
|
+
@@client = c
|
321
|
+
end
|
274
322
|
end
|
275
323
|
end
|
276
324
|
end
|
data/vmc-ng/lib/vmc/version.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.require(:default, :development)
|
4
|
+
|
5
|
+
require 'rake/dsl_definition'
|
6
|
+
require 'rake'
|
7
|
+
require 'rspec'
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.pattern = "**/*_spec.rb"
|
12
|
+
t.rspec_opts = ["--format", "documentation", "--colour"]
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "./helpers"
|
2
|
+
|
3
|
+
describe "App#apps" do
|
4
|
+
it "lists app names" do
|
5
|
+
with_random_apps do |apps|
|
6
|
+
shell("apps").split("\n").should =~
|
7
|
+
apps.collect(&:name)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "filters by name with --name" do
|
12
|
+
with_random_apps do |apps|
|
13
|
+
app = apps[rand(apps.size)]
|
14
|
+
|
15
|
+
result = shell("apps", "--name", app.name).split("\n")
|
16
|
+
result.should =~ [app.name]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "filters by runtime with --runtime" do
|
21
|
+
with_random_apps do |apps|
|
22
|
+
app = apps[rand(apps.size)]
|
23
|
+
|
24
|
+
result = shell("apps", "--runtime", app.runtime.name).split("\n")
|
25
|
+
actual =
|
26
|
+
apps.select { |a|
|
27
|
+
/#{app.runtime.name}/ =~ a.runtime.name
|
28
|
+
}.collect(&:name)
|
29
|
+
|
30
|
+
result.should =~ actual
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "filters by framework with --framework" do
|
35
|
+
with_random_apps do |apps|
|
36
|
+
app = apps[rand(apps.size)]
|
37
|
+
|
38
|
+
result = shell("apps", "--framework", app.framework.name).split("\n")
|
39
|
+
actual =
|
40
|
+
apps.select { |a|
|
41
|
+
/#{app.framework.name}/ =~ a.framework.name
|
42
|
+
}.collect(&:name)
|
43
|
+
|
44
|
+
result.should =~ actual
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# TODO: use space other than current
|
49
|
+
it "can be told which space with --space" do
|
50
|
+
with_random_apps do |apps|
|
51
|
+
app = apps[rand(apps.size)]
|
52
|
+
|
53
|
+
result = shell("apps", "--space", client.current_space.name).split("\n")
|
54
|
+
actual = client.current_space.apps.collect(&:name)
|
55
|
+
|
56
|
+
result.should =~ actual
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO: v2
|
61
|
+
#it "filters by url with --url" do
|
62
|
+
#with_random_apps do |apps|
|
63
|
+
#app = apps[rand(apps.size)]
|
64
|
+
#url = app.urls[rand(app.urls.size)]
|
65
|
+
|
66
|
+
#result = shell("apps", "--url", url).split("\n")
|
67
|
+
#actual =
|
68
|
+
#apps.select { |a|
|
69
|
+
#a.urls.include? url
|
70
|
+
#}.collect(&:name)
|
71
|
+
|
72
|
+
#result.should =~ actual
|
73
|
+
#end
|
74
|
+
#end
|
75
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "cfoundry"
|
2
|
+
require "vmc"
|
3
|
+
|
4
|
+
TARGET = ENV["VMC_TEST_TARGET"] || "http://localhost:8181"
|
5
|
+
USER = ENV["VMC_TEST_USER"] || "sre@vmware.com"
|
6
|
+
PASSWORD = ENV["VMC_TEST_PASSWORD"] || "test"
|
7
|
+
|
8
|
+
module VMCHelpers
|
9
|
+
def random_str
|
10
|
+
format("%x", rand(1000000))
|
11
|
+
end
|
12
|
+
|
13
|
+
def client
|
14
|
+
VMC::CLI.client
|
15
|
+
end
|
16
|
+
|
17
|
+
# invoke a block while logged out
|
18
|
+
def without_auth
|
19
|
+
proxy = client.proxy
|
20
|
+
client.logout
|
21
|
+
client.proxy = nil
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
client.login(USER, PASSWORD)
|
25
|
+
client.proxy = proxy
|
26
|
+
end
|
27
|
+
|
28
|
+
# same as Ruby 1.9's Array#sample
|
29
|
+
def sample(ary)
|
30
|
+
ary[rand(ary.size)]
|
31
|
+
end
|
32
|
+
|
33
|
+
# cache frameworks for app generation
|
34
|
+
def frameworks
|
35
|
+
@@frameworks ||= client.frameworks(0)
|
36
|
+
end
|
37
|
+
|
38
|
+
# cache runtimes for app generation
|
39
|
+
def runtimes
|
40
|
+
@@runtimes ||= client.runtimes(0)
|
41
|
+
end
|
42
|
+
|
43
|
+
def with_random_app
|
44
|
+
with_random_apps(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
# create 2-5 random apps, call the block, and then delete them
|
48
|
+
def with_random_apps(num = rand(3) + 2)
|
49
|
+
apps = []
|
50
|
+
|
51
|
+
num.times do |n|
|
52
|
+
app = client.app
|
53
|
+
app.name = "app-#{n + 1}-#{random_str}"
|
54
|
+
app.space = client.current_space
|
55
|
+
app.instances = rand(2)
|
56
|
+
|
57
|
+
app.framework = sample(frameworks)
|
58
|
+
app.runtime = sample(runtimes)
|
59
|
+
app.memory = sample([64, 128, 256, 512])
|
60
|
+
app.create!
|
61
|
+
|
62
|
+
apps << app
|
63
|
+
end
|
64
|
+
|
65
|
+
yield apps
|
66
|
+
ensure
|
67
|
+
apps.each(&:delete!)
|
68
|
+
end
|
69
|
+
|
70
|
+
# invoke a command with a given arglist
|
71
|
+
def shell(*argv)
|
72
|
+
before_out = $stdout
|
73
|
+
before_err = $stderr
|
74
|
+
|
75
|
+
$stdout = StringIO.new
|
76
|
+
$stderr = StringIO.new
|
77
|
+
|
78
|
+
begin
|
79
|
+
VMC::CLI.start(argv)
|
80
|
+
rescue SystemExit => e
|
81
|
+
unless e.status == 0
|
82
|
+
raise "execution failed! output:\n#{$stderr.string}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
$stdout.string
|
87
|
+
ensure
|
88
|
+
$stdout = before_out
|
89
|
+
$stderr = before_err
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
RSpec.configure do |c|
|
94
|
+
c.include VMCHelpers
|
95
|
+
|
96
|
+
c.before(:all) do
|
97
|
+
VMC::CLI.client = CFoundry::Client.new(TARGET)
|
98
|
+
|
99
|
+
client.login(:username => USER, :password => PASSWORD)
|
100
|
+
client.current_organization = client.organizations.first
|
101
|
+
client.current_space = client.current_organization.spaces.first
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "./helpers"
|
2
|
+
|
3
|
+
describe "Start#target" do
|
4
|
+
it "shows target url with no arguments" do
|
5
|
+
shell("target").rstrip.should == client.target
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "switching target url" do
|
9
|
+
before(:each) do
|
10
|
+
@old_client = client
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
VMC::CLI.client = @old_client
|
15
|
+
end
|
16
|
+
|
17
|
+
it "switches target url if given one argument" do
|
18
|
+
shell("target", "http://api.cloudfoundry.com")
|
19
|
+
client.target.should == "http://api.cloudfoundry.com"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "defaults to https if supported by remote" do
|
23
|
+
shell("target", "api.cloudfoundry.com")
|
24
|
+
client.target.should == "https://api.cloudfoundry.com"
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO: this assumes locally running cc without https support
|
28
|
+
it "defaults to http if not supported by remote" do
|
29
|
+
base_target = client.target.sub(/^https?:\/\//, "")
|
30
|
+
shell("target", base_target)
|
31
|
+
client.target.should == "http://#{base_target}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vmc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196425
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
9
|
- 0
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 0.4.0.beta.
|
11
|
+
- 21
|
12
|
+
version: 0.4.0.beta.21
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- VMware
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-07-
|
20
|
+
date: 2012-07-19 00:00:00 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: json_pure
|
@@ -249,12 +249,12 @@ dependencies:
|
|
249
249
|
requirements:
|
250
250
|
- - ~>
|
251
251
|
- !ruby/object:Gem::Version
|
252
|
-
hash:
|
252
|
+
hash: 3
|
253
253
|
segments:
|
254
254
|
- 0
|
255
255
|
- 3
|
256
|
-
-
|
257
|
-
version: 0.3.
|
256
|
+
- 8
|
257
|
+
version: 0.3.8
|
258
258
|
type: :runtime
|
259
259
|
version_requirements: *id014
|
260
260
|
- !ruby/object:Gem::Dependency
|
@@ -265,12 +265,12 @@ dependencies:
|
|
265
265
|
requirements:
|
266
266
|
- - ~>
|
267
267
|
- !ruby/object:Gem::Version
|
268
|
-
hash:
|
268
|
+
hash: 15
|
269
269
|
segments:
|
270
270
|
- 0
|
271
271
|
- 0
|
272
|
-
-
|
273
|
-
version: 0.0.
|
272
|
+
- 8
|
273
|
+
version: 0.0.8
|
274
274
|
type: :runtime
|
275
275
|
version_requirements: *id015
|
276
276
|
- !ruby/object:Gem::Dependency
|
@@ -289,6 +289,34 @@ dependencies:
|
|
289
289
|
version: 0.3.1
|
290
290
|
type: :runtime
|
291
291
|
version_requirements: *id016
|
292
|
+
- !ruby/object:Gem::Dependency
|
293
|
+
name: rake
|
294
|
+
prerelease: false
|
295
|
+
requirement: &id017 !ruby/object:Gem::Requirement
|
296
|
+
none: false
|
297
|
+
requirements:
|
298
|
+
- - ">="
|
299
|
+
- !ruby/object:Gem::Version
|
300
|
+
hash: 3
|
301
|
+
segments:
|
302
|
+
- 0
|
303
|
+
version: "0"
|
304
|
+
type: :runtime
|
305
|
+
version_requirements: *id017
|
306
|
+
- !ruby/object:Gem::Dependency
|
307
|
+
name: rspec
|
308
|
+
prerelease: false
|
309
|
+
requirement: &id018 !ruby/object:Gem::Requirement
|
310
|
+
none: false
|
311
|
+
requirements:
|
312
|
+
- - ">="
|
313
|
+
- !ruby/object:Gem::Version
|
314
|
+
hash: 3
|
315
|
+
segments:
|
316
|
+
- 0
|
317
|
+
version: "0"
|
318
|
+
type: :runtime
|
319
|
+
version_requirements: *id018
|
292
320
|
description:
|
293
321
|
email: support@vmware.com
|
294
322
|
executables:
|
@@ -355,6 +383,10 @@ files:
|
|
355
383
|
- vmc-ng/lib/vmc/plugin.rb
|
356
384
|
- vmc-ng/lib/vmc/version.rb
|
357
385
|
- vmc-ng/lib/vmc.rb
|
386
|
+
- vmc-ng/spec/app/apps_spec.rb
|
387
|
+
- vmc-ng/spec/helpers.rb
|
388
|
+
- vmc-ng/spec/Rakefile
|
389
|
+
- vmc-ng/spec/start/target_spec.rb
|
358
390
|
- vmc-ng/bin/vmc
|
359
391
|
- bin/vmc
|
360
392
|
homepage: http://vmware.com
|