From e2f1871ed95fad79c4673e58be9a2537b963aa5b Mon Sep 17 00:00:00 2001 From: Mo8it Date: Sun, 31 Jul 2022 04:33:31 +0200 Subject: [PATCH] Add containers deploy script --- podman/deploy.py | 177 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100755 podman/deploy.py diff --git a/podman/deploy.py b/podman/deploy.py new file mode 100755 index 0000000..73103ef --- /dev/null +++ b/podman/deploy.py @@ -0,0 +1,177 @@ +#!/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")