jdc 0.2.1.pre → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/LICENSE +24 -1277
  2. data/README.md +102 -0
  3. data/bin/jdc +2 -12
  4. data/{lib/tunnel/helper-app → caldecott_helper}/server.rb +5 -5
  5. data/{lib/tunnel/config → config}/clients.yml +2 -2
  6. data/config/micro/paths.yml +22 -0
  7. data/config/micro/refresh_ip.rb +20 -0
  8. data/lib/cli/commands/admin.rb +58 -0
  9. data/lib/cli/commands/apps.rb +1129 -0
  10. data/lib/cli/commands/base.rb +228 -0
  11. data/lib/cli/commands/manifest.rb +56 -0
  12. data/lib/cli/commands/micro.rb +115 -0
  13. data/lib/cli/commands/misc.rb +126 -0
  14. data/lib/cli/commands/services.rb +178 -0
  15. data/lib/cli/commands/user.rb +14 -0
  16. data/lib/cli/config.rb +173 -0
  17. data/lib/cli/console_helper.rb +170 -0
  18. data/lib/cli/core_ext.rb +122 -0
  19. data/lib/cli/errors.rb +19 -0
  20. data/lib/cli/frameworks.rb +265 -0
  21. data/lib/cli/manifest_helper.rb +300 -0
  22. data/lib/cli/runner.rb +505 -0
  23. data/lib/cli/services_helper.rb +84 -0
  24. data/lib/cli/tunnel_helper.rb +332 -0
  25. data/lib/cli/usage.rb +86 -0
  26. data/lib/cli/version.rb +7 -0
  27. data/lib/cli/zip_util.rb +77 -0
  28. data/lib/cli.rb +53 -0
  29. data/lib/jdc/client.rb +457 -0
  30. data/lib/jdc/const.rb +25 -0
  31. data/lib/jdc/micro/switcher/base.rb +97 -0
  32. data/lib/{micro → jdc/micro}/switcher/darwin.rb +3 -5
  33. data/lib/{micro → jdc/micro}/switcher/dummy.rb +1 -1
  34. data/lib/jdc/micro/switcher/linux.rb +16 -0
  35. data/lib/{micro → jdc/micro}/switcher/windows.rb +5 -5
  36. data/lib/{micro → jdc/micro}/vmrun.rb +19 -26
  37. data/lib/{micro → jdc}/micro.rb +15 -15
  38. data/lib/jdc/signature/version.rb +27 -0
  39. data/lib/jdc/signer.rb +13 -0
  40. data/lib/jdc/timer.rb +12 -0
  41. data/lib/jdc.rb +2 -15
  42. metadata +210 -360
  43. data/Rakefile +0 -13
  44. data/lib/admin/README.md +0 -15
  45. data/lib/admin/curl.rb +0 -60
  46. data/lib/admin/guid.rb +0 -89
  47. data/lib/admin/plugin.rb +0 -6
  48. data/lib/admin/service_auth_token.rb +0 -94
  49. data/lib/admin/service_broker/add.rb +0 -47
  50. data/lib/admin/service_broker/service_brokers.rb +0 -24
  51. data/lib/admin/set_quota.rb +0 -44
  52. data/lib/console/README.md +0 -8
  53. data/lib/console/console.rb +0 -187
  54. data/lib/console/plugin.rb +0 -33
  55. data/lib/jdc/cli/app/app.rb +0 -43
  56. data/lib/jdc/cli/app/apps.rb +0 -87
  57. data/lib/jdc/cli/app/base.rb +0 -72
  58. data/lib/jdc/cli/app/delete.rb +0 -95
  59. data/lib/jdc/cli/app/deprecated.rb +0 -11
  60. data/lib/jdc/cli/app/env.rb +0 -78
  61. data/lib/jdc/cli/app/events.rb +0 -45
  62. data/lib/jdc/cli/app/files.rb +0 -137
  63. data/lib/jdc/cli/app/health.rb +0 -26
  64. data/lib/jdc/cli/app/instances.rb +0 -53
  65. data/lib/jdc/cli/app/logs.rb +0 -76
  66. data/lib/jdc/cli/app/push/create.rb +0 -108
  67. data/lib/jdc/cli/app/push/interactions.rb +0 -86
  68. data/lib/jdc/cli/app/push/sync.rb +0 -57
  69. data/lib/jdc/cli/app/push.rb +0 -103
  70. data/lib/jdc/cli/app/rename.rb +0 -35
  71. data/lib/jdc/cli/app/restart.rb +0 -31
  72. data/lib/jdc/cli/app/scale.rb +0 -63
  73. data/lib/jdc/cli/app/start.rb +0 -161
  74. data/lib/jdc/cli/app/stats.rb +0 -67
  75. data/lib/jdc/cli/app/stop.rb +0 -27
  76. data/lib/jdc/cli/domain/base.rb +0 -9
  77. data/lib/jdc/cli/domain/domains.rb +0 -40
  78. data/lib/jdc/cli/domain/map.rb +0 -55
  79. data/lib/jdc/cli/domain/unmap.rb +0 -56
  80. data/lib/jdc/cli/help.rb +0 -15
  81. data/lib/jdc/cli/interactive.rb +0 -105
  82. data/lib/jdc/cli/login_requirements.rb +0 -15
  83. data/lib/jdc/cli/organization/base.rb +0 -14
  84. data/lib/jdc/cli/organization/create.rb +0 -37
  85. data/lib/jdc/cli/organization/delete.rb +0 -63
  86. data/lib/jdc/cli/organization/org.rb +0 -45
  87. data/lib/jdc/cli/organization/orgs.rb +0 -30
  88. data/lib/jdc/cli/organization/rename.rb +0 -37
  89. data/lib/jdc/cli/populators/base.rb +0 -16
  90. data/lib/jdc/cli/populators/organization.rb +0 -32
  91. data/lib/jdc/cli/populators/populator_methods.rb +0 -64
  92. data/lib/jdc/cli/populators/space.rb +0 -33
  93. data/lib/jdc/cli/populators/target.rb +0 -13
  94. data/lib/jdc/cli/route/base.rb +0 -9
  95. data/lib/jdc/cli/route/delete.rb +0 -28
  96. data/lib/jdc/cli/route/map.rb +0 -68
  97. data/lib/jdc/cli/route/routes.rb +0 -26
  98. data/lib/jdc/cli/route/unmap.rb +0 -56
  99. data/lib/jdc/cli/service/base.rb +0 -9
  100. data/lib/jdc/cli/service/bind.rb +0 -44
  101. data/lib/jdc/cli/service/create.rb +0 -159
  102. data/lib/jdc/cli/service/delete.rb +0 -83
  103. data/lib/jdc/cli/service/rename.rb +0 -36
  104. data/lib/jdc/cli/service/service.rb +0 -42
  105. data/lib/jdc/cli/service/service_instance_helper.rb +0 -99
  106. data/lib/jdc/cli/service/services.rb +0 -111
  107. data/lib/jdc/cli/service/unbind.rb +0 -37
  108. data/lib/jdc/cli/space/base.rb +0 -29
  109. data/lib/jdc/cli/space/create.rb +0 -67
  110. data/lib/jdc/cli/space/delete.rb +0 -56
  111. data/lib/jdc/cli/space/rename.rb +0 -38
  112. data/lib/jdc/cli/space/space.rb +0 -66
  113. data/lib/jdc/cli/space/spaces.rb +0 -57
  114. data/lib/jdc/cli/space/switch.rb +0 -19
  115. data/lib/jdc/cli/start/base.rb +0 -41
  116. data/lib/jdc/cli/start/colors.rb +0 -13
  117. data/lib/jdc/cli/start/target.rb +0 -50
  118. data/lib/jdc/cli/start/target_prettifier.rb +0 -17
  119. data/lib/jdc/cli/start/targets.rb +0 -16
  120. data/lib/jdc/cli/user/base.rb +0 -30
  121. data/lib/jdc/cli/user/create.rb +0 -52
  122. data/lib/jdc/cli/user/passwd.rb +0 -37
  123. data/lib/jdc/cli/user/register.rb +0 -43
  124. data/lib/jdc/cli/user/users.rb +0 -32
  125. data/lib/jdc/cli.rb +0 -556
  126. data/lib/jdc/constants.rb +0 -11
  127. data/lib/jdc/errors.rb +0 -19
  128. data/lib/jdc/object_extensions.rb +0 -15
  129. data/lib/jdc/plugin.rb +0 -56
  130. data/lib/jdc/spacing.rb +0 -89
  131. data/lib/jdc/spec_helper.rb +0 -1
  132. data/lib/jdc/test_support.rb +0 -6
  133. data/lib/jdc/version.rb +0 -3
  134. data/lib/manifests/errors.rb +0 -35
  135. data/lib/manifests/loader/builder.rb +0 -39
  136. data/lib/manifests/loader/normalizer.rb +0 -145
  137. data/lib/manifests/loader/resolver.rb +0 -79
  138. data/lib/manifests/loader.rb +0 -31
  139. data/lib/manifests/manifests.rb +0 -344
  140. data/lib/manifests/plugin.rb +0 -140
  141. data/lib/micro/README.md +0 -9
  142. data/lib/micro/errors.rb +0 -4
  143. data/lib/micro/plugin.rb +0 -197
  144. data/lib/micro/switcher/base.rb +0 -79
  145. data/lib/micro/switcher/linux.rb +0 -16
  146. data/lib/tasks/gem_release.rake +0 -42
  147. data/lib/tunnel/README.md +0 -29
  148. data/lib/tunnel/helper-app/Gemfile +0 -10
  149. data/lib/tunnel/helper-app/Gemfile.lock +0 -48
  150. data/lib/tunnel/plugin.rb +0 -183
  151. data/lib/tunnel/tunnel.rb +0 -295
@@ -0,0 +1,265 @@
1
+ module JDC::Cli
2
+
3
+ class Framework
4
+
5
+ DEFAULT_FRAMEWORK = "http://b20nine.com/unknown"
6
+ DEFAULT_MEM = '256M'
7
+
8
+ FRAMEWORKS = {
9
+ 'Rails' => ['rails3', { :mem => '256M', :description => 'Rails Application', :console=>true}],
10
+ 'Spring' => ['spring', { :mem => '512M', :description => 'Java SpringSource Spring Application'}],
11
+ 'Grails' => ['grails', { :mem => '512M', :description => 'Java SpringSource Grails Application'}],
12
+ 'Lift' => ['lift', { :mem => '512M', :description => 'Scala Lift Application'}],
13
+ 'JavaWeb' => ['java_web',{ :mem => '512M', :description => 'Java Web Application'}],
14
+ 'Standalone' => ['standalone', { :mem => '64M', :description => 'Standalone Application'}],
15
+ 'Sinatra' => ['sinatra', { :mem => '128M', :description => 'Sinatra Application'}],
16
+ 'Node' => ['node', { :mem => '64M', :description => 'Node.js Application'}],
17
+ 'PHP' => ['php', { :mem => '128M', :description => 'PHP Application'}],
18
+ 'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}],
19
+ 'WSGI' => ['wsgi', { :mem => '64M', :description => 'Python WSGI Application'}],
20
+ 'Django' => ['django', { :mem => '128M', :description => 'Python Django Application'}],
21
+ 'dotNet' => ['dotNet', { :mem => '128M', :description => '.Net Web Application'}],
22
+ 'Rack' => ['rack', { :mem => '128M', :description => 'Rack Application'}],
23
+ 'Play' => ['play', { :mem => '256M', :description => 'Play Framework Application'}]
24
+ }
25
+
26
+ class << self
27
+
28
+ def known_frameworks(available_frameworks)
29
+ frameworks = []
30
+ FRAMEWORKS.each do |key,fw|
31
+ frameworks << key if available_frameworks.include? [fw[0]]
32
+ end
33
+ frameworks
34
+ end
35
+
36
+ def lookup(name)
37
+ return create(*FRAMEWORKS[name])
38
+ end
39
+
40
+ def lookup_by_framework(name)
41
+ FRAMEWORKS.each do |key,fw|
42
+ return create(fw[0],fw[1]) if fw[0] == name
43
+ end
44
+ end
45
+
46
+ def create(name,opts)
47
+ if name == "standalone"
48
+ return StandaloneFramework.new(name, opts)
49
+ else
50
+ return Framework.new(name,opts)
51
+ end
52
+ end
53
+
54
+ def detect(path, available_frameworks)
55
+ if !File.directory? path
56
+ if path.end_with?('.war')
57
+ return detect_framework_from_war path
58
+ elsif path.end_with?('.zip')
59
+ return detect_framework_from_zip path, available_frameworks
60
+ elsif available_frameworks.include?(["standalone"])
61
+ return Framework.lookup('Standalone')
62
+ else
63
+ return nil
64
+ end
65
+ end
66
+ Dir.chdir(path) do
67
+ # Rails
68
+ if File.exist?('config/environment.rb')
69
+ return Framework.lookup('Rails')
70
+
71
+ # Rack
72
+ elsif File.exist?('config.ru') && available_frameworks.include?(["rack"])
73
+ return Framework.lookup('Rack')
74
+
75
+ # Java Web Apps
76
+ elsif Dir.glob('*.war').first
77
+ return detect_framework_from_war(Dir.glob('*.war').first)
78
+
79
+ elsif File.exist?('WEB-INF/web.xml')
80
+ return detect_framework_from_war
81
+
82
+ # Simple Ruby Apps
83
+ elsif !Dir.glob('*.rb').empty?
84
+ matched_file = nil
85
+ Dir.glob('*.rb').each do |fname|
86
+ next if matched_file
87
+ File.open(fname, 'r') do |f|
88
+ str = f.read # This might want to be limited
89
+ matched_file = fname if (str && str.match(/^\s*require[\s\(]*['"]sinatra(\/base)?['"]/))
90
+ end
91
+ end
92
+ if matched_file
93
+ # Sinatra apps
94
+ f = Framework.lookup('Sinatra')
95
+ f.exec = "ruby #{matched_file}"
96
+ return f
97
+ end
98
+
99
+ # PHP
100
+ elsif !Dir.glob('*.php').empty?
101
+ return Framework.lookup('PHP')
102
+
103
+ # Erlang/OTP using Rebar
104
+ elsif !Dir.glob('releases/*/*.rel').empty? && !Dir.glob('releases/*/*.boot').empty?
105
+ return Framework.lookup('Erlang/OTP Rebar')
106
+
107
+ # Python Django
108
+ # XXX: not all django projects keep settings.py in top-level directory
109
+ elsif File.exist?('manage.py') && File.exist?('settings.py')
110
+ return Framework.lookup('Django')
111
+
112
+ # Python
113
+ elsif !Dir.glob('wsgi.py').empty?
114
+ return Framework.lookup('WSGI')
115
+
116
+ # .Net
117
+ elsif !Dir.glob('web.config').empty?
118
+ return Framework.lookup('dotNet')
119
+
120
+ # Node.js
121
+ elsif !Dir.glob('*.js').empty?
122
+ if File.exist?('server.js') || File.exist?('app.js') || File.exist?('index.js') || File.exist?('main.js')
123
+ return Framework.lookup('Node')
124
+ end
125
+
126
+ # Play or Standalone Apps
127
+ elsif Dir.glob('*.zip').first
128
+ zip_file = Dir.glob('*.zip').first
129
+ return detect_framework_from_zip zip_file, available_frameworks
130
+ end
131
+
132
+ # Default to Standalone if no other match was made
133
+ return Framework.lookup('Standalone') if available_frameworks.include?(["standalone"])
134
+ end
135
+ end
136
+
137
+ def detect_framework_from_war(war_file=nil)
138
+ if war_file
139
+ contents = ZipUtil.entry_lines(war_file)
140
+ else
141
+ #assume we are working with current dir
142
+ contents = Dir['**/*'].join("\n")
143
+ end
144
+
145
+ # Spring/Lift Variations
146
+ if contents =~ /WEB-INF\/lib\/grails-web.*\.jar/
147
+ return Framework.lookup('Grails')
148
+ elsif contents =~ /WEB-INF\/lib\/lift-webkit.*\.jar/
149
+ return Framework.lookup('Lift')
150
+ elsif contents =~ /WEB-INF\/classes\/org\/springframework/
151
+ return Framework.lookup('Spring')
152
+ elsif contents =~ /WEB-INF\/lib\/spring-core.*\.jar/
153
+ return Framework.lookup('Spring')
154
+ elsif contents =~ /WEB-INF\/lib\/org\.springframework\.core.*\.jar/
155
+ return Framework.lookup('Spring')
156
+ else
157
+ return Framework.lookup('JavaWeb')
158
+ end
159
+ end
160
+
161
+ def detect_framework_from_zip(zip_file, available_frameworks)
162
+ contents = ZipUtil.entry_lines(zip_file)
163
+ detect_framework_from_zip_contents(contents, available_frameworks)
164
+ end
165
+
166
+ def detect_framework_from_zip_contents(contents, available_frameworks)
167
+ if available_frameworks.include?(["play"]) && contents =~ /lib\/play\..*\.jar/
168
+ return Framework.lookup('Play')
169
+ elsif available_frameworks.include?(["standalone"])
170
+ return Framework.lookup('Standalone')
171
+ end
172
+ end
173
+ end
174
+
175
+ attr_reader :name, :description, :console
176
+ attr_accessor :exec
177
+
178
+ def initialize(framework=nil, opts={})
179
+ @name = framework || DEFAULT_FRAMEWORK
180
+ @memory = opts[:mem] || DEFAULT_MEM
181
+ @description = opts[:description] || 'Unknown Application Type'
182
+ @exec = opts[:exec]
183
+ @console = opts[:console] || false
184
+ end
185
+
186
+ def to_s
187
+ description
188
+ end
189
+
190
+ def require_url?
191
+ true
192
+ end
193
+
194
+ def require_start_command?
195
+ false
196
+ end
197
+
198
+ def prompt_for_runtime?
199
+ false
200
+ end
201
+
202
+ def default_runtime(path)
203
+ nil
204
+ end
205
+
206
+ def memory(runtime=nil)
207
+ @memory
208
+ end
209
+
210
+ alias :mem :memory
211
+ end
212
+
213
+ class StandaloneFramework < Framework
214
+ def require_url?
215
+ false
216
+ end
217
+
218
+ def require_start_command?
219
+ true
220
+ end
221
+
222
+ def prompt_for_runtime?
223
+ true
224
+ end
225
+
226
+ def default_runtime(path)
227
+ if !File.directory? path
228
+ if path =~ /\.(jar|class)$/
229
+ return "java"
230
+ elsif path =~ /\.(rb)$/
231
+ return "ruby18"
232
+ elsif path =~ /\.(zip)$/
233
+ return detect_runtime_from_zip path
234
+ end
235
+ else
236
+ Dir.chdir(path) do
237
+ return "ruby18" if not Dir.glob('**/*.rb').empty?
238
+ if !Dir.glob('**/*.class').empty? || !Dir.glob('**/*.jar').empty?
239
+ return "java"
240
+ elsif Dir.glob('*.zip').first
241
+ zip_file = Dir.glob('*.zip').first
242
+ return detect_runtime_from_zip zip_file
243
+ end
244
+ end
245
+ end
246
+ return nil
247
+ end
248
+
249
+ def memory(runtime=nil)
250
+ default_mem = @memory
251
+ default_mem = '128M' if runtime =~ /\Aruby/ || runtime == "php"
252
+ default_mem = '512M' if runtime == "java" || runtime == "java7"
253
+ default_mem
254
+ end
255
+
256
+ private
257
+ def detect_runtime_from_zip(zip_file)
258
+ contents = ZipUtil.entry_lines(zip_file)
259
+ if contents =~ /\.(jar)$/
260
+ return "java"
261
+ end
262
+ end
263
+ end
264
+
265
+ end
@@ -0,0 +1,300 @@
1
+ require "set"
2
+
3
+ module JDC::Cli::ManifestHelper
4
+ include JDC::Cli::ServicesHelper
5
+
6
+ DEFAULTS = {
7
+ "url" => "${name}.${target-base}",
8
+ "mem" => "128M",
9
+ "instances" => 1
10
+ }
11
+
12
+ MANIFEST = "manifest.yml"
13
+
14
+ YES_SET = Set.new(["y", "Y", "yes", "YES"])
15
+
16
+ # take a block and call it once for each app to push/update.
17
+ # with @application and @app_info set appropriately
18
+ def each_app(panic=true)
19
+ if @manifest and all_apps = @manifest["applications"]
20
+ where = File.expand_path(@path)
21
+ single = false
22
+
23
+ all_apps.each do |path, info|
24
+ app = File.expand_path("../" + path, manifest_file)
25
+ if where.start_with?(app)
26
+ @application = app
27
+ @app_info = info
28
+ yield info["name"]
29
+ single = true
30
+ break
31
+ end
32
+ end
33
+
34
+ unless single
35
+ if where == File.expand_path("../", manifest_file)
36
+ ordered_by_deps(all_apps).each do |path, info|
37
+ app = File.expand_path("../" + path, manifest_file)
38
+ @application = app
39
+ @app_info = info
40
+ yield info["name"]
41
+ end
42
+ else
43
+ err "Path '#{@path}' is not known to manifest '#{manifest_file}'."
44
+ end
45
+ end
46
+ else
47
+ @application = @path
48
+ @app_info = @manifest
49
+ if @app_info
50
+ yield @app_info["name"]
51
+ elsif panic
52
+ err "No applications."
53
+ end
54
+ end
55
+
56
+ nil
57
+ ensure
58
+ @application = nil
59
+ @app_info = nil
60
+ end
61
+
62
+ def interact(many=false)
63
+ @manifest ||= {}
64
+ configure_app(many)
65
+ end
66
+
67
+ def target_manifest
68
+ @options[:manifest] || MANIFEST
69
+ end
70
+
71
+ def save_manifest(save_to = nil)
72
+ save_to ||= target_manifest
73
+
74
+ File.open(save_to, "w") do |f|
75
+ f.write @manifest.to_yaml
76
+ end
77
+
78
+ say "Manifest written to #{save_to}."
79
+ end
80
+
81
+ def configure_app(many=false)
82
+ name = manifest("name") ||
83
+ set(ask("Application Name", :default => manifest("name")), "name")
84
+
85
+
86
+
87
+ if manifest "framework"
88
+ framework = JDC::Cli::Framework.lookup_by_framework manifest("framework","name")
89
+ else
90
+ framework = detect_framework
91
+ set framework.name, "framework", "name"
92
+ set(
93
+ { "mem" => framework.mem,
94
+ "description" => framework.description,
95
+ "exec" => framework.exec
96
+ },
97
+ "framework",
98
+ "info"
99
+ )
100
+ end
101
+
102
+ default_runtime = manifest "runtime"
103
+ if not default_runtime
104
+ default_runtime = framework.default_runtime(@application)
105
+ set(detect_runtime(default_runtime), "runtime") if framework.prompt_for_runtime?
106
+ end
107
+ default_command = manifest "command"
108
+ set ask("Start Command", :default => default_command), "command" if framework.require_start_command?
109
+
110
+ url_template = manifest("url") || DEFAULTS["url"]
111
+ url_resolved = url_template.dup
112
+ resolve_lexically(url_resolved)
113
+
114
+ if !framework.require_url?
115
+ url_resolved = "None"
116
+ end
117
+ url = ask("Application Deployed URL", :default => url_resolved)
118
+
119
+ if url == url_resolved && url != "None"
120
+ url = url_template
121
+ end
122
+
123
+ # common error case is for prompted users to answer y or Y or yes or
124
+ # YES to this ask() resulting in an unintended URL of y. Special
125
+ # case this common error
126
+ url = url_resolved if YES_SET.member? url
127
+
128
+ if(url == "None")
129
+ url = nil
130
+ end
131
+
132
+ set url, "url"
133
+
134
+ default_mem = manifest("mem")
135
+ default_mem = framework.memory(manifest("runtime")) if not default_mem
136
+ set ask(
137
+ "Memory reservation",
138
+ :default =>
139
+ default_mem ||
140
+ DEFAULTS["mem"],
141
+ :choices => ["128M", "256M", "512M", "1G", "2G"]
142
+ ), "mem"
143
+
144
+ set ask(
145
+ "How many instances?",
146
+ :default => manifest("instances") || DEFAULTS["instances"]
147
+ ), "instances"
148
+ unless manifest "services"
149
+ user_services = client.services
150
+ user_services.sort! {|a, b| a[:name] <=> b[:name] }
151
+
152
+ unless user_services.empty?
153
+ if ask "Bind existing services to '#{name}'?", :default => false
154
+ bind_services(user_services)
155
+ end
156
+ end
157
+
158
+ services = client.services_info
159
+ unless services.empty?
160
+ if ask "Create services to bind to '#{name}'?", :default => false
161
+ create_services(services.values.collect(&:keys).flatten)
162
+ end
163
+ end
164
+ end
165
+ if many and ask("Configure for another application?", :default => false)
166
+ @application = ask "Application path?"
167
+ configure_app
168
+ end
169
+ end
170
+
171
+ def set(what, *where)
172
+ where.unshift "applications", @application
173
+
174
+ which = @manifest
175
+ where.each_with_index do |k, i|
176
+ if i + 1 == where.size
177
+ which[k] = what
178
+ else
179
+ which = (which[k] ||= {})
180
+ end
181
+ end
182
+
183
+ what
184
+ end
185
+
186
+ # Detect the appropriate framework.
187
+ def detect_framework(prompt_ok = true)
188
+ framework = JDC::Cli::Framework.detect(@application, frameworks_info)
189
+ framework_correct = ask("Detected a #{framework}, is this correct?", :default => true) if prompt_ok && framework
190
+ if prompt_ok && (framework.nil? || !framework_correct)
191
+ display "#{"[WARNING]".yellow} Can't determine the Application Type." unless framework
192
+ framework = nil if !framework_correct
193
+ framework = JDC::Cli::Framework.lookup(
194
+ ask(
195
+ "Select Application Type",
196
+ :indexed => true,
197
+ :default => framework,
198
+ :choices => JDC::Cli::Framework.known_frameworks(frameworks_info)
199
+ )
200
+ )
201
+ display "Selected #{framework}"
202
+ end
203
+
204
+ framework
205
+ end
206
+
207
+ # Detect the appropriate runtime.
208
+ def detect_runtime(default, prompt_ok=true)
209
+ runtime = nil
210
+ runtime_keys=[]
211
+ runtimes_info.keys.each {|runtime_key| runtime_keys << runtime_key.dup }
212
+ runtime_keys.sort!
213
+ if prompt_ok
214
+ runtime = ask(
215
+ "Select Runtime",
216
+ :indexed => true,
217
+ :default => default,
218
+ :choices => runtime_keys
219
+ )
220
+ display "Selected #{runtime}"
221
+ end
222
+ runtime
223
+ end
224
+
225
+ def bind_services(user_services, chosen = 0)
226
+ svcname = ask(
227
+ "Which one?",
228
+ :indexed => true,
229
+ :choices => user_services.collect { |p| p[:name] })
230
+
231
+ svc = user_services.find { |p| p[:name] == svcname }
232
+
233
+ set svc[:vendor], "services", svcname, "type"
234
+
235
+ if chosen + 1 < user_services.size && ask("Bind another?", :default => false)
236
+ bind_services(user_services, chosen + 1)
237
+ end
238
+ end
239
+
240
+ def create_services(services)
241
+ svcs = services.collect(&:to_s).sort!
242
+
243
+ configure_service(
244
+ ask(
245
+ "What kind of service?",
246
+ :indexed => true,
247
+ :choices => svcs
248
+ )
249
+ )
250
+
251
+ if ask "Create another?", :default => false
252
+ create_services(services)
253
+ end
254
+ end
255
+
256
+ def configure_service(vendor)
257
+ default_name = random_service_name(vendor)
258
+ name = ask "Specify the name of the service", :default => default_name
259
+
260
+ set vendor, "services", name, "type"
261
+ end
262
+
263
+ private
264
+ def ordered_by_deps(apps, abspaths = nil, processed = Set[])
265
+ unless abspaths
266
+ abspaths = {}
267
+ apps.each do |p, i|
268
+ ep = File.expand_path("../" + p, manifest_file)
269
+ abspaths[ep] = i
270
+ end
271
+ end
272
+
273
+ ordered = []
274
+ apps.each do |path, info|
275
+ epath = File.expand_path("../" + path, manifest_file)
276
+
277
+ if deps = info["depends-on"]
278
+ dep_apps = {}
279
+ deps.each do |dep|
280
+ edep = File.expand_path("../" + dep, manifest_file)
281
+
282
+ err "Circular dependency detected." if processed.include? edep
283
+
284
+ dep_apps[dep] = abspaths[edep]
285
+ end
286
+
287
+ processed.add(epath)
288
+
289
+ ordered += ordered_by_deps(dep_apps, abspaths, processed)
290
+ ordered << [path, info]
291
+ elsif not processed.include? epath
292
+ ordered << [path, info]
293
+ processed.add(epath)
294
+ end
295
+ end
296
+
297
+ ordered
298
+ end
299
+
300
+ end