cf 0.1.5 → 0.6.0.rc1

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 (140) hide show
  1. data/LICENSE +1277 -30
  2. data/Rakefile +12 -1
  3. data/bin/cf +0 -3
  4. data/lib/cf.rb +6 -0
  5. data/lib/cf/cli.rb +389 -190
  6. data/lib/cf/cli/app/app.rb +45 -0
  7. data/lib/cf/cli/app/apps.rb +99 -0
  8. data/lib/cf/cli/app/base.rb +90 -0
  9. data/lib/cf/cli/app/crashes.rb +42 -0
  10. data/lib/cf/cli/app/delete.rb +95 -0
  11. data/lib/cf/cli/app/deprecated.rb +11 -0
  12. data/lib/cf/cli/app/env.rb +78 -0
  13. data/lib/cf/cli/app/files.rb +137 -0
  14. data/lib/cf/cli/app/health.rb +26 -0
  15. data/lib/cf/cli/app/instances.rb +53 -0
  16. data/lib/cf/cli/app/logs.rb +76 -0
  17. data/lib/cf/cli/app/push.rb +105 -0
  18. data/lib/cf/cli/app/push/create.rb +149 -0
  19. data/lib/cf/cli/app/push/interactions.rb +94 -0
  20. data/lib/cf/cli/app/push/sync.rb +64 -0
  21. data/lib/cf/cli/app/rename.rb +35 -0
  22. data/lib/cf/cli/app/restart.rb +20 -0
  23. data/lib/cf/cli/app/scale.rb +69 -0
  24. data/lib/cf/cli/app/start.rb +143 -0
  25. data/lib/cf/cli/app/stats.rb +67 -0
  26. data/lib/cf/cli/app/stop.rb +27 -0
  27. data/lib/cf/cli/domain/base.rb +8 -0
  28. data/lib/cf/cli/domain/domains.rb +40 -0
  29. data/lib/cf/cli/domain/map.rb +55 -0
  30. data/lib/cf/cli/domain/unmap.rb +56 -0
  31. data/lib/cf/cli/help.rb +15 -0
  32. data/lib/cf/cli/interactive.rb +105 -0
  33. data/lib/cf/cli/organization/base.rb +12 -0
  34. data/lib/cf/cli/organization/create.rb +32 -0
  35. data/lib/cf/cli/organization/delete.rb +73 -0
  36. data/lib/cf/cli/organization/org.rb +45 -0
  37. data/lib/cf/cli/organization/orgs.rb +35 -0
  38. data/lib/cf/cli/organization/rename.rb +36 -0
  39. data/lib/cf/cli/route/base.rb +8 -0
  40. data/lib/cf/cli/route/map.rb +70 -0
  41. data/lib/cf/cli/route/routes.rb +26 -0
  42. data/lib/cf/cli/route/unmap.rb +62 -0
  43. data/lib/cf/cli/service/base.rb +8 -0
  44. data/lib/cf/cli/service/bind.rb +44 -0
  45. data/lib/cf/cli/service/create.rb +107 -0
  46. data/lib/cf/cli/service/delete.rb +82 -0
  47. data/lib/cf/cli/service/rename.rb +35 -0
  48. data/lib/cf/cli/service/service.rb +40 -0
  49. data/lib/cf/cli/service/services.rb +99 -0
  50. data/lib/cf/cli/service/unbind.rb +38 -0
  51. data/lib/cf/cli/space/base.rb +19 -0
  52. data/lib/cf/cli/space/create.rb +63 -0
  53. data/lib/cf/cli/space/delete.rb +95 -0
  54. data/lib/cf/cli/space/rename.rb +39 -0
  55. data/lib/cf/cli/space/space.rb +64 -0
  56. data/lib/cf/cli/space/spaces.rb +55 -0
  57. data/lib/cf/cli/space/switch.rb +16 -0
  58. data/lib/cf/cli/start/base.rb +93 -0
  59. data/lib/cf/cli/start/colors.rb +13 -0
  60. data/lib/cf/cli/start/info.rb +124 -0
  61. data/lib/cf/cli/start/login.rb +94 -0
  62. data/lib/cf/cli/start/logout.rb +17 -0
  63. data/lib/cf/cli/start/target.rb +69 -0
  64. data/lib/cf/cli/start/target_interactions.rb +37 -0
  65. data/lib/cf/cli/start/targets.rb +16 -0
  66. data/lib/cf/cli/user/base.rb +29 -0
  67. data/lib/cf/cli/user/create.rb +39 -0
  68. data/lib/cf/cli/user/passwd.rb +43 -0
  69. data/lib/cf/cli/user/register.rb +42 -0
  70. data/lib/cf/cli/user/users.rb +32 -0
  71. data/lib/cf/constants.rb +10 -7
  72. data/lib/cf/detect.rb +113 -48
  73. data/lib/cf/errors.rb +17 -0
  74. data/lib/cf/plugin.rb +28 -12
  75. data/lib/cf/spacing.rb +89 -0
  76. data/lib/cf/spec_helper.rb +1 -0
  77. data/lib/cf/test_support.rb +6 -0
  78. data/lib/cf/version.rb +1 -1
  79. data/spec/assets/hello-sinatra/Gemfile +3 -0
  80. data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
  81. data/spec/assets/hello-sinatra/config.ru +3 -0
  82. data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
  83. data/spec/assets/hello-sinatra/main.rb +6 -0
  84. data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
  85. data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
  86. data/spec/cf/cli/app/base_spec.rb +17 -0
  87. data/spec/cf/cli/app/delete_spec.rb +188 -0
  88. data/spec/cf/cli/app/instances_spec.rb +65 -0
  89. data/spec/cf/cli/app/push/create_spec.rb +661 -0
  90. data/spec/cf/cli/app/push_spec.rb +369 -0
  91. data/spec/cf/cli/app/rename_spec.rb +104 -0
  92. data/spec/cf/cli/app/scale_spec.rb +75 -0
  93. data/spec/cf/cli/app/start_spec.rb +208 -0
  94. data/spec/cf/cli/app/stats_spec.rb +68 -0
  95. data/spec/cf/cli/domain/map_spec.rb +130 -0
  96. data/spec/cf/cli/domain/unmap_spec.rb +69 -0
  97. data/spec/cf/cli/organization/orgs_spec.rb +108 -0
  98. data/spec/cf/cli/organization/rename_spec.rb +113 -0
  99. data/spec/cf/cli/route/map_spec.rb +121 -0
  100. data/spec/cf/cli/route/unmap_spec.rb +155 -0
  101. data/spec/cf/cli/service/bind_spec.rb +25 -0
  102. data/spec/cf/cli/service/delete_spec.rb +22 -0
  103. data/spec/cf/cli/service/rename_spec.rb +105 -0
  104. data/spec/cf/cli/service/service_spec.rb +23 -0
  105. data/spec/cf/cli/service/unbind_spec.rb +25 -0
  106. data/spec/cf/cli/space/create_spec.rb +93 -0
  107. data/spec/cf/cli/space/rename_spec.rb +102 -0
  108. data/spec/cf/cli/space/spaces_spec.rb +104 -0
  109. data/spec/cf/cli/space/switch_space_spec.rb +55 -0
  110. data/spec/cf/cli/start/info_spec.rb +160 -0
  111. data/spec/cf/cli/start/login_spec.rb +142 -0
  112. data/spec/cf/cli/start/logout_spec.rb +50 -0
  113. data/spec/cf/cli/start/target_spec.rb +123 -0
  114. data/spec/cf/cli/user/create_spec.rb +54 -0
  115. data/spec/cf/cli/user/passwd_spec.rb +102 -0
  116. data/spec/cf/cli/user/register_spec.rb +140 -0
  117. data/spec/cf/cli_spec.rb +442 -0
  118. data/spec/cf/detect_spec.rb +54 -0
  119. data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
  120. data/spec/console_app_specker/specker_runner_spec.rb +167 -0
  121. data/spec/features/account_lifecycle_spec.rb +85 -0
  122. data/spec/features/login_spec.rb +66 -0
  123. data/spec/features/push_flow_spec.rb +125 -0
  124. data/spec/features/switching_targets_spec.rb +32 -0
  125. data/spec/spec_helper.rb +72 -0
  126. data/spec/support/command_helper.rb +81 -0
  127. data/spec/support/config_helper.rb +15 -0
  128. data/spec/support/console_app_specker_matchers.rb +86 -0
  129. data/spec/support/fake_home_dir.rb +55 -0
  130. data/spec/support/interact_helper.rb +29 -0
  131. data/spec/support/shared_examples/errors.rb +40 -0
  132. data/spec/support/shared_examples/input.rb +14 -0
  133. data/spec/support/specker_runner.rb +80 -0
  134. data/spec/support/tracking_expector.rb +71 -0
  135. metadata +427 -66
  136. data/lib/cf/cli/app.rb +0 -595
  137. data/lib/cf/cli/command.rb +0 -444
  138. data/lib/cf/cli/dots.rb +0 -133
  139. data/lib/cf/cli/service.rb +0 -112
  140. data/lib/cf/cli/user.rb +0 -71
@@ -1,595 +0,0 @@
1
- require "cf/cli/command"
2
- require "cf/detect"
3
-
4
- module CF
5
- class App < Command
6
- MEM_CHOICES = ["64M", "128M", "256M", "512M"]
7
-
8
- desc "apps", "List your applications"
9
- def apps
10
- apps =
11
- with_progress("Getting applications") do
12
- client.apps
13
- end
14
-
15
- if apps.empty? and !simple_output?
16
- puts ""
17
- puts "No applications."
18
- return
19
- end
20
-
21
- apps.each.with_index do |a, num|
22
- display_app(a)
23
- end
24
- end
25
-
26
- desc "health ...APPS", "Get application health"
27
- def health(*names)
28
- apps =
29
- with_progress("Getting application health") do
30
- names.collect do |n|
31
- [n, app_status(client.app(n))]
32
- end
33
- end
34
-
35
- apps.each do |name, status|
36
- unless simple_output?
37
- puts ""
38
- print "#{c(name, :blue)}: "
39
- end
40
-
41
- puts status
42
- end
43
- end
44
-
45
- desc "stop [APP]", "Stop an application"
46
- def stop(name)
47
- with_progress("Stopping #{c(name, :blue)}") do |s|
48
- app = client.app(name)
49
-
50
- unless app.exists?
51
- s.fail do
52
- err "Unknown application."
53
- end
54
- end
55
-
56
- if app.stopped?
57
- s.skip do
58
- err "Application is not running."
59
- end
60
- end
61
-
62
- app.stop!
63
- end
64
- end
65
-
66
- desc "start [APP]", "Start an application"
67
- flag(:debug_mode)
68
- def start(name)
69
- app = client.app(name)
70
-
71
- unless app.exists?
72
- err "Unknown application."
73
- return
74
- end
75
-
76
- switch_mode(app, input(:debug_mode))
77
-
78
- with_progress("Starting #{c(name, :blue)}") do |s|
79
- if app.running?
80
- s.skip do
81
- err "Already started."
82
- return
83
- end
84
- end
85
-
86
- app.start!
87
- end
88
-
89
- check_application(app)
90
-
91
- if app.debug_mode && !simple_output?
92
- puts ""
93
- instances(name)
94
- end
95
- end
96
-
97
- desc "restart [APP]", "Stop and start an application"
98
- flag(:debug_mode)
99
- def restart(name)
100
- stop(name)
101
- start(name)
102
- end
103
-
104
- desc "delete [APP]", "Delete an application"
105
- flag(:really) { |name, color = :blue|
106
- force? || ask("Really delete #{c(name, color)}?", :default => false)
107
- }
108
- flag(:name) { |names|
109
- ask("Delete which application?", :choices => names)
110
- }
111
- flag(:all, :default => false)
112
- def delete(name = nil)
113
- if input(:all)
114
- return unless input(:really, "ALL APPS", :red)
115
-
116
- with_progress("Deleting all applications") do
117
- client.apps.collect(&:delete!)
118
- end
119
-
120
- return
121
- end
122
-
123
- unless name
124
- apps = client.apps
125
- return err "No applications." if apps.empty?
126
-
127
- name = input(:name, apps.collect(&:name))
128
- end
129
-
130
- return unless input(:really, name)
131
-
132
- with_progress("Deleting #{c(name, :blue)}") do
133
- client.app(name).delete!
134
- end
135
- ensure
136
- forget(:really)
137
- end
138
-
139
- desc "instances [APP]", "List an app's instances"
140
- def instances(name)
141
- instances =
142
- with_progress("Getting instances for #{c(name, :blue)}") do
143
- client.app(name).instances
144
- end
145
-
146
- instances.each do |i|
147
- if simple_output?
148
- puts i.index
149
- else
150
- puts ""
151
- display_instance(i)
152
- end
153
- end
154
- end
155
-
156
- desc "files [APP] [PATH]", "Examine an app's files"
157
- def files(name, path = "/")
158
- files =
159
- with_progress("Getting file listing") do
160
- client.app(name).files(*path.split("/"))
161
- end
162
-
163
- puts "" unless simple_output?
164
-
165
- files.each do |file|
166
- puts file
167
- end
168
- end
169
-
170
- desc "file [APP] [PATH]", "Print out an app's file contents"
171
- def file(name, path = "/")
172
- file =
173
- with_progress("Getting file contents") do
174
- client.app(name).file(*path.split("/"))
175
- end
176
-
177
- puts "" unless simple_output?
178
-
179
- print file
180
- end
181
-
182
- desc "logs [APP]", "Print out an app's logs"
183
- flag(:instance, :type => :numeric, :default => 0)
184
- def logs(name)
185
- app = client.app(name)
186
- unless app.exists?
187
- err "Unknown application."
188
- return
189
- end
190
-
191
- instances =
192
- if input(:instance) == "all"
193
- app.instances
194
- else
195
- app.instances.select { |i| i.index == input(:instance) }
196
- end
197
-
198
- if instances.empty?
199
- if input(:instance) == "all"
200
- err "No instances found."
201
- else
202
- err "Instance #{name} \##{input(:instance)} not found."
203
- end
204
-
205
- return
206
- end
207
-
208
- instances.each do |i|
209
- logs =
210
- with_progress(
211
- "Getting logs for " +
212
- c(name, :blue) + " " +
213
- c("\##{i.index}", :yellow)) do
214
- i.files("logs")
215
- end
216
-
217
- puts "" unless simple_output?
218
-
219
- logs.each do |log|
220
- body =
221
- with_progress("Reading " + b(log.join("/"))) do
222
- i.file(*log)
223
- end
224
-
225
- puts body
226
- puts "" unless body.empty?
227
- end
228
- end
229
- end
230
-
231
- desc "push [NAME]", "Push an application, syncing changes if it exists"
232
- flag(:name) { ask("Name") }
233
- flag(:path) {
234
- ask("Push from...", :default => ".")
235
- }
236
- flag(:url) { |name, target|
237
- ask("URL", :default => "#{name}.#{target}")
238
- }
239
- flag(:memory) {
240
- ask("Memory Limit",
241
- :choices => MEM_CHOICES,
242
-
243
- # TODO: base this on framework choice
244
- :default => "64M")
245
- }
246
- flag(:instances) {
247
- ask("Instances", :default => 1)
248
- }
249
- flag(:framework) { |choices, default|
250
- ask("Framework", :choices => choices, :default => default)
251
- }
252
- flag(:runtime) { |choices|
253
- ask("Runtime", :choices => choices)
254
- }
255
- flag(:start, :default => true)
256
- flag(:restart, :default => true)
257
- def push(name = nil)
258
- path = File.expand_path(input(:path))
259
-
260
- name ||= input(:name)
261
-
262
- detector = Detector.new(client, path)
263
- frameworks = detector.all_frameworks
264
- detected, default = detector.frameworks
265
-
266
- app = client.app(name)
267
-
268
- if app.exists?
269
- upload_app(app, path)
270
- restart(app.name) if input(:restart)
271
- return
272
- end
273
-
274
- app.total_instances = input(:instances)
275
-
276
- domain = client.target.sub(/^https?:\/\/api\.(.+)\/?/, '\1')
277
- app.urls = [input(:url, name, domain)]
278
-
279
- framework = input(:framework, ["other"] + detected.keys, default)
280
- if framework == "other"
281
- forget(:framework)
282
- framework = input(:framework, frameworks.keys)
283
- end
284
-
285
- framework_runtimes =
286
- frameworks[framework]["runtimes"].collect do |k|
287
- "#{k["name"]} (#{k["description"]})"
288
- end
289
-
290
- # TODO: include descriptions
291
- runtime = input(:runtime, framework_runtimes).split.first
292
-
293
- app.framework = framework
294
- app.runtime = runtime
295
-
296
- app.memory = megabytes(input(:memory))
297
-
298
- with_progress("Creating #{c(name, :blue)}") do
299
- app.create!
300
- end
301
-
302
- begin
303
- upload_app(app, path)
304
- rescue
305
- err "Upload failed. Try again with 'vmc push'."
306
- raise
307
- end
308
-
309
- start(name) if input(:start)
310
- end
311
-
312
- desc "update", "DEPRECATED", :hide => true
313
- def update(*args)
314
- err "The 'update' command is no longer used; use 'push' instead."
315
- end
316
-
317
- desc "stats [APP]", "Display application instance status"
318
- def stats(name)
319
- stats =
320
- with_progress("Getting stats") do
321
- client.app(name).stats
322
- end
323
-
324
- stats.sort_by { |k, _| k }.each do |idx, info|
325
- stats = info["stats"]
326
- usage = stats["usage"]
327
- puts ""
328
- puts "instance #{c("#" + idx, :blue)}:"
329
- print " cpu: #{percentage(usage["cpu"])} of"
330
- puts " #{b(stats["cores"])} cores"
331
- puts " memory: #{usage(usage["mem"] * 1024, stats["mem_quota"])}"
332
- puts " disk: #{usage(usage["disk"], stats["disk_quota"])}"
333
- end
334
- end
335
-
336
- desc "scale [APP]", "Update the instances/memory limit for an application"
337
- flag(:instances, :type => :numeric) { |default|
338
- ask("Instances", :default => default)
339
- }
340
- flag(:memory) { |default|
341
- ask("Memory Limit",
342
- :default => human_size(default * 1024 * 1024, 0),
343
- :choices => MEM_CHOICES)
344
- }
345
- def scale(name)
346
- app = client.app(name)
347
-
348
- instances = passed_value(:instances)
349
- memory = passed_value(:memory)
350
-
351
- unless instances || memory
352
- instances = input(:instances, app.total_instances)
353
- memory = input(:memory, app.memory)
354
- end
355
-
356
- with_progress("Scaling #{c(name, :blue)}") do
357
- app.total_instances = instances.to_i if instances
358
- app.memory = megabytes(memory) if memory
359
- app.update!
360
- end
361
- end
362
-
363
- desc "map NAME URL", "Add a URL mapping for an app"
364
- def map(name, url)
365
- simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
366
-
367
- with_progress("Updating #{c(name, :blue)}") do
368
- app = client.app(name)
369
- app.urls << simple
370
- app.update!
371
- end
372
- end
373
-
374
- desc "unmap NAME URL", "Remove a URL mapping from an app"
375
- def unmap(name, url)
376
- simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
377
-
378
- with_progress("Updating #{c(name, :blue)}") do |s|
379
- app = client.app(name)
380
-
381
- unless app.urls.delete(simple)
382
- s.fail do
383
- err "URL #{url} is not mapped to this application."
384
- return
385
- end
386
- end
387
-
388
- app.update!
389
- end
390
- end
391
-
392
- class Env < Command
393
- VALID_NAME = /^[a-zA-Za-z_][[:alnum:]_]*$/
394
-
395
- desc "set [APP] [NAME] [VALUE]", "Set an environment variable"
396
- def set(appname, name, value)
397
- app = client.app(appname)
398
- unless name =~ VALID_NAME
399
- err "Invalid variable name; must match #{VALID_NAME.inspect}"
400
- return
401
- end
402
-
403
- unless app.exists?
404
- err "Unknown application."
405
- return
406
- end
407
-
408
- with_progress("Updating #{c(app.name, :blue)}") do
409
- app.update!("env" =>
410
- app.env.reject { |v|
411
- v.start_with?("#{name}=")
412
- }.push("#{name}=#{value}"))
413
- end
414
- end
415
-
416
- desc "unset [APP] [NAME]", "Remove an environment variable"
417
- def unset(appname, name)
418
- app = client.app(appname)
419
-
420
- unless app.exists?
421
- err "Unknown application."
422
- return
423
- end
424
-
425
- with_progress("Updating #{c(app.name, :blue)}") do
426
- app.update!("env" =>
427
- app.env.reject { |v|
428
- v.start_with?("#{name}=")
429
- })
430
- end
431
- end
432
-
433
- desc "list [APP]", "Show all environment variables set for an app"
434
- def list(appname)
435
- vars =
436
- with_progress("Getting variables") do |s|
437
- app = client.app(appname)
438
-
439
- unless app.exists?
440
- s.fail do
441
- err "Unknown application."
442
- return
443
- end
444
- end
445
-
446
- app.env
447
- end
448
-
449
- puts "" unless simple_output?
450
-
451
- vars.each do |pair|
452
- name, val = pair.split("=", 2)
453
- puts "#{c(name, :blue)}: #{val}"
454
- end
455
- end
456
- end
457
-
458
- desc "env SUBCOMMAND ...ARGS", "Manage application environment variables"
459
- subcommand "env", Env
460
-
461
- private
462
-
463
- def upload_app(app, path)
464
- with_progress("Uploading #{c(app.name, :blue)}") do
465
- app.upload(path)
466
- end
467
- end
468
-
469
- # set app debug mode, ensuring it's valid, and shutting it down
470
- def switch_mode(app, mode)
471
- mode = nil if mode == "none"
472
-
473
- return false if app.debug_mode == mode
474
-
475
- if mode.nil?
476
- with_progress("Removing debug mode") do
477
- app.debug_mode = nil
478
- app.stop! if app.running?
479
- end
480
-
481
- return true
482
- end
483
-
484
- with_progress("Switching mode to #{c(mode, :blue)}") do |s|
485
- runtimes = client.system_runtimes
486
- modes = runtimes[app.runtime]["debug_modes"] || []
487
- if modes.include?(mode)
488
- app.debug_mode = mode
489
- app.stop! if app.running?
490
- true
491
- else
492
- s.fail do
493
- err "Unknown mode '#{mode}'; available: #{modes.inspect}"
494
- false
495
- end
496
- end
497
- end
498
- end
499
-
500
- APP_CHECK_LIMIT = 60
501
-
502
- def check_application(app)
503
- with_progress("Checking #{c(app.name, :blue)}") do |s|
504
- if app.debug_mode == "suspend"
505
- s.skip do
506
- puts "Application is in suspended debugging mode."
507
- puts "It will wait for you to attach to it before starting."
508
- end
509
- end
510
-
511
- seconds = 0
512
- until app.healthy?
513
- sleep 1
514
- seconds += 1
515
- if seconds == APP_CHECK_LIMIT
516
- s.give_up do
517
- err "Application failed to start."
518
- # TODO: print logs
519
- end
520
- end
521
- end
522
- end
523
- end
524
-
525
- # choose the right color for app/instance state
526
- def state_color(s)
527
- case s
528
- when "STARTING"
529
- :blue
530
- when "STARTED", "RUNNING"
531
- :green
532
- when "DOWN"
533
- :red
534
- when "FLAPPING"
535
- :magenta
536
- when "N/A"
537
- :cyan
538
- else
539
- :yellow
540
- end
541
- end
542
-
543
- def app_status(a)
544
- health = a.health
545
-
546
- if a.debug_mode == "suspend" && health == "0%"
547
- c("suspended", :yellow)
548
- else
549
- c(health.downcase, state_color(health))
550
- end
551
- end
552
-
553
- def display_app(a)
554
- if simple_output?
555
- puts a.name
556
- return
557
- end
558
-
559
- puts ""
560
-
561
- status = app_status(a)
562
-
563
- print "#{c(a.name, :blue)}: #{status}"
564
-
565
- unless a.total_instances == 1
566
- print ", #{b(a.total_instances)} instances"
567
- end
568
-
569
- puts ""
570
-
571
- unless a.urls.empty?
572
- puts " urls: #{a.urls.collect { |u| b(u) }.join(", ")}"
573
- end
574
-
575
- unless a.services.empty?
576
- puts " services: #{a.services.collect { |s| b(s) }.join(", ")}"
577
- end
578
- end
579
-
580
- def display_instance(i)
581
- print "instance #{c("\##{i.index}", :blue)}: "
582
- puts "#{b(c(i.state.downcase, state_color(i.state)))} "
583
-
584
- puts " started: #{c(i.since.strftime("%F %r"), :cyan)}"
585
-
586
- if d = i.debugger
587
- puts " debugger: port #{c(d["port"], :blue)} at #{c(d["ip"], :blue)}"
588
- end
589
-
590
- if c = i.console
591
- puts " console: port #{b(c["port"])} at #{b(c["ip"])}"
592
- end
593
- end
594
- end
595
- end