vmc 0.4.0.beta.12 → 0.4.0.beta.13

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.
@@ -1,8 +1,8 @@
1
- require "vmc/cli/command"
1
+ require "vmc/cli"
2
2
  require "vmc/detect"
3
3
 
4
4
  module VMC
5
- class App < Command
5
+ class App < CLI
6
6
  MEM_CHOICES = ["64M", "128M", "256M", "512M"]
7
7
 
8
8
  # TODO: don't hardcode; bring in from remote
@@ -33,14 +33,40 @@ module VMC
33
33
  }
34
34
 
35
35
 
36
- desc "push [NAME]", "Push an application, syncing changes if it exists"
36
+ desc "List your applications"
37
+ group :apps
38
+ input :name, :desc => "Filter by name regexp"
39
+ input :runtime, :desc => "Filter by runtime regexp"
40
+ input :framework, :desc => "Filter by framework regexp"
41
+ input :url, :desc => "Filter by url regexp"
42
+ def apps(input)
43
+ apps =
44
+ with_progress("Getting applications") do
45
+ client.apps
46
+ end
47
+
48
+ if apps.empty? and !quiet?
49
+ puts ""
50
+ puts "No applications."
51
+ return
52
+ end
53
+
54
+ apps.each.with_index do |a, num|
55
+ display_app(a) if app_matches(a, input)
56
+ end
57
+ end
58
+
59
+
60
+ desc "Push an application, syncing changes if it exists"
37
61
  group :apps, :manage
38
- flag(:name) { ask("Name") }
39
- flag(:path)
40
- flag(:url) { |default|
62
+ input(:name, :argument => true, :desc => "Application name") {
63
+ ask("Name")
64
+ }
65
+ input :path, :desc => "Path containing the application"
66
+ input(:url, :desc => "URL bound to app") { |default|
41
67
  ask("URL", :default => default)
42
68
  }
43
- flag(:memory) { |framework, runtime|
69
+ input(:memory, :desc => "Memory limit") { |framework, runtime|
44
70
  ask("Memory Limit",
45
71
  :choices => MEM_CHOICES,
46
72
  :default =>
@@ -48,33 +74,38 @@ module VMC
48
74
  MEM_DEFAULTS_FRAMEWORK[framework] ||
49
75
  "64M")
50
76
  }
51
- flag(:instances) {
77
+ input(:instances, :type => :integer,
78
+ :desc => "Number of instances to run") {
52
79
  ask("Instances", :default => 1)
53
80
  }
54
- flag(:framework) { |choices, default|
81
+ input(:framework, :desc => "Framework to use") { |choices, default|
55
82
  opts = {:choices => choices}
56
83
  opts[:default] = default if default
57
84
 
58
85
  ask("Framework", opts)
59
86
  }
60
- flag(:runtime) { |choices|
87
+ input(:runtime, :desc => "Runtime to run it with") { |choices|
61
88
  ask("Runtime", :choices => choices)
62
89
  }
63
- flag(:command) {
90
+ input(:command, :desc => "Startup command for standalone app") {
64
91
  ask("Startup command")
65
92
  }
66
- flag(:start, :default => true)
67
- flag(:restart, :default => true)
68
- flag(:create_services, :type => :boolean) {
93
+ input :start, :type => :boolean, :default => true,
94
+ :desc => "Start app after pushing?"
95
+ input :restart, :type => :boolean, :default => true,
96
+ :desc => "Restart app after updating?"
97
+ input(:create_services, :type => :boolean,
98
+ :desc => "Interactively create services?") {
69
99
  ask "Create services for application?", :default => false
70
100
  }
71
- flag(:bind_services, :type => :boolean) {
101
+ input(:bind_services, :type => :boolean,
102
+ :desc => "Interactively bind services?") {
72
103
  ask "Bind other services to application?", :default => false
73
104
  }
74
- def push(name = nil)
75
- path = File.expand_path(input(:path) || ".")
105
+ def push(input)
106
+ path = File.expand_path(input[:path] || ".")
76
107
 
77
- name = input(:name) if input(:name)
108
+ name = input[:name] if input[:name]
78
109
 
79
110
  detector = Detector.new(client, path)
80
111
  frameworks = detector.all_frameworks
@@ -84,47 +115,47 @@ module VMC
84
115
 
85
116
  if app.exists?
86
117
  upload_app(app, path)
87
- restart(app.name) if input(:restart)
118
+ invoke :restart, :name => app.name if input[:restart]
88
119
  return
89
120
  end
90
121
 
91
- app.total_instances = input(:instances)
122
+ app.total_instances = input[:instances]
92
123
 
93
124
  if detected.empty?
94
- framework = input(:framework, frameworks.keys.sort, nil)
125
+ framework = input[:framework, frameworks.keys.sort, nil]
95
126
  else
96
- framework = input(:framework, detected.keys.sort + ["other"], default)
127
+ framework = input[:framework, detected.keys.sort + ["other"], default]
97
128
  if framework == "other"
98
- forget(:framework)
99
- framework = input(:framework, frameworks.keys.sort, nil)
129
+ input.forget(:framework)
130
+ framework = input[:framework, frameworks.keys.sort, nil]
100
131
  end
101
132
  end
102
133
 
103
134
  framework_runtimes =
104
135
  frameworks[framework]["runtimes"].collect { |k| k["name"] }
105
136
 
106
- runtime = input(:runtime, framework_runtimes.sort)
137
+ runtime = input[:runtime, framework_runtimes.sort]
107
138
 
108
139
  app.framework = framework
109
140
  app.runtime = runtime
110
141
 
111
142
  if framework == "standalone"
112
- app.command = input(:command)
143
+ app.command = input[:command]
113
144
 
114
- if (url = input(:url, "none")) != "none"
145
+ if (url = input[:url, "none"]) != "none"
115
146
  app.urls = [url]
116
147
  else
117
148
  app.urls = []
118
149
  end
119
150
  else
120
151
  domain = client.target.sub(/^https?:\/\/api\.(.+)\/?/, '\1')
121
- app.urls = [input(:url, "#{name}.#{domain}")]
152
+ app.urls = [input[:url, "#{name}.#{domain}"]]
122
153
  end
123
154
 
124
- app.memory = megabytes(input(:memory, framework, runtime))
155
+ app.memory = megabytes(input[:memory, framework, runtime])
125
156
 
126
157
  bindings = []
127
- if input(:create_services) && !force?
158
+ if input[:create_services] && !force?
128
159
  services = client.system_services
129
160
 
130
161
  while true
@@ -157,7 +188,7 @@ module VMC
157
188
  end
158
189
  end
159
190
 
160
- if input(:bind_services) && !force?
191
+ if input[:bind_services] && !force?
161
192
  services = client.services.collect(&:name)
162
193
 
163
194
  while true
@@ -188,18 +219,18 @@ module VMC
188
219
  raise
189
220
  end
190
221
 
191
- start(name) if input(:start)
222
+ invoke :start, :name => app.name if input[:start]
192
223
  end
193
224
 
194
- desc "start APPS...", "Start an application"
195
- group :apps, :manage
196
- flag :name
197
- flag :debug_mode, :aliases => "-d"
198
- def start(*names)
199
- if name = passed_value(:name)
200
- names = [name]
201
- end
202
225
 
226
+ desc "Start an application"
227
+ group :apps, :manage
228
+ input :names, :argument => :splat, :singular => :name,
229
+ :desc => "Applications to start"
230
+ input :debug_mode, :aliases => "-d",
231
+ :desc => "Debug mode to start in"
232
+ def start(input)
233
+ names = input[:names]
203
234
  fail "No applications given." if names.empty?
204
235
 
205
236
  names.each do |name|
@@ -209,7 +240,7 @@ module VMC
209
240
 
210
241
  app = filter(:start_app, app)
211
242
 
212
- switch_mode(app, input(:debug_mode))
243
+ switch_mode(app, input[:debug_mode])
213
244
 
214
245
  with_progress("Starting #{c(name, :name)}") do |s|
215
246
  if app.started?
@@ -223,21 +254,20 @@ module VMC
223
254
 
224
255
  check_application(app)
225
256
 
226
- if app.debug_mode && !simple_output?
257
+ if app.debug_mode && !quiet?
227
258
  puts ""
228
259
  instances(name)
229
260
  end
230
261
  end
231
262
  end
232
263
 
233
- desc "stop APPS...", "Stop an application"
234
- group :apps, :manage
235
- flag :name
236
- def stop(*names)
237
- if name = passed_value(:name)
238
- names = [name]
239
- end
240
264
 
265
+ desc "Stop an application"
266
+ group :apps, :manage
267
+ input :names, :argument => :splat, :singular => :name,
268
+ :desc => "Applications to stop"
269
+ def stop(input)
270
+ names = input[:names]
241
271
  fail "No applications given." if names.empty?
242
272
 
243
273
  names.each do |name|
@@ -261,30 +291,36 @@ module VMC
261
291
  end
262
292
  end
263
293
 
264
- desc "restart APPS...", "Stop and start an application"
294
+
295
+ desc "Stop and start an application"
265
296
  group :apps, :manage
266
- flag :name
267
- flag :debug_mode, :aliases => "-d"
268
- def restart(*names)
269
- stop(*names)
270
- start(*names)
297
+ input :names, :argument => :splat, :singular => :name,
298
+ :desc => "Applications to stop"
299
+ input :debug_mode, :aliases => "-d",
300
+ :desc => "Debug mode to start in"
301
+ def restart(input)
302
+ invoke :stop, :names => input[:names]
303
+ invoke :start, :names => input[:names],
304
+ :debug_mode => input[:debug_mode]
271
305
  end
272
306
 
273
- desc "delete APPS...", "Delete an application"
307
+
308
+ desc "Delete an application"
274
309
  group :apps, :manage
275
- flag :name
276
- flag(:really) { |name, color|
310
+ input(:really, :type => :boolean) { |name, color|
277
311
  force? || ask("Really delete #{c(name, color)}?", :default => false)
278
312
  }
279
- flag(:name) { |names|
280
- ask("Delete which application?", :choices => names)
313
+ input(:names, :argument => :splat, :singular => :name,
314
+ :desc => "Applications to delete") { |names|
315
+ [ask("Delete which application?", :choices => names)]
281
316
  }
282
- flag(:orphaned, :aliases => "-o", :type => :boolean,
283
- :desc => "Delete orphaned instances")
284
- flag(:all, :default => false)
285
- def delete(*names)
286
- if input(:all)
287
- return unless input(:really, "ALL APPS", :bad)
317
+ input :orphaned, :aliases => "-o", :type => :boolean,
318
+ :desc => "Delete orphaned instances"
319
+ input :all, :default => false,
320
+ :desc => "Delete all applications"
321
+ def delete(input)
322
+ if input[:all]
323
+ return unless input[:really, "ALL APPS", :bad]
288
324
 
289
325
  apps = client.apps
290
326
 
@@ -296,18 +332,15 @@ module VMC
296
332
  end
297
333
  end
298
334
 
299
- delete_orphaned_services(orphaned)
335
+ delete_orphaned_services(orphaned, input[:orphaned])
300
336
 
301
337
  return
302
338
  end
303
339
 
304
340
  apps = client.apps
341
+ fail "No applications." if apps.empty?
305
342
 
306
- if names.empty?
307
- fail "No applications." if apps.empty?
308
-
309
- names = [input(:name, apps.collect(&:name).sort)]
310
- end
343
+ names = input[:names, apps.collect(&:name).sort]
311
344
 
312
345
  to_delete = names.collect do |n|
313
346
  if app = apps.find { |a| a.name == n }
@@ -317,31 +350,32 @@ module VMC
317
350
  end
318
351
  end
319
352
 
320
- orphaned = find_orphaned_services(to_delete)
321
-
353
+ deleted = []
322
354
  to_delete.each do |app|
323
- really = input(:really, app.name, :name)
324
-
325
- forget(:really)
326
-
355
+ really = input[:really, app.name, :name]
327
356
  next unless really
328
357
 
358
+ deleted << app
359
+
329
360
  with_progress("Deleting #{c(app.name, :name)}") do
330
361
  app.delete!
331
362
  end
332
363
  end
333
364
 
334
- delete_orphaned_services(orphaned)
365
+ unless deleted.empty?
366
+ delete_orphaned_services(
367
+ find_orphaned_services(deleted),
368
+ input[:orphaned])
369
+ end
335
370
  end
336
371
 
337
- desc "instances APPS...", "List an app's instances"
338
- group :apps, :info, :hidden => true
339
- flag :name
340
- def instances(*names)
341
- if name = passed_value(:name)
342
- names = [name]
343
- end
344
372
 
373
+ desc "List an app's instances"
374
+ group :apps, :info, :hidden => true
375
+ input :names, :argument => :splat, :singular => :name,
376
+ :desc => "Applications to list instances of"
377
+ def instances(input)
378
+ names = input[:names]
345
379
  fail "No applications given." if names.empty?
346
380
 
347
381
  names.each do |name|
@@ -351,7 +385,7 @@ module VMC
351
385
  end
352
386
 
353
387
  instances.each do |i|
354
- if simple_output?
388
+ if quiet?
355
389
  puts i.index
356
390
  else
357
391
  puts ""
@@ -361,29 +395,30 @@ module VMC
361
395
  end
362
396
  end
363
397
 
364
- desc "scale APP", "Update the instances/memory limit for an application"
398
+
399
+ desc "Update the instances/memory limit for an application"
365
400
  group :apps, :info, :hidden => true
366
- flag :name
367
- flag(:instances, :type => :numeric) { |default|
401
+ input :name, :argument => true, :desc => "Application to update"
402
+ input(:instances, :type => :numeric,
403
+ :desc => "Number of instances to run") { |default|
368
404
  ask("Instances", :default => default)
369
405
  }
370
- flag(:memory) { |default|
371
- ask("Memory Limit",
372
- :default => human_size(default * 1024 * 1024, 0),
373
- :choices => MEM_CHOICES)
406
+ input(:memory, :desc => "Memory limit") { |default|
407
+ ask("Memory Limit", :choices => MEM_CHOICES,
408
+ :default => human_size(default * 1024 * 1024, 0))
374
409
  }
375
- flag :restart, :default => true
376
- def scale(name = nil)
377
- name ||= input(:name)
378
-
410
+ input :restart, :default => true,
411
+ :desc => "Restart app after updating?"
412
+ def scale(input)
413
+ name = input[:name]
379
414
  app = client.app(name)
380
415
 
381
- instances = passed_value(:instances)
382
- memory = passed_value(:memory)
416
+ instances = input.given(:instances)
417
+ memory = input.given(:memory)
383
418
 
384
419
  unless instances || memory
385
- instances = input(:instances, app.total_instances)
386
- memory = input(:memory, app.memory)
420
+ instances = input[:instances, app.total_instances]
421
+ memory = input[:memory, app.memory]
387
422
  end
388
423
 
389
424
  megs = megabytes(memory)
@@ -399,36 +434,38 @@ module VMC
399
434
  app.update!
400
435
  end
401
436
 
402
- if memory_changed && app.started? && input(:restart)
403
- with_progress("Restarting #{c(name, :name)}") do
404
- app.restart!
405
- end
437
+ if memory_changed && app.started? && input[:restart]
438
+ invoke :restart, :name => name
406
439
  end
407
440
  end
408
441
 
409
- desc "logs APP", "Print out an app's logs"
442
+
443
+ desc "Print out an app's logs"
410
444
  group :apps, :info, :hidden => true
411
- flag :name
412
- flag(:instance, :type => :numeric, :default => 0)
413
- flag(:all, :default => false)
414
- def logs(name = nil)
415
- name ||= input(:name)
445
+ input :name, :argument => true,
446
+ :desc => "Application to get the logs of"
447
+ input :instance, :type => :numeric, :default => 0,
448
+ :desc => "Instance of application to get the logs of"
449
+ input :all, :default => false,
450
+ :desc => "Get logs for every instance"
451
+ def logs(input)
452
+ name = input[:name]
416
453
 
417
454
  app = client.app(name)
418
455
  fail "Unknown application '#{name}'" unless app.exists?
419
456
 
420
457
  instances =
421
- if input(:all)
458
+ if input[:all]
422
459
  app.instances
423
460
  else
424
- app.instances.select { |i| i.index == input(:instance) }
461
+ app.instances.select { |i| i.index == input[:instance] }
425
462
  end
426
463
 
427
464
  if instances.empty?
428
- if input(:all)
465
+ if input[:all]
429
466
  fail "No instances found."
430
467
  else
431
- fail "Instance #{name} \##{input(:instance)} not found."
468
+ fail "Instance #{name} \##{input[:instance]} not found."
432
469
  end
433
470
  end
434
471
 
@@ -441,7 +478,7 @@ module VMC
441
478
  i.files("logs")
442
479
  end
443
480
 
444
- puts "" unless simple_output?
481
+ puts "" unless quiet?
445
482
 
446
483
  logs.each do |log|
447
484
  body =
@@ -455,56 +492,57 @@ module VMC
455
492
  end
456
493
  end
457
494
 
458
- desc "file APP [PATH]", "Print out an app's file contents"
459
- group :apps, :info, :hidden => true
460
- flag :name
461
- def file(name = nil, path = "/")
462
- name ||= input(:name)
463
495
 
496
+ desc "Print out an app's file contents"
497
+ group :apps, :info, :hidden => true
498
+ input :name, :argument => true,
499
+ :desc => "Application to inspect the files of"
500
+ input :path, :argument => true, :default => "/",
501
+ :desc => "Path of file to read"
502
+ def file(input)
464
503
  file =
465
504
  with_progress("Getting file contents") do
466
- client.app(name).file(*path.split("/"))
505
+ client.app(input[:name]).file(*input[:path].split("/"))
467
506
  end
468
507
 
469
- puts "" unless simple_output?
508
+ puts "" unless quiet?
470
509
 
471
510
  print file
472
511
  end
473
512
 
474
- desc "files APP [PATH]", "Examine an app's files"
513
+ desc "Examine an app's files"
475
514
  group :apps, :info, :hidden => true
476
- flag :name
477
- def files(name = nil, path = "/")
478
- name ||= input(:name)
479
-
515
+ input :name, :argument => true,
516
+ :desc => "Application to inspect the files of"
517
+ input :path, :argument => true, :default => "/",
518
+ :desc => "Path of directory to list"
519
+ def files(input)
480
520
  files =
481
521
  with_progress("Getting file listing") do
482
- client.app(name).files(*path.split("/"))
522
+ client.app(input[:name]).files(*input[:path].split("/"))
483
523
  end
484
524
 
485
- puts "" unless simple_output?
525
+ puts "" unless quiet?
486
526
  files.each do |file|
487
527
  puts file.join("/")
488
528
  end
489
529
  end
490
530
 
491
- desc "health ...APPS", "Get application health"
492
- group :apps, :info, :hidden => true
493
- flag :name
494
- def health(*names)
495
- if name = passed_value(:name)
496
- names = [name]
497
- end
498
531
 
532
+ desc "Get application health"
533
+ group :apps, :info, :hidden => true
534
+ input :names, :argument => :splat, :singular => :name,
535
+ :desc => "Application to check the status of"
536
+ def health(input)
499
537
  apps =
500
538
  with_progress("Getting application health") do
501
- names.collect do |n|
539
+ input[:names].collect do |n|
502
540
  [n, app_status(client.app(n))]
503
541
  end
504
542
  end
505
543
 
506
544
  apps.each do |name, status|
507
- unless simple_output?
545
+ unless quiet?
508
546
  puts ""
509
547
  print "#{c(name, :name)}: "
510
548
  end
@@ -513,15 +551,15 @@ module VMC
513
551
  end
514
552
  end
515
553
 
516
- desc "stats APP", "Display application instance status"
517
- group :apps, :info, :hidden => true
518
- flag :name
519
- def stats(name = nil)
520
- name ||= input(:name)
521
554
 
555
+ desc "Display application instance status"
556
+ group :apps, :info, :hidden => true
557
+ input :name, :argument => true,
558
+ :desc => "Application to get the stats for"
559
+ def stats(input)
522
560
  stats =
523
- with_progress("Getting stats") do
524
- client.app(name).stats
561
+ with_progress("Getting stats for #{c(input[:name], :name)}") do
562
+ client.app(input[:name]).stats
525
563
  end
526
564
 
527
565
  stats.sort_by { |k, _| k }.each do |idx, info|
@@ -542,128 +580,218 @@ module VMC
542
580
  end
543
581
  end
544
582
 
545
- desc "update", "DEPRECATED", :hide => true
546
- def update(*args)
547
- fail "The 'update' command is no longer used; use 'push' instead."
583
+
584
+ desc "Add a URL mapping for an app"
585
+ group :apps, :info, :hidden => true
586
+ input :name, :argument => true,
587
+ :desc => "Application to add the URL to"
588
+ input :url, :argument => true,
589
+ :desc => "URL to route"
590
+ def map(input)
591
+ name = input[:name]
592
+ simple = input[:url].sub(/^https?:\/\/(.*)\/?/i, '\1')
593
+
594
+ with_progress("Updating #{c(name, :name)}") do
595
+ app = client.app(name)
596
+ app.urls << simple
597
+ app.update!
598
+ end
548
599
  end
549
600
 
550
- class URL < Command
551
- desc "map APP URL", "Add a URL mapping for an app"
552
- group :apps, :info, :hidden => true
553
- def map(name, url)
554
- simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
555
601
 
556
- with_progress("Updating #{c(name, :name)}") do
557
- app = client.app(name)
558
- app.urls << simple
559
- app.update!
602
+ desc "Remove a URL mapping from an app"
603
+ group :apps, :info, :hidden => true
604
+ input :name, :argument => true,
605
+ :desc => "Application to remove the URL from"
606
+ input(:url, :argument => true, :desc => "URL to unmap") { |choices|
607
+ ask("Which URL?", :choices => choices)
608
+ }
609
+ def unmap(input)
610
+ name = input[:name]
611
+ app = client.app(name)
612
+
613
+ url = input[:url, app.urls]
614
+
615
+ simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
616
+
617
+ fail "Unknown application '#{name}'" unless app.exists?
618
+
619
+ with_progress("Updating #{c(name, :name)}") do |s|
620
+ unless app.urls.delete(simple)
621
+ s.fail do
622
+ err "URL #{url} is not mapped to this application."
623
+ return
624
+ end
560
625
  end
626
+
627
+ app.update!
561
628
  end
629
+ end
562
630
 
563
- desc "unmap APP URL", "Remove a URL mapping from an app"
564
- group :apps, :info, :hidden => true
565
- def unmap(name, url)
566
- simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
567
631
 
568
- app = client.app(name)
569
- fail "Unknown application '#{name}'" unless app.exists?
632
+ desc "Show all environment variables set for an app"
633
+ group :apps, :info, :hidden => true
634
+ input :name, :argument => true,
635
+ :desc => "Application to inspect the environment of"
636
+ def env(input)
637
+ appname = input[:name]
570
638
 
571
- with_progress("Updating #{c(name, :name)}") do |s|
572
- unless app.urls.delete(simple)
639
+ vars =
640
+ with_progress("Getting env for #{c(input[:name], :name)}") do |s|
641
+ app = client.app(appname)
642
+
643
+ unless app.exists?
573
644
  s.fail do
574
- err "URL #{url} is not mapped to this application."
645
+ err "Unknown application '#{appname}'"
575
646
  return
576
647
  end
577
648
  end
578
649
 
579
- app.update!
650
+ app.env
580
651
  end
652
+
653
+ puts "" unless quiet?
654
+
655
+ vars.each do |pair|
656
+ name, val = pair.split("=", 2)
657
+ puts "#{c(name, :name)}: #{val}"
581
658
  end
582
659
  end
583
660
 
584
- desc "url SUBCOMMAND ...ARGS", "Manage application URL bindings"
585
- subcommand "url", URL
586
661
 
587
- class Env < Command
588
- VALID_NAME = /^[a-zA-Za-z_][[:alnum:]_]*$/
662
+ VALID_ENV_VAR = /^[a-zA-Za-z_][[:alnum:]_]*$/
589
663
 
590
- desc "set APP [NAME] [VALUE]", "Set an environment variable"
591
- group :apps, :info, :hidden => true
592
- flag :restart, :default => true
593
- def set(appname, name, value)
594
- unless name =~ VALID_NAME
595
- fail "Invalid variable name; must match #{VALID_NAME.inspect}"
596
- end
597
-
598
- app = client.app(appname)
599
- fail "Unknown application '#{appname}'" unless app.exists?
664
+ desc "Set an environment variable"
665
+ group :apps, :info, :hidden => true
666
+ input :name, :argument => true,
667
+ :desc => "Application to set the variable for"
668
+ input :var, :argument => true,
669
+ :desc => "Environment variable name"
670
+ input :value, :argument => :optional,
671
+ :desc => "Environment variable value"
672
+ input :restart, :default => true,
673
+ :desc => "Restart app after updating?"
674
+ def set_env(input)
675
+ appname = input[:name]
676
+ name = input[:var]
600
677
 
601
- with_progress("Updating #{c(app.name, :name)}") do
602
- app.update!("env" =>
603
- app.env.reject { |v|
604
- v.start_with?("#{name}=")
605
- }.push("#{name}=#{value}"))
606
- end
678
+ if value = input[:value]
679
+ name = input[:var]
680
+ elsif name["="]
681
+ name, value = name.split("=")
682
+ end
607
683
 
608
- if app.started? && input(:restart)
609
- with_progress("Restarting #{c(app.name, :name)}") do
610
- app.restart!
611
- end
612
- end
684
+ unless name =~ VALID_ENV_VAR
685
+ fail "Invalid variable name; must match #{VALID_ENV_VAR.inspect}"
613
686
  end
614
687
 
615
- desc "unset APP [NAME]", "Remove an environment variable"
616
- group :apps, :info, :hidden => true
617
- flag :restart, :default => true
618
- def unset(appname, name)
619
- app = client.app(appname)
620
- fail "Unknown application '#{appname}'" unless app.exists?
688
+ app = client.app(appname)
689
+ fail "Unknown application '#{appname}'" unless app.exists?
621
690
 
622
- with_progress("Updating #{c(app.name, :name)}") do
623
- app.update!("env" =>
624
- app.env.reject { |v|
625
- v.start_with?("#{name}=")
626
- })
627
- end
691
+ with_progress("Updating #{c(app.name, :name)}") do
692
+ app.update!("env" =>
693
+ app.env.reject { |v|
694
+ v.start_with?("#{name}=")
695
+ }.push("#{name}=#{value}"))
696
+ end
628
697
 
629
- if app.started? && input(:restart)
630
- with_progress("Restarting #{c(app.ame, :name)}") do
631
- app.restart!
632
- end
633
- end
698
+ if app.started? && input[:restart]
699
+ invoke :restart, :name => app.name
634
700
  end
701
+ end
635
702
 
636
- desc "list APP", "Show all environment variables set for an app"
637
- group :apps, :info, :hidden => true
638
- def list(appname)
639
- vars =
640
- with_progress("Getting variables") do |s|
641
- app = client.app(appname)
703
+ alias_command :set_env, :env_set
704
+ alias_command :set_env, :add_env
705
+ alias_command :set_env, :env_add
642
706
 
643
- unless app.exists?
644
- s.fail do
645
- err "Unknown application '#{appname}'"
646
- return
647
- end
648
- end
649
707
 
650
- app.env
651
- end
708
+ desc "Remove an environment variable"
709
+ group :apps, :info, :hidden => true
710
+ input :name, :argument => true,
711
+ :desc => "Application to remove the variable from"
712
+ input :var, :argument => true,
713
+ :desc => "Environment variable name"
714
+ input :restart, :default => true,
715
+ :desc => "Restart app after updating?"
716
+ def delete_env(input)
717
+ appname = input[:name]
718
+ name = input[:var]
652
719
 
653
- puts "" unless simple_output?
720
+ app = client.app(appname)
721
+ fail "Unknown application '#{appname}'" unless app.exists?
654
722
 
655
- vars.each do |pair|
656
- name, val = pair.split("=", 2)
657
- puts "#{c(name, :name)}: #{val}"
658
- end
723
+ with_progress("Updating #{c(app.name, :name)}") do
724
+ app.update!("env" =>
725
+ app.env.reject { |v|
726
+ v.start_with?("#{name}=")
727
+ })
728
+ end
729
+
730
+ if app.started? && input[:restart]
731
+ invoke :restart, :name => app.name
659
732
  end
660
733
  end
661
734
 
662
- desc "env SUBCOMMAND ...ARGS", "Manage application environment variables"
663
- subcommand "env", Env
735
+ alias_command :delete_env, :env_del
736
+
737
+
738
+ desc "DEPRECATED. Use 'push' instead."
739
+ def update(input)
740
+ fail "The 'update' command is no longer needed; use 'push' instead."
741
+ end
664
742
 
665
743
  private
666
744
 
745
+ def app_matches(a, options)
746
+ if name = options[:name]
747
+ return false if a.name !~ /#{name}/
748
+ end
749
+
750
+ if runtime = options[:runtime]
751
+ return false if a.runtime !~ /#{runtime}/
752
+ end
753
+
754
+ if framework = options[:framework]
755
+ return false if a.framework !~ /#{framework}/
756
+ end
757
+
758
+ if url = options[:url]
759
+ return false if a.urls.none? { |u| u =~ /#{url}/ }
760
+ end
761
+
762
+ true
763
+ end
764
+
765
+ IS_UTF8 = !!(ENV["LC_ALL"] || ENV["LC_CTYPE"] || ENV["LANG"])["UTF-8"]
766
+
767
+ def display_app(a)
768
+ if quiet?
769
+ puts a.name
770
+ return
771
+ end
772
+
773
+ puts ""
774
+
775
+ status = app_status(a)
776
+
777
+ puts "#{c(a.name, :name)}: #{status}"
778
+
779
+ puts " platform: #{b(a.framework)} on #{b(a.runtime)}"
780
+
781
+ print " usage: #{b(human_size(a.memory * 1024 * 1024, 0))}"
782
+ print " #{c(IS_UTF8 ? "\xc3\x97" : "x", :dim)} #{b(a.total_instances)}"
783
+ print " instance#{a.total_instances == 1 ? "" : "s"}"
784
+ puts ""
785
+
786
+ unless a.urls.empty?
787
+ puts " urls: #{a.urls.collect { |u| b(u) }.join(", ")}"
788
+ end
789
+
790
+ unless a.services.empty?
791
+ puts " services: #{a.services.collect { |s| b(s) }.join(", ")}"
792
+ end
793
+ end
794
+
667
795
  def upload_app(app, path)
668
796
  with_progress("Uploading #{c(app.name, :name)}") do
669
797
  app.upload(path)
@@ -780,13 +908,13 @@ module VMC
780
908
  orphaned
781
909
  end
782
910
 
783
- def delete_orphaned_services(names)
911
+ def delete_orphaned_services(names, orphaned)
784
912
  return if names.empty?
785
913
 
786
- puts "" unless simple_output?
914
+ puts "" unless quiet?
787
915
 
788
916
  names.select { |s|
789
- input(:orphaned) ||
917
+ orphaned ||
790
918
  ask("Delete orphaned service #{c(s, :name)}?", :default => false)
791
919
  }.each do |s|
792
920
  with_progress("Deleting service #{c(s, :name)}") do