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

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 (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