jdc 0.2.1 → 0.2.2.pre

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 (151) hide show
  1. data/LICENSE +1277 -24
  2. data/Rakefile +13 -0
  3. data/bin/jdc +12 -2
  4. data/lib/admin/README.md +15 -0
  5. data/lib/admin/curl.rb +60 -0
  6. data/lib/admin/guid.rb +89 -0
  7. data/lib/admin/plugin.rb +6 -0
  8. data/lib/admin/service_auth_token.rb +94 -0
  9. data/lib/admin/service_broker/add.rb +47 -0
  10. data/lib/admin/service_broker/service_brokers.rb +24 -0
  11. data/lib/admin/set_quota.rb +44 -0
  12. data/lib/console/README.md +8 -0
  13. data/lib/console/console.rb +187 -0
  14. data/lib/console/plugin.rb +33 -0
  15. data/lib/jdc.rb +15 -2
  16. data/lib/jdc/cli.rb +556 -0
  17. data/lib/jdc/cli/app/app.rb +43 -0
  18. data/lib/jdc/cli/app/apps.rb +87 -0
  19. data/lib/jdc/cli/app/base.rb +72 -0
  20. data/lib/jdc/cli/app/delete.rb +95 -0
  21. data/lib/jdc/cli/app/deprecated.rb +11 -0
  22. data/lib/jdc/cli/app/env.rb +78 -0
  23. data/lib/jdc/cli/app/events.rb +45 -0
  24. data/lib/jdc/cli/app/files.rb +137 -0
  25. data/lib/jdc/cli/app/health.rb +26 -0
  26. data/lib/jdc/cli/app/instances.rb +53 -0
  27. data/lib/jdc/cli/app/logs.rb +76 -0
  28. data/lib/jdc/cli/app/push.rb +103 -0
  29. data/lib/jdc/cli/app/push/create.rb +108 -0
  30. data/lib/jdc/cli/app/push/interactions.rb +86 -0
  31. data/lib/jdc/cli/app/push/sync.rb +57 -0
  32. data/lib/jdc/cli/app/rename.rb +35 -0
  33. data/lib/jdc/cli/app/restart.rb +31 -0
  34. data/lib/jdc/cli/app/scale.rb +63 -0
  35. data/lib/jdc/cli/app/start.rb +161 -0
  36. data/lib/jdc/cli/app/stats.rb +67 -0
  37. data/lib/jdc/cli/app/stop.rb +27 -0
  38. data/lib/jdc/cli/domain/base.rb +9 -0
  39. data/lib/jdc/cli/domain/domains.rb +40 -0
  40. data/lib/jdc/cli/domain/map.rb +55 -0
  41. data/lib/jdc/cli/domain/unmap.rb +56 -0
  42. data/lib/jdc/cli/help.rb +15 -0
  43. data/lib/jdc/cli/interactive.rb +105 -0
  44. data/lib/jdc/cli/login_requirements.rb +15 -0
  45. data/lib/jdc/cli/organization/base.rb +14 -0
  46. data/lib/jdc/cli/organization/create.rb +37 -0
  47. data/lib/jdc/cli/organization/delete.rb +63 -0
  48. data/lib/jdc/cli/organization/org.rb +45 -0
  49. data/lib/jdc/cli/organization/orgs.rb +30 -0
  50. data/lib/jdc/cli/organization/rename.rb +37 -0
  51. data/lib/jdc/cli/populators/base.rb +16 -0
  52. data/lib/jdc/cli/populators/organization.rb +32 -0
  53. data/lib/jdc/cli/populators/populator_methods.rb +64 -0
  54. data/lib/jdc/cli/populators/space.rb +33 -0
  55. data/lib/jdc/cli/populators/target.rb +13 -0
  56. data/lib/jdc/cli/route/base.rb +9 -0
  57. data/lib/jdc/cli/route/delete.rb +28 -0
  58. data/lib/jdc/cli/route/map.rb +68 -0
  59. data/lib/jdc/cli/route/routes.rb +26 -0
  60. data/lib/jdc/cli/route/unmap.rb +56 -0
  61. data/lib/jdc/cli/service/base.rb +9 -0
  62. data/lib/jdc/cli/service/bind.rb +44 -0
  63. data/lib/jdc/cli/service/create.rb +159 -0
  64. data/lib/jdc/cli/service/delete.rb +83 -0
  65. data/lib/jdc/cli/service/rename.rb +36 -0
  66. data/lib/jdc/cli/service/service.rb +42 -0
  67. data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
  68. data/lib/jdc/cli/service/services.rb +111 -0
  69. data/lib/jdc/cli/service/unbind.rb +37 -0
  70. data/lib/jdc/cli/space/base.rb +29 -0
  71. data/lib/jdc/cli/space/create.rb +67 -0
  72. data/lib/jdc/cli/space/delete.rb +56 -0
  73. data/lib/jdc/cli/space/rename.rb +38 -0
  74. data/lib/jdc/cli/space/space.rb +66 -0
  75. data/lib/jdc/cli/space/spaces.rb +57 -0
  76. data/lib/jdc/cli/space/switch.rb +19 -0
  77. data/lib/jdc/cli/start/base.rb +41 -0
  78. data/lib/jdc/cli/start/colors.rb +13 -0
  79. data/lib/jdc/cli/start/target.rb +50 -0
  80. data/lib/jdc/cli/start/target_prettifier.rb +17 -0
  81. data/lib/jdc/cli/start/targets.rb +16 -0
  82. data/lib/jdc/cli/user/base.rb +30 -0
  83. data/lib/jdc/cli/user/create.rb +52 -0
  84. data/lib/jdc/cli/user/passwd.rb +37 -0
  85. data/lib/jdc/cli/user/register.rb +43 -0
  86. data/lib/jdc/cli/user/users.rb +32 -0
  87. data/lib/jdc/constants.rb +11 -0
  88. data/lib/jdc/errors.rb +19 -0
  89. data/lib/jdc/object_extensions.rb +15 -0
  90. data/lib/jdc/plugin.rb +56 -0
  91. data/lib/jdc/spacing.rb +89 -0
  92. data/lib/jdc/spec_helper.rb +1 -0
  93. data/lib/jdc/test_support.rb +6 -0
  94. data/lib/jdc/version.rb +3 -0
  95. data/lib/manifests/errors.rb +35 -0
  96. data/lib/manifests/loader.rb +31 -0
  97. data/lib/manifests/loader/builder.rb +39 -0
  98. data/lib/manifests/loader/normalizer.rb +145 -0
  99. data/lib/manifests/loader/resolver.rb +79 -0
  100. data/lib/manifests/manifests.rb +344 -0
  101. data/lib/manifests/plugin.rb +140 -0
  102. data/lib/micro/README.md +9 -0
  103. data/lib/micro/errors.rb +4 -0
  104. data/lib/{jdc → micro}/micro.rb +15 -15
  105. data/lib/micro/plugin.rb +197 -0
  106. data/lib/micro/switcher/base.rb +79 -0
  107. data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
  108. data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
  109. data/lib/micro/switcher/linux.rb +16 -0
  110. data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
  111. data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
  112. data/lib/tasks/gem_release.rake +42 -0
  113. data/lib/tunnel/README.md +29 -0
  114. data/{config → lib/tunnel/config}/clients.yml +2 -2
  115. data/lib/tunnel/helper-app/Gemfile +10 -0
  116. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  117. data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
  118. data/lib/tunnel/plugin.rb +183 -0
  119. data/lib/tunnel/tunnel.rb +295 -0
  120. metadata +371 -210
  121. data/README.md +0 -102
  122. data/config/micro/paths.yml +0 -22
  123. data/config/micro/refresh_ip.rb +0 -20
  124. data/lib/cli.rb +0 -53
  125. data/lib/cli/commands/admin.rb +0 -58
  126. data/lib/cli/commands/apps.rb +0 -1129
  127. data/lib/cli/commands/base.rb +0 -228
  128. data/lib/cli/commands/manifest.rb +0 -56
  129. data/lib/cli/commands/micro.rb +0 -115
  130. data/lib/cli/commands/misc.rb +0 -126
  131. data/lib/cli/commands/services.rb +0 -178
  132. data/lib/cli/commands/user.rb +0 -14
  133. data/lib/cli/config.rb +0 -173
  134. data/lib/cli/console_helper.rb +0 -170
  135. data/lib/cli/core_ext.rb +0 -122
  136. data/lib/cli/errors.rb +0 -19
  137. data/lib/cli/frameworks.rb +0 -265
  138. data/lib/cli/manifest_helper.rb +0 -300
  139. data/lib/cli/runner.rb +0 -505
  140. data/lib/cli/services_helper.rb +0 -84
  141. data/lib/cli/tunnel_helper.rb +0 -332
  142. data/lib/cli/usage.rb +0 -86
  143. data/lib/cli/version.rb +0 -7
  144. data/lib/cli/zip_util.rb +0 -77
  145. data/lib/jdc/client.rb +0 -457
  146. data/lib/jdc/const.rb +0 -25
  147. data/lib/jdc/micro/switcher/base.rb +0 -97
  148. data/lib/jdc/micro/switcher/linux.rb +0 -16
  149. data/lib/jdc/signature/version.rb +0 -27
  150. data/lib/jdc/signer.rb +0 -13
  151. data/lib/jdc/timer.rb +0 -12
@@ -0,0 +1,26 @@
1
+ require "jdc/cli/app/base"
2
+
3
+ module JDC::App
4
+ class Health < Base
5
+ desc "Get application health"
6
+ group :apps, :info
7
+ input :apps, :desc => "Show the health information for one or more applications", :argument => :splat,
8
+ :singular => :app, :from_given => by_name(:app)
9
+ def health
10
+ apps = input[:apps]
11
+ fail "No applications given." if apps.empty?
12
+
13
+ health =
14
+ with_progress("Getting health status") do
15
+ apps.collect { |a| [a, app_status(a)] }
16
+ end
17
+
18
+ line unless quiet?
19
+
20
+ spaced(health) do |app, status|
21
+ start_line "#{c(app.name, :name)}: " unless quiet?
22
+ puts status
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ require "jdc/cli/app/base"
2
+
3
+ module JDC::App
4
+ class Instances < Base
5
+ desc "List an app's instances"
6
+ group :apps, :info
7
+ input :apps, :desc => "Applications whose instances to list",
8
+ :argument => :splat, :singular => :app,
9
+ :from_given => by_name(:app)
10
+ def instances
11
+ apps = input[:apps]
12
+ fail "No applications given." if apps.empty?
13
+
14
+ spaced(apps) do |app|
15
+ instances =
16
+ with_progress("Getting instances for #{c(app.name, :name)}") do
17
+ app.instances
18
+ end
19
+
20
+ line unless quiet?
21
+
22
+ spaced(instances.sort { |a, b| a.id.to_i <=> b.id.to_i }) do |i|
23
+ if quiet?
24
+ line i.id
25
+ else
26
+ display_instance(i)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def display_instance(i)
35
+ start_line "instance #{c("\##{i.id}", :instance)}: "
36
+ puts "#{b(c(i.state.downcase, state_color(i.state)))}"
37
+
38
+ indented do
39
+ if s = i.since
40
+ line "started: #{c(s.strftime("%F %r"), :neutral)}"
41
+ end
42
+
43
+ if d = i.debugger
44
+ line "debugger: port #{b(d[:port])} at #{b(d[:ip])}"
45
+ end
46
+
47
+ if c = i.console
48
+ line "console: port #{b(c[:port])} at #{b(c[:ip])}"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,76 @@
1
+ require "jdc/cli/app/base"
2
+
3
+ module JDC::App
4
+ class Logs < Base
5
+ desc "Print out an app's logs"
6
+ group :apps, :info
7
+ input :app, :desc => "Application to get the logs of", :argument => true,
8
+ :from_given => by_name(:app)
9
+ input :instance, :desc => "Instance of application to get the logs of",
10
+ :default => "0"
11
+ input :all, :desc => "Get logs for every instance", :default => false
12
+ def logs
13
+ app = input[:app]
14
+
15
+ instances =
16
+ if input[:all] || input[:instance] == "all"
17
+ app.instances
18
+ else
19
+ app.instances.select { |i| i.id == input[:instance] }
20
+ end
21
+
22
+ if instances.empty?
23
+ if input[:all]
24
+ fail "No instances found."
25
+ else
26
+ fail "Instance #{app.name} \##{input[:instance]} not found."
27
+ end
28
+ end
29
+
30
+ spaced(instances) do |i|
31
+ show_instance_logs(app, i)
32
+ end
33
+ end
34
+
35
+ desc "Print out the logs for an app's crashed instances"
36
+ group :apps, :info
37
+ input :app, :desc => "Application to get the logs of", :argument => true,
38
+ :from_given => by_name(:app)
39
+ def crashlogs
40
+ app = input[:app]
41
+
42
+ crashes = app.crashes
43
+
44
+ fail "No crashed instances found." if crashes.empty?
45
+
46
+ most_recent = crashes.sort_by(&:since).last
47
+ show_instance_logs(app, most_recent)
48
+ end
49
+
50
+ def show_instance_logs(app, i)
51
+ return unless i.id
52
+
53
+ logs =
54
+ with_progress(
55
+ "Getting logs for #{c(app.name, :name)} " +
56
+ c("\##{i.id}", :instance)) do
57
+ i.files("logs")
58
+ end
59
+
60
+ line unless quiet?
61
+
62
+ spaced(logs) do |log|
63
+ begin
64
+ body =
65
+ with_progress("Reading " + b(log.join("/"))) do |s|
66
+ i.file(*log)
67
+ end
68
+
69
+ lines body
70
+ line unless body.empty?
71
+ rescue JFoundry::NotFound
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,103 @@
1
+ require "jdc/cli/app/base"
2
+ require "jdc/cli/app/push/sync"
3
+ require "jdc/cli/app/push/create"
4
+ require "jdc/cli/app/push/interactions"
5
+
6
+ module JDC::App
7
+ class Push < Base
8
+ include Sync
9
+ include Create
10
+
11
+ desc "Push an application, syncing changes if it exists"
12
+ group :apps, :manage
13
+ input :name, :desc => "Application name", :argument => :optional
14
+ input :path, :desc => "Path containing the bits", :default => "."
15
+ input :host, :desc => "Subdomain for the app's URL"
16
+ input :domain, :desc => "Domain for the app",
17
+ :from_given => proc { |given, app|
18
+ if given == "none"
19
+ given
20
+ else
21
+ app.space.domain_by_name(given) ||
22
+ fail_unknown("domain", given)
23
+ end
24
+ }
25
+ input :memory, :desc => "Memory limit"
26
+ input :instances, :desc => "Number of instances to run", :type => :integer
27
+ input :command, :desc => "Startup command", :default => nil
28
+ input :plan, :desc => "Application plan"
29
+ input :start, :desc => "Start app after pushing?", :default => true
30
+ input :restart, :desc => "Restart app after updating?", :default => true
31
+ input :buildpack, :desc => "Custom buildpack URL", :default => nil
32
+ input :stack, :desc => "Stack to use", :default => nil,
33
+ :from_given => by_name(:stack)
34
+ input :create_services, :desc => "Interactively create services?",
35
+ :type => :boolean, :default => proc { force? ? false : interact }
36
+ input :bind_services, :desc => "Interactively bind services?",
37
+ :type => :boolean, :default => proc { force? ? false : interact }
38
+ interactions PushInteractions
39
+
40
+ def push
41
+ name = input[:name]
42
+ path = File.expand_path(input[:path])
43
+ app = client.app_by_name(name)
44
+
45
+ if app
46
+ sync_app(app, path)
47
+ else
48
+ setup_new_app(path)
49
+ end
50
+ end
51
+
52
+ def sync_app(app, path)
53
+ upload_app(app, path)
54
+ apply_changes(app)
55
+ display_changes(app)
56
+ commit_changes(app)
57
+
58
+ warn "\n#{c(app.name, :name)} is currently stopped, start it with 'jdc start'" unless app.started?
59
+ end
60
+
61
+ def setup_new_app(path)
62
+ self.path = path
63
+ app = create_app(get_inputs)
64
+ map_route(app)
65
+ create_services(app)
66
+ bind_services(app)
67
+ upload_app(app, path)
68
+ start_app(app)
69
+ end
70
+
71
+ private
72
+
73
+ def url_choices(name)
74
+ client.current_space.domains.sort_by(&:name).collect do |d|
75
+ # TODO: check availability
76
+ "#{name}.#{d.name}"
77
+ end
78
+ end
79
+
80
+ def upload_app(app, path)
81
+ app = filter(:push_app, app)
82
+
83
+ with_progress("Uploading #{c(app.name, :name)}") do
84
+ app.upload(path)
85
+ end
86
+ rescue
87
+ err "Upload failed. Try again with 'jdc push'."
88
+ raise
89
+ end
90
+
91
+ def wrap_message_format_errors
92
+ yield
93
+ rescue JFoundry::MessageParseError => e
94
+ md = e.description.match /Field: ([^,]+)/
95
+ field = md[1]
96
+
97
+ case field
98
+ when "buildpack"
99
+ fail "Buildpack must be a public git repository URI."
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,108 @@
1
+ module JDC::App
2
+ module Create
3
+ attr_accessor :input
4
+ attr_writer :path
5
+
6
+ def get_inputs
7
+ inputs = {}
8
+ inputs[:name] = input[:name]
9
+ inputs[:total_instances] = input[:instances]
10
+ inputs[:space] = client.current_space if client.current_space
11
+
12
+ inputs[:buildpack] = input[:buildpack]
13
+ inputs[:command] = input[:command] if input.has?(:command) || !has_procfile?
14
+
15
+ inputs[:memory] = megabytes(input[:memory, human_mb(256)])
16
+ inputs[:stack] = input[:stack]
17
+
18
+ inputs
19
+ end
20
+
21
+ def create_app(inputs)
22
+ app = client.app
23
+
24
+ inputs.each { |key, value| app.send(:"#{key}=", value) }
25
+ finalize
26
+
27
+ app = filter(:create_app, app)
28
+
29
+ with_progress("Creating #{c(app.name, :name)}") do
30
+ wrap_message_format_errors do
31
+ begin
32
+ app.create!
33
+ rescue JFoundry::NotAuthorized
34
+ fail "You need the Project Developer role in #{b(client.current_space.name)} to push."
35
+ end
36
+ end
37
+ end
38
+
39
+ app
40
+ end
41
+
42
+ def map_route(app)
43
+ line unless quiet?
44
+
45
+ host = input[:host, app.name]
46
+ finalize
47
+ domain = input[:domain, app]
48
+ finalize
49
+
50
+ mapped_url = false
51
+ until domain == "none" || !domain || mapped_url
52
+ begin
53
+ host = "" if host == "none"
54
+ invoke :map, :app => app, :host => host, :domain => domain
55
+ mapped_url = true
56
+ rescue JFoundry::RouteHostTaken, JFoundry::UriAlreadyTaken => e
57
+ raise if force?
58
+
59
+ line c(e.description, :bad)
60
+ line
61
+
62
+ input.forget(:host)
63
+ input.forget(:domain)
64
+
65
+ host = input[:host, app.name]
66
+ domain = input[:domain, app]
67
+ end
68
+ end
69
+ end
70
+
71
+ def create_services(app)
72
+ return unless input[:create_services]
73
+ finalize
74
+ while true
75
+ invoke :create_service, { :app => app }, :plan => :interact
76
+ break unless ask("Create another service?", :default => false)
77
+ end
78
+ end
79
+
80
+ def bind_services(app)
81
+ return unless input[:bind_services]
82
+
83
+ while true
84
+ invoke :bind_service, :app => app
85
+ break if (all_instances - app.services).empty?
86
+ break unless ask("Bind another service?", :default => false)
87
+ end
88
+ end
89
+
90
+ def start_app(app)
91
+ invoke :start, :app => app if input[:start]
92
+ end
93
+
94
+ private
95
+
96
+ def has_procfile?
97
+ File.exists?("#@path/Procfile")
98
+ end
99
+
100
+ def all_instances
101
+ @all_instances ||= client.service_instances
102
+ end
103
+
104
+ def target_base
105
+ client.target.sub(/^https?:\/\/([^\.]+\.)?(.+)\/?/, '\2')
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,86 @@
1
+ module JDC::App
2
+ module PushInteractions
3
+ def ask_name
4
+ ask("Name")
5
+ end
6
+
7
+ def ask_host(name)
8
+ ask "Subdomain", :choices => [name, "none"],
9
+ :default => name,
10
+ :allow_other => true
11
+ end
12
+
13
+ def ask_domain(app)
14
+ choices = app.space.domains
15
+
16
+ options = {
17
+ :choices => choices + ["none"],
18
+ :display => proc { |choice| choice.is_a?(String) ? choice : choice.name },
19
+ :allow_other => true
20
+ }
21
+
22
+ options[:default] = choices.first
23
+
24
+ ask "Domain", options
25
+ end
26
+
27
+ def ask_memory(default)
28
+ ask("Memory Limit",
29
+ :choices => memory_choices,
30
+ :allow_other => true,
31
+ :default => default || "128M")
32
+ end
33
+
34
+ def ask_instances
35
+ ask("Instances", :default => 1)
36
+ end
37
+
38
+ def ask_command
39
+ command = ask("Custom startup command", :default => "none")
40
+
41
+ if command != "none"
42
+ command
43
+ end
44
+ end
45
+
46
+ def ask_create_services
47
+ line unless quiet?
48
+ ask "Create services for application?", :default => false
49
+ end
50
+
51
+ def ask_bind_services
52
+ return if all_instances.empty?
53
+
54
+ ask "Bind other services to application?", :default => false
55
+ end
56
+
57
+ private
58
+
59
+ def ask_with_other(message, all, choices, default, other)
60
+ choices = choices.sort_by(&:name)
61
+ choices << other if other
62
+
63
+ opts = {
64
+ :choices => choices,
65
+ :display => proc { |x|
66
+ if other && x == other
67
+ "other"
68
+ else
69
+ x.name
70
+ end
71
+ }
72
+ }
73
+
74
+ opts[:default] = default if default
75
+
76
+ res = ask(message, opts)
77
+
78
+ if other && res == other
79
+ opts[:choices] = all
80
+ res = ask(message, opts)
81
+ end
82
+
83
+ res
84
+ end
85
+ end
86
+ end