Merge pull request 'master' (#48) from master into prod

Reviewed-on: #48
This commit is contained in:
emmatveev 2025-06-12 01:58:33 +03:00
commit 911c6225dc
4 changed files with 94 additions and 78 deletions

View File

@ -15,6 +15,7 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- configurator
- queues-development
deploy:
mode: replicated
restart_policy:
@ -28,3 +29,5 @@ services:
networks:
configurator:
external: true
queues-development:
external: true

View File

@ -15,6 +15,7 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- configurator
- queues
deploy:
mode: replicated
restart_policy:
@ -28,3 +29,5 @@ services:
networks:
configurator:
external: true
queues:
external: true

124
main.py
View File

@ -3,6 +3,8 @@ import io
import os
import subprocess
import time
from requests import post
from configurator import configurator
from mongo import mongo
from blob import minio
@ -14,60 +16,92 @@ class Response:
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)
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')
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")) + ["platform.develop.sprinthub.ru"]))
return list(set(list(configurator.get_config("hosts"))))
else:
return list(set(list(configurator.get_config("hosts")) + ["platform.sprinthub.ru"]))
return list(set(list(configurator.get_config("hosts"))))
def update_host(host: str) -> bool:
def update_host(host: str) -> str | None:
if os.getenv("STAGE") == "development":
container_id_run = call(f"echo $(docker ps -q -f name=infra-development_nginx)")
container_id_run = call("echo $(docker ps -q -f name=infra-development_nginx)")
else:
container_id_run = call(f"echo $(docker ps -q -f name=infra_nginx)")
container_id_run = call("echo $(docker ps -q -f name=infra_nginx)")
if container_id_run.code != 0:
print(f"something wrong {container_id_run.err}")
return False
return container_id_run.err
container_name = container_id_run.out.strip()
if not container_name:
print("No nginx container")
return False
gen_command = f"docker exec {container_name} certbot --nginx --email emmtvv@gmail.com --agree-tos --non-interactive -d \"{host}\""
print(gen_command)
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:
print(f"failed generating certificate: {gen_cert.err}")
print("Here is the log")
print(call(f"docker exec {container_name} cat /var/log/letsencrypt/letsencrypt.log").out)
return False
fullchain_command = call(f"docker exec {container_name} cat /etc/letsencrypt/live/{host}/fullchain.pem")
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:
print(f"failed getting fullchain: {fullchain_command.err}")
return True
privkey_command = call(f"docker exec {container_name} cat /etc/letsencrypt/live/{host}/privkey.pem")
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:
print(f"failed getting fullchain: {privkey_command.err}")
return True
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 True
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:
@ -75,18 +109,36 @@ while True:
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"]:
if (
now + datetime.timedelta(days=14)
> mongo_hosts.get(
host, {"expire_time": datetime.datetime.fromtimestamp(1)}
)["expire_time"]
):
success = update_host(host)
if success:
print(f"Host {host} updated")
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(f"echo $(docker ps -q -f name=infra-development_nginx)")
result = call(f"docker restart {container_id_run.out}")
container_id_run = call(
"echo $(docker ps -q -f name=infra-development_nginx)"
)
else:
result = call("docker service update --force infra_nginx")
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")
print(result.err, result.out)
time.sleep(30)

View File

@ -1,42 +0,0 @@
from cachetools import TTLCache
import os
from utils.mongo import mongo
CACHE_SIZE = int(os.getenv("CACHE_SIZE", 1000))
CACHE_TTL = int(os.getenv("CACHE_TTL", 3600))
cache = TTLCache(CACHE_SIZE, CACHE_TTL)
def get_chat_info(chat_id: int) -> dict:
cached_info = cache.get(chat_id)
if cached_info is not None:
return cached_info
mongo_info = mongo.chats_collection.find_one({"chat_id": chat_id})
if mongo_info is not None:
cache[chat_id] = mongo_info
return mongo_info
chat_info = {"chat_id": chat_id, "state": "default", "probability": 100}
mongo.chats_collection.insert_one(chat_info)
cache[chat_id] = chat_info
return chat_info
def set_values(chat_id: int, **values):
cached_info = cache.get(chat_id)
if cached_info is None:
mongo_info = mongo.chats_collection.find_one({"chat_id": chat_id})
if mongo_info is None:
chat_info = {"chat_id": chat_id, "state": "default", "probability": 100}
chat_info.update(values)
mongo.chats_collection.insert_one(chat_info)
cache[chat_id] = chat_info
else:
mongo.chats_collection.update_one({"chat_id": chat_id}, {"$set": values})
mongo_info = dict(mongo_info)
mongo_info.update(values)
cache[chat_id] = mongo_info
else:
cached_info.update(values)
mongo.chats_collection.update_one({"chat_id": chat_id}, {"$set": values})