diff --git a/bot.py b/bot.py index 783e625..7c312ce 100644 --- a/bot.py +++ b/bot.py @@ -1,5 +1,3 @@ -bot.py docker-compose.yml venv -lionel@ubuntuserver1:~/krotbot$ cat bot.py import os import time import subprocess @@ -10,9 +8,10 @@ load_dotenv() BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") ALLOWED_USER_ID = int(os.getenv("TELEGRAM_ALLOWED_USER_ID")) -DEPLOY_DIR = os.getenv("DEPLOY_DIR", "/home/lionel/docker-compose/arcade") -CI_COMPOSE_FILE = os.getenv("CI_COMPOSE_FILE", "docker-compose.ci.yml") -PROD_COMPOSE_FILE = os.getenv("PROD_COMPOSE_FILE", "docker-compose.prod.yml") +NAMESPACE = os.getenv("NAMESPACE", "devsecops") +DEPLOYMENT = os.getenv("DEPLOYMENT", "arcade") +CONTAINER = os.getenv("CONTAINER", "arcade") +IMAGE_REPO = os.getenv("IMAGE_REPO", "git.onlionel.com/gitea/arcade") if not BOT_TOKEN: raise RuntimeError("TELEGRAM_BOT_TOKEN ontbreekt") @@ -26,12 +25,12 @@ offset = None def send_message(chat_id: int, text: str) -> None: requests.post( f"{BASE_URL}/sendMessage", - data={"chat_id": chat_id, "text": text}, + data={"chat_id": chat_id, "text": text[:4000]}, timeout=20, ) -def run_cmd(cmd: str, timeout: int = 300) -> str: +def run_cmd(cmd: str, timeout: int = 120) -> str: result = subprocess.run( ["bash", "-lc", cmd], capture_output=True, @@ -44,47 +43,100 @@ def run_cmd(cmd: str, timeout: int = 300) -> str: return output +def k(cmd: str, timeout: int = 120) -> str: + return run_cmd(f"kubectl -n {NAMESPACE} {cmd}", timeout=timeout) + + def handle_command(chat_id: int, user_id: int, text: str) -> None: - text = text.strip().split()[0].split("@")[0] + parts = text.strip().split() + command = parts[0].split("@")[0] if parts else "" if user_id != ALLOWED_USER_ID: send_message(chat_id, "Niet toegestaan.") return - if text == "/start": - send_message(chat_id, "Bot actief. Beschikbare commando's: /status /deploy_stable") + if command == "/start": + send_message( + chat_id, + "Bot actief.\nBeschikbare commando's:\n" + "/status\n" + "/current\n" + "/history\n" + "/rollback\n" + "/deploy_sha " + ) return - if text == "/status": + if command == "/status": try: - output = run_cmd( - f"cd {DEPLOY_DIR} && docker compose -f {PROD_COMPOSE_FILE} ps", + rollout = k(f"rollout status deployment/{DEPLOYMENT} --timeout=60s", timeout=70) + pods = k(f"get pods -l app={DEPLOYMENT} -o wide", timeout=30) + send_message(chat_id, f"Rollout status:\n{rollout}\n\nPods:\n{pods}") + except Exception as e: + send_message(chat_id, f"Status ophalen mislukt:\n{str(e)}") + return + + if command == "/current": + try: + image = k( + f"get deployment {DEPLOYMENT} " + f"-o jsonpath='{{.spec.template.spec.containers[0].image}}'", + timeout=30, + ) + send_message(chat_id, f"Huidige image:\n{image}") + except Exception as e: + send_message(chat_id, f"Huidige image ophalen mislukt:\n{str(e)}") + return + + if command == "/history": + try: + history = k(f"rollout history deployment/{DEPLOYMENT}", timeout=30) + send_message(chat_id, f"Rollout history:\n{history}") + except Exception as e: + send_message(chat_id, f"History ophalen mislukt:\n{str(e)}") + return + + if command == "/rollback": + send_message(chat_id, "Rollback gestart...") + try: + undo = k(f"rollout undo deployment/{DEPLOYMENT}", timeout=60) + status = k(f"rollout status deployment/{DEPLOYMENT} --timeout=180s", timeout=190) + image = k( + f"get deployment {DEPLOYMENT} " + f"-o jsonpath='{{.spec.template.spec.containers[0].image}}'", + timeout=30, + ) + send_message(chat_id, f"Rollback voltooid.\n\n{undo}\n\n{status}\n\nNieuwe image:\n{image}") + except Exception as e: + send_message(chat_id, f"Rollback mislukt:\n{str(e)}") + return + + if command == "/deploy_sha": + if len(parts) < 2: + send_message(chat_id, "Gebruik: /deploy_sha ") + return + + sha = parts[1].strip() + if not sha or "/" in sha or ":" in sha: + send_message(chat_id, "Ongeldige sha/tag.") + return + + image = f"{IMAGE_REPO}:{sha}" + send_message(chat_id, f"Deploy gestart naar:\n{image}") + + try: + set_image = k( + f"set image deployment/{DEPLOYMENT} " + f"{CONTAINER}={image}", timeout=60, ) - send_message(chat_id, f"Productie status:\n\n{output[:3500]}") + status = k(f"rollout status deployment/{DEPLOYMENT} --timeout=180s", timeout=190) + send_message(chat_id, f"Deploy voltooid.\n\n{set_image}\n\n{status}") except Exception as e: - send_message(chat_id, f"Status ophalen mislukt:\n{str(e)[:3500]}") + send_message(chat_id, f"Deploy mislukt:\n{str(e)}") return - if text == "/deploy_stable": - send_message(chat_id, "Stable deployment gestart...") - - try: - commands = f""" - set -e - cd {DEPLOY_DIR} - docker compose -f {CI_COMPOSE_FILE} down || true - docker compose -f {PROD_COMPOSE_FILE} pull - docker compose -f {PROD_COMPOSE_FILE} up -d - docker compose -f {PROD_COMPOSE_FILE} ps - """ - output = run_cmd(commands, timeout=300) - send_message(chat_id, f"Stable uitgerold.\n\n{output[:3500]}") - except Exception as e: - send_message(chat_id, f"Deployment mislukt:\n{str(e)[:3500]}") - return - - send_message(chat_id, "Onbekend commando. Gebruik /deploy_stable of /status") + send_message(chat_id, "Onbekend commando. Gebruik /status, /current, /history, /rollback of /deploy_sha .") while True: @@ -100,12 +152,12 @@ while True: for update in updates: offset = update["update_id"] + 1 message = update.get("message", {}) - text = message.get("text", "").strip() + msg_text = message.get("text", "").strip() chat_id = message.get("chat", {}).get("id") user_id = message.get("from", {}).get("id") - if text and chat_id and user_id: - handle_command(chat_id, user_id, text) + if msg_text and chat_id and user_id: + handle_command(chat_id, user_id, msg_text) except Exception as e: print(f"Loop error: {e}")