tac 0.6.0

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 (43) hide show
  1. data/LICENSE +24 -0
  2. data/README.md +102 -0
  3. data/Rakefile +101 -0
  4. data/bin/tac +6 -0
  5. data/caldecott_helper/Gemfile +10 -0
  6. data/caldecott_helper/Gemfile.lock +48 -0
  7. data/caldecott_helper/server.rb +43 -0
  8. data/config/clients.yml +17 -0
  9. data/config/micro/offline.conf +2 -0
  10. data/config/micro/paths.yml +22 -0
  11. data/config/micro/refresh_ip.rb +20 -0
  12. data/lib/cli/commands/admin.rb +108 -0
  13. data/lib/cli/commands/apps.rb +1133 -0
  14. data/lib/cli/commands/base.rb +232 -0
  15. data/lib/cli/commands/manifest.rb +56 -0
  16. data/lib/cli/commands/micro.rb +115 -0
  17. data/lib/cli/commands/misc.rb +129 -0
  18. data/lib/cli/commands/services.rb +242 -0
  19. data/lib/cli/commands/user.rb +65 -0
  20. data/lib/cli/config.rb +173 -0
  21. data/lib/cli/console_helper.rb +160 -0
  22. data/lib/cli/core_ext.rb +122 -0
  23. data/lib/cli/errors.rb +19 -0
  24. data/lib/cli/frameworks.rb +276 -0
  25. data/lib/cli/manifest_helper.rb +341 -0
  26. data/lib/cli/runner.rb +547 -0
  27. data/lib/cli/services_helper.rb +92 -0
  28. data/lib/cli/tunnel_helper.rb +332 -0
  29. data/lib/cli/usage.rb +115 -0
  30. data/lib/cli/version.rb +7 -0
  31. data/lib/cli/zip_util.rb +77 -0
  32. data/lib/cli.rb +47 -0
  33. data/lib/vmc/client.rb +573 -0
  34. data/lib/vmc/const.rb +24 -0
  35. data/lib/vmc/micro/switcher/base.rb +97 -0
  36. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  37. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  38. data/lib/vmc/micro/switcher/linux.rb +16 -0
  39. data/lib/vmc/micro/switcher/windows.rb +31 -0
  40. data/lib/vmc/micro/vmrun.rb +158 -0
  41. data/lib/vmc/micro.rb +56 -0
  42. data/lib/vmc.rb +3 -0
  43. metadata +295 -0
@@ -0,0 +1,122 @@
1
+ module VMCExtensions
2
+
3
+ def say(message)
4
+ VMC::Cli::Config.output.puts(message) if VMC::Cli::Config.output
5
+ end
6
+
7
+ def header(message, filler = '-')
8
+ say "\n"
9
+ say message
10
+ say filler.to_s * message.size
11
+ end
12
+
13
+ def banner(message)
14
+ say "\n"
15
+ say message
16
+ end
17
+
18
+ def display(message, nl=true)
19
+ if nl
20
+ say message
21
+ else
22
+ if VMC::Cli::Config.output
23
+ VMC::Cli::Config.output.print(message)
24
+ VMC::Cli::Config.output.flush
25
+ end
26
+ end
27
+ end
28
+
29
+ def clear(size=80)
30
+ return unless VMC::Cli::Config.output
31
+ VMC::Cli::Config.output.print("\r")
32
+ VMC::Cli::Config.output.print(" " * size)
33
+ VMC::Cli::Config.output.print("\r")
34
+ #VMC::Cli::Config.output.flush
35
+ end
36
+
37
+ def err(message, prefix='Error: ')
38
+ raise VMC::Cli::CliExit, "#{prefix}#{message}"
39
+ end
40
+
41
+ def warn(msg)
42
+ say "#{"[WARNING]".yellow} #{msg}"
43
+ end
44
+
45
+ def quit(message = nil)
46
+ raise VMC::Cli::GracefulExit, message
47
+ end
48
+
49
+ def blank?
50
+ self.to_s.blank?
51
+ end
52
+
53
+ def uptime_string(delta)
54
+ num_seconds = delta.to_i
55
+ days = num_seconds / (60 * 60 * 24);
56
+ num_seconds -= days * (60 * 60 * 24);
57
+ hours = num_seconds / (60 * 60);
58
+ num_seconds -= hours * (60 * 60);
59
+ minutes = num_seconds / 60;
60
+ num_seconds -= minutes * 60;
61
+ "#{days}d:#{hours}h:#{minutes}m:#{num_seconds}s"
62
+ end
63
+
64
+ def pretty_size(size, prec=1)
65
+ return 'NA' unless size
66
+ return "#{size}B" if size < 1024
67
+ return sprintf("%.#{prec}fK", size/1024.0) if size < (1024*1024)
68
+ return sprintf("%.#{prec}fM", size/(1024.0*1024.0)) if size < (1024*1024*1024)
69
+ return sprintf("%.#{prec}fG", size/(1024.0*1024.0*1024.0))
70
+ end
71
+ end
72
+
73
+ module VMCStringExtensions
74
+
75
+ def red
76
+ colorize("\e[0m\e[31m")
77
+ end
78
+
79
+ def green
80
+ colorize("\e[0m\e[32m")
81
+ end
82
+
83
+ def yellow
84
+ colorize("\e[0m\e[33m")
85
+ end
86
+
87
+ def bold
88
+ colorize("\e[0m\e[1m")
89
+ end
90
+
91
+ def colorize(color_code)
92
+ if VMC::Cli::Config.colorize
93
+ "#{color_code}#{self}\e[0m"
94
+ else
95
+ self
96
+ end
97
+ end
98
+
99
+ def blank?
100
+ self =~ /^\s*$/
101
+ end
102
+
103
+ def truncate(limit = 30)
104
+ return "" if self.blank?
105
+ etc = "..."
106
+ stripped = self.strip[0..limit]
107
+ if stripped.length > limit
108
+ stripped.gsub(/\s+?(\S+)?$/, "") + etc
109
+ else
110
+ stripped
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ class Object
117
+ include VMCExtensions
118
+ end
119
+
120
+ class String
121
+ include VMCStringExtensions
122
+ end
data/lib/cli/errors.rb ADDED
@@ -0,0 +1,19 @@
1
+ module VMC::Cli
2
+
3
+ class CliError < StandardError
4
+ def self.error_code(code = nil)
5
+ define_method(:error_code) { code }
6
+ end
7
+ end
8
+
9
+ class UnknownCommand < CliError; error_code(100); end
10
+ class TargetMissing < CliError; error_code(102); end
11
+ class TargetInaccessible < CliError; error_code(103); end
12
+
13
+ class TargetError < CliError; error_code(201); end
14
+ class AuthError < TargetError; error_code(202); end
15
+
16
+ class CliExit < CliError; error_code(400); end
17
+ class GracefulExit < CliExit; error_code(401); end
18
+
19
+ end
@@ -0,0 +1,276 @@
1
+ module VMC::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
+ 'JavaWeb_tomcat' => ['java_web', { :mem => '512M', :description => 'Java Web Application on Toncat'}],
25
+ 'JavaWeb_tongweb' => ['java_web_tongweb', { :mem => '512M', :description => 'Java Web Application on Tongweb'}]
26
+ }
27
+ JAVAWEB_APPSERVERS = {
28
+ 'JavaWeb_tomcat' => ['java_web',{ :mem => '512M', :description => 'Java Web Application on tomcat'}],
29
+ 'JavaWeb_tongweb' => ['java_web_tongweb', { :mem => '512M', :description => 'Java Web Application on tongweb'}]
30
+ }
31
+ class << self
32
+ def javaweb_appservers
33
+ frameworks = []
34
+ JAVAWEB_APPSERVERS.each do |key,fw|
35
+ frameworks << key
36
+ end
37
+ frameworks
38
+ end
39
+ def known_frameworks(available_frameworks)
40
+ frameworks = []
41
+ FRAMEWORKS.each do |key,fw|
42
+ frameworks << key if available_frameworks.include? [fw[0]]
43
+ end
44
+ frameworks
45
+ end
46
+
47
+ def lookup(name)
48
+ return create(*FRAMEWORKS[name])
49
+ end
50
+
51
+ def lookup_by_framework(name)
52
+ FRAMEWORKS.each do |key,fw|
53
+ return create(fw[0],fw[1]) if fw[0] == name
54
+ end
55
+ end
56
+
57
+ def create(name,opts)
58
+ if name == "standalone"
59
+ return StandaloneFramework.new(name, opts)
60
+ else
61
+ return Framework.new(name,opts)
62
+ end
63
+ end
64
+
65
+ def detect(path, available_frameworks)
66
+ if !File.directory? path
67
+ if path.end_with?('.war')
68
+ return detect_framework_from_war path
69
+ elsif path.end_with?('.zip')
70
+ return detect_framework_from_zip path, available_frameworks
71
+ elsif available_frameworks.include?(["standalone"])
72
+ return Framework.lookup('Standalone')
73
+ else
74
+ return nil
75
+ end
76
+ end
77
+ Dir.chdir(path) do
78
+ # Rails
79
+ if File.exist?('config/environment.rb')
80
+ return Framework.lookup('Rails')
81
+
82
+ # Rack
83
+ elsif File.exist?('config.ru') && available_frameworks.include?(["rack"])
84
+ return Framework.lookup('Rack')
85
+
86
+ # Java Web Apps
87
+ elsif Dir.glob('*.war').first
88
+ return detect_framework_from_war(Dir.glob('*.war').first)
89
+
90
+ elsif File.exist?('WEB-INF/web.xml')
91
+ return detect_framework_from_war
92
+
93
+ # Simple Ruby Apps
94
+ elsif !Dir.glob('*.rb').empty?
95
+ matched_file = nil
96
+ Dir.glob('*.rb').each do |fname|
97
+ next if matched_file
98
+ File.open(fname, 'r') do |f|
99
+ str = f.read # This might want to be limited
100
+ matched_file = fname if (str && str.match(/^\s*require[\s\(]*['"]sinatra['"]/))
101
+ end
102
+ end
103
+ if matched_file
104
+ # Sinatra apps
105
+ f = Framework.lookup('Sinatra')
106
+ f.exec = "ruby #{matched_file}"
107
+ return f
108
+ end
109
+
110
+ # PHP
111
+ elsif !Dir.glob('*.php').empty?
112
+ return Framework.lookup('PHP')
113
+
114
+ # Erlang/OTP using Rebar
115
+ elsif !Dir.glob('releases/*/*.rel').empty? && !Dir.glob('releases/*/*.boot').empty?
116
+ return Framework.lookup('Erlang/OTP Rebar')
117
+
118
+ # Python Django
119
+ # XXX: not all django projects keep settings.py in top-level directory
120
+ elsif File.exist?('manage.py') && File.exist?('settings.py')
121
+ return Framework.lookup('Django')
122
+
123
+ # Python
124
+ elsif !Dir.glob('wsgi.py').empty?
125
+ return Framework.lookup('WSGI')
126
+
127
+ # .Net
128
+ elsif !Dir.glob('web.config').empty?
129
+ return Framework.lookup('dotNet')
130
+
131
+ # Node.js
132
+ elsif !Dir.glob('*.js').empty?
133
+ if File.exist?('server.js') || File.exist?('app.js') || File.exist?('index.js') || File.exist?('main.js')
134
+ return Framework.lookup('Node')
135
+ end
136
+
137
+ # Play or Standalone Apps
138
+ elsif Dir.glob('*.zip').first
139
+ zip_file = Dir.glob('*.zip').first
140
+ return detect_framework_from_zip zip_file, available_frameworks
141
+ end
142
+
143
+ # Default to Standalone if no other match was made
144
+ return Framework.lookup('Standalone') if available_frameworks.include?(["standalone"])
145
+ end
146
+ end
147
+
148
+ def detect_framework_from_war(war_file=nil)
149
+ if war_file
150
+ contents = ZipUtil.entry_lines(war_file)
151
+ else
152
+ #assume we are working with current dir
153
+ contents = Dir['**/*'].join("\n")
154
+ end
155
+
156
+ # Spring/Lift Variations
157
+ if contents =~ /WEB-INF\/lib\/grails-web.*\.jar/
158
+ return Framework.lookup('Grails')
159
+ elsif contents =~ /WEB-INF\/lib\/lift-webkit.*\.jar/
160
+ return Framework.lookup('Lift')
161
+ elsif contents =~ /WEB-INF\/classes\/org\/springframework/
162
+ return Framework.lookup('Spring')
163
+ elsif contents =~ /WEB-INF\/lib\/spring-core.*\.jar/
164
+ return Framework.lookup('Spring')
165
+ elsif contents =~ /WEB-INF\/lib\/org\.springframework\.core.*\.jar/
166
+ return Framework.lookup('Spring')
167
+ else
168
+ return Framework.lookup('JavaWeb')
169
+ end
170
+ end
171
+
172
+ def detect_framework_from_zip(zip_file, available_frameworks)
173
+ contents = ZipUtil.entry_lines(zip_file)
174
+ detect_framework_from_zip_contents(contents, available_frameworks)
175
+ end
176
+
177
+ def detect_framework_from_zip_contents(contents, available_frameworks)
178
+ if available_frameworks.include?(["play"]) && contents =~ /lib\/play\..*\.jar/
179
+ return Framework.lookup('Play')
180
+ elsif available_frameworks.include?(["standalone"])
181
+ return Framework.lookup('Standalone')
182
+ end
183
+ end
184
+ end
185
+
186
+ attr_reader :name, :description, :console
187
+ attr_accessor :exec
188
+
189
+ def initialize(framework=nil, opts={})
190
+ @name = framework || DEFAULT_FRAMEWORK
191
+ @memory = opts[:mem] || DEFAULT_MEM
192
+ @description = opts[:description] || 'Unknown Application Type'
193
+ @exec = opts[:exec]
194
+ @console = opts[:console] || false
195
+ end
196
+
197
+ def to_s
198
+ description
199
+ end
200
+
201
+ def require_url?
202
+ true
203
+ end
204
+
205
+ def require_start_command?
206
+ false
207
+ end
208
+
209
+ def prompt_for_runtime?
210
+ false
211
+ end
212
+
213
+ def default_runtime(path)
214
+ nil
215
+ end
216
+
217
+ def memory(runtime=nil)
218
+ @memory
219
+ end
220
+
221
+ alias :mem :memory
222
+ end
223
+
224
+ class StandaloneFramework < Framework
225
+ def require_url?
226
+ false
227
+ end
228
+
229
+ def require_start_command?
230
+ true
231
+ end
232
+
233
+ def prompt_for_runtime?
234
+ true
235
+ end
236
+
237
+ def default_runtime(path)
238
+ if !File.directory? path
239
+ if path =~ /\.(jar|class)$/
240
+ return "java"
241
+ elsif path =~ /\.(rb)$/
242
+ return "ruby18"
243
+ elsif path =~ /\.(zip)$/
244
+ return detect_runtime_from_zip path
245
+ end
246
+ else
247
+ Dir.chdir(path) do
248
+ return "ruby18" if not Dir.glob('**/*.rb').empty?
249
+ if !Dir.glob('**/*.class').empty? || !Dir.glob('**/*.jar').empty?
250
+ return "java"
251
+ elsif Dir.glob('*.zip').first
252
+ zip_file = Dir.glob('*.zip').first
253
+ return detect_runtime_from_zip zip_file
254
+ end
255
+ end
256
+ end
257
+ return nil
258
+ end
259
+
260
+ def memory(runtime=nil)
261
+ default_mem = @memory
262
+ default_mem = '128M' if runtime =~ /\Aruby/ || runtime == "php"
263
+ default_mem = '512M' if runtime == "java" || runtime == "java7"
264
+ default_mem
265
+ end
266
+
267
+ private
268
+ def detect_runtime_from_zip(zip_file)
269
+ contents = ZipUtil.entry_lines(zip_file)
270
+ if contents =~ /\.(jar)$/
271
+ return "java"
272
+ end
273
+ end
274
+ end
275
+
276
+ end