diff options
Diffstat (limited to 'tools/cru-py/crupest/aio.py')
| -rw-r--r-- | tools/cru-py/crupest/aio.py | 319 | 
1 files changed, 319 insertions, 0 deletions
| diff --git a/tools/cru-py/crupest/aio.py b/tools/cru-py/crupest/aio.py new file mode 100644 index 0000000..0a26146 --- /dev/null +++ b/tools/cru-py/crupest/aio.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 + +try: +    import rich +    import jsonschema +    import cryptography +except ImportError: +    print("Some necessary crupest can't be imported. Please run `pip install -r requirements.txt` to install them.") +    exit(1) + +from os.path import * +import argparse +import subprocess +from rich.prompt import Confirm +from install_docker import * +from path import * +from nginx import * +from config import * +from check import * +from backup import * +from download_tools import * +from test import * +from dns import * +from setup import * + +from tui import console + + +parser = argparse.ArgumentParser( +    description="Crupest server all-in-one setup script. Have fun play with it!") +parser.add_argument("--no-hello", action="store_true", +                    default=False, help="Do not print hello message.") +parser.add_argument("--no-bye-bye", action="store_true", +                    default=False, help="Do not print bye-bye message.") + +parser.add_argument("--no-check-python-version", action="store_true", +                    default=False, help="Do not check python version.") +parser.add_argument("--no-check-system", action="store_true", +                    default=False, help="Do not check system type.") +parser.add_argument("-y", "--yes", action="store_true", +                    default=False, help="Yes to all confirmation.") + +subparsers = parser.add_subparsers(dest="action") + +setup_parser = subparsers.add_parser( +    "setup", help="Do everything necessary to setup the server.") + +print_path_parser = subparsers.add_parser( +    "print-path", help="Print the paths of all related files and dirs.") + +download_tools_parser = subparsers.add_parser( +    "download-tools", help="Download some extra tools to manage the server.") + +list_domain_parser = subparsers.add_parser( +    "list-domain", help="Misc things about domains.") + +nginx_parser = subparsers.add_parser( +    "nginx", help="Generate nginx config.") + +certbot_parser = subparsers.add_parser( +    "certbot", help="Get some common certbot commands.") + +certbot_command_group = certbot_parser.add_mutually_exclusive_group() + +certbot_command_group.add_argument( +    "-C", "--create", action="store_true", default=False, help="Only print the command for 'create' action.") +certbot_command_group.add_argument( +    "-E", "--expand", action="store_true", default=False, help="Only print the command for 'expand' action.") +certbot_command_group.add_argument( +    "-R", "--renew", action="store_true", default=False, help="Only print the command for 'renew' action.") + +certbot_parser.add_argument( +    "-t", "--test", action="store_true", default=False, help="Make the commands for test use.") + +clear_parser = subparsers.add_parser( +    "clear", help="Delete existing data so you can make a fresh start.") +clear_parser.add_argument("-D", "--include-data-dir", action="store_true", +                          default=False, help="Also delete the data directory.") + +install_docker_parser = subparsers.add_parser( +    "install-docker", help="Install docker and docker-compose.") + +backup_parser = subparsers.add_parser( +    "backup", help="Backup related things." +) + +backup_subparsers = backup_parser.add_subparsers(dest="backup_action") +backup_restore_parser = backup_subparsers.add_parser( +    "restore", help="Restore data from url.") +backup_restore_parser.add_argument( +    "restore_url", help="Restore archive url. Can be local path or http/https.") +backup_backup_parser = backup_subparsers.add_parser( +    "backup", help="Backup data to specified path.") +backup_backup_parser.add_argument( +    "backup_path", nargs="?", help="Backup path. Can be empty for a timestamp as name. Must be local path.") + +docker_parser = subparsers.add_parser("docker", help="Docker related things.") +docker_subparsers = docker_parser.add_subparsers(dest="docker_action") +docker_subparsers.add_parser("up", help="Run docker compose up -d.") +docker_subparsers.add_parser("down", help="Run docker compose down.") +docker_subparsers.add_parser( +    "prune", help="Run docker system prune -a -f.") + +test_parser = subparsers.add_parser("test", help="Test things.") +test_parser.add_argument( +    "test_action", help="Test action.", choices=["crupest-api"]) + +dns_parser = subparsers.add_parser("dns", help="Generate dns zone.") + +dns_parser.add_argument("-i", "--ip", help="IP address of the server.") + +git_update_parser = subparsers.add_parser( +    "git-update", help="Update git submodules.") + +update_blog_parser = subparsers.add_parser( +    "update-blog", help="Update and regenerate blog.") + +up_parser = subparsers.add_parser( +    "up", help="Do something necessary and then docker compose up.") + +down_parser = subparsers.add_parser( +    "down", help="Do something necessary and then docker compose down.") + +args = parser.parse_args() + +if args.yes: +    old_ask = Confirm.ask + +    def new_ask(prompt, *args, console=console, default=None, **kwargs): +        default_text = "" +        if default is not None: +            default_text = "(y)" if default else "(n)" +        text = f"[prompt]{prompt}[/] [prompt.choices]\\[y/n][/] [prompt.default]{default_text}[/]" +        console.print(text) +        return True + +    Confirm.ask = new_ask + +if (args.action == "certbot" and (args.create or args.renew or args.expand)) or (args.action == "dns" and args.ip is not None): +    args.no_hello = True +    args.no_bye_bye = True + + +if not args.no_check_python_version: +    if check_python_version(): +        console.print("This script works well on python 3.10. Otherwise you may encounter some problems. But I would like to improve some rational compatibility.", style="yellow") + +if not args.no_check_system: +    if not check_ubuntu(): +        console.print("This script works well on Ubuntu 22.04. Otherwise you may encounter some problems. But I would like to improve some rational compatibility.", style="yellow") + + +if not args.no_hello: +    console.print("Nice to see you! :waving_hand:", style="cyan") + + +def check_domain_is_defined(): +    try: +        return get_domain() +    except Exception as e: +        console.print(e.args[0], style="red") +        raise e + + +def git_update(): +    def do_it(): +        subprocess.run(["git", "pull"], check=True) +    run_in_project_dir(do_it) + + +def update_blog(): +    def do_it(): +        subprocess.run(["docker", "compose", "exec", +                       "crupest-blog", "/scripts/update.bash"], check=True) +    run_in_project_dir(do_it) + + +def docker_compose_up(): +    def do_docker_compose_up(): +        subprocess.run(["docker", "compose", "up", "-d"], check=True) +    run_in_dir(project_abs_path, do_docker_compose_up) + + +def docker_compose_down(): +    def do_docker_compose_down(): +        subprocess.run( +            ["docker", "compose", "down"], check=True) +    run_in_dir(project_abs_path, do_docker_compose_down) + + +action = args.action + + +def run(): +    match action: +        case "install-docker": +            install_docker() +            console.print( +                "Succeeded to install docker. Please re-login to take effect.", style="green") + +        case "docker": +            docker_action = args.docker_action + +            match docker_action: +                case "up": +                    docker_compose_up() +                case "down": +                    docker_compose_down() +                case "prune": +                    to_do = Confirm.ask( +                        "[yellow]Are you sure to prune docker?[/]", console=console) +                    if to_do: +                        subprocess.run( +                            ["docker", "system", "prune", "-a", "-f"], check=True) +                case _: +                    raise ValueError("Unknown docker action.") + +        case "backup": +            backup_action = args.backup_action +            match backup_action: +                case "backup": +                    backup_backup(args.backup_path, console) +                    console.print("Succeeded to restore data.", style="green") +                case "restore": +                    backup_restore(args.restore_path, console) +                    console.print("Succeeded to backup data.", style="green") + +        case 'print-path': +            console.print("Project path =", project_dir) +            console.print("Project absolute path =", project_abs_path) +            console.print("Data path =", data_dir) + +        case "download-tools": +            download_tools(console) + +        case "list-domain": +            domain = check_domain_is_defined() +            domains = list_domains(domain) +            for domain in domains: +                console.print(domain) + +        case "nginx": +            raise Exception("This command is deprecated.") + +        case "certbot": +            domain = check_domain_is_defined() +            is_test = args.test +            if args.create: +                console.print(certbot_command_gen(domain, "create", +                                                  test=is_test), soft_wrap=True, highlight=False) +            elif args.expand: +                console.print(certbot_command_gen(domain, "expand", +                                                  test=is_test), soft_wrap=True, highlight=False) +            elif args.renew: +                console.print(certbot_command_gen(domain, "renew", +                                                  test=is_test), soft_wrap=True, highlight=False) +            else: +                console.print( +                    "Here is some commands you can use to do certbot related work.") +                if is_test: +                    console.print( +                        "Note you specified --test, so the commands are for test use.", style="yellow") +                console.print( +                    "To create certs for init (standalone):", style="cyan") +                console.print(certbot_command_gen( +                    domain, 'create', test=is_test), soft_wrap=True) +                console.print("To expand certs (nginx):", style="cyan") +                console.print(certbot_command_gen( +                    domain, 'create', test=is_test), soft_wrap=True) +                console.print( +                    "To renew certs previously created (nginx):", style="cyan") +                console.print(certbot_command_gen( +                    domain, 'renew', test=is_test), soft_wrap=True) +        case "test": +            match args.test_action: +                case "crupest-api": +                    test_crupest_api(console) +                case _: +                    console.print("Test action invalid.", style="red") + +        case "dns": +            domain = check_domain_is_defined() +            if domain is not None: +                if args.ip is None: +                    ip = Prompt.ask( +                        "Please enter your server ip", console=console) +                else: +                    ip = args.ip +                console.print(generate_dns_zone_with_dkim( +                    domain, ip), soft_wrap=True, highlight=False) + +        case "git-update": +            git_update() + +        case "update-blog": +            update_blog() + +        case "up": +            git_update() +            template_generate(console) +            docker_compose_up() + +        case "down": +            docker_compose_down() + +        case "clear": +            clear(console, args.include_data_dir) + +        case _: +            template_generate(console) +            if Confirm.ask( +                    "By the way, would you like to download some scripts to do some extra setup like creating email user?", console=console, default=True): +                download_tools(console) + + +run() + +if not args.no_bye_bye: +    console.print(":beers: All done! Bye bye!", style="green") | 
