193 lines
6.5 KiB
Python
193 lines
6.5 KiB
Python
"""
|
|
DDNS Service - Dynamic DNS update service.
|
|
|
|
Main executable for CLI and daemon mode.
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
|
|
from . import __version__
|
|
from .app import Application
|
|
from .cli import (
|
|
cmd_cleanup,
|
|
cmd_hostname_add,
|
|
cmd_hostname_delete,
|
|
cmd_hostname_list,
|
|
cmd_hostname_modify,
|
|
cmd_user_add,
|
|
cmd_user_delete,
|
|
cmd_user_email,
|
|
cmd_user_list,
|
|
cmd_user_passwd,
|
|
)
|
|
from .config import ConfigError, find_config_file, load_config
|
|
from .logging import disable_logging, setup_logging
|
|
from .server import run_daemon
|
|
|
|
|
|
def build_parser():
|
|
"""Build the argument parser."""
|
|
parser = argparse.ArgumentParser(
|
|
description="DDNS Service - Dynamic DNS update service",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
)
|
|
parser.add_argument(
|
|
"--version", action="version", version=f"%(prog)s {__version__}"
|
|
)
|
|
parser.add_argument("-c", "--config", help="Path to config file")
|
|
parser.add_argument(
|
|
"-d", "--daemon", action="store_true", help="Run as daemon"
|
|
)
|
|
parser.add_argument(
|
|
"--init-db", action="store_true", help="Initialize database"
|
|
)
|
|
parser.add_argument(
|
|
"--debug", action="store_true", help="Enable debug logging"
|
|
)
|
|
|
|
subparsers = parser.add_subparsers(dest="command", title="commands")
|
|
|
|
# User commands
|
|
user_parser = subparsers.add_parser("user", help="User management")
|
|
user_subparsers = user_parser.add_subparsers(dest="user_command")
|
|
|
|
user_list = user_subparsers.add_parser("list", help="List users")
|
|
user_list.set_defaults(func=cmd_user_list)
|
|
|
|
user_add = user_subparsers.add_parser("add", help="Add user")
|
|
user_add.add_argument("username", help="Username")
|
|
user_add.add_argument("email", help="Email address")
|
|
user_add.set_defaults(func=cmd_user_add)
|
|
|
|
user_delete = user_subparsers.add_parser("delete", help="Delete user")
|
|
user_delete.add_argument("username", help="Username")
|
|
user_delete.set_defaults(func=cmd_user_delete)
|
|
|
|
user_passwd = user_subparsers.add_parser("passwd", help="Change password")
|
|
user_passwd.add_argument("username", help="Username")
|
|
user_passwd.set_defaults(func=cmd_user_passwd)
|
|
|
|
user_email = user_subparsers.add_parser("email", help="Update email")
|
|
user_email.add_argument("username", help="Username")
|
|
user_email.add_argument("email", help="New email address")
|
|
user_email.set_defaults(func=cmd_user_email)
|
|
|
|
# Hostname commands
|
|
hostname_parser = subparsers.add_parser("hostname", help="Hostname management")
|
|
hostname_subparsers = hostname_parser.add_subparsers(dest="hostname_command")
|
|
|
|
hostname_list = hostname_subparsers.add_parser("list", help="List hostnames")
|
|
hostname_list.add_argument("--user", help="Filter by username")
|
|
hostname_list.set_defaults(func=cmd_hostname_list)
|
|
|
|
hostname_add = hostname_subparsers.add_parser("add", help="Add hostname")
|
|
hostname_add.add_argument("username", help="Username")
|
|
hostname_add.add_argument("hostname", help="Hostname (FQDN)")
|
|
hostname_add.add_argument("zone", help="DNS zone")
|
|
hostname_add.add_argument("--dns-ttl", type=int, help="DNS record TTL")
|
|
hostname_add.add_argument("--expiry-ttl", type=int, help="Expiry TTL")
|
|
hostname_add.set_defaults(func=cmd_hostname_add)
|
|
|
|
hostname_delete = hostname_subparsers.add_parser(
|
|
"delete", help="Delete hostname"
|
|
)
|
|
hostname_delete.add_argument("hostname", help="Hostname (FQDN)")
|
|
hostname_delete.add_argument("zone", help="DNS zone")
|
|
hostname_delete.set_defaults(func=cmd_hostname_delete)
|
|
|
|
hostname_modify = hostname_subparsers.add_parser(
|
|
"modify", help="Modify hostname"
|
|
)
|
|
hostname_modify.add_argument("hostname", help="Hostname (FQDN)")
|
|
hostname_modify.add_argument("zone", help="DNS zone")
|
|
hostname_modify.add_argument("--dns-ttl", type=int, help="DNS record TTL")
|
|
hostname_modify.add_argument("--expiry-ttl", type=int, help="Expiry TTL")
|
|
hostname_modify.set_defaults(func=cmd_hostname_modify)
|
|
|
|
# Cleanup command
|
|
cleanup_parser = subparsers.add_parser("cleanup", help="Run cleanup manually")
|
|
cleanup_parser.set_defaults(func=cmd_cleanup)
|
|
|
|
return parser
|
|
|
|
|
|
def main():
|
|
"""Main entry point."""
|
|
parser = build_parser()
|
|
args = parser.parse_args()
|
|
|
|
# Load config
|
|
try:
|
|
config_path = find_config_file(args.config)
|
|
config = load_config(config_path)
|
|
except ConfigError as e:
|
|
print(f"Error: {e}", file=sys.stderr)
|
|
return 1
|
|
|
|
# Setup logging based on mode
|
|
if args.daemon:
|
|
log_level = "DEBUG" if args.debug else config["daemon"]["log_level"]
|
|
setup_logging(
|
|
level=log_level,
|
|
target=config["daemon"]["log_target"],
|
|
syslog_socket=config["daemon"]["syslog_socket"],
|
|
syslog_facility=config["daemon"]["syslog_facility"],
|
|
log_file=config["daemon"]["log_file"],
|
|
log_file_size=config["daemon"]["log_file_size"],
|
|
log_versions=config["daemon"]["log_versions"],
|
|
)
|
|
else:
|
|
if config["daemon"]["log_target"] == "stdout" and not args.debug:
|
|
disable_logging()
|
|
else:
|
|
log_level = "DEBUG" if args.debug else config["daemon"]["log_level"]
|
|
setup_logging(
|
|
level=log_level,
|
|
target=config["daemon"]["log_target"],
|
|
syslog_socket=config["daemon"]["syslog_socket"],
|
|
syslog_facility=config["daemon"]["syslog_facility"],
|
|
log_file=config["daemon"]["log_file"],
|
|
log_file_size=config["daemon"]["log_file_size"],
|
|
log_versions=config["daemon"]["log_versions"],
|
|
)
|
|
|
|
# Create application instance
|
|
app = Application(config, config_path)
|
|
|
|
# Initialize database
|
|
try:
|
|
app.init_database()
|
|
except Exception as e:
|
|
print(f"Error: Database initialization failed: {e}", file=sys.stderr)
|
|
return 1
|
|
|
|
# Handle --init-db
|
|
if args.init_db:
|
|
return
|
|
|
|
# Handle --daemon
|
|
if args.daemon:
|
|
try:
|
|
# Initialize all services for daemon mode
|
|
app.init_dns()
|
|
app.init_email()
|
|
app.init_rate_limiters()
|
|
run_daemon(app)
|
|
return 0
|
|
except Exception as e:
|
|
print(f"Error: Daemon error: {e}", file=sys.stderr)
|
|
return 1
|
|
|
|
# Handle subcommands
|
|
if args.command and hasattr(args, "func"):
|
|
return args.func(args, app)
|
|
|
|
# No command specified
|
|
parser.print_help()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|