Files
pet-project-server/tasks.py
Anton Vakhrushev 6350a1112d
Some checks failed
Linting / YAML Lint (push) Successful in 11s
Linting / Ansible Lint (push) Failing after 35s
Add zellij
2026-03-04 20:17:35 +03:00

148 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Invoke tasks — замена Taskfile.yml"""
import os
import subprocess
import sys
from invoke.context import Context
from invoke.exceptions import Exit
from invoke.tasks import task
HOSTS_FILE = "production.yml"
AUTHELIA_DOCKER = "docker run --rm -v $PWD:/data authelia/authelia:4.39.4 authelia"
def _yq(query: str) -> str:
result = subprocess.run(
["yq", query, HOSTS_FILE], capture_output=True, text=True, check=True
)
return result.stdout.strip()
def _remote_user() -> str:
return _yq(".ungrouped.hosts.server.ansible_user")
def _remote_host() -> str:
return _yq(".ungrouped.hosts.server.ansible_host")
def _rest_args() -> list[str]:
"""Возвращает аргументы после '--' из sys.argv"""
try:
return sys.argv[sys.argv.index("--") + 1 :]
except ValueError:
return []
def _resolve_playbook(name: str) -> str:
candidates = [name, f"{name}.yml", f"playbook-{name}.yml"]
for candidate in candidates:
if os.path.isfile(candidate):
return candidate
raise Exit(
f"Плейбук для '{name}' не найден. Проверял: {', '.join(candidates)}", code=1
)
@task
def install_roles(ctx: Context) -> None:
"""Установить ansible-galaxy roles"""
ctx.run("uv run ansible-galaxy role install --role-file requirements.yml --force")
@task
def pl(ctx: Context) -> None:
"""Запустить плейбуки по имени: inv pl -- gitea miniflux"""
names = _rest_args()
if not names:
raise Exit("Укажи хотя бы один плейбук: inv pl -- <name> [name ...]", code=1)
playbooks = [_resolve_playbook(name) for name in names]
ctx.run(
f"uv run ansible-playbook -i production.yml --diff {' '.join(playbooks)}",
pty=True,
)
@task
def ssh(ctx: Context) -> None:
"""SSH на удалённый сервер"""
subprocess.run(f"ssh {_remote_user()}@{_remote_host()}", shell=True)
@task
def zj(ctx: Context) -> None:
"""Запуск zellij на удаленном сервере"""
subprocess.run(
f"ssh {_remote_user()}@{_remote_host()} -t zellij attach --create main",
shell=True,
)
@task
def btop(ctx: Context) -> None:
"""Запустить btop на удалённом сервере"""
subprocess.run(f"ssh {_remote_user()}@{_remote_host()} -t btop", shell=True)
@task
def encrypt(ctx: Context, file: str) -> None:
"""Зашифровать файлы через ansible-vault"""
ctx.run(f"uv run ansible-vault encrypt {file}")
@task
def decrypt(ctx: Context, file: str) -> None:
"""Расшифровать файлы через ansible-vault"""
ctx.run(f"uv run ansible-vault decrypt {file}")
@task
def authelia_cli(ctx: Context, args: str = "") -> None:
"""Запустить authelia CLI в docker"""
ctx.run(f"{AUTHELIA_DOCKER} {args}")
@task
def authelia_validate_config(ctx: Context) -> None:
"""Отрендерить конфиг authelia из шаблона и проверить его"""
dest = "temp/configuration.yml"
try:
ctx.run(
"uv run ansible localhost"
" --module-name template"
f' --args "src=files/authelia/configuration.template.yml dest={dest}"'
" --extra-vars @vars/secrets.yml"
" --extra-vars @files/authelia/secrets.yml"
)
ctx.run(f"{AUTHELIA_DOCKER} validate-config --config /data/{dest}")
finally:
ctx.run(f"rm -f {dest}", warn=True)
@task
def authelia_gen_random_string(ctx: Context, length: int = 10) -> None:
"""Сгенерировать случайную alphanumeric-строку"""
ctx.run(f"{AUTHELIA_DOCKER} crypto rand --length {length} --charset alphanumeric")
@task
def authelia_gen_secret_and_hash(ctx: Context, length: int = 72) -> None:
"""Сгенерировать случайный секрет и его pbkdf2-sha512 хэш"""
ctx.run(
f"{AUTHELIA_DOCKER} crypto hash generate pbkdf2"
f" --variant sha512 --random --random.length {length} --random.charset rfc3986"
)
@task
def format_py_files(ctx: Context) -> None:
"""Отформатировать Python-файлы через Black в docker"""
uid = os.getuid()
gid = os.getgid()
ctx.run(
f"docker run --rm -u {uid}:{gid} -v $PWD:/app -w /app"
" pyfound/black:latest_release black ."
)