#!/usr/bin/python3 import subprocess # nosec 404 import sys from argparse import ArgumentParser from pathlib import Path ADVLABDB_REPO_LINK = "https://gitlab.rlp.net/mobitar/advlabdb.git" VOLUMES_DIR = Path.home() / "volumes" ADVLABDB_VOLUMES_DIR = VOLUMES_DIR / "advlabdb" ADVLABDB_REPO_DIR = ADVLABDB_VOLUMES_DIR / "repo" ADVLABDB_LOGS_DIR = ADVLABDB_VOLUMES_DIR / "logs" TRAEFIK_VOLUMES_DIR = VOLUMES_DIR / "traefik" TRAEFIK_ETC_DIR = TRAEFIK_VOLUMES_DIR / "etc" NGINX_CONF_D_DIR = VOLUMES_DIR / "nginx/conf.d" TRAEFIK_LOGS_DIR = TRAEFIK_VOLUMES_DIR / "logs" TRAEFIK_CERTS_DIR = TRAEFIK_VOLUMES_DIR / "certs" SYSTEMD_USER_DIR = Path.home() / ".config/systemd/user" def run(command: str, **kwargs): return subprocess.run(command, shell=True, **kwargs) # nosec B602 SYSTEMD_USER_DIR.mkdir(parents=True, exist_ok=True) def create_container(container_name: str, podman_args: str): run( f"""podman create \ --name {container_name} \ {podman_args}""", check=True, ) run( f"podman generate systemd --new --files --name {container_name}", cwd=SYSTEMD_USER_DIR, check=True, ) run( f"systemctl --user enable --now container-{container_name}", check=True, ) parser = ArgumentParser( description="Build the AdvLabDB image and deploy related containers", ) parser.add_argument( "--skip-traefik", action="store_true", help="Do not deploy the Traefik container", ) parser.add_argument( "--skip-nginx", action="store_true", help="Do not deploy the Nginx container", ) parser.add_argument( "-n", "--network", default="traefik", help="Traefik's network. Default: traefik", ) args = parser.parse_args() env_file = ADVLABDB_REPO_DIR / ".env" if ADVLABDB_REPO_DIR.is_dir(): run( "git pull", cwd=ADVLABDB_REPO_DIR, check=True, ) if not env_file.is_file(): sys.exit(f"{env_file} missing!") else: ADVLABDB_VOLUMES_DIR.mkdir(parents=True, exist_ok=True) print("Cloning repository") run( f"git clone {ADVLABDB_REPO_LINK} {ADVLABDB_REPO_DIR}", check=True, ) sys.exit(f"{env_file} missing!") if not args.skip_traefik: if not TRAEFIK_ETC_DIR.is_dir(): sys.exit(f"{TRAEFIK_ETC_DIR} missing!") if not args.skip_nginx: if not NGINX_CONF_D_DIR.is_dir(): sys.exit(f"{NGINX_CONF_D_DIR} missing!") if run(f"podman network exists {args.network}").returncode != 0: if args.skip_traefik: sys.exit(f"Skipped Traefik's deployment although Traefik's network {args.network} does not exist!") else: run( f"podman network create {args.network}", check=True, ) run( "buildah rm builder", stderr=subprocess.DEVNULL, ) commands = [ "buildah from --pull --name builder docker.io/library/python:slim", "buildah config --workingdir / builder", f"buildah copy builder {ADVLABDB_REPO_DIR} /volumes/repo", "buildah config --workingdir /volumes/repo builder", "buildah run builder -- pip3 install -r requirements.txt", # TODO: Only when database does not exist "buildah run builder -- python3 -m advlabdb.scripts.setup.init_database", "buildah config --cmd 'gunicorn --bind 0.0.0.0:80 --workers 5 --log-file /volumes/logs/gunicorn.log run:app' builder", ] for command in commands: run(command, check=True) if run("systemctl --user is-enabled container-advlabdb").returncode == 0: run( "systemctl --user disable --now container-advlabdb", check=True, ) if run("podman image exists advlabdb").returncode == 0: run( "podman rmi advlabdb", check=True, ) run( "buildah commit --rm builder advlabdb", check=True, ) ADVLABDB_LOGS_DIR.mkdir(parents=True, exist_ok=True) create_container( "advlabdb", # TODO: Add database as volume f"""--network {args.network} \ -v {ADVLABDB_LOGS_DIR}:/volumes/logs:Z \ localhost/advlabdb:latest""", ) if not args.skip_traefik and run("systemctl --user is-enabled container-traefik").returncode != 0: TRAEFIK_LOGS_DIR.mkdir(parents=True, exist_ok=True) TRAEFIK_CERTS_DIR.mkdir(parents=True, exist_ok=True) create_container( "traefik", f"""--label "io.containers.autoupdate=registry" \ --network {args.network} \ -p 80:80 \ -p 443:443 \ -v {TRAEFIK_ETC_DIR}:/etc/traefik:ro:Z,ro \ -v {TRAEFIK_LOGS_DIR}:/volumes/logs:Z \ -v {TRAEFIK_CERTS_DIR}:/volumes/certs:Z \ docker.io/library/traefik:latest""", ) if not args.skip_nginx and run("systemctl --user is-enabled container-nginx").returncode != 0: create_container( "nginx", f"""--label "io.containers.autoupdate=registry" \ --network {args.network} \ -v {NGINX_CONF_D_DIR}:/etc/nginx/conf.d:Z,ro \ docker.io/library/nginx:alpine""", ) print("\nDone!\n")