Better handling of commands.
parent
3ca16cfcce
commit
bdeb23c275
308
src/service.cr
308
src/service.cr
|
@ -13,17 +13,6 @@ args = [] of String
|
|||
|
||||
parser = OptionParser.parse do |parser|
|
||||
parser.banner = "usage: service <command> [options]\n" +
|
||||
"\n" +
|
||||
"commands:\n" +
|
||||
" start Starts a stopped or dead service.\n" +
|
||||
" stop Stops a running service.\n" +
|
||||
" status Shows the current state of a service.\n" +
|
||||
" show Describe a service in detail.\n" +
|
||||
" add Add a service to an environment.\n" +
|
||||
" del Remove a service from an environment.\n" +
|
||||
" add-environment Creates a new, empty environment.\n" +
|
||||
" list-environments Lists registered environments.\n" +
|
||||
"\n" +
|
||||
"options:\n"
|
||||
|
||||
parser.on "-h", "--help", "Prints this help message." do
|
||||
|
@ -35,9 +24,177 @@ parser = OptionParser.parse do |parser|
|
|||
end
|
||||
end
|
||||
|
||||
command = args[0]?
|
||||
alias Command = Proc(Array(String), Nil)
|
||||
alias CommandTuple = Tuple(String, String, Command)
|
||||
class CommandsList
|
||||
def initialize
|
||||
@commands = Array(CommandTuple).new
|
||||
end
|
||||
|
||||
def push(name : String, description : String, &proc : Command)
|
||||
@commands << Tuple.new(name, description, proc)
|
||||
end
|
||||
|
||||
def find(&block : Proc(CommandTuple, Bool))
|
||||
@commands.find do |tuple|
|
||||
if block.call tuple
|
||||
next true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
"commands:\n\n"+ @commands.map do |tuple|
|
||||
" %-32s %s" % [tuple[0], tuple[1]]
|
||||
end.join "\n"
|
||||
end
|
||||
end
|
||||
commands = CommandsList.new
|
||||
|
||||
commands.push "add", "Adds a service to an environment." do |args|
|
||||
providers = Hash(String, String).new
|
||||
|
||||
environment, service = Service.parse_id args[0]
|
||||
|
||||
args.each_with_index do |arg, i|
|
||||
next if i == 0
|
||||
|
||||
match = arg.match /(.*)=(.*)/
|
||||
|
||||
if match.nil?
|
||||
raise ::Service::Exception.new "usage: service add <service> <token=provider>"
|
||||
next
|
||||
end
|
||||
|
||||
providers[match[1]] = match[2]
|
||||
end
|
||||
|
||||
Service.new(service, environment).tap do |service|
|
||||
service.consumes.each do |token|
|
||||
provider = providers[token.token]?
|
||||
|
||||
if provider.nil?
|
||||
provider = service.get_default_provider token.token
|
||||
end
|
||||
|
||||
if provider.nil?
|
||||
STDERR.puts "This service consumes a “#{token.token}” token, but you have not specified what other service is supposed to provide it."
|
||||
STDERR.puts "Use the `service add #{args[1]} #{token.token}=<provider>` syntax to specify it."
|
||||
exit 1
|
||||
end
|
||||
|
||||
service.providers[token.token] = provider
|
||||
end
|
||||
pp! service.providers
|
||||
end.write RC_DIRECTORY
|
||||
end
|
||||
|
||||
commands.push "del", "Removes a service from an environment." do |args|
|
||||
Service.new(args[0], args[1]?).remove RC_DIRECTORY
|
||||
end
|
||||
|
||||
commands.push "start", "Starts a service." do
|
||||
services = args.map do |arg|
|
||||
service = Service.get_by_id(arg)
|
||||
|
||||
unless service
|
||||
raise Service::Exception.new "Service '#{arg}' does not exist."
|
||||
end
|
||||
|
||||
service
|
||||
end
|
||||
|
||||
services.each do |service|
|
||||
service.dependency_tree.flatten.reverse.each do |service|
|
||||
next if service.running? PID_DIRECTORY
|
||||
|
||||
puts "starting #{service.to_s}"
|
||||
service.start PID_DIRECTORY, LOG_DIRECTORY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
commands.push "stop", "Stops a running service." do |args|
|
||||
services = args.map do |arg|
|
||||
service = Service.get_by_id(arg)
|
||||
|
||||
unless service
|
||||
raise Service::Exception.new "Service '#{arg}' does not exist."
|
||||
end
|
||||
|
||||
service
|
||||
end
|
||||
|
||||
services.each do |service|
|
||||
# FIXME: Build revdep tree and stop services started as dependencies?
|
||||
next if ! service.running? PID_DIRECTORY
|
||||
# FIXME: Should we remove duplicate services from the
|
||||
# tree once flattened?
|
||||
service.reverse_dependency_tree.flatten.reverse.each do |service|
|
||||
next if ! service.running? PID_DIRECTORY
|
||||
|
||||
puts "stopping #{service.to_s}"
|
||||
service.stop PID_DIRECTORY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
commands.push "status", "Prints the status of services." do |args|
|
||||
child = Process.run "#{OWN_LIBEXEC_DIR}/status", args,
|
||||
output: Process::Redirect::Inherit,
|
||||
error: Process::Redirect::Inherit
|
||||
return_value = (child.exit_status / 256).to_i
|
||||
|
||||
# Errors not registered here should probably be verbose in `status`.
|
||||
if return_value == 1
|
||||
STDERR << "No such service.\n"
|
||||
end
|
||||
|
||||
exit return_value
|
||||
end
|
||||
|
||||
commands.push "show", "Shows a service's configuration and state." do |args|
|
||||
service = Service.all.find do |service|
|
||||
unless service.name == args[0]
|
||||
next false
|
||||
end
|
||||
|
||||
env = args[1]? || "root"
|
||||
if service.environment.name != env
|
||||
next false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
if service
|
||||
puts service.summary
|
||||
else
|
||||
STDERR << "No such service is registered.\n"
|
||||
exit 2
|
||||
end
|
||||
end
|
||||
|
||||
commands.push "add-environment", "Creates a new (empty) environment." do |arg|
|
||||
Environment.new(args[9]).write ENVIRONMENTS_DIRECTORY
|
||||
end
|
||||
|
||||
commands.push "list-environments", "Lists all currently defined environments.s", do |arg|
|
||||
Environment.all.map do |env|
|
||||
puts env.to_s
|
||||
end
|
||||
end
|
||||
|
||||
commands.push "help", "Prints this help message." do
|
||||
puts parser
|
||||
puts
|
||||
puts commands.to_s
|
||||
end
|
||||
|
||||
command = commands.find &.[0].==(args[0]?)
|
||||
if command.nil?
|
||||
STDERR << parser << "\n"
|
||||
STDERR << "\n"
|
||||
STDERR << commands.to_s << "\n"
|
||||
exit 1
|
||||
end
|
||||
|
||||
|
@ -46,131 +203,8 @@ Environment.load ENVIRONMENTS_DIRECTORY
|
|||
Service.load RC_DIRECTORY
|
||||
|
||||
begin
|
||||
if args[0] == "help"
|
||||
puts parser
|
||||
elsif args[0] == "add"
|
||||
providers = Hash(String, String).new
|
||||
|
||||
environment, service = Service.parse_id args[1]
|
||||
|
||||
args.shift
|
||||
args.each_with_index do |arg, i|
|
||||
next if i == 0
|
||||
|
||||
match = arg.match /(.*)=(.*)/
|
||||
|
||||
if match.nil?
|
||||
raise ::Service::Exception.new "usage: service add <service> <token=provider>"
|
||||
next
|
||||
end
|
||||
|
||||
providers[match[1]] = match[2]
|
||||
end
|
||||
|
||||
Service.new(service, environment).tap do |service|
|
||||
service.consumes.each do |token|
|
||||
provider = providers[token.token]?
|
||||
|
||||
if provider.nil?
|
||||
provider = service.get_default_provider token.token
|
||||
end
|
||||
|
||||
if provider.nil?
|
||||
STDERR.puts "This service consumes a “#{token.token}” token, but you have not specified what other service is supposed to provide it."
|
||||
STDERR.puts "Use the `service add #{args[1]} #{token.token}=<provider>` syntax to specify it."
|
||||
exit 1
|
||||
end
|
||||
|
||||
service.providers[token.token] = provider
|
||||
end
|
||||
pp! service.providers
|
||||
end.write RC_DIRECTORY
|
||||
elsif args[0] == "del"
|
||||
Service.new(args[1], args[2]?).remove RC_DIRECTORY
|
||||
elsif args[0] == "start"
|
||||
services = args[1..args.size].map do |arg|
|
||||
service = Service.get_by_id(arg)
|
||||
|
||||
unless service
|
||||
raise Service::Exception.new "Service '#{arg}' does not exist."
|
||||
end
|
||||
|
||||
service
|
||||
end
|
||||
|
||||
services.each do |service|
|
||||
service.dependency_tree.flatten.reverse.each do |service|
|
||||
next if service.running? PID_DIRECTORY
|
||||
|
||||
puts "starting #{service.to_s}"
|
||||
service.start PID_DIRECTORY, LOG_DIRECTORY
|
||||
end
|
||||
end
|
||||
elsif args[0] == "stop"
|
||||
services = args[1..args.size].map do |arg|
|
||||
service = Service.get_by_id(arg)
|
||||
|
||||
unless service
|
||||
raise Service::Exception.new "Service '#{arg}' does not exist."
|
||||
end
|
||||
|
||||
service
|
||||
end
|
||||
|
||||
services.each do |service|
|
||||
# FIXME: Build revdep tree and stop services started as dependencies?
|
||||
next if ! service.running? PID_DIRECTORY
|
||||
# FIXME: Should we remove duplicate services from the
|
||||
# tree once flattened?
|
||||
service.reverse_dependency_tree.flatten.reverse.each do |service|
|
||||
next if ! service.running? PID_DIRECTORY
|
||||
|
||||
puts "stopping #{service.to_s}"
|
||||
service.stop PID_DIRECTORY
|
||||
end
|
||||
end
|
||||
elsif args[0] == "status"
|
||||
args.shift
|
||||
child = Process.run "#{OWN_LIBEXEC_DIR}/status", args,
|
||||
output: Process::Redirect::Inherit,
|
||||
error: Process::Redirect::Inherit
|
||||
return_value = (child.exit_status / 256).to_i
|
||||
|
||||
# Errors not registered here should probably be verbose in `status`.
|
||||
if return_value == 1
|
||||
STDERR << "No such service.\n"
|
||||
end
|
||||
|
||||
exit return_value
|
||||
elsif args[0] == "show"
|
||||
service = Service.all.find do |service|
|
||||
unless service.name == args[1]
|
||||
next false
|
||||
end
|
||||
|
||||
env = args[2]? || "root"
|
||||
if service.environment.name != env
|
||||
next false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
if service
|
||||
puts service.summary
|
||||
else
|
||||
STDERR << "No such service is registered.\n"
|
||||
exit 2
|
||||
end
|
||||
elsif args[0] == "add-environment"
|
||||
Environment.new(args[1]).write ENVIRONMENTS_DIRECTORY
|
||||
elsif args[0] == "list-environments"
|
||||
Environment.all.map do |env|
|
||||
puts env.to_s
|
||||
end
|
||||
else
|
||||
STDERR << parser << "\n"
|
||||
exit 1
|
||||
end
|
||||
args.shift
|
||||
command.[2].call(args)
|
||||
rescue e : Service::Exception
|
||||
STDERR << e.message << "\n"
|
||||
exit 2
|
||||
|
|
Loading…
Reference in New Issue