mongrel2 0.53.0 → 0.54.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d437852dd09b80cd9925ec41dbc8b29d9d2d0d758e30cd5acab9d378167fd1bd
4
- data.tar.gz: 1de4e99640b27b825d1540e28d99ec0d9338f1cf6907ed34217cb10c87f6163d
3
+ metadata.gz: '078af1a5d9ded05f97bdc0f0ffb9491480ee1102372e454ffbd3af91326f2206'
4
+ data.tar.gz: 8203090de25b79b5cbee3a8d57c64f4b3d9336e4bb5ab3739008d53c5a217e26
5
5
  SHA512:
6
- metadata.gz: 398bf47544d029215eb81829999ea3fd3438e03576cb1be8abbc9e5a842bb95044e29faf000d5e863e9b2f3ef5f69d1d15b33a647d1c13d9e1f3ad191f5f902a
7
- data.tar.gz: 39d7771ea0811fccb299d61cf960ee6d50e708012e099b7eec10dcf20290ecdb7b7bd01cb5db6eefc4bbe787d14a5eee7ad810963d13f43a5757d6b332f77d6f
6
+ metadata.gz: 50e7fff95804311a9f1aae03916b5b6d2a0910ce440696b006c942783b0be2d6cd1bd32ac5546e57ec5a2023529b69ef636b866e8f84c91cff2f69edbad8f046
7
+ data.tar.gz: 8d3c22401d5ea408ae3415bf5c8af8512d5bf58418c46fb8497d9aadba4aa33967ab06aca29b8f43151c8e39afe52731caf0ab92c9c828196f75a792d92273a6
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,9 +1,63 @@
1
+ 2019-09-04 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ @ * lib/mongrel2/cli/_.rb:
4
+ | Remove the temporary command template
5
+ | [a45595593fe9] [tip]
6
+ |
7
+ o * .hgignore, Gemfile, Rakefile, gem.deps.rb, mongrel2.gemspec:
8
+ | Move deps to Rubygems style
9
+ | [3394aa0fb6d7]
10
+ |
11
+ 2019-08-30 Michael Granger <ged@FaerieMUD.org>
12
+
13
+ o * bin/m2sh.rb:
14
+ | Convert the `version` command
15
+ | [f0e8cc815f35]
16
+ |
17
+ o * bin/m2sh.rb, lib/mongrel2/cli/settings.rb:
18
+ | Add the `settings` command
19
+ | [3318e96c026c]
20
+ |
21
+ o * .gems, bin/m2sh.rb, example.rb, lib/mongrel2/cli.rb,
22
+ | lib/mongrel2/cli/_.rb, lib/mongrel2/cli/access.rb,
23
+ | lib/mongrel2/cli/bootstrap.rb, lib/mongrel2/cli/commit.rb,
24
+ | lib/mongrel2/cli/hosts.rb, lib/mongrel2/cli/init.rb,
25
+ | lib/mongrel2/cli/load.rb, lib/mongrel2/cli/log.rb,
26
+ | lib/mongrel2/cli/quickstart.rb, lib/mongrel2/cli/reload.rb,
27
+ | lib/mongrel2/cli/routes.rb, lib/mongrel2/cli/running.rb,
28
+ | lib/mongrel2/cli/servers.rb, lib/mongrel2/cli/start.rb,
29
+ | lib/mongrel2/cli/stop.rb, lib/mongrel2/config/directory.rb,
30
+ | lib/mongrel2/config/handler.rb, lib/mongrel2/config/proxy.rb,
31
+ | mongrel2.gemspec:
32
+ | Convert a bunch more commands to GLI
33
+ | [a3e36d56b290]
34
+ |
35
+ 2019-08-14 Michael Granger <ged@FaerieMUD.org>
36
+
37
+ o * certs/ged.pem:
38
+ | Update my gem-signing cert
39
+ | [3ace11b97f05]
40
+ |
41
+ o * lib/mongrel2/config.rb, lib/mongrel2/config/dsl.rb,
42
+ | lib/mongrel2/config/host.rb, lib/mongrel2/config/server.rb,
43
+ | spec/mongrel2/config/dsl_spec.rb:
44
+ | Fixed create vs. re-create in config DSL
45
+ | [62a155659470]
46
+ |
1
47
  2019-06-26 Michael Granger <ged@FaerieMUD.org>
2
48
 
3
- @ * History.rdoc, Rakefile, lib/mongrel2.rb:
49
+ o * .hgtags:
50
+ | Added tag v0.53.0 for changeset 9a0ef111c743
51
+ | [f2fa2ed85e26]
52
+ |
53
+ o * .hgsigs:
54
+ | Added signature for changeset cfedd3805c13
55
+ | [9a0ef111c743] [v0.53.0]
56
+ |
57
+ o * History.rdoc, Rakefile, lib/mongrel2.rb:
4
58
  | Bump the minor version, update history, bump minimum Ruby version to
5
59
  | 2.4.x
6
- | [cfedd3805c13] [tip]
60
+ | [cfedd3805c13]
7
61
  |
8
62
  o * Manifest.txt, lib/mongrel2/table.rb, lib/mongrel2/testing.rb,
9
63
  | spec/mongrel2/testing_spec.rb:
@@ -1,3 +1,10 @@
1
+ == v0.54.0 [2019-09-04] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Enhancements:
4
+
5
+ - Convert the CLI to use GLI instead of (deprecated) Trollop
6
+
7
+
1
8
  == v0.53.0 [2019-05-07] Michael Granger <ged@FaerieMUD.org>
2
9
 
3
10
  Enhancements:
@@ -11,7 +11,24 @@ bin/m2sh.rb
11
11
  data/mongrel2/config.rb.in
12
12
  data/mongrel2/config.sql
13
13
  data/mongrel2/mimetypes.sql
14
+ gem.deps.rb
14
15
  lib/mongrel2.rb
16
+ lib/mongrel2/cli.rb
17
+ lib/mongrel2/cli/access.rb
18
+ lib/mongrel2/cli/bootstrap.rb
19
+ lib/mongrel2/cli/commit.rb
20
+ lib/mongrel2/cli/hosts.rb
21
+ lib/mongrel2/cli/init.rb
22
+ lib/mongrel2/cli/load.rb
23
+ lib/mongrel2/cli/log.rb
24
+ lib/mongrel2/cli/quickstart.rb
25
+ lib/mongrel2/cli/reload.rb
26
+ lib/mongrel2/cli/routes.rb
27
+ lib/mongrel2/cli/running.rb
28
+ lib/mongrel2/cli/servers.rb
29
+ lib/mongrel2/cli/settings.rb
30
+ lib/mongrel2/cli/start.rb
31
+ lib/mongrel2/cli/stop.rb
15
32
  lib/mongrel2/config.rb
16
33
  lib/mongrel2/config/directory.rb
17
34
  lib/mongrel2/config/dsl.rb
data/Rakefile CHANGED
@@ -25,24 +25,27 @@ hoespec = Hoe.spec 'mongrel2' do
25
25
 
26
26
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
27
27
 
28
- self.dependency 'cztop', '~> 0.11'
29
- self.dependency 'cztop-reactor', '~> 0.6'
30
- self.dependency 'libxml-ruby', '~> 3.0'
31
- self.dependency 'loggability', '~> 0.12'
32
- self.dependency 'sequel', '~> 5.2'
33
- self.dependency 'sqlite3', '~> 1.3'
34
- self.dependency 'sysexits', '~> 1.1'
35
- self.dependency 'tnetstring', '~> 0.3'
36
- self.dependency 'trollop', '~> 2.0'
37
- self.dependency 'yajl-ruby', '~> 1.0'
38
-
39
- self.dependency 'amalgalite', '~> 1.5', :developer
40
- self.dependency 'configurability', '~> 3.1', :developer
41
- self.dependency 'simplecov', '~> 0.12', :developer
42
- self.dependency 'hoe-deveiate', '~> 0.8', :developer
43
- self.dependency 'rdoc-generator-fivefish', '~> 0', :development
44
-
45
- self.require_ruby_version( '>=2.4.0' )
28
+ self.dependency 'cztop', '~> 0.11'
29
+ self.dependency 'cztop-reactor', '~> 0.6'
30
+ self.dependency 'gli', '~> 2.19'
31
+ self.dependency 'libxml-ruby', '~> 3.1'
32
+ self.dependency 'loggability', '~> 0.14'
33
+ self.dependency 'pastel', '~> 0.7'
34
+ self.dependency 'sequel', '~> 5.2'
35
+ self.dependency 'sqlite3', '~> 1.3'
36
+ self.dependency 'sysexits', '~> 1.1'
37
+ self.dependency 'tnetstring', '~> 0.3'
38
+ self.dependency 'tty-prompt', '~> 0.19'
39
+ self.dependency 'tty-table', '~> 0.11'
40
+ self.dependency 'yajl-ruby', '~> 1.4'
41
+
42
+ self.dependency 'amalgalite', '~> 1.5', :developer
43
+ self.dependency 'configurability', '~> 3.4', :developer
44
+ self.dependency 'hoe-deveiate', '~> 0.10', :developer
45
+ self.dependency 'simplecov', '~> 0.12', :developer
46
+ self.dependency 'rdoc-generator-fivefish', '~> 0', :developer
47
+
48
+ self.require_ruby_version( '>=2.5.0' )
46
49
  self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
47
50
  self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
48
51
  self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
@@ -1,744 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'uri'
4
- require 'pathname'
5
- require 'fileutils'
6
- require 'tnetstring'
7
3
  require 'loggability'
8
- require 'shellwords'
4
+ Loggability.level = :fatal
9
5
 
10
- require 'trollop'
11
- require 'highline'
6
+ require 'mongrel2/cli'
7
+ exit Mongrel2::CLI.run( ARGV )
12
8
 
13
- # Have to do it this way to avoid the vendored 'sysexits' under OSX.
14
- gem 'sysexits'
15
- require 'sysexits'
16
-
17
- require 'mongrel2'
18
- require 'mongrel2/config'
19
-
20
-
21
- # A tool for interacting with a Mongrel2 config database and server. This isn't
22
- # quite a replacement for the real m2sh yet; here's what I have working so far:
23
- #
24
- # [√] load Load a config.
25
- # [√] config Alias for load.
26
- # [-] shell Starts an interactive shell.
27
- # [√] access Prints the access log.
28
- # [√] servers Lists the servers in a config database.
29
- # [√] hosts Lists the hosts in a server.
30
- # [√] routes Lists the routes in a host.
31
- # [√] commit Adds a message to the log.
32
- # [√] log Prints the commit log.
33
- # [√] start Starts a server.
34
- # [√] stop Stops a server.
35
- # [√] reload Reloads a server.
36
- # [√] running Tells you what's running.
37
- # [-] control Connects to the control port.
38
- # [√] version Prints the Mongrel2 and m2sh version.
39
- # [√] help Get help, lists commands.
40
- # [-] uuid Prints out a randomly generated UUID.
41
- #
42
- # I just use 'uuidgen' to generate uuids (which is all m2sh does, as
43
- # well), so I don't plan to implement that. The 'control' command is more-easily
44
- # accessed via pry+Mongrel2::Control, so I'm not going to implement that, either.
45
- # Everything else should be analagous to (or better than) the m2sh that comes with
46
- # mongrel2. I implemented the 'shell' mode, but I found I never used it, and it
47
- # introduced a dependency on the Termios library, so I removed it.
48
- #
49
- class Mongrel2::M2SHCommand
50
- extend ::Sysexits,
51
- Loggability
52
- include Sysexits,
53
- Mongrel2::Constants
54
-
55
- # Loggability API -- set up logging under the 'strelka' log host
56
- log_to :mongrel2
57
-
58
-
59
- # Make a HighLine color scheme
60
- COLOR_SCHEME = HighLine::ColorScheme.new do |scheme|
61
- scheme[:header] = [ :bold, :yellow ]
62
- scheme[:subheader] = [ :bold, :white ]
63
- scheme[:key] = [ :white ]
64
- scheme[:value] = [ :bold, :white ]
65
- scheme[:error] = [ :red ]
66
- scheme[:warning] = [ :yellow ]
67
- scheme[:message] = [ :reset ]
68
- end
69
-
70
-
71
- # Number of items to store in history by default
72
- DEFAULT_HISTORY_SIZE = 100
73
-
74
-
75
- # Class instance variables
76
- @command_help = Hash.new {|h,k| h[k] = { :desc => nil, :usage => ''} }
77
- @prompt = @option_parser = nil
78
-
79
-
80
- ### Add a help string for the given +command+.
81
- def self::help( command, helpstring=nil )
82
- if helpstring
83
- @command_help[ command.to_sym ][:desc] = helpstring
84
- end
85
-
86
- return @command_help[ command.to_sym ][:desc]
87
- end
88
-
89
-
90
- ### Add/fetch the +usagestring+ for +command+.
91
- def self::usage( command, usagestring=nil )
92
- if usagestring
93
- prefix = usagestring[ /\A(\s+)/, 1 ]
94
- usagestring.gsub!( /^#{prefix}/m, '' ) if prefix
95
-
96
- @command_help[ command.to_sym ][:usage] = usagestring
97
- end
98
-
99
- return @command_help[ command.to_sym ][:usage]
100
- end
101
-
102
-
103
- ### Return the global Highline prompt object, creating it if necessary.
104
- def self::prompt
105
- unless @prompt
106
- @prompt = HighLine.new
107
- # @prompt.wrap_at = @prompt.output_cols - 3
108
- end
109
-
110
- return @prompt
111
- end
112
-
113
-
114
- ### Run the utility with the given +args+.
115
- def self::run( args )
116
- HighLine.color_scheme = COLOR_SCHEME
117
-
118
- oparser = self.make_option_parser
119
- opts = Trollop.with_standard_exception_handling( oparser ) do
120
- oparser.parse( args )
121
- end
122
-
123
- command = oparser.leftovers.shift
124
- self.new( opts ).run( command, *oparser.leftovers )
125
- exit :ok
126
-
127
- rescue => err
128
- self.log.fatal "Oops: %s: %s" % [ err.class.name, err.message ]
129
- self.log.debug { ' ' + err.backtrace.join("\n ") }
130
-
131
- exit :software_error
132
- end
133
-
134
-
135
- ### Return a String that describes the available commands, e.g., for the 'help'
136
- ### command.
137
- def self::make_command_table
138
- commands = self.available_commands
139
-
140
- # Build the command table
141
- col1len = commands.map( &:length ).max
142
- return commands.collect do |cmd|
143
- helptext = self.help( cmd.to_sym ) or next # no help == invisible command
144
- "%s %s" % [
145
- self.prompt.color(cmd.rjust(col1len), :key),
146
- self.prompt.color(helptext, :value)
147
- ]
148
- end.compact
149
- end
150
-
151
-
152
- ### Return an Array of the available commands.
153
- def self::available_commands
154
- return self.public_instance_methods( false ).
155
- map( &:to_s ).
156
- grep( /_command$/ ).
157
- map {|methodname| methodname.sub(/_command$/, '') }.
158
- sort
159
- end
160
-
161
-
162
- ### Create and configure a command-line option parser for the command.
163
- ### Returns a Trollop::Parser.
164
- def self::make_option_parser
165
- unless @option_parser
166
- progname = File.basename( $0 )
167
- default_configdb = Mongrel2::DEFAULT_CONFIG_URI
168
-
169
- # Make a list of the log level names and the available commands
170
- loglevels = Loggability::LOG_LEVELS.
171
- sort_by {|name,lvl| lvl }.
172
- collect {|name,lvl| name.to_s }.
173
- join( ', ' )
174
- command_table = self.make_command_table
175
-
176
- @option_parser = Trollop::Parser.new do
177
- banner "Mongrel2 (Ruby) Shell has these commands available:"
178
-
179
- text ''
180
- command_table.each {|line| text(line) }
181
- text ''
182
-
183
- text 'Global Options'
184
- opt :config, "Specify the config database to use.",
185
- :default => DEFAULT_CONFIG_URI
186
- opt :sudo, "Use 'sudo' to run the mongrel2 server."
187
- opt :port, "Reset the server port to <i> before starting it.",
188
- :type => :integer
189
- opt :why, "Specify the reason for an action for the event log.",
190
- :type => :string
191
- text ''
192
-
193
- text 'Other Options:'
194
- opt :debug, "Turn debugging on. Also sets the --loglevel to 'debug'."
195
- opt :loglevel, "Set the logging level. Must be one of: #{loglevels}",
196
- :default => Mongrel2.logger.level.to_s
197
- end
198
- end
199
-
200
- return @option_parser
201
- end
202
-
203
-
204
- #################################################################
205
- ### I N S T A N C E M E T H O D S
206
- #################################################################
207
-
208
- ### Create a new instance of the command and set it up with the given
209
- ### +options+.
210
- def initialize( options )
211
- Loggability.format_as( :color ) if $stderr.tty?
212
- @options = options
213
-
214
- if @options.debug
215
- $DEBUG = true
216
- $VERBOSE = true
217
- Loggability.level = Logger::DEBUG
218
- elsif @options.loglevel
219
- Loggability.level = @options.loglevel
220
- end
221
-
222
- Mongrel2::Config.configure( :configdb => @options.config )
223
- end
224
-
225
-
226
- ######
227
- public
228
- ######
229
-
230
- # The Trollop options hash the command will read its configuration from
231
- attr_reader :options
232
-
233
-
234
- # Delegate the instance #prompt method to the class method instead
235
- define_method( :prompt, &self.method(:prompt) )
236
-
237
-
238
- ### Run the command with the specified +command+ and +args+.
239
- def run( command, *args )
240
- command ||= 'help'
241
- cmd_method = nil
242
-
243
- begin
244
- cmd_method = self.method( "#{command}_command" )
245
- rescue NoMethodError => err
246
- error "No such command"
247
- exit :usage
248
- end
249
-
250
- cmd_method.call( *args )
251
- end
252
-
253
-
254
- #
255
- # Commands
256
- #
257
-
258
- ### The 'help' command
259
- def help_command( *args )
260
-
261
- # Subcommand help
262
- if !args.empty?
263
- command = args.shift
264
-
265
- if self.class.available_commands.include?( command )
266
- header( self.class.help(command) )
267
- desc = "\n" + 'Usage: ' + command + ' ' + self.class.usage(command) + "\n"
268
- message( desc )
269
- else
270
- error "No such command %p" % [ command ]
271
- end
272
-
273
- # Help by itself show the table of available commands
274
- else
275
- command_table = self.class.make_command_table
276
- header "Available Commands"
277
- message( *command_table )
278
- end
279
-
280
- end
281
- help :help, "Show help for a single COMMAND if given, or list available commands if not"
282
- usage :help, "[COMMAND]"
283
-
284
-
285
- ### The 'load' command
286
- def load_command( *args )
287
- configfile = args.shift or
288
- raise "No configfile specified."
289
-
290
- runspace = Module.new do
291
- extend Mongrel2::Config::DSL, FileUtils::Verbose
292
- end
293
-
294
- header "Loading config from #{configfile}"
295
- source = File.read( configfile )
296
-
297
- runspace.module_eval( source, configfile, 1 )
298
- Mongrel2::Config.log_action( "Loaded config from #{configfile}", self.options.why )
299
- end
300
- help :load, "Overwrite the config database with the values from the speciifed CONFIGFILE."
301
- usage :load, <<-END_USAGE
302
- CONFIGFILE
303
- Note: the CONFIGFILE should contain a configuration described using the
304
- Ruby config DSL, not a Python-ish normal one. m2sh already works perfectly
305
- fine for loading those.
306
- END_USAGE
307
-
308
-
309
- ### The 'config' command
310
- alias_method :config_command, :load_command
311
- help :config, "Alias for 'load'."
312
-
313
-
314
- ### The 'init' command
315
- def init_command( * )
316
- if Mongrel2::Config.database_initialized?
317
- abort "Okay, aborting." unless
318
- self.prompt.agree( "Are you sure you want to destroy the current config? " )
319
- end
320
-
321
- header "Initializing #{self.options.config}"
322
- Mongrel2::Config.init_database!
323
- end
324
- help :init, "Initialize a new empty config database."
325
-
326
-
327
- ### The 'access' command
328
- def access_command( logfile='logs/access.log', * )
329
- # 1$ 2$ 3$ 4$ 5$ 6$ 7$ 8$ 9$
330
- # ["localhost", "127.0.0.1", 53420, 1315533812, "GET", "/favicon.ico", "HTTP/1.1", 404, 0]
331
- # -> [1315533812] 127.0.0.1:53420 localhost "GET /favicon.ico HTTP/1.1" 404 0
332
- IO.foreach( logfile ) do |line|
333
- row, _ = TNetstring.parse( line )
334
- message %{[%4$d] %2$s:%3$d %1$s "%5$s %6$s %7$s" %8$03d %9$d} % row
335
- end
336
- end
337
- help :access, "Dump the access log."
338
- usage :access, "[logfile]\nThe logfile defaults to 'logs/access.log'."
339
-
340
-
341
- ### The 'servers' command
342
- def servers_command( * )
343
- header 'SERVERS:'
344
- Mongrel2::Config.servers.each do |server|
345
- message "%s [%s]: %s" % [
346
- self.prompt.color( server.name, :key ),
347
- server.default_host,
348
- server.uuid,
349
- ]
350
- end
351
- end
352
- help :servers, "Lists the servers in a config database."
353
-
354
-
355
- ### The 'hosts' command
356
- def hosts_command( *args )
357
- servername = args.shift
358
-
359
- # Start with all servers, then narrow it down if they specified a server name.
360
- servers = Mongrel2::Config::Server.dataset
361
- servers = servers.filter( :name => servername ) if servername
362
-
363
- # Output a section for each server
364
- servers.each do |server|
365
- header "HOSTS for server #{server.name}:"
366
- server.hosts.each do |host|
367
- line = "%d: %s" % [ host.id, host.name ]
368
- line << " /%s/" % [ host.matching ] if host.matching != host.name
369
-
370
- message( line )
371
- end
372
-
373
- $stdout.puts
374
- end
375
- end
376
- help :hosts, "Lists the hosts in a server, or in all servers if none is specified."
377
- usage :hosts, "[server]"
378
-
379
-
380
- ### The 'routes' command
381
- def routes_command( *args )
382
- servername = args.shift
383
- hostname = args.shift
384
-
385
- # Start with all hosts, then narrow it down if a server and/or host was given.
386
- hosts = Mongrel2::Config::Host.dataset
387
- if servername
388
- server = Mongrel2::Config::Server[ servername ] or
389
- raise "No such server '#{servername}'"
390
- hosts = server.hosts_dataset
391
- end
392
- hosts = hosts.filter( :name => hostname ) if hostname
393
-
394
- # Output a section for each host
395
- hosts.each do |host|
396
- header "ROUTES for host #{host.server.name}/#{host.name}:"
397
-
398
- host.routes.each do |route|
399
- message( route.path )
400
- end
401
- end
402
-
403
- end
404
- help :routes, "Show the routes under a host."
405
- usage :routes, "[server [host]]"
406
-
407
-
408
- ### The 'commit' command
409
- def commit_command( *args )
410
- what, where, why, how = *args
411
- what ||= ''
412
-
413
- log = Mongrel2::Config::Log.log_action( what, where, why, how )
414
-
415
- header "Okay, logged."
416
- message( log.to_s )
417
- end
418
- help :commit, "Add a message to the commit log."
419
- usage :commit, "[WHAT [WHERE [WHY [HOW]]]]"
420
-
421
-
422
- ### The 'log' command
423
- def log_command( *args )
424
- header "Log Messages"
425
- Mongrel2::Config::Log.order_by( :happened_at ).each do |log|
426
- message( log.to_s )
427
- end
428
- end
429
- help :log, "Prints the commit log."
430
-
431
-
432
- ### The 'start' command
433
- def start_command( *args )
434
- server = find_server( args.shift )
435
- mongrel2 = find_mongrel2()
436
-
437
- if options.port
438
- message "Resetting %s server's port to %d" % [ server.name, options.port ]
439
- server.port = options.port
440
- server.save
441
- end
442
-
443
- cmd = [ mongrel2.to_s, Mongrel2::Config.dbname.to_s, server.uuid ]
444
- cmd.unshift( 'sudo' ) if self.options.sudo
445
-
446
- url = "http%s://%s:%d" % [
447
- server.use_ssl? ? 's' : '',
448
- server.bind_addr,
449
- server.port,
450
- ]
451
-
452
- # Change into the server's chroot directory so paths line up whether or not
453
- # it's started as root
454
-
455
- message '*' * 70
456
- header "Starting mongrel2 at: #{url}"
457
- message '*' * 70
458
-
459
- if server.chroot && server.chroot != '' && server.chroot != '.'
460
- Dir.chdir( server.chroot )
461
- message " changed PWD to: #{Dir.pwd}"
462
- end
463
-
464
- Mongrel2::Config.log_action( "Starting server: #{server}", self.options.why )
465
- self.log.debug " command is: #{Shellwords.shelljoin(cmd)}"
466
- exec( *cmd )
467
- end
468
- help :start, "Starts a server."
469
- usage :start, <<-END_USAGE
470
- [SERVER]
471
- If not specified, SERVER is assumed to be the only server entry in the
472
- current config. If there are more than one, you must specify a SERVER.
473
-
474
- The SERVER can be a uuid, hostname, or server name, and are searched for
475
- in that order.
476
- END_USAGE
477
-
478
-
479
- ### The 'reload' command
480
- def reload_command( *args )
481
- server = find_server( args.shift )
482
- control = server.control_socket
483
-
484
- header "Reloading '%s'" % [ server.name ]
485
- control.reload
486
- control.close
487
- message "done."
488
-
489
- Mongrel2::Config.log_action( "Restarted server #{server}", self.options.why )
490
- end
491
- help :reload, "Reload the specified server's configuration"
492
- usage :reload, "[server]"
493
-
494
-
495
- ### The 'stop' command
496
- def stop_command( *args )
497
- server = find_server( args.shift )
498
- control = server.control_socket
499
-
500
- header "Stopping '%s' gracefully." % [ server.name ]
501
- control.stop
502
- control.close
503
- message "done."
504
-
505
- Mongrel2::Config.log_action( "Stopped server #{server}", self.options.why )
506
- end
507
- help :stop, "Stop the specified server gracefully"
508
- usage :stop, "[server]"
509
-
510
-
511
- ### The 'running' command
512
- def running_command( *args )
513
- server = find_server( args.shift )
514
- pidfile = server.pid_file_path
515
-
516
- header "Checking the status of the '%s' server." % [ server.name ]
517
- unless pidfile.exist?
518
- message "Not running: PID file (%s) doesn't exist." % [ pidfile ]
519
- exit :noinput
520
- end
521
-
522
- pid = Integer( pidfile.read )
523
- begin
524
- Process.kill( 0, pid )
525
- rescue Errno::ESRCH
526
- message " mongrel2 at PID %d is NOT running" % [ pid ]
527
- exit :unavailable
528
- rescue => err
529
- error " %p while signalling PID %d: %s" % [ err.class, pid, err.message ]
530
- end
531
-
532
- message " mongrel2 at PID %d is running." % [ pid ]
533
- end
534
- help :running, "Show the status of a server."
535
- usage :running, "[server]"
536
-
537
-
538
- ### The 'bootstrap' command.
539
- def bootstrap_command( *args )
540
- scriptname = args.shift || DEFAULT_CONFIG_SCRIPT
541
- template = Mongrel2::DATA_DIR + 'config.rb.in'
542
-
543
- # Read the config DSL template
544
- data = template.read
545
- data.gsub!( /%% PWD %%/, Dir.pwd )
546
-
547
- # Write it out
548
- header "Writing a config-generation script to %s" % [ scriptname ]
549
- File.open( scriptname, File::WRONLY|File::EXCL|File::CREAT, 0755, encoding: 'utf-8' ) do |fh|
550
- fh.print( data )
551
- end
552
- message "Done."
553
- end
554
- help :bootstrap, "Generate a basic config-generation script."
555
- usage :boostrap, "[scriptname]"
556
-
557
-
558
- ### The 'quickstart' command.
559
- def quickstart_command( *args )
560
- idx_template = Mongrel2::DATA_DIR + 'index.html.in'
561
- configfile = 'config.rb'
562
-
563
- header "Quickstart!"
564
- self.bootstrap_command( configfile )
565
- edit( configfile )
566
- self.load_command( configfile )
567
-
568
- # Now load the new config DB and fetch the configured server
569
- host = Mongrel2::Config.servers.first.hosts.first
570
- hello_route = host.routes_dataset.filter( target_type: 'handler' ).first
571
-
572
- # Read the index page template
573
- data = idx_template.read
574
- data.gsub!( /%% VERSION %%/, Mongrel2.version_string(true) )
575
- data.gsub!( /%% HELLOWORLD_SEND_SPEC %%/, hello_route.target.send_spec )
576
- data.gsub!( /%% HELLOWORLD_RECV_SPEC %%/, hello_route.target.recv_spec )
577
- data.gsub!( /%% HELLOWORLD_URI %%/, hello_route.path[ /([^\(]*)/ ] )
578
-
579
- # Write it out to the public directory
580
- header "Writing an index file to public/index.html"
581
- Dir.mkdir( 'public' ) unless File.directory?( 'public' )
582
- File.open( 'public/index.html', File::WRONLY|File::EXCL|File::CREAT, 0755,
583
- encoding: 'utf-8' ) do |fh|
584
- fh.print( data )
585
- end
586
- message "Done."
587
-
588
- self.start_command()
589
- end
590
- help :quickstart, "Set up a basic mongrel2 server and run it."
591
- usage :quickstart
592
-
593
-
594
- ### The 'settings' command
595
- def settings_command( *args )
596
- header "Advanced Server Settings"
597
- Mongrel2::Config.settings.each do |key,val|
598
- message( %{<%= color "#{key}:", :subheader %> #{val}} )
599
- end
600
- end
601
- help :settings, "Show the 'advanced' server settings."
602
- usage :settings
603
-
604
-
605
- ### The 'version' command
606
- def version_command( *args )
607
- message( "<%= color 'Version:', :header %> " + Mongrel2.version_string(true) )
608
- end
609
- help :version, "Prints the Ruby-Mongrel2 version."
610
-
611
-
612
- #
613
- # Utility methods
614
- #
615
-
616
- #######
617
- private
618
- #######
619
-
620
- ### Output normal output
621
- def message( *parts )
622
- self.prompt.say( parts.map(&:to_s).join($/) )
623
- end
624
-
625
-
626
- ### Output the given +text+ highlighted as a header.
627
- def header( text )
628
- message( self.prompt.color(text, :header) )
629
- end
630
-
631
-
632
- ### Output the given +text+ highlighted as an error.
633
- def error( text )
634
- message( self.prompt.color(text, :error) )
635
- end
636
-
637
-
638
- ### Read command line history from HISTORY_FILE
639
- def read_history
640
- histfile = HISTORY_FILE.expand_path
641
-
642
- if histfile.exist?
643
- lines = histfile.readlines.collect {|line| line.chomp }
644
- self.log.debug "Read %d saved history commands from %s." % [ lines.length, histfile ]
645
- Readline::HISTORY.push( *lines )
646
- else
647
- self.log.debug "History file '%s' was empty or non-existant." % [ histfile ]
648
- end
649
- end
650
-
651
-
652
- ### Save command line history to HISTORY_FILE
653
- def save_history
654
- histfile = HISTORY_FILE.expand_path
655
-
656
- lines = Readline::HISTORY.to_a.reverse.uniq.reverse
657
- lines = lines[ -DEFAULT_HISTORY_SIZE, DEFAULT_HISTORY_SIZE ] if
658
- lines.length > DEFAULT_HISTORY_SIZE
659
-
660
- self.log.debug "Saving %d history lines to %s." % [ lines.length, histfile ]
661
-
662
- histfile.open( File::WRONLY|File::CREAT|File::TRUNC ) do |ofh|
663
- ofh.puts( *lines )
664
- end
665
- end
666
-
667
-
668
- ### Search the current mongrel2 config for a server matching +serverspec+ and
669
- ### return it as a Mongrel2::Config::Server object.
670
- def find_server( serverspec=nil )
671
- server = nil
672
- servers = Mongrel2::Config.servers
673
-
674
- raise "No servers are configured." if servers.empty?
675
-
676
- # If there's only one configured server, just make sure if a serverspec was given
677
- # that it would have matched.
678
- if servers.length == 1
679
- server = servers.first if !serverspec ||
680
- servers.first.values.values_at( :uuid, :default_host, :name ).include?( serverspec )
681
-
682
- # Otherwise, require an argument and search for the desired server if there is one
683
- else
684
- raise "You must specify a server uuid/hostname/name when more " +
685
- "than one server is configured." if servers.length > 1 && !serverspec
686
-
687
- server = servers.find {|s| s.uuid == serverspec } ||
688
- servers.find {|s| s.default_host == serverspec } ||
689
- servers.find {|s| s.name == serverspec }
690
- end
691
-
692
- raise "No servers match '#{serverspec}'" unless server
693
-
694
- return server
695
- end
696
-
697
-
698
- ### Invoke the user's editor on the given +filename+ and return the exit code
699
- ### from doing so.
700
- def edit( filename )
701
- editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
702
- system editor, filename.to_s
703
- unless $?.success? || editor =~ /vim/i
704
- raise "Editor exited with an error status (%d)" % [ $?.exitstatus ]
705
- end
706
- end
707
-
708
-
709
- ### Search the PATH for a mongrel2 binary, returning the absolute Pathname to it if found, and
710
- ### outputting a warning and describing how to set ENV['MONGREL2'] if not.
711
- def find_mongrel2
712
- if ENV['MONGREL2']
713
- m2 = Pathname( ENV['MONGREL2'] )
714
- error = nil
715
- if !m2.file?
716
- error = "but it isn't a plain file."
717
- elsif !m2.executable?
718
- error = "but it isn't executable."
719
- end
720
-
721
- raise "MONGREL2 was set to #{m2}, #{error}" if error
722
-
723
- return m2
724
- else
725
- m2 = ENV['PATH'].split( File::PATH_SEPARATOR ).
726
- map {|dir| Pathname(dir) + 'mongrel2' }.
727
- find {|path| path.executable? }
728
-
729
- return m2 if m2
730
-
731
- raise "The 'mongrel2' binary doesn't seem to be in your PATH. Either " +
732
- "add the appropriate directory to your PATH or set the MONGREL2 " +
733
- "environment variable to the full path."
734
- end
735
-
736
- end
737
-
738
-
739
-
740
- end # class Mongrel2::M2SHCommand
741
-
742
-
743
- Mongrel2::M2SHCommand.run( ARGV.dup )
744
9