vmc 0.4.0.beta.93 → 0.4.0.beta.94

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/vmc-ng/Rakefile +21 -30
  2. data/vmc-ng/lib/vmc.rb +4 -3
  3. data/vmc-ng/lib/vmc/cli.rb +10 -9
  4. data/vmc-ng/lib/vmc/cli/app/app.rb +45 -0
  5. data/vmc-ng/lib/vmc/cli/app/apps.rb +97 -0
  6. data/vmc-ng/lib/vmc/cli/app/base.rb +82 -0
  7. data/vmc-ng/lib/vmc/cli/app/crashes.rb +41 -0
  8. data/vmc-ng/lib/vmc/cli/app/delete.rb +90 -0
  9. data/vmc-ng/lib/vmc/cli/app/deprecated.rb +11 -0
  10. data/vmc-ng/lib/vmc/cli/app/env.rb +86 -0
  11. data/vmc-ng/lib/vmc/cli/app/files.rb +85 -0
  12. data/vmc-ng/lib/vmc/cli/app/health.rb +27 -0
  13. data/vmc-ng/lib/vmc/cli/app/instances.rb +49 -0
  14. data/vmc-ng/lib/vmc/cli/app/logs.rb +80 -0
  15. data/vmc-ng/lib/vmc/cli/app/push.rb +336 -0
  16. data/vmc-ng/lib/vmc/cli/app/rename.rb +31 -0
  17. data/vmc-ng/lib/vmc/cli/app/restart.rb +23 -0
  18. data/vmc-ng/lib/vmc/cli/app/routes.rb +97 -0
  19. data/vmc-ng/lib/vmc/cli/app/scale.rb +67 -0
  20. data/vmc-ng/lib/vmc/cli/app/start.rb +96 -0
  21. data/vmc-ng/lib/vmc/cli/app/stats.rb +68 -0
  22. data/vmc-ng/lib/vmc/cli/app/stop.rb +29 -0
  23. data/vmc-ng/lib/vmc/cli/domain/add_domain.rb +27 -0
  24. data/vmc-ng/lib/vmc/cli/domain/base.rb +12 -0
  25. data/vmc-ng/lib/vmc/cli/domain/create_domain.rb +31 -0
  26. data/vmc-ng/lib/vmc/cli/domain/delete_domain.rb +51 -0
  27. data/vmc-ng/lib/vmc/cli/domain/domains.rb +43 -0
  28. data/vmc-ng/lib/vmc/cli/domain/remove_domain.rb +26 -0
  29. data/vmc-ng/lib/vmc/cli/help.rb +0 -1
  30. data/vmc-ng/lib/vmc/cli/interactive.rb +4 -0
  31. data/vmc-ng/lib/vmc/cli/route/base.rb +12 -0
  32. data/vmc-ng/lib/vmc/cli/route/create_route.rb +42 -0
  33. data/vmc-ng/lib/vmc/cli/route/delete_route.rb +42 -0
  34. data/vmc-ng/lib/vmc/cli/route/routes.rb +26 -0
  35. data/vmc-ng/lib/vmc/detect.rb +2 -2
  36. data/vmc-ng/lib/vmc/spec_helper.rb +1 -0
  37. data/vmc-ng/lib/vmc/version.rb +1 -1
  38. data/vmc-ng/spec/cli/app/push_spec.rb +34 -0
  39. data/vmc-ng/spec/cli/app/rename_spec.rb +108 -0
  40. data/vmc-ng/spec/cli/route/delete_route_spec.rb +160 -0
  41. data/vmc-ng/spec/detect_spec.rb +54 -0
  42. data/vmc-ng/spec/factories/app_factory.rb +9 -0
  43. data/vmc-ng/spec/factories/client_factory.rb +16 -0
  44. data/vmc-ng/spec/factories/domain_factory.rb +9 -0
  45. data/vmc-ng/spec/factories/factory.rb +3 -0
  46. data/vmc-ng/spec/factories/framework_factory.rb +9 -0
  47. data/vmc-ng/spec/factories/route_factory.rb +10 -0
  48. data/vmc-ng/spec/spec_helper.rb +17 -0
  49. data/vmc-ng/spec/support/interact_helpers.rb +23 -0
  50. metadata +135 -62
  51. data/vmc-ng/lib/vmc/cli/app.rb +0 -1333
  52. data/vmc-ng/lib/vmc/cli/domain.rb +0 -164
  53. data/vmc-ng/lib/vmc/cli/route.rb +0 -106
  54. data/vmc-ng/lib/vmc/spec_helpers.rb +0 -431
  55. data/vmc-ng/lib/vmc/spec_helpers/eventlog.rb +0 -277
  56. data/vmc-ng/lib/vmc/spec_helpers/patches.rb +0 -94
  57. data/vmc-ng/spec/Rakefile +0 -13
  58. data/vmc-ng/spec/app/app_spec.rb +0 -19
  59. data/vmc-ng/spec/app/apps_spec.rb +0 -79
  60. data/vmc-ng/spec/app/push_spec.rb +0 -74
  61. data/vmc-ng/spec/assets/hello-sinatra/Gemfile +0 -2
  62. data/vmc-ng/spec/assets/hello-sinatra/main.rb +0 -5
  63. data/vmc-ng/spec/assets/hello-sinatra/manifest.yml +0 -9
  64. data/vmc-ng/spec/helpers.rb +0 -7
  65. data/vmc-ng/spec/start/target_spec.rb +0 -60
data/vmc-ng/Rakefile CHANGED
@@ -6,43 +6,34 @@ require "vmc/version"
6
6
  task :default => :spec
7
7
 
8
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
- sh "rm vmc-#{VMC::VERSION}.gem"
21
- end
22
-
23
- task :uninstall do
24
- sh "gem uninstall vmc"
9
+ task :spec => "bundler:install" do
10
+ sh("rspec")
25
11
  end
26
12
 
27
- task :reinstall => [:uninstall, :install]
28
-
29
- task :release => :build do
30
- sh "gem push vmc-#{VMC::VERSION}.gem"
31
- end
32
-
33
- namespace "bundler" do
34
- desc "Install gems"
13
+ namespace :bundler do
14
+ desc "Install bundler and gems"
35
15
  task "install" do
36
- sh("bundle install")
16
+ sh("(gem list --local bundler | grep bundler || gem install bundler) && (bundle check || bundle install)")
37
17
  end
38
18
  end
39
19
 
40
- namespace "test" do
41
- task "spec" do |t|
42
- # nothing
20
+ namespace :gem do
21
+ desc "Build Gem"
22
+ task :build do
23
+ sh "gem build vmc.gemspec"
43
24
  end
44
25
 
45
- task "integration" do |t|
46
- sh("cd spec && bundle exec rake spec")
26
+ desc "Install Gem"
27
+ task :install => :build do
28
+ sh "gem install --local vmc-#{VMC::VERSION}"
29
+ sh "rm vmc-#{VMC::VERSION}.gem"
47
30
  end
31
+
32
+ desc "Uninstall Gem"
33
+ task :uninstall do
34
+ sh "gem uninstall vmc"
35
+ end
36
+
37
+ desc "Reinstall Gem"
38
+ task :reinstall => [:uninstall, :install]
48
39
  end
data/vmc-ng/lib/vmc.rb CHANGED
@@ -2,10 +2,11 @@ require "vmc/version"
2
2
 
3
3
  require "vmc/cli"
4
4
  require "vmc/cli/start"
5
- require "vmc/cli/app"
6
5
  require "vmc/cli/service"
7
6
  require "vmc/cli/user"
8
7
  require "vmc/cli/space"
9
8
  require "vmc/cli/organization"
10
- require "vmc/cli/route"
11
- require "vmc/cli/domain"
9
+
10
+ Dir[File.expand_path("../vmc/cli/{app,route,domain}/*.rb", __FILE__)].each do |file|
11
+ require file unless File.basename(file) == 'base.rb'
12
+ end
@@ -2,10 +2,9 @@ require "yaml"
2
2
  require "socket"
3
3
  require "net/http"
4
4
  require "multi_json"
5
+ require "fileutils"
5
6
 
6
7
  require "mothership"
7
- require "mothership/pretty"
8
- require "mothership/progress"
9
8
 
10
9
  require "cfoundry"
11
10
 
@@ -23,8 +22,6 @@ module VMC
23
22
  class CLI < Mothership
24
23
  include VMC::Interactive
25
24
  include VMC::Spacing
26
- include Mothership::Pretty
27
- include Mothership::Progress
28
25
 
29
26
  option :help, :alias => "-h", :type => :boolean,
30
27
  :desc => "Show command usage & instructions"
@@ -148,7 +145,11 @@ module VMC
148
145
  msg = e.class.name
149
146
  msg << ": #{e}" unless e.to_s.empty?
150
147
 
151
- File.open(File.expand_path(VMC::CRASH_FILE), "w") do |f|
148
+ crash_file = File.expand_path(VMC::CRASH_FILE)
149
+
150
+ FileUtils.mkdir_p(File.dirname(crash_file))
151
+
152
+ File.open(crash_file, "w") do |f|
152
153
  f.puts "Time of crash:"
153
154
  f.puts " #{Time.now}"
154
155
  f.puts ""
@@ -260,7 +261,7 @@ module VMC
260
261
  return exp if File.exist? exp
261
262
  end
262
263
 
263
- paths.first
264
+ File.expand_path(paths.first)
264
265
  end
265
266
 
266
267
  def client_target
@@ -396,21 +397,21 @@ module VMC
396
397
  def find_by_name(what)
397
398
  proc { |name, choices, *_|
398
399
  choices.find { |c| c.name == name } ||
399
- fail("Unknown #{what} '#{name}'")
400
+ fail("Unknown #{what} '#{name}'.")
400
401
  }
401
402
  end
402
403
 
403
404
  def by_name(what, obj = what)
404
405
  proc { |name, *_|
405
406
  client.send(:"#{obj}_by_name", name) ||
406
- fail("Unknown #{what} '#{name}'")
407
+ fail("Unknown #{what} '#{name}'.")
407
408
  }
408
409
  end
409
410
 
410
411
  def find_by_name_insensitive(what)
411
412
  proc { |name, choices|
412
413
  choices.find { |c| c.name.upcase == name.upcase } ||
413
- fail("Unknown #{what} '#{name}'")
414
+ fail("Unknown #{what} '#{name}'.")
414
415
  }
415
416
  end
416
417
  end
@@ -0,0 +1,45 @@
1
+ require "vmc/cli/app/base"
2
+
3
+ module VMC::App
4
+ class Apps < Base
5
+ IS_UTF8 = !!(ENV["LC_ALL"] || ENV["LC_CTYPE"] || ENV["LANG"] || "")["UTF-8"].freeze
6
+
7
+ desc "Show app information"
8
+ group :apps
9
+ input :app, :argument => :required, :from_given => by_name("app"),
10
+ :desc => "App to show"
11
+ def app
12
+ app = input[:app]
13
+
14
+ if quiet?
15
+ line app.name
16
+ else
17
+ display_app(app)
18
+ end
19
+ end
20
+
21
+ def display_app(a)
22
+ status = app_status(a)
23
+
24
+ line "#{c(a.name, :name)}: #{status}"
25
+
26
+ indented do
27
+ line "platform: #{b(a.framework.name)} on #{b(a.runtime.name)}"
28
+
29
+ start_line "usage: #{b(human_mb(a.memory))}"
30
+ print " #{d(IS_UTF8 ? "\xc3\x97" : "x")} #{b(a.total_instances)}"
31
+ print " instance#{a.total_instances == 1 ? "" : "s"}"
32
+
33
+ line
34
+
35
+ unless a.urls.empty?
36
+ line "urls: #{a.urls.collect { |u| b(u) }.join(", ")}"
37
+ end
38
+
39
+ unless a.services.empty?
40
+ line "services: #{a.services.collect { |s| b(s.name) }.join(", ")}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,97 @@
1
+ require "vmc/cli/app/base"
2
+
3
+ module VMC::App
4
+ class Apps < Base
5
+ desc "List your applications"
6
+ group :apps
7
+ input :space, :from_given => by_name("space"),
8
+ :default => proc { client.current_space },
9
+ :desc => "Show apps in given space"
10
+ input :name, :desc => "Filter by name regexp"
11
+ input :runtime, :desc => "Filter by runtime regexp"
12
+ input :framework, :desc => "Filter by framework regexp"
13
+ input :url, :desc => "Filter by url regexp"
14
+ input :full, :type => :boolean, :default => false,
15
+ :desc => "Verbose output format"
16
+ def apps
17
+ if space = input[:space]
18
+ space.summarize! rescue CFoundry::APIError
19
+
20
+ apps =
21
+ with_progress("Getting applications in #{c(space.name, :name)}") do
22
+ space.apps
23
+ end
24
+ else
25
+ apps =
26
+ with_progress("Getting applications") do
27
+ client.apps(:depth => 2)
28
+ end
29
+ end
30
+
31
+ line unless quiet?
32
+
33
+ if apps.empty? and !quiet?
34
+ line "No applications."
35
+ return
36
+ end
37
+
38
+ apps.reject! do |a|
39
+ !app_matches?(a, input)
40
+ end
41
+
42
+ apps = apps.sort_by(&:name)
43
+
44
+ if input[:full]
45
+ spaced(apps) do |a|
46
+ invoke :app, :app => a
47
+ end
48
+ elsif quiet?
49
+ apps.each do |a|
50
+ line a.name
51
+ end
52
+ else
53
+ display_apps_table(apps)
54
+ end
55
+ end
56
+
57
+ def display_apps_table(apps)
58
+ table(
59
+ ["name", "status", "usage", v2? && "plan", "runtime", "url"],
60
+ apps.collect { |a|
61
+ [ c(a.name, :name),
62
+ app_status(a),
63
+ "#{a.total_instances} x #{human_mb(a.memory)}",
64
+ v2? && (a.production ? "prod" : "dev"),
65
+ a.runtime.name,
66
+ if a.urls.empty?
67
+ d("none")
68
+ elsif a.urls.size == 1
69
+ a.url
70
+ else
71
+ "#{a.url}, ..."
72
+ end
73
+ ]
74
+ })
75
+ end
76
+
77
+ def app_matches?(a, options)
78
+ if name = options[:name]
79
+ return false if a.name !~ /#{name}/
80
+ end
81
+
82
+ if runtime = options[:runtime]
83
+ return false if a.runtime.name !~ /#{runtime}/
84
+ end
85
+
86
+ if framework = options[:framework]
87
+ return false if a.framework.name !~ /#{framework}/
88
+ end
89
+
90
+ if url = options[:url]
91
+ return false if a.urls.none? { |u| u =~ /#{url}/ }
92
+ end
93
+
94
+ true
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,82 @@
1
+ require "vmc/cli"
2
+
3
+ module VMC
4
+ module App
5
+ class Base < CLI
6
+ # choose the right color for app/instance state
7
+ def state_color(s)
8
+ case s
9
+ when "STARTING"
10
+ :neutral
11
+ when "STARTED", "RUNNING"
12
+ :good
13
+ when "DOWN"
14
+ :bad
15
+ when "FLAPPING"
16
+ :error
17
+ when "N/A"
18
+ :unknown
19
+ else
20
+ :warning
21
+ end
22
+ end
23
+
24
+ def app_status(a)
25
+ health = a.health
26
+
27
+ if a.debug_mode == "suspend" && health == "0%"
28
+ c("suspended", :neutral)
29
+ else
30
+ c(health.downcase, state_color(health))
31
+ end
32
+ end
33
+
34
+ def memory_choices(exclude = 0)
35
+ info = client.info
36
+ used = info[:usage][:memory]
37
+ limit = info[:limits][:memory]
38
+ available = limit - used + exclude
39
+
40
+ mem = 64
41
+ choices = []
42
+ until mem > available
43
+ choices << human_mb(mem)
44
+ mem *= 2
45
+ end
46
+
47
+ choices
48
+ end
49
+
50
+ def human_mb(num)
51
+ human_size(num * 1024 * 1024, 0)
52
+ end
53
+
54
+ def human_size(num, precision = 1)
55
+ sizes = ["G", "M", "K"]
56
+ sizes.each.with_index do |suf, i|
57
+ pow = sizes.size - i
58
+ unit = 1024 ** pow
59
+ if num >= unit
60
+ return format("%.#{precision}f%s", num / unit, suf)
61
+ end
62
+ end
63
+
64
+ format("%.#{precision}fB", num)
65
+ end
66
+
67
+ def megabytes(str)
68
+ if str =~ /T$/i
69
+ str.to_i * 1024 * 1024
70
+ elsif str =~ /G$/i
71
+ str.to_i * 1024
72
+ elsif str =~ /M$/i
73
+ str.to_i
74
+ elsif str =~ /K$/i
75
+ str.to_i / 1024
76
+ else # assume megabytes
77
+ str.to_i
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
1
+ require "vmc/cli/app/base"
2
+
3
+ module VMC::App
4
+ class Crashes < Base
5
+ desc "List an app's crashed instances"
6
+ group :apps, :info, :hidden => true
7
+ input :apps, :argument => :splat, :singular => :app,
8
+ :desc => "Applications whose crashed instances to list",
9
+ :from_given => by_name("app")
10
+ def crashes
11
+ apps = input[:apps]
12
+ fail "No applications given." if apps.empty?
13
+
14
+ spaced(apps) do |app|
15
+ instances =
16
+ with_progress("Getting crashed instances for #{c(app.name, :name)}") do
17
+ app.crashes
18
+ end
19
+
20
+ spaced(instances) do |i|
21
+ if quiet?
22
+ line i.id
23
+ else
24
+ display_crashed_instance(i)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def display_crashed_instance(i)
31
+ start_line "instance #{c("\##{i.id}", :instance)}: "
32
+ puts "#{b(c("crashed", :error))} "
33
+
34
+ indented do
35
+ if s = i.since
36
+ line "since: #{c(s.strftime("%F %r"), :neutral)}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,90 @@
1
+ require "set"
2
+
3
+ require "vmc/cli/app/base"
4
+
5
+ module VMC::App
6
+ class Delete < Base
7
+ desc "Delete an application"
8
+ group :apps, :manage
9
+ input(:apps, :argument => :splat, :singular => :app,
10
+ :desc => "Applications to delete",
11
+ :from_given => by_name("app")) {
12
+ apps = client.apps
13
+ fail "No applications." if apps.empty?
14
+
15
+ [ask("Delete which application?", :choices => apps.sort_by(&:name),
16
+ :display => proc(&:name))]
17
+ }
18
+ input(:really, :type => :boolean, :forget => true,
19
+ :default => proc { force? || interact }) { |name, color|
20
+ ask("Really delete #{c(name, color)}?", :default => false)
21
+ }
22
+ input :routes, :type => :boolean, :default => false,
23
+ :desc => "Delete associated routes"
24
+ input :orphaned, :aliases => "-o", :type => :boolean,
25
+ :desc => "Delete orphaned instances"
26
+ input :all, :type => :boolean, :default => false,
27
+ :desc => "Delete all applications"
28
+ def delete
29
+ apps = client.apps
30
+
31
+ if input[:all]
32
+ return unless input[:really, "ALL APPS", :bad]
33
+
34
+ to_delete = apps
35
+ others = []
36
+ else
37
+ to_delete = input[:apps]
38
+ others = apps - to_delete
39
+ end
40
+
41
+ orphaned = find_orphaned_services(to_delete, others)
42
+
43
+ deleted = []
44
+ spaced(to_delete) do |app|
45
+ really = input[:all] || input[:really, app.name, :name]
46
+ next unless really
47
+
48
+ deleted << app
49
+
50
+ with_progress("Deleting #{c(app.name, :name)}") do
51
+ app.routes.collect(&:delete!) if input[:routes]
52
+ app.delete!
53
+ end
54
+ end
55
+
56
+ delete_orphaned_services(orphaned, input[:orphaned])
57
+
58
+ to_delete
59
+ end
60
+
61
+ def find_orphaned_services(apps, others = [])
62
+ orphaned = Set.new
63
+
64
+ apps.each do |a|
65
+ a.services.each do |i|
66
+ if others.none? { |x| x.binds?(i) }
67
+ orphaned << i
68
+ end
69
+ end
70
+ end
71
+
72
+ orphaned.each(&:invalidate!)
73
+ end
74
+
75
+ def delete_orphaned_services(instances, orphaned)
76
+ return if instances.empty?
77
+
78
+ line unless quiet? || force?
79
+
80
+ instances.select { |i|
81
+ orphaned ||
82
+ ask("Delete orphaned service instance #{c(i.name, :name)}?",
83
+ :default => false)
84
+ }.each do |instance|
85
+ # TODO: splat
86
+ invoke :delete_service, :instance => instance, :really => true
87
+ end
88
+ end
89
+ end
90
+ end