require "authd" require "ipc" require "../network.cr" require "../storage.cr" require "yaml" require "baguette-crystal-base" require "../config" require "./lib/*" require "../lib" class Context class_property command = "not-implemented" class_property args : Array(String)? = nil end require "./parser.cr" def read_zones Array(DNSManager::Storage::Zone).from_json_files Context.args.not_nil! end class Actions property the_call = {} of String => Proc(Nil) property dnsmanagerd : DNSManager::Client property config : Baguette::Configuration::DNSManager def initialize(@dnsmanagerd, @config) # # Admin section. # # Maintenance. @the_call["admin-maintenance"] = ->admin_maintenance # Domain operations. @the_call["user-domain-add"] = ->user_domain_add @the_call["user-domain-del"] = ->user_domain_del @the_call["user-domain-list"] = ->user_domain_list # Zone operations. @the_call["user-zone-add"] = ->user_zone_add @the_call["user-zone-get"] = ->user_zone_get # Zone RR operations. @the_call["user-rr-add-a"] = ->user_rr_add_a @the_call["user-rr-update-a"] = ->user_rr_update_a @the_call["user-rr-del"] = ->user_rr_del end def admin_maintenance 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 if past_is_verbosity sub = DNSManager::Request::Maintenance::Subject::Verbosity value = subject.to_i @dnsmanagerd.admin_maintenance sub, value else sub = DNSManager::Request::Maintenance::Subject.parse(subject) pp! sub pp! @dnsmanagerd.admin_maintenance sub end rescue e puts "error for admin_maintenance #{subject}: #{e.message}" end end end def user_domain_add domains = Context.args.not_nil! domains.each do |domain| begin pp! domain pp! @dnsmanagerd.user_domain_add domain rescue e puts "error for user_domain_add: #{e.message}" end end end def user_domain_del domains = Context.args.not_nil! domains.each do |domain| begin pp! domain pp! @dnsmanagerd.user_domain_del domain rescue e puts "error for user_domain_del: #{e.message}" end end end def user_zone_add zones = read_zones zones.each do |zone| begin pp! zone pp! @dnsmanagerd.user_zone_add zone rescue e puts "error for user_zone_add: #{e.message}" end end end def user_zone_get domains = Context.args.not_nil! domains.each do |domain| begin pp! domain response = @dnsmanagerd.user_zone_get domain case response when DNSManager::Response::Zone pp! response.zone puts response.zone else puts "Didn't get the zone" pp! response end rescue e puts "error for user_zone_get: #{e.message}" end end end def user_domain_list response = @dnsmanagerd.user_domain_list case response when DNSManager::Response::DomainList response.domains.each do |domain| puts "- #{domain}" end else pp! response end rescue e puts "error for user_zone_del: #{e.message}" end def user_rr_add_a domain, name, ttl, target = Context.args.not_nil! rr = DNSManager::Storage::Zone::A.new name, ttl.to_u32, target pp! @dnsmanagerd.user_rr_add domain, rr rescue e puts "error for user_rr_add_a: #{e.message}" end def user_rr_update_a domain, rrid, name, ttl, target = Context.args.not_nil! rr = DNSManager::Storage::Zone::A.new name, ttl.to_u32, target rr.rrid = rrid.to_u32 pp! @dnsmanagerd.user_rr_update domain, rr rescue e puts "error for user_rr_update_a: #{e.message}" end def user_rr_del domain, rrid = Context.args.not_nil! pp! @dnsmanagerd.user_rr_delete domain, rrid.to_u32 rescue e puts "error for user_rr_del: #{e.message}" 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 (authd)." Baguette::Configuration::Auth.new else # Configuration file is for dnsmanagerd. Baguette::Configuration::Auth.get || Baguette::Configuration::Auth.new end # DNSmanager configuration. config = if no_configuration Baguette::Log.info "do not load a configuration file (dnsmanagerd)." 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 if simulation pp! authd_config pp! Context.command pp! Context.args exit 0 end # dnsmanagerd connection and authentication dnsmanagerd = DNSManager::Client.new if authd_config.login.nil? || authd_config.pass.nil? Baguette::Log.info "no authd login." else Baguette::Log.info "authd login..." login = authd_config.login.not_nil! pass = authd_config.pass.not_nil! # Authd authentication, get the token and quit right away. token = authd_get_token login: login, pass: pass # Then push the token to the dnsmanager daemon. dnsmanagerd.login token Baguette::Log.info "logged." end actions = Actions.new dnsmanagerd, 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)." Baguette::Log.info "Exception: #{e}." pp! e end # dnsmanagerd disconnection dnsmanagerd.close rescue e Baguette::Log.info "Exception: #{e}" end # Command line: # tool [options] command subcommand [options-for-subcommand] [YAML-or-JSON-files] main