Client: first draft.
parent
ce74c1c2c1
commit
c1ef4f6235
|
@ -21,5 +21,7 @@ dependencies:
|
||||||
targets:
|
targets:
|
||||||
dnsmanager:
|
dnsmanager:
|
||||||
main: src/main.cr
|
main: src/main.cr
|
||||||
|
dnsmanager-client:
|
||||||
|
main: src/client/main.cr
|
||||||
|
|
||||||
license: MIT
|
license: MIT
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
require "authd"
|
||||||
|
require "ipc"
|
||||||
|
require "../network.cr"
|
||||||
|
require "../storage.cr"
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
|
require "../config"
|
||||||
|
|
||||||
|
require "./lib/*"
|
||||||
|
|
||||||
|
class Context
|
||||||
|
class_property command = "not-implemented"
|
||||||
|
class_property args : Array(String)? = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
require "./parser.cr"
|
||||||
|
|
||||||
|
#def read_searches
|
||||||
|
# Array(DNSManager::Request::BLAH).from_json_files Context.args.not_nil!
|
||||||
|
#end
|
||||||
|
|
||||||
|
class Actions
|
||||||
|
property the_call = {} of String => Proc(Nil)
|
||||||
|
property dnsmanagerd : DNSManager::Client
|
||||||
|
property authd : AuthD::Client
|
||||||
|
property authd_config : Baguette::Configuration::Auth
|
||||||
|
property config : Baguette::Configuration::DNSManager
|
||||||
|
|
||||||
|
def initialize(@dnsmanagerd, @authd, @authd_config, @config)
|
||||||
|
#
|
||||||
|
# Admin section.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Maintainance
|
||||||
|
@the_call["admin-maintainance"] = ->admin_maintainance
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin_maintainance
|
||||||
|
subjects = Context.args.not_nil!
|
||||||
|
past_is_verbosity = false
|
||||||
|
subjects.each do |subject|
|
||||||
|
begin
|
||||||
|
case subject
|
||||||
|
when /verbosity/i
|
||||||
|
Baguette::Log.info "changing verbosity"
|
||||||
|
past_is_verbosity = true
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
key = @authd_config.shared_key
|
||||||
|
|
||||||
|
if past_is_verbosity
|
||||||
|
sub = DNSManager::Request::Maintainance::Subject::Verbosity
|
||||||
|
value = subject.to_i
|
||||||
|
pp! sub, value
|
||||||
|
pp! @dnsmanagerd.admin_maintainance key, sub, value
|
||||||
|
else
|
||||||
|
sub = DNSManager::Request::Maintainance::Subject.parse(subject)
|
||||||
|
pp! sub
|
||||||
|
pp! @dnsmanagerd.admin_maintainance key, sub
|
||||||
|
end
|
||||||
|
rescue e
|
||||||
|
puts "error for admin_maintainance #{subject}: #{e.message}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def main
|
||||||
|
|
||||||
|
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
|
||||||
|
|
||||||
|
# Authd configuration.
|
||||||
|
authd_config = if no_configuration
|
||||||
|
Baguette::Log.info "do not load a configuration file."
|
||||||
|
Baguette::Configuration::Auth.new
|
||||||
|
else
|
||||||
|
# Configuration file is for dnsmanagerd.
|
||||||
|
Baguette::Configuration::Auth.get || Baguette::Configuration::Auth.new
|
||||||
|
end
|
||||||
|
if key_file = authd_config.shared_key_file
|
||||||
|
authd_config.shared_key = File.read(key_file).chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
# Authd configuration.
|
||||||
|
config = if no_configuration
|
||||||
|
Baguette::Log.info "do not load a configuration file."
|
||||||
|
Baguette::Configuration::DNSManager.new
|
||||||
|
else
|
||||||
|
# Configuration file is for dnsmanagerd.
|
||||||
|
Baguette::Configuration::DNSManager.get || Baguette::Configuration::DNSManager.new
|
||||||
|
end
|
||||||
|
|
||||||
|
Baguette::Context.verbosity = config.verbosity
|
||||||
|
Baguette::Log.info "verbosity: #{config.verbosity}."
|
||||||
|
|
||||||
|
parsing_cli authd_config
|
||||||
|
|
||||||
|
# dnsmanagerd connection and authentication
|
||||||
|
dnsmanagerd = DNSManager::Client.new
|
||||||
|
|
||||||
|
if simulation
|
||||||
|
pp! authd_config
|
||||||
|
pp! Context.command
|
||||||
|
pp! Context.args
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Authd authentication, get the token and quit right away.
|
||||||
|
# If login == pass == "undef": do not even try.
|
||||||
|
if authd_config.login.nil? || authd_config.pass.nil?
|
||||||
|
Baguette::Log.info "no authd login"
|
||||||
|
else
|
||||||
|
login = authd_config.login.not_nil!
|
||||||
|
pass = authd_config.pass.not_nil!
|
||||||
|
token = authd_get_token login: login, pass: pass
|
||||||
|
dnsmanagerd.login token
|
||||||
|
end
|
||||||
|
|
||||||
|
authd = AuthD::Client.new
|
||||||
|
actions = Actions.new dnsmanagerd, authd, authd_config, config
|
||||||
|
|
||||||
|
# Now we did read the intent, we should proceed doing what was asked.
|
||||||
|
begin
|
||||||
|
actions.the_call[Context.command].call
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.info "The command is not recognized (or implemented)."
|
||||||
|
end
|
||||||
|
|
||||||
|
# dnsmanagerd disconnection
|
||||||
|
dnsmanagerd.close
|
||||||
|
authd.close
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.info "Exception: #{e}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Command line:
|
||||||
|
# tool [options] command subcommand [options-for-subcommand] [YAML-or-JSON-files]
|
||||||
|
|
||||||
|
main
|
|
@ -0,0 +1,115 @@
|
||||||
|
require "option_parser"
|
||||||
|
|
||||||
|
|
||||||
|
class OptionParser
|
||||||
|
def to_s(io : IO)
|
||||||
|
if banner = @banner
|
||||||
|
io << banner
|
||||||
|
io << "\n\n"
|
||||||
|
end
|
||||||
|
@flags.join io, "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def parsing_cli(authd_config : Baguette::Configuration::Auth)
|
||||||
|
|
||||||
|
opt_authd_admin = -> (parser : OptionParser, authd_config : Baguette::Configuration::Auth) {
|
||||||
|
parser.on "-k file", "--key-file file", "Read the authd shared key from a file." do |file|
|
||||||
|
authd_config.shared_key = File.read(file).chomp
|
||||||
|
Baguette::Log.info "Key for admin operations: #{authd_config.shared_key}."
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
# frequently used functions
|
||||||
|
opt_authd_login = -> (parser : OptionParser, authd_config : Baguette::Configuration::Auth) {
|
||||||
|
parser.on "-l LOGIN", "--login LOGIN", "Authd user login." do |login|
|
||||||
|
authd_config.login = login
|
||||||
|
Baguette::Log.info "User login for authd: #{authd_config.login}."
|
||||||
|
end
|
||||||
|
parser.on "-p PASSWORD", "--password PASSWORD", "Authd user password." do |password|
|
||||||
|
authd_config.pass = password
|
||||||
|
Baguette::Log.info "User password for authd: #{authd_config.pass}."
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_help = -> (parser : OptionParser) {
|
||||||
|
parser.on "-h", "--help", "Prints command usage." do
|
||||||
|
puts "usage: #{PROGRAM_NAME} command -h"
|
||||||
|
puts
|
||||||
|
puts parser
|
||||||
|
|
||||||
|
case Context.command
|
||||||
|
when /admin-maintainance/
|
||||||
|
Baguette::Log.warning "should provide subjects to request"
|
||||||
|
Baguette::Log.warning "as in:"
|
||||||
|
DNSManager::Request::Maintainance::Subject.names.each do |n|
|
||||||
|
Baguette::Log.warning "- #{n}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unrecognized parameters are used to create commands with multiple arguments.
|
||||||
|
# Example: user add _login email phone_
|
||||||
|
# Here, login, email and phone are unrecognized arguments.
|
||||||
|
# Still, the "user add" command expect them.
|
||||||
|
unrecognized_args_to_context_args = -> (parser : OptionParser,
|
||||||
|
nexact : Int32?,
|
||||||
|
at_least : Int32?) {
|
||||||
|
|
||||||
|
# With the right args, these will be interpreted as serialized data.
|
||||||
|
parser.unknown_args do |args|
|
||||||
|
|
||||||
|
# either we test with the exact expected number of arguments or the least.
|
||||||
|
if exact = nexact
|
||||||
|
if args.size != exact
|
||||||
|
Baguette::Log.error "#{parser}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
elsif least = at_least
|
||||||
|
if args.size < least
|
||||||
|
Baguette::Log.error "#{parser}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Baguette::Log.error "Number of parameters not even provided!"
|
||||||
|
Baguette::Log.error "#{parser}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
args.each do |arg|
|
||||||
|
Baguette::Log.debug "Unrecognized argument: #{arg} (adding to Context.args)"
|
||||||
|
if Context.args.nil?
|
||||||
|
Context.args = Array(String).new
|
||||||
|
end
|
||||||
|
Context.args.not_nil! << arg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
parser = OptionParser.new do |parser|
|
||||||
|
parser.banner = "Welcome on the DNSManager CLI administration."
|
||||||
|
|
||||||
|
# Admin section.
|
||||||
|
parser.on "admin", "Admin operations." do
|
||||||
|
# All admin operations require the shared key.
|
||||||
|
opt_authd_admin.call parser, authd_config
|
||||||
|
|
||||||
|
# Maintenance.
|
||||||
|
parser.on("maintainance", "Maintainance operation of the website.") do
|
||||||
|
Baguette::Log.info "Maintainance operation of the website."
|
||||||
|
Context.command = "admin-maintainance"
|
||||||
|
parser.banner = "COMMAND: admin maintainance subject [value]"
|
||||||
|
unrecognized_args_to_context_args.call parser, nil, 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
opt_help.call parser
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.parse
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
class Baguette::Configuration
|
||||||
|
class DNSManager < IPC
|
||||||
|
property service_name : String = "dnsmanager"
|
||||||
|
property recreate_indexes : Bool = false
|
||||||
|
property storage_directory : String = "storage"
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
11
src/main.cr
11
src/main.cr
|
@ -6,16 +6,7 @@ require "ipc/json"
|
||||||
require "authd"
|
require "authd"
|
||||||
require "baguette-crystal-base"
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
class Baguette::Configuration
|
require "./config"
|
||||||
class DNSManager < IPC
|
|
||||||
property service_name : String = "dnsmanager"
|
|
||||||
property recreate_indexes : Bool = false
|
|
||||||
property storage_directory : String = "storage"
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module DNSManager
|
module DNSManager
|
||||||
class Exception < ::Exception
|
class Exception < ::Exception
|
||||||
|
|
Loading…
Reference in New Issue