certupdater/main.py
Egor Matveev 32377d93fe
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 11s
Deploy Dev / Deploy dev (pull_request) Successful in 14s
fix
2025-06-12 00:54:10 +03:00

145 lines
4.2 KiB
Python

import datetime
import io
import os
import subprocess
import time
from requests import post
from configurator import configurator
from mongo import mongo
from blob import minio
class Response:
code: int
out: str
err: str
def send_notification(text: str):
post(
"http://queues:1239/api/v1/put",
headers={"queue": "botalka_mailbox"},
json={
"payload": {
"project": "notifications-bot",
"name": "telegram-bot",
"body": {
"text": text,
"chat_id": 84367486,
},
},
"seconds_to_execute": 1,
"delay": None,
},
)
def call(command: str) -> Response:
p = subprocess.Popen(
command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True
)
resp = p.wait()
response = Response()
response.code = resp
response.out, response.err = p.stdout.read().decode(
"utf-8"
), p.stderr.read().decode("utf-8")
return response
def get_hosts() -> list[str]:
if os.getenv("STAGE") == "development":
return list(set(list(configurator.get_config("hosts"))))
else:
return list(set(list(configurator.get_config("hosts"))))
def update_host(host: str) -> str | None:
if os.getenv("STAGE") == "development":
container_id_run = call("echo $(docker ps -q -f name=infra-development_nginx)")
else:
container_id_run = call("echo $(docker ps -q -f name=infra_nginx)")
if container_id_run.code != 0:
return container_id_run.err
container_name = container_id_run.out.strip()
if not container_name:
return "no nginx container"
gen_command = f'docker exec {container_name} certbot --nginx --email emmtvv@gmail.com --agree-tos --non-interactive -d "{host}"'
gen_cert = call(gen_command)
if gen_cert.code != 0:
log = call(
f"docker exec {container_name} cat /var/log/letsencrypt/letsencrypt.log"
).out
return f"failed generating certificate: {log}"
fullchain_command = call(
f"docker exec {container_name} cat /etc/letsencrypt/live/{host}/fullchain.pem"
)
if fullchain_command.code != 0:
return f"failed getting fullchain: {fullchain_command.err}"
privkey_command = call(
f"docker exec {container_name} cat /etc/letsencrypt/live/{host}/privkey.pem"
)
if privkey_command.code != 0:
return f"failed getting fullchain: {privkey_command.err}"
fullchain = fullchain_command.out.encode("utf-8")
privkey = privkey_command.out.encode("utf-8")
minio.put_object(
"certupdater",
f"certificates/{host}/fullchain.pem",
io.BytesIO(fullchain),
len(fullchain),
)
minio.put_object(
"certupdater",
f"certificates/{host}/privkey.pem",
io.BytesIO(privkey),
len(privkey),
)
return None
while True:
now = datetime.datetime.now()
mongo_hosts = mongo.hosts
updated = False
for host in get_hosts():
if (
now + datetime.timedelta(days=14)
> mongo_hosts.get(
host, {"expire_time": datetime.datetime.fromtimestamp(1)}
)["expire_time"]
):
success = update_host(host)
if success:
send_notification(
f"host {host} was not updated with an error: {success}"
)
else:
mongo.update_date(host)
updated = True
send_notification(f"host {host} updated")
if updated:
if os.getenv("STAGE") == "development":
container_id_run = call(
"echo $(docker ps -q -f name=infra-development_nginx)"
)
else:
container_id_run = call("echo $(docker ps -q -f name=infra_nginx)")
print(container_id_run.code, container_id_run.out, container_id_run.err)
command = f"docker exec {container_id_run.out.strip()} ./refre.sh"
print(command)
restart = call(command)
print(restart.code, restart.out, restart.err)
send_notification(f"Balancer for {os.getenv("STAGE")} was restarted")
time.sleep(30)