From 1b5a810520496f11146cc45261302520c7099dbe Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 1 Feb 2023 16:05:29 +0700 Subject: [PATCH] finalize connection check manage.py command --- docker_assets/run.sh | 15 +-- .../management/commands/ta_connection.py | 109 +++++++++++++++--- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/docker_assets/run.sh b/docker_assets/run.sh index ca1fdd9..d18267d 100644 --- a/docker_assets/run.sh +++ b/docker_assets/run.sh @@ -1,25 +1,12 @@ #!/bin/bash # startup script inside the container for tubearchivist +set -e # check environment python manage.py ta_envcheck python manage.py ta_connection -# wait for elasticsearch -# counter=0 -# until curl -u "$ELASTIC_USER":"$ELASTIC_PASSWORD" "$ES_URL" -fs; do -# echo "waiting for elastic search to start" -# counter=$((counter+1)) -# if [[ $counter -eq 12 ]]; then -# # fail after 2 min -# echo "failed to connect to elastic search, exiting..." -# curl -v -u "$ELASTIC_USER":"$ELASTIC_PASSWORD" "$ES_URL"?pretty -# exit 1 -# fi -# sleep 10 -# done - # start python application python manage.py makemigrations python manage.py migrate diff --git a/tubearchivist/config/management/commands/ta_connection.py b/tubearchivist/config/management/commands/ta_connection.py index 9c68821..15bb91b 100644 --- a/tubearchivist/config/management/commands/ta_connection.py +++ b/tubearchivist/config/management/commands/ta_connection.py @@ -3,13 +3,12 @@ Functionality: - check that all connections are working """ -import sys from time import sleep import requests from django.core.management.base import BaseCommand, CommandError from home.src.es.connect import ElasticWrap - +from home.src.ta.ta_redis import RedisArchivist TOPIC = """ @@ -19,10 +18,13 @@ TOPIC = """ """ + class Command(BaseCommand): """command framework""" TIMEOUT = 120 + MIN_MAJOR, MAX_MAJOR = 8, 8 + MIN_MINOR = 0 # pylint: disable=no-member help = "Check connections" @@ -30,28 +32,109 @@ class Command(BaseCommand): def handle(self, *args, **options): """run all commands""" self.stdout.write(TOPIC) + self._redis_connection_check() + self._redis_config_set() self._es_connection_check() + self._es_version_check() + self._es_path_check() + + def _redis_connection_check(self): + """check ir redis connection is established""" + self.stdout.write("[1] connect to Redis") + redis_conn = RedisArchivist().conn + for _ in range(5): + sleep(2) + try: + pong = redis_conn.execute_command("PING") + if pong: + self.stdout.write( + self.style.SUCCESS(" ✓ Redis connection verified") + ) + return + + except Exception: # pylint: disable=broad-except + self.stdout.write(" ... retry Redis connection") + + message = " 🗙 Redis connection failed" + self.stdout.write(self.style.ERROR(f"{message}")) + RedisArchivist().exec("PING") + raise CommandError(message) + + def _redis_config_set(self): + """set config for redis if not set already""" + self.stdout.write("[2] set Redis config") + redis_conn = RedisArchivist().conn + timeout_is = int(redis_conn.config_get("timeout").get("timeout")) + if not timeout_is: + redis_conn.config_set("timeout", 3600) + + self.stdout.write(self.style.SUCCESS(" ✓ Redis config set")) def _es_connection_check(self): """wait for elasticsearch connection""" - self.stdout.write("[1] connect to Elastic Search") - sys.stdout.write(" .") - for _ in range(self.TIMEOUT // 5): + self.stdout.write("[3] connect to Elastic Search") + total = self.TIMEOUT // 5 + for i in range(total): sleep(2) - sys.stdout.write(".") + self.stdout.write(f" ... waiting for ES [{i}/{total}]") try: - response, status_code = ElasticWrap("/").get( + _, status_code = ElasticWrap("/").get( timeout=1, print_error=False ) except requests.exceptions.ConnectionError: - pass + continue - if status_code == 200: - self.stdout.write("\n ✓ ES connection established") + if status_code and status_code == 200: + self.stdout.write( + self.style.SUCCESS(" ✓ ES connection established") + ) return + response, status_code = ElasticWrap("/").get( + timeout=1, print_error=False + ) + message = " 🗙 ES connection failed" - self.stdout.write(self.style.ERROR(f"\n{message}")) - self.stdout.write(f" error message: {response | None}") - self.stdout.write(f" status code: {status_code | None}") + self.stdout.write(self.style.ERROR(f"{message}")) + self.stdout.write(f" error message: {response}") + self.stdout.write(f" status code: {status_code}") raise CommandError(message) + + def _es_version_check(self): + """check for minimal elasticsearch version""" + self.stdout.write("[4] Elastic Search version check") + response, _ = ElasticWrap("/").get() + version = response["version"]["number"] + major = int(version.split(".")[0]) + + if self.MIN_MAJOR <= major <= self.MAX_MAJOR: + self.stdout.write( + self.style.SUCCESS(" ✓ ES version check passed") + ) + return + + message = ( + " 🗙 ES connection failed. " + + f"Expected {self.MIN_MAJOR}.{self.MIN_MINOR} but got {version}" + ) + self.stdout.write(self.style.ERROR(f"{message}")) + raise CommandError(message) + + def _es_path_check(self): + """check that path.repo var is set""" + self.stdout.write("[5] check ES path.repo env var") + response, _ = ElasticWrap("_nodes/_all/settings").get() + for node in response["nodes"].values(): + if node["settings"]["path"].get("repo"): + self.stdout.write( + self.style.SUCCESS(" ✓ path.repo env var is set") + ) + return + + message = ( + " 🗙 path.repo env var not found. " + + "set the following env var to the ES container:\n" + + " path.repo=/usr/share/elasticsearch/data/snapshot" + ) + self.stdout.write(self.style.ERROR(f"{message}")) + raise CommandError(message)