add envcheck and basic connection check startup command
parent
991ab6a2bd
commit
cacf6e43b8
@ -0,0 +1,57 @@
|
|||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
TOPIC = """
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Connection check #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""command framework"""
|
||||||
|
|
||||||
|
TIMEOUT = 120
|
||||||
|
|
||||||
|
# pylint: disable=no-member
|
||||||
|
help = "Check connections"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""run all commands"""
|
||||||
|
self.stdout.write(TOPIC)
|
||||||
|
self._es_connection_check()
|
||||||
|
|
||||||
|
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):
|
||||||
|
sleep(2)
|
||||||
|
sys.stdout.write(".")
|
||||||
|
try:
|
||||||
|
response, status_code = ElasticWrap("/").get(
|
||||||
|
timeout=1, print_error=False
|
||||||
|
)
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if status_code == 200:
|
||||||
|
self.stdout.write("\n ✓ ES connection established")
|
||||||
|
return
|
||||||
|
|
||||||
|
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}")
|
||||||
|
raise CommandError(message)
|
@ -0,0 +1,195 @@
|
|||||||
|
"""
|
||||||
|
Functionality:
|
||||||
|
- Check environment at startup
|
||||||
|
- Process config file overwrites from env var
|
||||||
|
- Stop startup on error
|
||||||
|
- python management.py ta_envcheck
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from home.models import Account
|
||||||
|
|
||||||
|
LOGO = """
|
||||||
|
|
||||||
|
.... .....
|
||||||
|
...'',;:cc,. .;::;;,'...
|
||||||
|
..,;:cccllclc, .:ccllllcc;,..
|
||||||
|
..,:cllcc:;,'.',. ....'',;ccllc:,..
|
||||||
|
..;cllc:,'.. ...,:cccc:'.
|
||||||
|
.;cccc;.. ..,:ccc:'.
|
||||||
|
.ckkkOkxollllllllllllc. .,:::;. .,cclc;
|
||||||
|
.:0MMMMMMMMMMMMMMMMMMMX: .cNMMMWx. .;clc:
|
||||||
|
.;lOXK0000KNMMMMX00000KO; ;KMMMMMNl. .;ccl:,.
|
||||||
|
.;:c:'.....kMMMNo........ 'OMMMWMMMK: '::;;'.
|
||||||
|
....... .xMMMNl .dWMMXdOMMMO' ........
|
||||||
|
.:cc:;. .xMMMNc .lNMMNo.:XMMWx. .:cl:.
|
||||||
|
.:llc,. .:xxxd, ;KMMMk. .oWMMNl. .:llc'
|
||||||
|
.cll:. .;:;;:::,. 'OMMMK:';''kWMMK: .;llc,
|
||||||
|
.cll:. .,;;;;;;,. .,xWMMNl.:l:.;KMMMO' .;llc'
|
||||||
|
.:llc. .cOOOk; .lKNMMWx..:l:..lNMMWx. .:llc'
|
||||||
|
.;lcc,. .xMMMNc :KMMMM0, .:lc. .xWMMNl.'ccl:.
|
||||||
|
.cllc. .xMMMNc 'OMMMMXc...:lc...,0MMMKl:lcc,.
|
||||||
|
.,ccl:. .xMMMNc .xWMMMWo.,;;:lc;;;.cXMMMXdcc;.
|
||||||
|
.,clc:. .xMMMNc .lNMMMWk. .':clc:,. .dWMMW0o;.
|
||||||
|
.,clcc,. .ckkkx; .okkkOx, .';,. 'kKKK0l.
|
||||||
|
.':lcc:'..... . .. ..,;cllc,.
|
||||||
|
.,cclc,.... ....;clc;..
|
||||||
|
..,:,..,c:'.. ...';:,..,:,.
|
||||||
|
....:lcccc:;,'''.....'',;;:clllc,....
|
||||||
|
.'',;:cllllllccccclllllcc:,'..
|
||||||
|
...'',,;;;;;;;;;,''...
|
||||||
|
.....
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
TOPIC = """
|
||||||
|
#######################
|
||||||
|
# Environment Setup #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXPECTED_ENV_VARS = [
|
||||||
|
"TA_USERNAME",
|
||||||
|
"TA_PASSWORD",
|
||||||
|
"ELASTIC_PASSWORD",
|
||||||
|
"ES_URL",
|
||||||
|
"TA_HOST",
|
||||||
|
]
|
||||||
|
INST = "https://github.com/tubearchivist/tubearchivist#installing-and-updating"
|
||||||
|
NGINX = "/etc/nginx/sites-available/default"
|
||||||
|
UWSGI = "/app/uwsgi.ini"
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""command framework"""
|
||||||
|
|
||||||
|
# pylint: disable=no-member
|
||||||
|
help = "Check environment before startup"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""run all commands"""
|
||||||
|
self.stdout.write(LOGO)
|
||||||
|
self.stdout.write(TOPIC)
|
||||||
|
self._expected_vars()
|
||||||
|
self._elastic_user_overwrite()
|
||||||
|
self._ta_port_overwrite()
|
||||||
|
self._ta_uwsgi_overwrite()
|
||||||
|
self._enable_cast_overwrite()
|
||||||
|
self._create_superuser()
|
||||||
|
|
||||||
|
def _expected_vars(self):
|
||||||
|
"""check if expected env vars are set"""
|
||||||
|
self.stdout.write("[1] checking expected env vars")
|
||||||
|
env = os.environ
|
||||||
|
for var in EXPECTED_ENV_VARS:
|
||||||
|
if not env.get(var):
|
||||||
|
message = f" 🗙 expected env var {var} not set\n {INST}"
|
||||||
|
self.stdout.write(self.style.ERROR(message))
|
||||||
|
raise CommandError(message)
|
||||||
|
|
||||||
|
message = " ✓ all expected env vars are set"
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
|
||||||
|
def _elastic_user_overwrite(self):
|
||||||
|
"""check for ELASTIC_USER overwrite"""
|
||||||
|
self.stdout.write("[2] set default ES user")
|
||||||
|
if not os.environ.get("ELASTIC_USER"):
|
||||||
|
os.environ.setdefault("ELASTIC_USER", "elastic")
|
||||||
|
|
||||||
|
env = os.environ.get("ELASTIC_USER")
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(f" ✓ ES user is set to {env}"))
|
||||||
|
|
||||||
|
def _ta_port_overwrite(self):
|
||||||
|
"""set TA_PORT overwrite for nginx"""
|
||||||
|
self.stdout.write("[3] check TA_PORT overwrite")
|
||||||
|
overwrite = os.environ.get("TA_PORT")
|
||||||
|
if not overwrite:
|
||||||
|
self.stdout.write(self.style.SUCCESS(" TA_PORT is not set"))
|
||||||
|
return
|
||||||
|
|
||||||
|
regex = re.compile(r"listen [0-9]{1,5}")
|
||||||
|
changed = file_overwrite(NGINX, regex, overwrite)
|
||||||
|
if changed:
|
||||||
|
message = f" ✓ TA_PORT changed to {overwrite}"
|
||||||
|
else:
|
||||||
|
message = f" ✓ TA_PORT already set to {overwrite}"
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
|
||||||
|
def _ta_uwsgi_overwrite(self):
|
||||||
|
"""set TA_UWSGI_PORT overwrite"""
|
||||||
|
self.stdout.write("[4] check TA_UWSGI_PORT overwrite")
|
||||||
|
overwrite = os.environ.get("TA_UWSGI_PORT")
|
||||||
|
if not overwrite:
|
||||||
|
message = " TA_UWSGI_PORT is not set"
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
return
|
||||||
|
|
||||||
|
# nginx
|
||||||
|
regex = re.compile(r"uwsgi_pass localhost:[0-9]{1,5}")
|
||||||
|
to_overwrite = f"uwsgi_pass localhost:{overwrite}"
|
||||||
|
changed = file_overwrite(NGINX, regex, to_overwrite)
|
||||||
|
|
||||||
|
# uwsgi
|
||||||
|
regex = re.compile(r"socket = :[0-9]{1,5}")
|
||||||
|
to_overwrite = f"socket = :{overwrite}"
|
||||||
|
changed = file_overwrite(UWSGI, regex, to_overwrite)
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
message = f" ✓ TA_UWSGI_PORT changed to {overwrite}"
|
||||||
|
else:
|
||||||
|
message = f" ✓ TA_UWSGI_PORT already set to {overwrite}"
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
|
||||||
|
def _enable_cast_overwrite(self):
|
||||||
|
"""cast workaround, remove auth for static files in nginx"""
|
||||||
|
self.stdout.write("[5] check ENABLE_CAST overwrite")
|
||||||
|
overwrite = os.environ.get("ENABLE_CAST")
|
||||||
|
if not overwrite:
|
||||||
|
self.stdout.write(self.style.SUCCESS(" ENABLE_CAST is not set"))
|
||||||
|
return
|
||||||
|
|
||||||
|
regex = re.compile(r"[^\S\r\n]*auth_request /api/ping/;\n")
|
||||||
|
changed = file_overwrite(NGINX, regex, "")
|
||||||
|
if changed:
|
||||||
|
message = " ✓ process nginx to enable Cast"
|
||||||
|
else:
|
||||||
|
message = " ✓ Cast is already enabled in nginx"
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
|
||||||
|
def _create_superuser(self):
|
||||||
|
"""create superuser if not exist"""
|
||||||
|
self.stdout.write("[6] create superuser")
|
||||||
|
is_created = Account.objects.filter(is_superuser=True)
|
||||||
|
if is_created:
|
||||||
|
message = " superuser already created"
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
return
|
||||||
|
|
||||||
|
name = os.environ.get("TA_USERNAME")
|
||||||
|
password = os.environ.get("TA_PASSWORD")
|
||||||
|
Account.objects.create_superuser(name, password)
|
||||||
|
message = f" ✓ new superuser with name {name} created"
|
||||||
|
self.stdout.write(self.style.SUCCESS(message))
|
||||||
|
|
||||||
|
|
||||||
|
def file_overwrite(file_path, regex, overwrite):
|
||||||
|
"""change file content from old to overwrite, return true when changed"""
|
||||||
|
with open(file_path, "r", encoding="utf-8") as f:
|
||||||
|
file_content = f.read()
|
||||||
|
|
||||||
|
changed = re.sub(regex, overwrite, file_content)
|
||||||
|
if changed == file_content:
|
||||||
|
return False
|
||||||
|
|
||||||
|
with open(file_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(changed)
|
||||||
|
|
||||||
|
return True
|
Loading…
Reference in New Issue