Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b510fb9b2 | ||
| c55bec5b5d | |||
|
|
15392f3373 | ||
|
|
3317bbf5cd | ||
|
|
e1ca5d7706 | ||
|
|
8447ab76bb | ||
|
|
2dbc0b9266 | ||
|
|
2993c12487 | ||
|
|
028abbe4d2 | ||
|
|
ae70f63fa3 | ||
|
|
bc7f8c4950 | ||
|
|
16c1c03b9e | ||
|
|
3cd5600f23 | ||
|
|
ecd758d944 | ||
|
|
12f3281deb | ||
|
|
19fe0a66c2 | ||
|
|
30d58ba9af | ||
|
|
abc4d756db | ||
|
|
af6135f2b0 | ||
|
|
9da34bb9cc | ||
|
|
8d9e1d3d9e | ||
|
|
db0b8988f1 | ||
|
|
218d233eb7 | ||
|
|
f88cf04434 | ||
|
|
d5884d3a3b | ||
|
|
d46ba48d22 | ||
|
|
638da92688 | ||
|
|
64412e1b94 | ||
|
|
4abcd33cd5 | ||
|
|
27e36cfa7c | ||
|
|
c7c244e95d | ||
|
|
3a5b3b07e6 | ||
|
|
172e889f00 | ||
|
|
e491466a37 | ||
|
|
6b107c872a | ||
|
|
9e4a27f898 | ||
|
|
da36ac822f | ||
|
|
4cd9a8b4d5 | ||
|
|
c4e6c079f7 | ||
|
|
6e94f826c3 | ||
|
|
3bb9514f1e | ||
|
|
16477cc6fd | ||
|
|
1e1280d74e | ||
|
|
a8a4f5e50d | ||
|
|
27327f2c9c | ||
|
|
a9ec189e91 | ||
|
|
9c892604fb | ||
|
|
0703f6a7ea | ||
|
|
c5ca007f03 | ||
|
|
a076995f3a | ||
|
|
0c04c357dc | ||
|
|
ebe1bbfd08 | ||
|
|
311abec040 | ||
|
|
3d80c69ed1 | ||
|
|
fb765a9cf9 | ||
|
|
8a0eee6538 | ||
|
|
f8a16fe423 | ||
|
|
48ec94afc9 | ||
|
|
30f669ed14 | ||
|
|
f55f25479a | ||
|
|
55c9f573c3 | ||
|
|
0dbe5dd0ac | ||
|
|
b84811a5b2 | ||
|
|
3b1878ca59 | ||
|
|
9c5dd7c860 | ||
|
|
bf5b04ace7 |
98
.env.example
98
.env.example
@ -1,98 +0,0 @@
|
||||
K3S_TOKEN=changeme
|
||||
|
||||
# Внешний адрес (IP или домен), по которому к kube-apiserver обращаются извне.
|
||||
# Попадёт в TLS-сертификат (--tls-san). Без него внешний kubectl упадёт на x509.
|
||||
K3S_API_HOST=10.0.0.10
|
||||
|
||||
# --- Инфраструктура для apps/django (sarex-backend) ---
|
||||
# Должны совпадать со значениями, которые Django получает в k3s (Vault/Secret).
|
||||
SAREX_POSTGRES_DB=sarex_db
|
||||
SAREX_POSTGRES_USER=sarex
|
||||
SAREX_POSTGRES_PASSWORD=sarex
|
||||
# Отдельные роли приложений с паролями (создаются контейнером postgres-init).
|
||||
# Приложения ходят в БД под ними, а не под суперпользователем. Без одинарных кавычек.
|
||||
SAREX_DJANGO_DB_USER=django
|
||||
SAREX_DJANGO_DB_PASSWORD=django-secret
|
||||
# Расширения PostgreSQL для базы django (создаёт postgres-init суперпользователем)
|
||||
SAREX_DJANGO_DB_EXTENSIONS=ltree
|
||||
# JWT-ключи backend (RS512): PEM в одну строку с литеральными \n (backend разворачивает).
|
||||
# Генерируются автоматически в .secrets ролью sarex_stack; здесь — плейсхолдеры.
|
||||
SAREX_JWT_PRIVATE_KEY=changeme
|
||||
SAREX_JWT_PUBLIC_KEY=changeme
|
||||
SAREX_PROCESSING_DB_USER=processing
|
||||
SAREX_PROCESSING_DB_PASSWORD=processing-secret
|
||||
# Расширения PostgreSQL для workflow_db (создаёт postgres-init суперпользователем;
|
||||
# роль processing прав на CREATE EXTENSION не имеет). Нужны миграциям workflows-api.
|
||||
SAREX_PROCESSING_DB_EXTENSIONS=uuid-ossp ltree hstore
|
||||
SAREX_BIM_DB_USER=bim
|
||||
SAREX_BIM_DB_PASSWORD=bim-secret
|
||||
SAREX_WORKSPACE_DB_USER=workspace
|
||||
SAREX_WORKSPACE_DB_PASSWORD=workspace-secret
|
||||
SAREX_RABBITMQ_VHOST=api
|
||||
SAREX_RABBITMQ_USER=rabbit
|
||||
SAREX_RABBITMQ_PASSWORD=rabbit
|
||||
SAREX_MINIO_ROOT_USER=minioadmin
|
||||
SAREX_MINIO_ROOT_PASSWORD=minioadmin
|
||||
SAREX_MINIO_BUCKET=sarex-media-storage
|
||||
# Отдельный пользователь приложения (не root) — под ним backend/celery ходят в S3.
|
||||
# Секрет минимум 8 символов. Политика ограничена бакетом SAREX_MINIO_BUCKET.
|
||||
SAREX_MINIO_APP_USER=sarex-app
|
||||
SAREX_MINIO_APP_PASSWORD=sarex-app-secret
|
||||
SAREX_MINIO_APP_POLICY=sarex-app-rw
|
||||
SAREX_MINIO_REGION=us-east-1
|
||||
# Внешний URL консоли MinIO (корень minio-домена на верхнем nginx, https)
|
||||
SAREX_MINIO_CONSOLE_URL=https://minio.sarex.local
|
||||
|
||||
# --- Домены верхнего nginx (замени на реальные, заведи в DNS/hosts) ---
|
||||
PLATFORM_DOMAIN=sarex.local # основной домен платформы (frontend + /api)
|
||||
ADMIN_DOMAIN=admin.sarex.local # RabbitMQ management UI
|
||||
MINIO_DOMAIN=minio.sarex.local # MinIO: S3 API (/) + консоль (/console/)
|
||||
|
||||
# --- GitOps-подложка: gitea (источник правды) + Vault + FluxCD в k3s ---
|
||||
# Админ gitea заводится контейнером gitea-init; этими же кредами flux-bootstrap
|
||||
# авторизуется при push'е манифестов. Пароль генерирует роль sarex_stack.
|
||||
GITEA_ADMIN_USER=sarex
|
||||
GITEA_ADMIN_PASSWORD=changeme
|
||||
GITEA_ADMIN_EMAIL=sarex@sarex.local
|
||||
# Организация и репозиторий, которые gitea-init создаёт, а Flux реконсилирует.
|
||||
GITEA_ORG=infra
|
||||
GITEA_REPO=iac
|
||||
# Ветка и путь внутри репозитория, за которыми следит Flux.
|
||||
AERO_GIT_BRANCH=master
|
||||
AERO_FLUX_PATH=clusters/aero
|
||||
|
||||
# --- Docker-образы инфраструктуры (тег/реестр можно переопределить) ---
|
||||
K3S_IMAGE=rancher/k3s:v1.36.2-k3s1
|
||||
GITEA_IMAGE=gitea/gitea:1.22
|
||||
VAULT_IMAGE=hashicorp/vault:1.18
|
||||
# Версия CLI должна совпадать с версией контроллеров Flux в остальных кластерах.
|
||||
FLUX_CLI_IMAGE=ghcr.io/fluxcd/flux-cli:v2.8.5
|
||||
POSTGRES_IMAGE=postgres:12-alpine
|
||||
NGINX_IMAGE=nginx:1.27-alpine
|
||||
SAREX_REDIS_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10
|
||||
SAREX_RABBITMQ_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/rabbimtq:3.11.23
|
||||
SAREX_MINIO_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/minio:250724
|
||||
SAREX_MC_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/mc:250724
|
||||
|
||||
# Образы приложения (приватный реестр cr.yandex — нужен docker login)
|
||||
SAREX_BACKEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/backend:production_80d1d847
|
||||
SAREX_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/frontend:contour_42138486
|
||||
# s3-proxy: отдаёт объекты MinIO/S3 браузеру с CORS и Range (media в namespace django)
|
||||
SAREX_S3_PROXY_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/s3-proxy:vault_6e586217
|
||||
|
||||
# Базы данных приложений (django использует SAREX_POSTGRES_DB)
|
||||
SAREX_PROCESSING_DB=workflow_db
|
||||
SAREX_BIM_DB=bim_db
|
||||
SAREX_WORKSPACE_DB=workspace_db
|
||||
|
||||
# Приложение processing (workflows-api + workflows-frontend)
|
||||
SAREX_PROCESSING_API_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0
|
||||
SAREX_PROCESSING_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c
|
||||
# workflows-engine (processing) — оркестратор Job'ов в k3s
|
||||
SAREX_WORKFLOWS_ENGINE_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-endigne_prod:075fc0
|
||||
|
||||
# Сервис measurements (FastAPI). Django-backend ходит в него по MEASUREMENTS_HOST.
|
||||
SAREX_MEASUREMENTS_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/measurements:production_a5bb3e84
|
||||
SAREX_MEASUREMENTS_HOST=http://measurements:8000/
|
||||
# measurements и processing используют единый бакет SAREX_MINIO_BUCKET
|
||||
# под пользователем SAREX_MINIO_APP_USER (отдельные бакеты не заводятся)
|
||||
28
.gitignore
vendored
28
.gitignore
vendored
@ -2,35 +2,7 @@
|
||||
.claude
|
||||
CLAUDE.md
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
tmp
|
||||
.tmp/
|
||||
snapshots/*
|
||||
|
||||
# --- Рантайм-артефакты контура aero (создаются docker-compose на хосте) ---
|
||||
# ВНИМАНИЕ: комментарии в .gitignore работают только с начала строки,
|
||||
# в конце строки они становятся частью паттерна и ломают его.
|
||||
|
||||
# данные gitea: репозитории, sqlite
|
||||
gitea-data/
|
||||
# PVC-данные local-path-provisioner
|
||||
k3s-storage/
|
||||
# kubeconfig, который пишет k3s-server
|
||||
k3s/kubeconfig.yaml
|
||||
# СОДЕРЖИТ КЛЮЧ реестра — рендерится ролью sarex_stack
|
||||
k3s/registries.yaml
|
||||
# СОДЕРЖИТ КЛЮЧ реестра — временный, удаляется после kubectl apply
|
||||
k3s/registry-secret.yaml
|
||||
# временная копия ключа реестра на хосте
|
||||
registry-key.json
|
||||
# самоподписанные TLS-сертификаты
|
||||
nginx/certs/
|
||||
|
||||
# --- Секреты и ключи: не коммитить никогда ---
|
||||
*.pem
|
||||
*.key
|
||||
*.p12
|
||||
kubeconfig*
|
||||
*service-account*.json
|
||||
|
||||
675
IAC-CATALOG.md
Normal file
675
IAC-CATALOG.md
Normal file
@ -0,0 +1,675 @@
|
||||
# Каталог IaC-компонентов и репозиториев
|
||||
|
||||
Карта ответственности: **какой репозиторий за что отвечает** в инфраструктуре `gitlab.sarex.io`
|
||||
и **из чего состоит** этот репозиторий (`infra/iac`).
|
||||
|
||||
- Источники: GitLab-группа `infra` (209 проектов, включая подгруппы) + содержимое `infra/iac`.
|
||||
- Дата среза: **2026-08-05**.
|
||||
- Все ссылки — на `https://gitlab.sarex.io`.
|
||||
|
||||
Пометки достоверности:
|
||||
|
||||
| Знак | Значение |
|
||||
|---|---|
|
||||
| ✅ | структура/назначение проверены — репозиторий открыт и прочитан |
|
||||
| ◻️ | назначение выведено из имени, описания в GitLab и веток; **требует подтверждения** |
|
||||
|
||||
---
|
||||
|
||||
## 1. Слои IaC и где они живут
|
||||
|
||||
```
|
||||
┌─ Железо / VM ─────────────────────────────────────────────────────────────┐
|
||||
│ ansible-playbooks, ansible-patroni-cluster, ansible-minio-cluster, │
|
||||
│ tools/ansible-vm-preparing, astra-linux, hardware, intervpc-vpn-tunnel │
|
||||
├─ Кластер Kubernetes ──────────────────────────────────────────────────────┤
|
||||
│ kubespray, k8s-provision │
|
||||
├─ Облачные и k8s-ресурсы (namespace/БД/S3/секреты/топики) ─────────────────┤
|
||||
│ terraform, terraform-contour, terraform-contour-mirror, │
|
||||
│ sarex-terraform-provider │
|
||||
├─ GitOps: состояние кластеров ─────────────────────────────────────────────┤
|
||||
│ ★ iac (Flux v2, этот репозиторий) iac-gpn (ArgoCD) poc/iac (архив) │
|
||||
├─ Поставка отдельных компонентов через GitLab CI (ветка = контур) ─────────┤
|
||||
│ vault, redis, kafka, postgresql, istio-config, keycloak, … (~60 репо) │
|
||||
├─ Библиотеки чартов ───────────────────────────────────────────────────────┤
|
||||
│ universal-helm-chart, common-charts, chart-museum │
|
||||
├─ Эксплуатация, аудит, наблюдаемость ──────────────────────────────────────┤
|
||||
│ k8s-changelog, cluster-maintenance, k8s-hustler, harvester, backups/* │
|
||||
└───────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Главный водораздел.** В инфраструктуре сосуществуют **две модели доставки**:
|
||||
|
||||
1. **GitOps (Flux)** — `infra/iac`. Один репозиторий, множество кластеров, состояние декларируется
|
||||
в `clusters/<кластер>/`, Flux сам подтягивает изменения.
|
||||
2. **Push-деплой (GitLab CI)** — по репозиторию на компонент, чарт лежит в `.helm/`,
|
||||
**ветка = контур/окружение** (`stage`, `preprod`, `contour`, `infra`, `brusnika-prod`, …).
|
||||
Проверено на [vault](https://gitlab.sarex.io/infra/vault),
|
||||
[redis](https://gitlab.sarex.io/infra/redis),
|
||||
[istio-config](https://gitlab.sarex.io/infra/istio-config),
|
||||
[kube-prometheus-stack](https://gitlab.sarex.io/infra/kube-prometheus-stack),
|
||||
[gitlab-runner](https://gitlab.sarex.io/infra/gitlab-runner). ✅
|
||||
|
||||
Для ряда компонентов (Vault, Redis, Kafka, PostgreSQL, Istio, Keycloak, Zitadel, OpenObserve,
|
||||
Superset, Trino, GoAlert, GlitchTip, argo-*, otel-*) **существуют оба источника**.
|
||||
См. раздел [6. Перекрытия](#6-перекрытия-и-как-выбирать-источник-истины).
|
||||
|
||||
---
|
||||
|
||||
## 2. Ядро IaC — репозитории верхнего уровня
|
||||
|
||||
| Репозиторий | Зона ответственности | Ключевое содержимое |
|
||||
|---|---|---|
|
||||
| ★ [infra/iac](https://gitlab.sarex.io/infra/iac) ✅ | **Основной GitOps-монорепозиторий (Flux v2).** Декларативное состояние 9 кластеров: инфраструктурные компоненты + прикладные сервисы | `clusters/`, `infrastructure/` (36), `apps/` (37), `inventory.yaml`, `docs/apps/` |
|
||||
| [infra/terraform](https://gitlab.sarex.io/infra/terraform) ✅ | **Ресурсы Yandex Cloud и Kubernetes**: namespaces, PostgreSQL БД/пользователи, S3-бакеты, Valkey/Redis-пользователи, Kafka-топики, RabbitMQ, k8s-секреты. Единый источник правды — `infrastructure.yaml`, секреты через SOPS | `live/prod` (Terragrunt), `modules/`: `k8s-namespace`, `k8s-secret`, `k8s-secrets`, `kafka-topics-yc`, `rabbitmq`, `yc-database`, `yc-s3`, `yc-valkey-user` |
|
||||
| [infra/terraform-contour](https://gitlab.sarex.io/infra/terraform-contour) ✅ | Тот же подход **для изолированного контура**: namespaces и секреты из Vault | `live/{namespace,vault-secrets}`, `modules/{k8s-namespace,vault-platform-secrets}` |
|
||||
| [infra/terraform-contour-mirror](https://gitlab.sarex.io/infra/terraform-contour-mirror) ✅ | **Зеркало `infra/terraform` для контура** (ветка `contour`, единственная). Тот же README и структура + `Dockerfile` для запуска в закрытом периметре | `live/`, `modules/`, `scripts/`, `Dockerfile` |
|
||||
| [infra/sarex-terraform-provider](https://gitlab.sarex.io/infra/sarex-terraform-provider) ✅ | **Внутренние Terraform-провайдеры**, генерируемые из OpenAPI-спек продуктовых API (например `workspaces-api`). В публичный реестр не публикуются — ставятся через dev overrides | `providers/`, `internal/`, `examples/`, `Makefile` |
|
||||
| [infra/iac-gpn](https://gitlab.sarex.io/infra/iac-gpn) ✅ | **GitOps-контур ГПН на ArgoCD** (не Flux): `root.yaml` + app-of-apps, конфигмапы бэкендов, образ `terraform-contour-stronghold` | `argocd/{root.yaml,apps}`, `infrastructure/*-configmaps`, `images/` |
|
||||
| [infra/poc/iac](https://gitlab.sarex.io/infra/poc/iac) ✅ | **Предшественник/PoC** текущего Flux-репозитория. Последняя активность 2026-02-16 — считать архивом | `clusters/`, `apps/`, `infra/`, `GUIDE.md` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Провижининг: от железа до кластера
|
||||
|
||||
| Репозиторий | Отвечает за |
|
||||
|---|---|
|
||||
| [infra/kubespray](https://gitlab.sarex.io/infra/kubespray) ✅ | Форк upstream Kubespray — **развёртывание самих кластеров Kubernetes** на VM |
|
||||
| [infra/k8s-provision](https://gitlab.sarex.io/infra/k8s-provision) ✅ | **Первичная обвязка свежего кластера**: `namespaces`, `cert_manager`, `istio` (+`ISTIO.md`), `ingress`, `dashboard`, `prometheus`, `postgres`/`ya_postgres`, `rabbitmq`, `pvc`, `gitlab`, `teamcity`, `migration` |
|
||||
| [infra/ansible-playbooks](https://gitlab.sarex.io/infra/ansible-playbooks) ✅ | Зонтичный Ansible-репозиторий: каталоги `minio/`, `patroni/` |
|
||||
| [infra/ansible-patroni-cluster](https://gitlab.sarex.io/infra/ansible-patroni-cluster) ✅ | **PostgreSQL HA на VM через Patroni** (`site.yml`, `roles/`, `inventory/`, `test.yml`) |
|
||||
| [infra/ansible-minio-cluster](https://gitlab.sarex.io/infra/ansible-minio-cluster) ✅ | **MinIO-кластер на VM** + сценарии проверок `fault-tolerance-test.yml`, `heal-test.yml` |
|
||||
| [infra/tools/ansible-vm-preparing](https://gitlab.sarex.io/infra/tools/ansible-vm-preparing) ✅ | Подготовка VM перед Ansible/Kubespray (Python-обвязка, `uv`). README — шаблонный, назначение по коду |
|
||||
| [infra/hardware](https://gitlab.sarex.io/infra/hardware) ◻️ | Учёт/конфигурация физического оборудования |
|
||||
| [infra/astra-linux](https://gitlab.sarex.io/infra/astra-linux) ◻️ | Сборка/настройка образов Astra Linux для импортозамещённых контуров |
|
||||
| [infra/intervpc-vpn-tunnel](https://gitlab.sarex.io/infra/intervpc-vpn-tunnel) ◻️ | VPN-туннель между VPC |
|
||||
| [infra/cluster-maintenance](https://gitlab.sarex.io/infra/cluster-maintenance) ◻️ | Регламентные операции обслуживания кластеров |
|
||||
|
||||
---
|
||||
|
||||
## 4. Компонентные репозитории (`.helm/` + GitLab CI, ветка = контур)
|
||||
|
||||
Формат ниже: **компонент → репозиторий**. Столбец «в `iac`» показывает, есть ли одноимённый
|
||||
компонент в этом монорепозитории (`infrastructure/<имя>`).
|
||||
|
||||
### 4.1 Сеть, Ingress, Service Mesh
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| Istio (base/pilot/gateway) | [infra/istio](https://gitlab.sarex.io/infra/istio) `infra` | ✔ `istio-base`, `istio-pilot`, `istio-gateway` |
|
||||
| Istio: Gateway/VirtualService/AuthPolicy/EnvoyFilter | [infra/istio-config](https://gitlab.sarex.io/infra/istio-config) ✅ ветки `stage`,`preprod`,`contour`,`infra`,`master` | ✔ `istio-config` |
|
||||
| Istio для контура НН | [infra/istio-nn](https://gitlab.sarex.io/infra/istio-nn) ◻️ | — |
|
||||
| cert-manager | [infra/cert-manager](https://gitlab.sarex.io/infra/cert-manager) ◻️ | ✔ `cert-manager` |
|
||||
| nginx (ingress для Django) | [infra/ingress-nginx-django](https://gitlab.sarex.io/infra/ingress-nginx-django) ◻️ | — |
|
||||
| nginx с Kerberos / hardened nginx | [infra/nginx-krb](https://gitlab.sarex.io/infra/nginx-krb), [infra/secure-nginx](https://gitlab.sarex.io/infra/secure-nginx) ◻️ | — |
|
||||
|
||||
### 4.2 Identity, доступ, безопасность
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| Keycloak | [infra/keycloak](https://gitlab.sarex.io/infra/keycloak) ◻️ | ✔ `keycloak` |
|
||||
| Zitadel | [infra/zitadel](https://gitlab.sarex.io/infra/zitadel) ◻️ | ✔ `zitadel` |
|
||||
| Zitadel auth proxy | [infra/zitadel-auth-proxy](https://gitlab.sarex.io/infra/zitadel-auth-proxy) ◻️ | — |
|
||||
| OpenLDAP | [infra/openldap](https://gitlab.sarex.io/infra/openldap) `contour` ◻️ | ✔ `openldap` |
|
||||
| HashiCorp Vault | [infra/vault](https://gitlab.sarex.io/infra/vault) ✅ `contour` | ✔ `vault`, `vault-unseal` |
|
||||
| SpiceDB (авторизация) | [infra/spicedb](https://gitlab.sarex.io/infra/spicedb) ◻️ | — |
|
||||
| OAuth2-фасад / gatekeeper | [infra/oauth2-facade](https://gitlab.sarex.io/infra/oauth2-facade), [infra/gogatekeeper](https://gitlab.sarex.io/infra/gogatekeeper) ◻️ | — |
|
||||
| Фильтрация JWKS | [infra/jwks-key-filter](https://gitlab.sarex.io/infra/jwks-key-filter) ◻️ | — |
|
||||
| Django ↔ Keycloak (библиотека) | [infra/django-keycloak](https://gitlab.sarex.io/infra/django-keycloak) ✅ | — |
|
||||
| Сканирование секретов / образов | [infra/gitleaks](https://gitlab.sarex.io/infra/gitleaks), [infra/clair](https://gitlab.sarex.io/infra/clair), [infra/sec/report](https://gitlab.sarex.io/infra/sec/report) ◻️ | — |
|
||||
|
||||
### 4.3 Данные и хранилища
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| PostgreSQL | [infra/postgresql](https://gitlab.sarex.io/infra/postgresql) ветки `contour`,`contour-13`,`preprod`,`stronghold` ✅ | ✔ `postgresql` |
|
||||
| PostgreSQL 16 (контур WB) | [infra/wb/postgresql16](https://gitlab.sarex.io/infra/wb/postgresql16) ◻️ | — |
|
||||
| pg_partman / TimescaleDB / CockroachDB | [infra/postgres-pgpartman](https://gitlab.sarex.io/infra/postgres-pgpartman), [infra/timescaledb](https://gitlab.sarex.io/infra/timescaledb), [infra/cockroachdb](https://gitlab.sarex.io/infra/cockroachdb) ◻️ | — |
|
||||
| Redis | [infra/redis](https://gitlab.sarex.io/infra/redis) ✅ `contour` | ✔ `redis` |
|
||||
| MinIO (в k8s) | [infra/minio-standalone](https://gitlab.sarex.io/infra/minio-standalone) `contour` ◻️ | ✔ `minio` |
|
||||
| ClickHouse (+оператор) | [infra/clickhouse](https://gitlab.sarex.io/infra/clickhouse), [infra/clickhouse-operator](https://gitlab.sarex.io/infra/clickhouse-operator) ◻️ | — |
|
||||
| OpenSearch (+оператор) | [infra/opensearch](https://gitlab.sarex.io/infra/opensearch), [infra/opensearch-operator](https://gitlab.sarex.io/infra/opensearch-operator) ◻️ | — |
|
||||
| S3-прокси | — (только в `iac`) | ✔ `s3-proxy` |
|
||||
|
||||
### 4.4 Брокеры и обмен сообщениями
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| Kafka | [infra/kafka](https://gitlab.sarex.io/infra/kafka) ветки `stage`,`preprod`,`brusnika-*` ✅ | ✔ `kafka` |
|
||||
| Kafka standalone (контур НН) | [infra/kafka-nn](https://gitlab.sarex.io/infra/kafka-nn) ◻️ | — |
|
||||
| Strimzi/Kafka-оператор | [infra/kafka-operator](https://gitlab.sarex.io/infra/kafka-operator) ◻️ | — |
|
||||
| Kafka exporter | [infra/kafka-exporter](https://gitlab.sarex.io/infra/kafka-exporter) ◻️ | ✔ `kafka-exporter` |
|
||||
| Маршрутизация между Kafka-кластерами | [infra/kafka-router](https://gitlab.sarex.io/infra/kafka-router) ✅ | — |
|
||||
| Kafka → Vector мост | [infra/kafka-vector-bridge](https://gitlab.sarex.io/infra/kafka-vector-bridge) ◻️ | — |
|
||||
| RabbitMQ (+оператор, контур НН) | [infra/rabbitmq](https://gitlab.sarex.io/infra/rabbitmq), [infra/rabbitmq-cluster-operator](https://gitlab.sarex.io/infra/rabbitmq-cluster-operator), [infra/rabbitmq-nn](https://gitlab.sarex.io/infra/rabbitmq-nn) ◻️ | ✔ `rabbitmq` |
|
||||
|
||||
### 4.5 Наблюдаемость
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| kube-prometheus-stack | [infra/kube-prometheus-stack](https://gitlab.sarex.io/infra/kube-prometheus-stack) ✅ `infra` | ✔ `prometheus-stack` |
|
||||
| prometheus-stack (описан как «A complete monitoring stack for Kubernetes») | [infra/prometheus-stack](https://gitlab.sarex.io/infra/prometheus-stack) `stage` | ✔ `prometheus-stack` |
|
||||
| Алерты и дашборды для Prometheus/Grafana | [infra/prometheus-stsack-resources](https://gitlab.sarex.io/infra/prometheus-stsack-resources) *(опечатка в имени — так в GitLab)* | — |
|
||||
| VictoriaMetrics stack / cluster | [infra/vm-stack](https://gitlab.sarex.io/infra/vm-stack), [infra/vm-cluster](https://gitlab.sarex.io/infra/vm-cluster) ◻️ | ✔ `vmstack` |
|
||||
| Экспортеры: node / postgres / blackbox | [infra/node-exporter](https://gitlab.sarex.io/infra/node-exporter), [infra/postgres-exporter](https://gitlab.sarex.io/infra/postgres-exporter), [infra/blackbox-exporter](https://gitlab.sarex.io/infra/blackbox-exporter) ◻️ | ✔ `postgres-exporter` |
|
||||
| OpenObserve | [infra/openobserve](https://gitlab.sarex.io/infra/openobserve) ветка `contour/cps` ✅ | ✔ `openobserve` |
|
||||
| Loki / SigNoz | [infra/loki](https://gitlab.sarex.io/infra/loki), [infra/signoz](https://gitlab.sarex.io/infra/signoz) ◻️ | — |
|
||||
| Sentry / GlitchTip | [infra/sentry](https://gitlab.sarex.io/infra/sentry), [infra/glitchtip](https://gitlab.sarex.io/infra/glitchtip) `contour/cps` ◻️ | ✔ `glitchtip` |
|
||||
| GoAlert (+ исходники, + Telegram-релей) | [infra/goalert](https://gitlab.sarex.io/infra/goalert), [infra/goalert-source](https://gitlab.sarex.io/infra/goalert-source), [infra/goalert-telegram-relay](https://gitlab.sarex.io/infra/goalert-telegram-relay) ◻️ | ✔ `goalert` |
|
||||
| OpenTelemetry collector / operator | [infra/opentelemetry-collector](https://gitlab.sarex.io/infra/opentelemetry-collector), [infra/opentelemetry-operator](https://gitlab.sarex.io/infra/opentelemetry-operator) ◻️ | ✔ `opentelemetry-collector`, `opentelemetry-operator` |
|
||||
| eBPF-экспортер OTel | [infra/otel-ebpf-exporter](https://gitlab.sarex.io/infra/otel-ebpf-exporter) ◻️ | — |
|
||||
| Конвейер телеметрии: OTel → Kafka → ClickHouse | [infra/otel-kafka-processor](https://gitlab.sarex.io/infra/otel-kafka-processor), [infra/otel-kafka-clickhouse-worker](https://gitlab.sarex.io/infra/otel-kafka-clickhouse-worker) ◻️ | — |
|
||||
| SDK-обвязки инструментирования | [infra/otel/django-otel-tools](https://gitlab.sarex.io/infra/otel/django-otel-tools), [infra/otel/fastapi-otel-tools](https://gitlab.sarex.io/infra/otel/fastapi-otel-tools), [infra/golang-fiber-otel-tools](https://gitlab.sarex.io/infra/golang-fiber-otel-tools), [infra/golang-net-http-otel-tools](https://gitlab.sarex.io/infra/golang-net-http-otel-tools), [infra/django-instrumented](https://gitlab.sarex.io/infra/django-instrumented), [infra/djano-autoinstrumentation](https://gitlab.sarex.io/infra/djano-autoinstrumentation) ◻️ | — |
|
||||
| PMM, Trickster, отчёты по Prometheus | [infra/pmm](https://gitlab.sarex.io/infra/pmm), [infra/trickster](https://gitlab.sarex.io/infra/trickster), [infra/prometheus-report](https://gitlab.sarex.io/infra/prometheus-report) ◻️ | — |
|
||||
| SIEM-шиппер (+UI) | [infra/siem-shiper](https://gitlab.sarex.io/infra/siem-shiper), [infra/siem-shiper-frontend](https://gitlab.sarex.io/infra/siem-shiper-frontend) ◻️ | — |
|
||||
|
||||
### 4.6 Платформа, аналитика, BPM
|
||||
|
||||
| Компонент | Репозиторий | в `iac` |
|
||||
|---|---|---|
|
||||
| Kubernetes Dashboard | [infra/dashboard](https://gitlab.sarex.io/infra/dashboard) ◻️ | ✔ `dashboard` |
|
||||
| local-path-provisioner | [infra/local-path-provisioner-nn](https://gitlab.sarex.io/infra/local-path-provisioner-nn) ◻️ | ✔ `local-path-provisioner` |
|
||||
| Camunda (+ модели процессов) | [infra/camunda](https://gitlab.sarex.io/infra/camunda) `camunda-prod`, [infra/camunda-processes](https://gitlab.sarex.io/infra/camunda-processes) ◻️ | ✔ `camunda` |
|
||||
| Argo Workflows / Argo Events | [infra/argo-workflows](https://gitlab.sarex.io/infra/argo-workflows), [infra/argo-events](https://gitlab.sarex.io/infra/argo-events) ◻️ | ✔ `argo-workflows`, `argo-events` |
|
||||
| Superset / Trino | [infra/superset](https://gitlab.sarex.io/infra/superset), [infra/trino](https://gitlab.sarex.io/infra/trino) ◻️ | ✔ `superset`, `trino` |
|
||||
| Jupyter, BI-эксперименты, ETL, ГИС | [infra/jupyter-notebook](https://gitlab.sarex.io/infra/jupyter-notebook), [infra/bi-test](https://gitlab.sarex.io/infra/bi-test), [infra/etl](https://gitlab.sarex.io/infra/etl), [infra/sarex-gis](https://gitlab.sarex.io/infra/sarex-gis) ◻️ | — |
|
||||
| Mailer | [infra/mailer](https://gitlab.sarex.io/infra/mailer) ◻️ | — |
|
||||
|
||||
### 4.7 CI/CD и Git-инфраструктура
|
||||
|
||||
| Компонент | Репозиторий |
|
||||
|---|---|
|
||||
| GitLab Runner | [infra/gitlab-runner](https://gitlab.sarex.io/infra/gitlab-runner) ✅ (`.helm` + CI) |
|
||||
| Gitea (Git-зеркала для изолированных контуров) | [infra/gitea](https://gitlab.sarex.io/infra/gitea) ◻️ — см. §5, Flux в закрытых контурах читает `iac` именно из Gitea |
|
||||
| ChartMuseum (реестр Helm-чартов) | [infra/chart-museum](https://gitlab.sarex.io/infra/chart-museum) ◻️ |
|
||||
| Базовые Docker-образы | [infra/base-images](https://gitlab.sarex.io/infra/base-images) ◻️ |
|
||||
| Миграция и утилиты GitLab | [infra/gitlab-migrator](https://gitlab.sarex.io/infra/gitlab-migrator), [infra/gitlab-tools](https://gitlab.sarex.io/infra/gitlab-tools) ◻️ |
|
||||
|
||||
### 4.8 Библиотеки чартов
|
||||
|
||||
| Репозиторий | Отвечает за |
|
||||
|---|---|
|
||||
| [infra/universal-helm-chart](https://gitlab.sarex.io/infra/universal-helm-chart) ✅ | Универсальный чарт (`.helm/`), на который ссылаются HelmRelease в `iac` (`openobserve`, `glitchtip` — `chart: universal-chart`) |
|
||||
| [infra/common-charts](https://gitlab.sarex.io/infra/common-charts) ✅ | Общие чарты, сейчас — `universal-static-site` |
|
||||
| [infra/helm-values-extractor](https://gitlab.sarex.io/infra/helm-values-extractor) ◻️ | Извлечение `values` из работающих релизов (ветка `draft-script`) |
|
||||
| [infra/poc/itworksonmyhelm](https://gitlab.sarex.io/infra/poc/itworksonmyhelm), [infra/wb/helm-of-business](https://gitlab.sarex.io/infra/wb/helm-of-business) ◻️ | Эксперименты/контурные наборы чартов |
|
||||
|
||||
---
|
||||
|
||||
## 5. Что внутри `infra/iac`
|
||||
|
||||
### 5.1 Кластеры и откуда Flux их читает
|
||||
|
||||
Точка входа Flux — `clusters/<кластер>/`. Источник (`gotk-sync.yaml`) различается: кластеры в
|
||||
периметре Yandex Cloud смотрят прямо в GitLab, изолированные контуры — в **зеркало Gitea**.
|
||||
|
||||
| Кластер | Git-источник Flux | Состав |
|
||||
|---|---|---|
|
||||
| `yc-infra-prod` | `gitlab.sarex.io/infra/iac` | argo-workflows, argo-events, postgresql, pg-sanitizer, vault, vault-unseal, yc-pg-dumper |
|
||||
| `yc-k8s-test` | `gitlab.sarex.io/infra/iac` | `bootstrap-jobs`, состав задаётся в `kustomization.yaml` кластера |
|
||||
| `yc-k8s-test-02` | `gitlab.sarex.io/infra/iac` | istio (base/pilot/gateway/config), dashboard, local-path-provisioner, minio, rabbitmq, kafka, redis, camunda, postgresql, zitadel, keycloak, vault |
|
||||
| `yc-cps-prod` | `gitea.cloud.cps.sarex.lonsdaleites.ru/sarex/iac` | vault, istio, gitea-istio |
|
||||
| `yc-ecp` | `gitea.invest.cps.sarex.lonsdaleites.ru/sarex/iac` | cert-manager, istio-config, dashboard, vault; apps: measurements, django, s3-proxy, s3-proxy-bim |
|
||||
| `brusnika-prod` | `gitea.prod.brusnika.sarex.lonsdaleites.ru/sarex/iac` | istio, vault, zitadel, minio, openobserve, vmstack, otel operator/collector, goalert, экспортеры, failed-pod-cleanup |
|
||||
| `brusnika-stage` | `gitea.stage.brusnika.sarex.lonsdaleites.ru/sarex/iac` | то же без minio |
|
||||
| `wb` | `gitea-srx.wb.ru/sarex/iac` | istio-config, openobserve, vmstack, otel, goalert, экспортеры, superset, trino |
|
||||
| `d8-ugmk-prod` | `10.222.255.165:3000/infra/iac` (Gitea) | только `istio-ingress` |
|
||||
| `contour` | — (шаблон: `apps.yaml`, `infrastructure.yaml`, `helm-repositories.yaml`) | эталонная точка входа из README |
|
||||
|
||||
### 5.2 `infrastructure/` — 36 компонентов
|
||||
|
||||
`argo-events` · `argo-workflows` · `camunda` · `cert-manager` · `dashboard` · `example-infra` ·
|
||||
`failed-pod-cleanup` · `glitchtip` · `goalert` · `istio-base` · `istio-config` · `istio-gateway` ·
|
||||
`istio-pilot` · `kafka` · `kafka-exporter` · `keycloak` · `local-path-provisioner` · `minio` ·
|
||||
`openldap` · `openobserve` · `opentelemetry-collector` · `opentelemetry-operator` · `pg-sanitizer` ·
|
||||
`postgres-exporter` · `postgresql` · `prometheus-stack` · `rabbitmq` · `redis` · `s3-proxy` ·
|
||||
`superset` · `trino` · `vault` · `vault-unseal` · `vmstack` · `yc-pg-dumper` · `zitadel`
|
||||
|
||||
Структура компонента: `base/` (namespace + HelmRelease/манифесты) + `patches/` + `kustomization.yaml`.
|
||||
|
||||
### 5.3 `apps/` — 37 прикладных сервисов
|
||||
|
||||
> ⚠️ `apps/` — **только манифесты деплоя**. Исходный код сервисов живёт в других группах GitLab
|
||||
> (`platform`, `pdm`, `proc`, `planning`, `aero`, `generic`) — полная карта в **[§5.3.8](#538-где-лежит-код-приложений)**.
|
||||
> Образы приезжают из одного реестра: `cr.yandex/crp3ccidau046kdj8g9q/<сервис>:<тег>`.
|
||||
|
||||
#### 5.3.1 Единый шаблон приложения
|
||||
|
||||
```
|
||||
apps/<app>/
|
||||
├── base/ # общий для всех кластеров слой
|
||||
│ ├── namespace.yaml # namespace = имя приложения
|
||||
│ ├── <компонент>.yaml # HelmRelease на universal-chart (по одному на процесс)
|
||||
│ └── kustomization.yaml
|
||||
├── <кластер>/ # оверлей: brusnika-prod | brusnika-stage | d8-ugmk-prod |
|
||||
│ └── kustomization.yaml # yc-ecp | yc-k8s-test | dsinv
|
||||
├── .env.example # ─┐
|
||||
├── CONFIGURATION.md # │ «паспорт сервиса» — документация рядом с деплоем
|
||||
├── ENDPOINTS.md # │
|
||||
└── openapi.yaml # ─┘
|
||||
```
|
||||
|
||||
Каждый процесс сервиса — отдельный `HelmRelease` на **общем чарте**:
|
||||
|
||||
```yaml
|
||||
chart: universal-chart # версия 0.1.9 (у 6 приложений осталась 0.1.7)
|
||||
sourceRef: HelmRepository/yc-oci-charts # OCI-реестр cr.yandex, ns flux-system
|
||||
values:
|
||||
global: { env: _default } # ключ окружения
|
||||
services:
|
||||
backend:
|
||||
image: { name: { _default: cr.yandex/…/bim-api:contour_f9f2a39-dirty } }
|
||||
deployment: { replicaCount: {_default: 1}, port: {_default: 8000}, probes: … }
|
||||
service: { name: {_default: backend-svc}, port: {_default: 80} }
|
||||
imagePullSecrets: { name: { _default: regcred } }
|
||||
envs: [ … ]
|
||||
podAnnotations: { _default: { vault.hashicorp.com/*: … } }
|
||||
```
|
||||
|
||||
Особенности, общие почти для всех приложений:
|
||||
|
||||
- **все значения обёрнуты в `_default`** — механизм пер-окруженческих переопределений
|
||||
`universal-chart` (`global.env` выбирает ключ);
|
||||
- **секреты не хранятся в git** — их подставляет **Vault Agent Injector** через
|
||||
`podAnnotations` (§5.3.5);
|
||||
- `traffic.sidecar.istio.io/excludeOutboundPorts: "8200"` — обращение к Vault мимо sidecar Istio;
|
||||
- поля `commitSha`/`gitlabUri`/`gitlabJobUrl`/`owner` в базовом слое пустые — заполняются CI.
|
||||
|
||||
**Исключения:** `resources` и `subscriptions` описаны голыми `Deployment`+`Service`+`ServiceAccount`
|
||||
без `HelmRelease`; у `ams-sync` и `control-interface` в `base/` нет `Namespace`.
|
||||
|
||||
#### 5.3.2 Состав приложений
|
||||
|
||||
Обозначения кластеров: **B** `brusnika-prod` · **S** `brusnika-stage` · **U** `d8-ugmk-prod` ·
|
||||
**E** `yc-ecp` · **T** `yc-k8s-test`. Код в скобках — **оверлей есть, но кластер его не подключает**.
|
||||
|
||||
| Приложение | ns | Компоненты (HelmRelease) | Образы `…/crp3ccidau046kdj8g9q/` | Кластеры |
|
||||
|---|---|---|---|---|
|
||||
| `ams-sync` | — | `ams-sync` | `ams-sync` | S |
|
||||
| `attachments` | `attachments` | `attachments` | `att9` | (B) S U T |
|
||||
| `auth-flow` | `auth-flow` | `frontend` | `auth-flow-frontend` | (B) S U T |
|
||||
| `bim` | `bim` | `backend` | `bim-api` | B S U T |
|
||||
| `cde` | `cde` | **13**: `cde` + `cde-splitpdf`, `cde-flowscallback`, `cde-worker-{alert,copy,copyv2,create-versions,create-versionsv2,markings,markingsv2,sign,signv2,update-bundles}` | `cde`, `orchestrator`, 11 × `*-worker` | (B) (S) U T |
|
||||
| `checklists` | `checklists` | `checklists` | `checklists-backend` | B S U T |
|
||||
| `comparisons` | `comparisons` | `backend`, `frontend` + 2 ConfigMap | `comparisons_backend_prod`, `comparisons-frontend` | (B) (S) U T |
|
||||
| `contracts` | `contracts` | `contracts` | `contracts` | B S U T |
|
||||
| `control-interface` | — | `frontend` | `srx-admin` | B S U T |
|
||||
| `cross-section` | `cross-section` | `cross-section-static` | `cross-section-app` | (B) (S) U T |
|
||||
| `django` | `django` | `backend`, `celery`, `frontend`, `srx-admin-frontend`, `s3-proxy` + Deployment/Service `redis` + ConfigMap `django`/`nginx`/`uwsgi`/`zitadel` | `backend`, `sarex-frontend-dev`, `srx-admin`, `s3-proxy`, `redis` | B S U **E** T |
|
||||
| `document-link` | `document-link` | `frontend` | `document-link-frontend` | B S U (T) |
|
||||
| `documentations` | `documentations` | `documentations-api`, `-filestream`, `-hasher`, `-pdf-markings-amqp`, `pdm-api`, `frontend` + Deployment `redis` | `documentations`, `documentations-api-files`, `hasher`, `pdf-markings-amqp`, `pdmv2`, `documentation-frontend-app`, `redis` | B S U T |
|
||||
| `drawings` | `drawings` | `backend` | `drawings-api` | B S U T |
|
||||
| `eav` | `eav` | `backend` + ConfigMap | `eav` | B S U T |
|
||||
| `faas` | `faas` | `export-reviews` | `export-reviews` | (B) (S) U T |
|
||||
| `flows` | `flows` | `backend`, `celery`, `frontend` | `flows-backend`, `flows-backend_worker`, `flows-frontend` | B S U T |
|
||||
| `iam` | `iam` | `iam-backend` + ConfigMap | `iams` | (B) S U (T) |
|
||||
| `inspections` | `inspections` | `backend` | `sarex-inspections`, `notification:email` | B (S) U T |
|
||||
| `issues` | `issues` | `backend`, `celery`, `frontend` + Deployment/Service `redis` + ConfigMap | `issues`, `contour_issues-frontend`, `redis` | B S U T |
|
||||
| `mapper` | `mapper` | `backend` | `mapper` | B S U T |
|
||||
| `measurements` | `measurements` | `measurements` | `measurements` | B S U **E** T |
|
||||
| `message-hub` | `message-hub` | `message-hub` | `message-hub` | B S U T |
|
||||
| `notes` | `notes` | `backend`, `frontend` + ConfigMap | `notes-backend`, `notes-frontend` | B S U T |
|
||||
| `pm` | `pm` | `backend`, `celery`, `frontend`, `resources-static` + ConfigMap | `pm-backend`, `pm-frontend`, `resources-frontend` | B S U T |
|
||||
| `prescriptions` | `prescriptions` | `frontend` | `prescriptions-frontend` | (B) (S) U T |
|
||||
| `processing` | `processing` | `workflows-api`, `engine`, `engine-low`, `frontend` + Role/RoleBinding | `workflows-api_prod`, `workflows-engine`, `workflows-endigne_prod`, `workflows-frontend` | B S U T |
|
||||
| `projects` | `projects` | `frontend` | `project-frontend-app` | (B) S U T |
|
||||
| `remarks` | `remarks` | `frontend` | `remarks-frontend` | B S U T |
|
||||
| `resources` | `resources` | — *(Deployment + Service + SA + 2 ConfigMap)* | `sarex-resources` | B S T |
|
||||
| `reviews` | `reviews` | `frontend` | `reviews-frontend` | B S U T |
|
||||
| `rfi` | `rfi` | `backend`, `celery`, `frontend` | `rfi-backend`, `rfi-frontend` | B S U T |
|
||||
| `stamp-verification` | `stamp-verification` | `frontend` | `stamp-verification-frontend` | U T |
|
||||
| `subscriptions` | `subscriptions` | — *(Deployment + Service + SA)* | `subscriptions` | B S U T |
|
||||
| `system-log` | `system-log` | `api`, `worker` | `system-log_prod`, `system-log-worker_prod` | B S U T |
|
||||
| `transmittal` | `transmittal` | `backend`, `frontend`, `worker` | `transmittal-api`, `transmittal-frontend` | B S U T |
|
||||
| `workspaces` | `workspaces` | `backend`, `frontend` | `workspaces`, `workspaces-v2-frontend` | B S U T |
|
||||
|
||||
**Как читать состав.** Типовой backend-сервис = `backend` (API) + `celery`/`worker` (асинхронные
|
||||
задачи) + `frontend` (статика). Девять приложений — **чисто фронтендовые**: `auth-flow`,
|
||||
`control-interface`, `cross-section`, `document-link`, `prescriptions`, `projects`, `remarks`,
|
||||
`reviews`, `stamp-verification`. Самое крупное — `cde` (13 релизов: оркестратор + 11 воркеров
|
||||
по типам операций над документами).
|
||||
|
||||
#### 5.3.3 Где приложения реально разворачиваются
|
||||
|
||||
| Кластер | Приложений подключено | Комментарий |
|
||||
|---|---|---|
|
||||
| `d8-ugmk-prod` | **35** | самый полный контур |
|
||||
| `yc-k8s-test` | **34** | тестовый, близок к полному |
|
||||
| `brusnika-stage` | **30** | |
|
||||
| `brusnika-prod` | **26** | |
|
||||
| `yc-ecp` | **2** | только `django` и `measurements` |
|
||||
| `wb`, `yc-cps-prod`, `yc-infra-prod`, `yc-k8s-test-02`, `contour` | **0** | приложений из `apps/` не деплоят: эти кластеры несут только `infrastructure/` |
|
||||
|
||||
**Мёртвые и неподключённые оверлеи** — каталог существует, но ни один
|
||||
`clusters/*/kustomization.yaml` на него не ссылается, то есть Flux его не применяет:
|
||||
|
||||
| Кластер | Неподключённые оверлеи |
|
||||
|---|---|
|
||||
| `brusnika-prod` | `attachments`, `auth-flow`, `cde`, `comparisons`, `cross-section`, `faas`, `iam`, `prescriptions`, `projects` |
|
||||
| `brusnika-stage` | `cde`, `comparisons`, `cross-section`, `faas`, `inspections`, `prescriptions` |
|
||||
| `yc-k8s-test` | `document-link`, `iam` |
|
||||
|
||||
Отдельно **`dsinv/`** — оверлей у **25 приложений**, но **кластера `clusters/dsinv/` не существует**
|
||||
и никто на него не ссылается. Судя по содержимому (готовые `Deployment` с `SERVICE_URL=https://srx.wb.ru`)
|
||||
и по каталогу `snapshots/dsinv/`, это **материализованный снимок живого контура WB**, а не рабочий
|
||||
оверлей. Использовать как справочник «что реально крутится», не как источник деплоя.
|
||||
|
||||
#### 5.3.4 Две несовместимые конвенции оверлеев ⚠️
|
||||
|
||||
| Кластер | Как устроен оверлей | Приложений |
|
||||
|---|---|---|
|
||||
| `d8-ugmk-prod`, `yc-k8s-test`, `dsinv` | ✅ **наследует `base`**: `resources: [../base]` + `patches:` | 35 / 36 / 25 |
|
||||
| `brusnika-prod`, `brusnika-stage`, `yc-ecp` | ⚠️ **самостоятельный**: `base` не подключается, `HelmRelease` скопирован целиком | 35 / 36 / 2 |
|
||||
|
||||
Последствие — **тихий дрейф**. Пример: `apps/bim/base/backend.yaml` использует
|
||||
`universal-chart` **0.1.9**, а его полная копия `apps/bim/brusnika-prod/backend.yaml` — **0.1.7**.
|
||||
Правка в `base/` до контуров Брусники не доедет, и никакой ошибки при этом не возникнет.
|
||||
|
||||
Это же объясняет разнобой версий чарта: 0.1.7 остался у `ams-sync`, `auth-flow`,
|
||||
`control-interface`, `cross-section`, `remarks`, `reviews`.
|
||||
|
||||
#### 5.3.5 Секреты: Vault Agent Injector
|
||||
|
||||
Пароли БД в git не лежат. Под получает их файлом от sidecar-инжектора Vault:
|
||||
|
||||
```yaml
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/agent-init-first: "true"
|
||||
vault.hashicorp.com/agent-pre-populate-only: "true" # только init-контейнер, без постоянного sidecar
|
||||
vault.hashicorp.com/auth-path: auth/kubernetes
|
||||
vault.hashicorp.com/role: bim # роль = имя приложения
|
||||
vault.hashicorp.com/agent-inject-secret-bim-postgresql: secrets/data/apps/bim/postgres
|
||||
vault.hashicorp.com/agent-inject-template-bim-postgresql: |- # → env-файл
|
||||
POSTGRES_ADDRESS={{ index .Data.data "host" }} …
|
||||
```
|
||||
|
||||
Дальше контейнер стартует как `sh -ec 'set -a; . /vault/secrets/<name>; set +a; exec ./httpserver'`.
|
||||
|
||||
**Соглашение о путях:** `secrets/data/apps/<приложение>/postgres`; нестандартные —
|
||||
`documentations/hasher/{rabbitmq,s3}`, `documentations/marks-s3`.
|
||||
Соответствующие ServiceAccount называются `<app>-vault`.
|
||||
|
||||
Vault используют **26 приложений**. Больше всего инъекций — у `cde` (13), `documentations` (5),
|
||||
`django` и `processing` (по 3). **Не используют** ровно те, у кого нет БД: девять фронтендов
|
||||
(§5.3.2) плюс `ams-sync` и `faas`.
|
||||
|
||||
> Сами БД, пользователи и бакеты, на которые ссылаются эти пути, создаются не здесь,
|
||||
> а в [infra/terraform](https://gitlab.sarex.io/infra/terraform) (`infrastructure.yaml`).
|
||||
|
||||
#### 5.3.6 Документация рядом с манифестами
|
||||
|
||||
Нетипичная и полезная особенность: в каталоге приложения лежит его «паспорт».
|
||||
|
||||
| Файл | Что внутри | Покрытие |
|
||||
|---|---|---|
|
||||
| `CONFIGURATION.md` | все переменные окружения, как они разбираются в коде, и **откуда берутся при каждом способе запуска** (локально / docker-compose / Helm в репозитории приложения / IaC+Vault / GitLab CI); команды и точки входа процессов | 32 / 37 |
|
||||
| `ENDPOINTS.md` | **исходящие** HTTP-вызовы сервиса: библиотека клиента, таймауты, ретраи, проброс JWT, базовые хосты по окружениям, таблица методов и путей | 28 / 37 |
|
||||
| `openapi.yaml` | **входящие** эндпоинты — спецификация того, что сервис предоставляет (от 9 КБ у `mapper` до 101 КБ у `issues`) | 25 / 37 |
|
||||
| `.env.example` | образец переменных с комментариями | 32 / 37 |
|
||||
|
||||
Многокомпонентные приложения используют префиксы вместо одного файла: у `documentations` —
|
||||
`api.*`, `api-v2.*`, `pdm.*`, `frontend.*`, `dps-message-hub.*`; у `processing` —
|
||||
`workflows-api.*`, `workflows-engine.*`, `workflows-frontend.*`; у `workspaces` —
|
||||
`ENDPOINTS-workspaces-frontend.md` и `ENDPOINTS-workspace-v2-frontend.md`.
|
||||
|
||||
**Пробелы в документации:**
|
||||
|
||||
- нет `CONFIGURATION.md`: `control-interface`, `cross-section`, `faas`, `remarks`, `reviews`;
|
||||
- нет `ENDPOINTS.md`: `attachments`, `checklists`, `drawings`, `eav`, `faas`, `measurements`,
|
||||
`resources`, `subscriptions`, `system-log`;
|
||||
- нет диаграммы в `docs/apps/`: `ams-sync`, `auth-flow`, `iam` *(остальные 34 покрыты)*.
|
||||
|
||||
Дополняющий слой — [`docs/apps/`](./docs/apps/README.md): по mermaid-диаграмме на сервис
|
||||
с его зависимостями, сгруппированные по доменам — Платформа/Core, Управление проектом,
|
||||
Документы/CDE, Контроль качества, Полевые данные.
|
||||
|
||||
#### 5.3.7 Внешние маршруты
|
||||
|
||||
Правила Istio живут не в `apps/`, а в `infrastructure/istio-config/<кластер>` и в патчах кластеров.
|
||||
Пример готовой карты маршрутов (`yc-ecp`):
|
||||
|
||||
| Путь | Сервис назначения |
|
||||
|---|---|
|
||||
| `/api`, `/admin/` | `backend-service.django` |
|
||||
| `/media/` | `s3-service.django` |
|
||||
| `/s3/` | `s3-bim-service.django` |
|
||||
| `/eav/api/`, `/eav/admin/` | `eav-service.eav` |
|
||||
| `/bim-gazpromcps/{api,files}/` | `bim-api-gazpromcps-service.bim` |
|
||||
| `/bim2-gazpromcps/api/` | `bim-backend-v2-service.bim` |
|
||||
| `/workflows/api/` | `workflows-backend-service.processing` |
|
||||
| `/projects/static/` | `projects-frontend-static-service.projects` |
|
||||
|
||||
В контурах Брусники и WB прикладной трафик уходит одним правилом на
|
||||
`nginx-service.global-ingress` — пути до конкретных сервисов раскрываются уже там, **вне этого
|
||||
репозитория**. Через Istio там опубликованы только платформенные UI (Gitea, GoAlert, OpenObserve,
|
||||
Superset, Kubernetes Dashboard, Camunda, Jupyter).
|
||||
|
||||
#### 5.3.8 Где лежит код приложений
|
||||
|
||||
Исходники продуктовых сервисов — **вне группы `infra`**: 14 групп верхнего уровня, ~393 проекта.
|
||||
Ориентир по владению:
|
||||
|
||||
| Группа | Домен | Что оттуда деплоится из `apps/` |
|
||||
|---|---|---|
|
||||
| [`platform`](https://gitlab.sarex.io/groups/platform) (95) | платформенное ядро, BIM, workflows, tracking | `bim`, `iam`, `mapper`, `contracts`, `eav`, `system-log`, `processing`, `control-interface`, `resources`, `ams-sync`, `auth-flow`, `cde` |
|
||||
| [`pdm`](https://gitlab.sarex.io/groups/pdm) (41) | документооборот, CDE, PDF | `documentations`, `attachments`, `transmittal`, `workspaces`, `document-link`, `stamp-verification`, `subscriptions`, `comparisons` |
|
||||
| [`proc`](https://gitlab.sarex.io/groups/proc) (24) | процессы и контроль качества | `inspections`, `issues`, `rfi`, `reviews`, `checklists`, `flows`, `remarks`, `prescriptions`, `faas` |
|
||||
| [`planning`](https://gitlab.sarex.io/groups/planning) (10) | планирование | `pm`, `projects`, `message-hub` |
|
||||
| [`aero`](https://gitlab.sarex.io/groups/aero) (50) | гео, полевые данные, обработка съёмки | `measurements`, `drawings`, `notes`, `cross-section` |
|
||||
| [`generic`](https://gitlab.sarex.io/groups/generic) (56) | сквозное: монолит, CI-шаблоны, утилиты | `django` |
|
||||
| [`algorithms`](https://gitlab.sarex.io/groups/algorithms) (82), [`render`](https://gitlab.sarex.io/groups/render) (16) | вычислительные библиотеки, конвертеры, рендер | напрямую не деплоятся — используются джобами и воркерами |
|
||||
| `ai`, `marketing`, `hackathon`, `product`, `algorithms1`, `planning1` | прочее / архив | — |
|
||||
|
||||
**Карта «приложение → репозитории с кодом».** Ключ сопоставления — имя образа
|
||||
`cr.yandex/crp3ccidau046kdj8g9q/<name>` и заголовок `CONFIGURATION.md` / `ENDPOINTS.md`.
|
||||
|
||||
| `apps/` | Компонент (образ) | Репозиторий с кодом |
|
||||
|---|---|---|
|
||||
| `ams-sync` | `ams-sync` | [platform/ams-sync](https://gitlab.sarex.io/platform/ams-sync) ✅ *(смежный: [platform/ams](https://gitlab.sarex.io/platform/ams))* |
|
||||
| `attachments` | `att9` / `attachments` | [pdm/attachments](https://gitlab.sarex.io/pdm/attachments) ✅ |
|
||||
| `auth-flow` | `auth-flow-frontend` | [platform/auth-flow-frontend](https://gitlab.sarex.io/platform/auth-flow-frontend) ✅ |
|
||||
| `bim` | `bim-backend-v2` | [platform/bim-backend-v2](https://gitlab.sarex.io/platform/bim-backend-v2) ✅ |
|
||||
| | `bim-api` (legacy) | [platform/bim](https://gitlab.sarex.io/platform/bim) ◻️ — репозитория с именем `bim-api` нет, привязка по смыслу |
|
||||
| `cde` | `cde`, `orchestrator`, 11 × `*-worker` | [platform/cde-orchestration-demo](https://gitlab.sarex.io/platform/cde-orchestration-demo) ✅ |
|
||||
| | смежные | [pdm/cde-api](https://gitlab.sarex.io/pdm/cde-api), [generic/cde-v2-write-service](https://gitlab.sarex.io/generic/cde-v2-write-service), [generic/level-cde-migration](https://gitlab.sarex.io/generic/level-cde-migration) |
|
||||
| `checklists` | `checklists-backend` | [proc/checklists-backend](https://gitlab.sarex.io/proc/checklists-backend) ✅ |
|
||||
| `comparisons` | `comparisons-backend` | [pdm/comparisons-backend](https://gitlab.sarex.io/pdm/comparisons-backend) ✅, v2 → [pdm/comparisons-api-v2](https://gitlab.sarex.io/pdm/comparisons-api-v2) |
|
||||
| | `comparisons-frontend` | [platform/comparisons-frontend](https://gitlab.sarex.io/platform/comparisons-frontend) ✅ |
|
||||
| | движок сравнения | [platform/comparator](https://gitlab.sarex.io/platform/comparator), [algorithms/comparator-algorithms](https://gitlab.sarex.io/algorithms/comparator-algorithms), [render/comparator-bins](https://gitlab.sarex.io/render/comparator-bins), [algorithms/diff-pdf-algorithm](https://gitlab.sarex.io/algorithms/diff-pdf-algorithm) |
|
||||
| `contracts` | `contracts` | [platform/contracts](https://gitlab.sarex.io/platform/contracts) ✅ + [platform/contracts-frontend](https://gitlab.sarex.io/platform/contracts-frontend) ✅ |
|
||||
| `control-interface` | `srx-admin` | [platform/srx-admin](https://gitlab.sarex.io/platform/srx-admin) ✅ |
|
||||
| `cross-section` | `cross-section-app` | [aero/cross-section](https://gitlab.sarex.io/aero/cross-section) ✅ *(джоба: [aero/cross-secttions-to-dwg-job](https://gitlab.sarex.io/aero/cross-secttions-to-dwg-job))* |
|
||||
| `django` | `backend` | [generic/sarex-backend](https://gitlab.sarex.io/generic/sarex-backend) ✅ |
|
||||
| | `sarex-frontend-dev` | [generic/sarex-frontend](https://gitlab.sarex.io/generic/sarex-frontend) ✅ |
|
||||
| | `s3-proxy` | [generic/s3-proxy](https://gitlab.sarex.io/generic/s3-proxy) ✅ |
|
||||
| | `srx-admin` | [platform/srx-admin](https://gitlab.sarex.io/platform/srx-admin) ✅ |
|
||||
| `document-link` | `document-link-frontend` | [pdm/document-link-frontend](https://gitlab.sarex.io/pdm/document-link-frontend) ✅ |
|
||||
| `documentations` | `documentations` | [pdm/documentation-api](https://gitlab.sarex.io/pdm/documentation-api) ✅ |
|
||||
| | `documentations-api-files` (v2) | [pdm/documentation-api-v2](https://gitlab.sarex.io/pdm/documentation-api-v2) ✅ |
|
||||
| | `hasher` | [pdm/documentation-hasher](https://gitlab.sarex.io/pdm/documentation-hasher) ✅ |
|
||||
| | `pdf-markings-amqp` | [pdm/pdf-markings](https://gitlab.sarex.io/pdm/pdf-markings) ✅ |
|
||||
| | `pdmv2` | [pdm/pdm](https://gitlab.sarex.io/pdm/pdm) ✅ |
|
||||
| | `documentation-frontend-app` | [pdm/documentation-frontend](https://gitlab.sarex.io/pdm/documentation-frontend) ✅ |
|
||||
| | `dps-message-hub` | [pdm/dps_message_hub](https://gitlab.sarex.io/pdm/dps_message_hub) ✅ |
|
||||
| `drawings` | `drawings-api` | [aero/drawings-api](https://gitlab.sarex.io/aero/drawings-api) ✅ |
|
||||
| `eav` | `eav` | [platform/eav_python](https://gitlab.sarex.io/platform/eav_python) ✅ *(gRPC-ветка: [platform/eav](https://gitlab.sarex.io/platform/eav))* |
|
||||
| `faas` | `export-reviews` | [proc/export-reviews](https://gitlab.sarex.io/proc/export-reviews) ✅ *(в GitLab называется `flows-export`)* |
|
||||
| `flows` | `flows-backend`, `flows-backend_worker` | [proc/flows-backend](https://gitlab.sarex.io/proc/flows-backend) ✅ |
|
||||
| | `flows-frontend` | [proc/flows-frontend](https://gitlab.sarex.io/proc/flows-frontend) ✅ |
|
||||
| `iam` | `iams` | [platform/iams-v2](https://gitlab.sarex.io/platform/iams-v2) ✅ *(смежный: [platform/srx-rebac](https://gitlab.sarex.io/platform/srx-rebac))* |
|
||||
| `inspections` | `sarex-inspections` | [proc/inspections-backend](https://gitlab.sarex.io/proc/inspections-backend) ✅ — подтверждено аннотацией `gitlab-uri` |
|
||||
| | фронтенд | [proc/inspections-frontend](https://gitlab.sarex.io/proc/inspections-frontend) ✅ |
|
||||
| | `notification:email` | [generic/jobs/email-notification-task](https://gitlab.sarex.io/generic/jobs/email-notification-task) ✅ |
|
||||
| `issues` | `issues` | [proc/issues-backend](https://gitlab.sarex.io/proc/issues-backend) ✅ |
|
||||
| | `contour_issues-frontend` | [proc/issues-frontend](https://gitlab.sarex.io/proc/issues-frontend) ✅ |
|
||||
| | `crop-issue-pin-area` | [proc/crop-issue-pin-area-task](https://gitlab.sarex.io/proc/crop-issue-pin-area-task) ✅ |
|
||||
| | `docx-to-pdf`, `rendering-template` | [pdm/docx-to-pdf](https://gitlab.sarex.io/pdm/docx-to-pdf), [pdm/rendering-template](https://gitlab.sarex.io/pdm/rendering-template) ✅ |
|
||||
| | `webhook-caller` | [platform/webhook-caller](https://gitlab.sarex.io/platform/webhook-caller) ✅ |
|
||||
| `mapper` | `mapper` | [platform/mapper](https://gitlab.sarex.io/platform/mapper) ✅ |
|
||||
| `measurements` | `measurements` | [aero/measurements](https://gitlab.sarex.io/aero/measurements) ✅ |
|
||||
| `message-hub` | `message-hub` | [planning/message-hub](https://gitlab.sarex.io/planning/message-hub) ✅ |
|
||||
| `notes` | `notes-backend` / `notes-frontend` | [aero/notes-backend](https://gitlab.sarex.io/aero/notes-backend), [aero/notes-frontend](https://gitlab.sarex.io/aero/notes-frontend) ✅ |
|
||||
| `pm` | `pm-backend` / `pm-frontend` | [planning/pm-backend](https://gitlab.sarex.io/planning/pm-backend), [planning/pm-frontend](https://gitlab.sarex.io/planning/pm-frontend) ✅ |
|
||||
| | `resources-frontend` | [planning/resources-frontend](https://gitlab.sarex.io/planning/resources-frontend) ✅ |
|
||||
| `prescriptions` | `prescriptions-frontend` | [proc/prescriptions-frontend](https://gitlab.sarex.io/proc/prescriptions-frontend) ✅ |
|
||||
| `processing` | `workflows-api` | [platform/workflows-api](https://gitlab.sarex.io/platform/workflows-api) ✅ |
|
||||
| | `workflows-engine`, `kubernetes-engine` | [platform/workflows-engine](https://gitlab.sarex.io/platform/workflows-engine) ✅ |
|
||||
| | `workflows-frontend` | [platform/workflows-frontend](https://gitlab.sarex.io/platform/workflows-frontend) ✅ |
|
||||
| | смежные | [platform/workflows-backend](https://gitlab.sarex.io/platform/workflows-backend), [generic/workflows-tools](https://gitlab.sarex.io/generic/workflows-tools), [generic/processing/job_template](https://gitlab.sarex.io/generic/processing/job_template) |
|
||||
| `projects` | `project-frontend-app` / `projects-frontend` | [planning/projects-frontend](https://gitlab.sarex.io/planning/projects-frontend) ✅ *(API: [planning/projects-backend](https://gitlab.sarex.io/planning/projects-backend))* |
|
||||
| `remarks` | `remarks-frontend` | [proc/remarks-frontend](https://gitlab.sarex.io/proc/remarks-frontend) ✅ |
|
||||
| | `remarks-api`, `export-remarks` | ⚠️ [proc/remarks-api](https://gitlab.sarex.io/proc/remarks-api), [proc/export-remarks](https://gitlab.sarex.io/proc/export-remarks) — **помечены `_archived_`** в GitLab, но образы ещё встречаются в манифестах |
|
||||
| `resources` | `sarex-resources` | [platform/sarex-resources](https://gitlab.sarex.io/platform/sarex-resources) ✅ *(старая копия: [generic/sarex-resources1](https://gitlab.sarex.io/generic/sarex-resources1))* |
|
||||
| `reviews` | `reviews-frontend` | [proc/reviews-frontend](https://gitlab.sarex.io/proc/reviews-frontend) ✅ |
|
||||
| `rfi` | `rfi-backend` / `rfi-frontend` | [proc/rfi-backend](https://gitlab.sarex.io/proc/rfi-backend), [proc/rfi-frontend](https://gitlab.sarex.io/proc/rfi-frontend) ✅ |
|
||||
| `stamp-verification` | `stamp-verification-frontend` | [pdm/stamp-verification-frontend](https://gitlab.sarex.io/pdm/stamp-verification-frontend) ✅ |
|
||||
| `subscriptions` | `subscriptions` / `sarex-subscriptions` | [pdm/sarex-subscriptions](https://gitlab.sarex.io/pdm/sarex-subscriptions) ✅ |
|
||||
| `system-log` | `system-log` / `system-log-worker` | [platform/system-log](https://gitlab.sarex.io/platform/system-log), [platform/system-log-worker](https://gitlab.sarex.io/platform/system-log-worker) ✅ |
|
||||
| `transmittal` | `transmittal-api` / `transmittal-frontend` | [pdm/transmittal-api](https://gitlab.sarex.io/pdm/transmittal-api), [pdm/transmittal-frontend](https://gitlab.sarex.io/pdm/transmittal-frontend) ✅ |
|
||||
| `workspaces` | `workspaces` | [pdm/workspaces-api](https://gitlab.sarex.io/pdm/workspaces-api) ✅ |
|
||||
| | `workspaces-frontend-static` | [platform/workspaces-frontend](https://gitlab.sarex.io/platform/workspaces-frontend) ✅ |
|
||||
| | `workspaces-v2-frontend` | [platform/workspace-v2-frontend](https://gitlab.sarex.io/platform/workspace-v2-frontend) ✅ |
|
||||
|
||||
**Как искать самому, если компонента нет в таблице.** Порядок надёжности:
|
||||
|
||||
1. Взять имя образа из `apps/<app>/base/*.yaml` — `cr.yandex/crp3ccidau046kdj8g9q/**<name>**:tag`.
|
||||
В большинстве случаев `<name>` = `path` репозитория.
|
||||
2. Открыть `apps/<app>/CONFIGURATION.md` — в первой строке стоит **настоящее имя проекта**
|
||||
(например `apps/eav` → «Конфигурация проекта eav-python» → `platform/eav_python`).
|
||||
3. Искать по GitLab: `scope: projects`, термин ≥ 3 символов, матч идёт по `path_with_namespace` —
|
||||
поэтому запрос по имени группы (`proc`, `pdm`, `planning`) выдаёт всю группу целиком.
|
||||
4. Если сервис уже работает в кластере — у его `Deployment` есть аннотации
|
||||
`gitlab-uri` и `gitlab-job`, проставляемые CI, с прямой ссылкой на репозиторий и джобу сборки.
|
||||
|
||||
⚠️ Имя образа **не всегда** совпадает с репозиторием: `att9` → `pdm/attachments`,
|
||||
`iams` → `platform/iams-v2`, `pdmv2` → `pdm/pdm`, `export-reviews` → `proc/export-reviews`
|
||||
(в GitLab отображается как `flows-export`), `sarex-inspections` → `proc/inspections-backend`.
|
||||
Суффиксы `_prod`, `contour_`, `-dev` в имени образа — артефакты веток CI, не часть имени проекта.
|
||||
|
||||
Общий CI-конвейер для всех этих репозиториев —
|
||||
[generic/common-ci](https://gitlab.sarex.io/generic/common-ci) (подключается в `.gitlab-ci.yml`
|
||||
каждого сервиса), базовый образ — [generic/base-image](https://gitlab.sarex.io/generic/base-image).
|
||||
|
||||
### 5.4 Вспомогательное в репозитории
|
||||
|
||||
| Путь | Назначение |
|
||||
|---|---|
|
||||
| `inventory.yaml` | Сгенерированный инвентарь prod: namespace → тип ресурса → имена (ConfigMap/Secret/Deployment/Service/EnvoyFilter) |
|
||||
| `snapshots/dsinv/` | Снимки живых манифестов (в `.gitignore`, локальный артефакт) |
|
||||
| `docs/apps/` | Диаграмма и описание по каждому бизнес-сервису |
|
||||
| `gitea-data/` | Локальные данные Gitea — рабочий артефакт, **не коммитить** |
|
||||
|
||||
---
|
||||
|
||||
## 6. Перекрытия и как выбирать источник истины
|
||||
|
||||
Для ~20 компонентов существуют оба источника — каталог в `infra/iac` и отдельный репозиторий.
|
||||
Наблюдаемое правило (по факту содержимого, **стоит подтвердить с владельцами**):
|
||||
|
||||
| Ситуация | Источник истины |
|
||||
|---|---|
|
||||
| Кластер перечислен в §5.1 (`yc-*`, `brusnika-*`, `wb`, `d8-ugmk-prod`) | **`infra/iac`**, ветка `master`. Правки в отдельном репозитории туда не доедут |
|
||||
| Контур деплоится GitLab CI (ветки `stage`, `preprod`, `contour`, `infra`, `contour/cps`, `stronghold`) | **Отдельный репозиторий компонента**, ветка = имя контура |
|
||||
| Контур ГПН | **`infra/iac-gpn`** (ArgoCD), не Flux |
|
||||
| Namespace, БД, S3-бакет, Kafka-топик, пользователь, k8s-секрет | **`infra/terraform`** (`infrastructure.yaml`) — не создавать вручную и не дублировать в Flux |
|
||||
| Изолированный контур без доступа к GitLab | `infra/iac` → зеркало **Gitea** → Flux. Пуш в GitLab обязателен, но недостаточен: нужно, чтобы зеркало обновилось |
|
||||
|
||||
Особые случаи:
|
||||
|
||||
- **`prometheus-stack` vs `kube-prometheus-stack`** — два разных репозитория с пересекающейся зоной;
|
||||
в `iac` компонент один (`prometheus-stack`). Требует ревизии.
|
||||
- **`terraform` vs `terraform-contour-mirror`** — README идентичны, `mirror` живёт только в ветке
|
||||
`contour` и активен (2026-08-04). Расхождение между ними — реальный риск дрейфа.
|
||||
- **`istio-config`** — самый «многоконтурный» репозиторий (7 веток) и одновременно компонент в `iac`.
|
||||
- **`poc/iac`** — архив; не путать с `infra/iac`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Эксплуатация, аудит и данные
|
||||
|
||||
| Репозиторий | Отвечает за |
|
||||
|---|---|
|
||||
| [infra/k8s-changelog](https://gitlab.sarex.io/infra/k8s-changelog) ✅ | Ежедневный снимок всех манифестов кластера в стабильную файловую структуру и коммит в git — **читаемый diff состояния кластера** для аудита и восстановления. Чистит `status`, `managedFields`, значения секретов |
|
||||
| [infra/harvester](https://gitlab.sarex.io/infra/harvester) ✅ | **Резервное копирование данных платформы Sarex** (документация, планирование, замечания, рабочие процессы). Kafka-download/sync приложения, манифесты, mkdocs |
|
||||
| [infra/scripts/extract-kuberntes-manifests-to-s3](https://gitlab.sarex.io/infra/scripts/extract-kuberntes-manifests-to-s3) ◻️ | Выгрузка манифестов кластера в S3 |
|
||||
| [infra/yc-pg-dumper](https://gitlab.sarex.io/infra/yc-pg-dumper) ◻️ (+ компонент `infrastructure/yc-pg-dumper`) | Дампы PostgreSQL в Yandex Cloud |
|
||||
| [infra/backups/*](https://gitlab.sarex.io/infra/backups) ◻️ | `frontend`, `workers`, `sendbox`, `collect-pdm-data-from-postgresql` — подсистема бэкапов |
|
||||
| [infra/postgresql-ddl-extractor](https://gitlab.sarex.io/infra/postgresql-ddl-extractor) ◻️ | Извлечение DDL из PostgreSQL |
|
||||
| [infra/k8s-hustler](https://gitlab.sarex.io/infra/k8s-hustler), [infra/revisor](https://gitlab.sarex.io/infra/revisor), [infra/peeping](https://gitlab.sarex.io/infra/peeping) ◻️ | Утилиты инспекции/ревизии кластера |
|
||||
| [infra/compnay-cleanup-kit](https://gitlab.sarex.io/infra/compnay-cleanup-kit) ◻️ | Очистка данных компании *(опечатка в имени — так в GitLab)* |
|
||||
| [infra/py-s3-size](https://gitlab.sarex.io/infra/py-s3-size), [infra/get_size_SOD](https://gitlab.sarex.io/infra/get_size_SOD), [infra/jobs/object-storage-size-by-project](https://gitlab.sarex.io/infra/jobs/object-storage-size-by-project) ◻️ | Учёт объёмов объектного хранилища |
|
||||
| [infra/s3-replication-poc](https://gitlab.sarex.io/infra/s3-replication-poc) ◻️ | Репликация S3 (PoC) |
|
||||
| [infra/wunderwaffe-operator](https://gitlab.sarex.io/infra/wunderwaffe-operator), [infra/wunderwaffe-tasks](https://gitlab.sarex.io/infra/wunderwaffe-tasks), [infra/wunderwaffe-dumpster](https://gitlab.sarex.io/infra/wunderwaffe-dumpster) ◻️ | Собственный k8s-оператор и его задачи |
|
||||
|
||||
---
|
||||
|
||||
## 8. Контуры заказчиков
|
||||
|
||||
| Подгруппа / репозиторий | Контур | Содержимое |
|
||||
|---|---|---|
|
||||
| [infra/wb/*](https://gitlab.sarex.io/infra/wb) ◻️ | WB | `manifestos-k8s`, `postgresql16`, `helm-of-business`. Кластер `wb` в `iac` синхронизируется из `gitea-srx.wb.ru` |
|
||||
| [infra/gpnt/*](https://gitlab.sarex.io/infra/gpnt) ◻️ | ГПН, OpenShift | UBI-образы: `base`, `backend`, `nginx`, `postgres`, `rabbitmq`, `redis`, `comparator`; `gpnt-os` — «manifest and helm templates for openshift» |
|
||||
| [infra/gpnr/*](https://gitlab.sarex.io/infra/gpnr) ◻️ | ГПН-Р | `docker-packaging-gdal-builder`, `docker-packaging-potree-builder`, `u190001439_skzssrx*` |
|
||||
| [infra/severstal/*](https://gitlab.sarex.io/infra/severstal) ◻️ | Северсталь | UBI-образы + `ingress`, `provision` |
|
||||
| [infra/iac-gpn](https://gitlab.sarex.io/infra/iac-gpn) ✅ | ГПН | ArgoCD-монорепозиторий контура |
|
||||
| [infra/brusnika](https://gitlab.sarex.io/infra/brusnika), [infra/uralchem](https://gitlab.sarex.io/infra/uralchem), [infra/ugok](https://gitlab.sarex.io/infra/ugok), [infra/cps2](https://gitlab.sarex.io/infra/cps2) ◻️ | Брусника, Уралхим, УГОК, ЦПС | Контурные наборы (низкая активность — часть с 2025-01) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Инструменты, скрипты, документация
|
||||
|
||||
| Репозиторий | Отвечает за |
|
||||
|---|---|
|
||||
| [infra/kafka-router](https://gitlab.sarex.io/infra/kafka-router) ✅ | Проксирование сообщений между Kafka-кластерами по `TOPIC_MAPPING`, с фильтрацией по компании (FastStream) |
|
||||
| [infra/tools/sarex-cli-service](https://gitlab.sarex.io/infra/tools/sarex-cli-service) | Python-скрипт подъёма локального окружения разработчика *(описание из GitLab)* |
|
||||
| [infra/tools/sdk-python](https://gitlab.sarex.io/infra/tools/sdk-python) ◻️ | Внутренний Python SDK |
|
||||
| [infra/bash-scripts](https://gitlab.sarex.io/infra/bash-scripts), [infra/python-scripts](https://gitlab.sarex.io/infra/python-scripts), [infra/scripts/*](https://gitlab.sarex.io/infra/scripts), [d.emelin/infra-scripts](https://gitlab.sarex.io/d.emelin/infra-scripts) ◻️ | Разрозненные операционные скрипты |
|
||||
| [infra/transfer-tools](https://gitlab.sarex.io/infra/transfer-tools) ◻️ | Перенос данных между контурами |
|
||||
| [infra/docs/deploy](https://gitlab.sarex.io/infra/docs/deploy), [infra/docs/services](https://gitlab.sarex.io/infra/docs/services), [infra/kb](https://gitlab.sarex.io/infra/kb) ◻️ | Документация по деплою и сервисам, база знаний |
|
||||
| [infra/automations/terraform-deletion_scheduled-454](https://gitlab.sarex.io/infra/automations/terraform-deletion_scheduled-454) ◻️ | Автоматизация; судя по имени — запланированное удаление ресурсов. **Проверить перед любыми действиями** |
|
||||
| [infra/poc/*](https://gitlab.sarex.io/infra/poc) (~30 репозиториев) ◻️ | Песочница: `k8s-teleport`, `k8s-events`, `contour-storage`, `git-server`, `minikube`, `offline-sentry`, `offline-signoz`, `cdc`, `delta`, `trace-viewer`, `streaming-dump`, `system-tests`, `s3-*`, `unity/*` и др. **Не источник истины для прода** |
|
||||
|
||||
---
|
||||
|
||||
## 10. Как пользоваться каталогом
|
||||
|
||||
**Меняю поведение компонента в кластере из §5.1** → `infra/iac`, `infrastructure/<компонент>/patches/`
|
||||
или оверлей кластера; проверка — `flux get kustomizations`, `flux get helmreleases -A`.
|
||||
|
||||
**Меняю поведение компонента в CI-контуре** → соответствующий `infra/<компонент>`, **ветка контура**,
|
||||
каталог `.helm/`.
|
||||
|
||||
**Выкатываю новую версию приложения** → `apps/<app>/`: тег образа в `base/<компонент>.yaml`,
|
||||
если кластер наследует базу (`d8-ugmk-prod`, `yc-k8s-test`), **и отдельно** в
|
||||
`apps/<app>/brusnika-*/`, `apps/<app>/yc-ecp/` — эти оверлеи базу не подключают (§5.3.4).
|
||||
Перед правкой сверься с §5.3.3: возможно, оверлей вообще не подключён к кластеру.
|
||||
|
||||
**Нужен новый секрет для приложения** → положить в Vault по пути `secrets/data/apps/<app>/…`
|
||||
и добавить `vault.hashicorp.com/agent-inject-*` в `podAnnotations` (§5.3.5). В git секрет не кладём.
|
||||
|
||||
**Ищу исходники сервиса по имени namespace или образа** → карта «приложение → репозиторий»
|
||||
в §5.3.8; там же порядок поиска, если компонента в таблице нет.
|
||||
|
||||
**Нужен новый namespace / БД / бакет / топик / секрет** → `infra/terraform`, `infrastructure.yaml`
|
||||
(секреты — через SOPS, см. `SOPS.md`); для контура — `terraform-contour` / `terraform-contour-mirror`.
|
||||
|
||||
**Нужен новый кластер** → `kubespray` → `k8s-provision` → `flux bootstrap --path=clusters/<имя>`
|
||||
в `infra/iac`.
|
||||
|
||||
**Понять, что реально крутится в кластере** → `inventory.yaml` в этом репозитории и
|
||||
`infra/k8s-changelog` (git-история состояния).
|
||||
|
||||
---
|
||||
|
||||
### Открытые вопросы
|
||||
|
||||
1. Привести оверлеи `brusnika-prod`, `brusnika-stage`, `yc-ecp` к наследованию `../base` — сейчас
|
||||
это полные копии, которые молча расходятся с базой (§5.3.4).
|
||||
2. Разобрать 17 неподключённых оверлеев приложений и 25 каталогов `dsinv/`: удалить или
|
||||
подключить (§5.3.3).
|
||||
3. Выровнять версию `universal-chart` — шесть приложений остались на 0.1.7 при базовой 0.1.9.
|
||||
4. Разграничить `prometheus-stack` и `kube-prometheus-stack` — какой из них актуален.
|
||||
5. Зафиксировать регламент синхронизации `terraform` ↔ `terraform-contour-mirror`.
|
||||
6. Для ~60 компонентных репозиториев определить, какие мигрируют в `infra/iac`, а какие остаются
|
||||
на CI-деплое; остальное — архивировать.
|
||||
7. Закрыть пробелы в паспортах сервисов (§5.3.6) и подтвердить назначение репозиториев с ◻️.
|
||||
3
aero/.gitattributes
vendored
3
aero/.gitattributes
vendored
@ -1,3 +0,0 @@
|
||||
* text=auto eol=lf
|
||||
*.sh text eol=lf
|
||||
*.cmd text eol=crlf
|
||||
5
aero/.gitignore
vendored
5
aero/.gitignore
vendored
@ -1,5 +0,0 @@
|
||||
.venv/
|
||||
.venv-*/
|
||||
.secrets/
|
||||
*.retry
|
||||
__pycache__/
|
||||
252
aero/README.md
252
aero/README.md
@ -1,252 +0,0 @@
|
||||
# aero — Ansible-провижининг docker-хостов
|
||||
|
||||
Ansible-роль `docker`, устанавливающая на сервер:
|
||||
|
||||
- **Docker Engine** (`docker-ce`, `docker-ce-cli`);
|
||||
- **containerd**;
|
||||
- **docker compose** и (где есть) buildx;
|
||||
- обновление пакетов системы при старте.
|
||||
|
||||
Ветка установки выбирается автоматически по пакетному менеджеру хоста:
|
||||
|
||||
| Семейство | Пакетный менеджер | Пакеты |
|
||||
| --- | --- | --- |
|
||||
| Ubuntu / Debian | `apt` | `docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin` |
|
||||
| RedOS / RHEL | `dnf` | `docker-ce docker-ce-cli containerd docker-compose` |
|
||||
|
||||
> Имена пакетов в RedOS отличаются (`containerd`, `docker-compose`), поэтому
|
||||
> списки разнесены по семействам в `roles/docker/defaults/main.yml`.
|
||||
|
||||
## Важно: где запускать
|
||||
|
||||
**Ansible не работает как управляющий узел на нативном Windows** (нужен POSIX).
|
||||
Запуск — из **WSL** (Ubuntu). Управление окружением — через **uv**.
|
||||
|
||||
### Разовая настройка WSL
|
||||
|
||||
```bash
|
||||
# 1. uv внутри WSL
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
source ~/.local/bin/env
|
||||
|
||||
# 2. Если DNS в WSL не резолвит (curl: Could not resolve host):
|
||||
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
|
||||
printf "\n[network]\ngenerateResolvConf = false\n" | sudo tee -a /etc/wsl.conf
|
||||
|
||||
# 3. SSH-ключ в домашку WSL с правами 600 (на /mnt/c ssh отвергает ключ)
|
||||
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||
cp /mnt/c/Users/user/.ssh/local/id_ed25519 ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
Из WSL, в каталоге проекта (`/mnt/c/.../iac/aero`).
|
||||
|
||||
### Установка с чистого листа — одной командой
|
||||
|
||||
```bash
|
||||
uv run poe install
|
||||
```
|
||||
|
||||
Последовательность: `sync` → `galaxy` → **`provision`** (базовые пакеты + docker
|
||||
и запуск службы) → **`stack`** (деплой конфигурации + `docker compose up -d`
|
||||
сервисов приложения) → **`superuser`** (генерация и создание Django-админа).
|
||||
Перед запуском впишите хосты в [inventory.ini](inventory.ini) и убедитесь, что
|
||||
на control-node есть SSH-ключ и `~/.ssh/local/authorized_key.json` для входа в
|
||||
реестр.
|
||||
|
||||
### Пошагово / отдельные команды
|
||||
|
||||
| Команда | Действие |
|
||||
| --- | --- |
|
||||
| `uv run poe ping` | проверка SSH + sudo |
|
||||
| `uv run poe provision` | базовые пакеты + docker/containerd + запуск службы |
|
||||
| `uv run poe deploy` | деплой конфигурации: файлы, `.env`, сертификаты, `docker login` |
|
||||
| `uv run poe platform` | деплой + поднять GitOps-подложку (k3s + gitea + vault + Flux) |
|
||||
| `uv run poe stack` | деплой + поднять стек (`docker compose up -d`) |
|
||||
| `uv run poe gen-env` | только сгенерировать пароли и `.env` |
|
||||
| `uv run poe login` | только `docker login` в реестр по ключу |
|
||||
| `uv run poe superuser` | сгенерировать логин+пароль и создать Django-суперпользователя |
|
||||
| `uv run poe flux-status` | состояние FluxCD в k3s |
|
||||
| `uv run poe vault-status` | состояние Vault (инициализирован / распечатан) |
|
||||
| `uv run poe check` / `deploy-check` | dry-run (`--check --diff`) |
|
||||
|
||||
Поднимаемые сервисы задаются в `sarex_services` (роль `sarex_stack`) —
|
||||
`postgres(+init)`, `redis`, `rabbitmq`, `minio(+init)`, `measurements`,
|
||||
`backend`, `celery`, `frontend`, `nginx` (k3s/gitea/processing не поднимаются).
|
||||
|
||||
> `ANSIBLE_CONFIG` и `UV_LINK_MODE` заданы в `[tool.poe.env]` — на диске `C:`
|
||||
> (через `/mnt/c`) права `0777`, и ansible игнорирует `ansible.cfg` в
|
||||
> world-writable каталоге, поэтому путь к конфигу передаётся явно.
|
||||
|
||||
### GitOps-подложка контура (k3s + gitea + vault + FluxCD)
|
||||
|
||||
Целевая схема контура — не «всё в compose», а **compose как подложка, k3s как
|
||||
среда выполнения**. Источником правды становится gitea внутри контура, а
|
||||
раскаткой занимается FluxCD.
|
||||
|
||||
```
|
||||
docker compose k3s (4 ноды в контейнерах)
|
||||
├── k3s-server ──► нода ┐
|
||||
├── k3s-worker-1..3 ──► ноды ├─► flux-system (controllers)
|
||||
├── gitea (172.28.0.12) ◄────── ┘ и всё, что опишем в clusters/aero
|
||||
│ └── infra/iac.git
|
||||
├── vault (+init)
|
||||
├── flux-k8s-init ──► namespace flux-system + Service-мост до gitea
|
||||
└── flux-bootstrap ──► ставит Flux в k3s и привязывает к gitea
|
||||
```
|
||||
|
||||
**Мост до gitea.** Контроллеры Flux работают внутри k3s, где резолвит CoreDNS,
|
||||
а имён compose-сети там нет. Поэтому `flux-k8s-init` заводит в namespace
|
||||
`flux-system` Service без селектора + Endpoints на статический IP gitea — тем же
|
||||
приёмом, что `bridge-postgres`/`bridge-minio` для processing. Источник в
|
||||
`GitRepository` указан именем `gitea.flux-system.svc.cluster.local`, а адрес
|
||||
задан ровно в одном месте — переменной `GITEA_BRIDGE_IP` (она же `ipv4_address`
|
||||
сервиса `gitea`). Контейнер `flux-bootstrap` резолвит то же имя через
|
||||
`extra_hosts` — иначе flux CLI не смог бы запушить манифесты.
|
||||
|
||||
**Имена нод закреплены** через `hostname:` в compose. Это не косметика: k3s
|
||||
берёт имя ноды из hostname, иначе им становится ID контейнера. Local-path
|
||||
привязывает PV к ноде через `nodeAffinity` по имени, и после пересоздания
|
||||
контейнера тома «повисли» бы.
|
||||
|
||||
### Хранилище PVC
|
||||
|
||||
`StorageClass local-path` (встроенный в k3s, он же default). Дефолтный путь
|
||||
провижинера `/var/lib/rancher/k3s/storage` перекрыт bind-mount'ом на хост —
|
||||
поэтому настраивать ConfigMap `local-path-config` не нужно:
|
||||
|
||||
```
|
||||
{{ deploy_dir }}/k3s-storage/
|
||||
├── server/ ← PVC, севшие на k3s-server
|
||||
├── worker-1/
|
||||
├── worker-2/
|
||||
└── worker-3/
|
||||
```
|
||||
|
||||
Файлы лежат на хосте обычными каталогами: переживают пересоздание контейнера
|
||||
k3s и `docker compose down -v`, бэкапятся штатными средствами.
|
||||
|
||||
> **Следствие для stateful-сервисов.** Хранилище **node-local**: PVC привязан к
|
||||
> той ноде, где под запустился первым. При переезде postgres/redis/rabbitmq/minio
|
||||
> в k3s их нужно явно прибивать к конкретной ноде (`nodeSelector`), иначе данные
|
||||
> размажутся по четырём каталогам, а потеря ноды сделает том недоступным.
|
||||
> Бэкап должен покрывать все каталоги `k3s-storage/*`.
|
||||
|
||||
```bash
|
||||
uv run poe platform # поднять подложку
|
||||
uv run poe flux-status # убедиться, что Flux реконсилирует
|
||||
```
|
||||
|
||||
Что происходит по шагам:
|
||||
|
||||
1. **Волна 1** — стартуют `k3s-server`, три воркера и `gitea`. Роль ждёт, пока
|
||||
k3s запишет `./k3s/kubeconfig.yaml` (и что файл непустой) — иначе
|
||||
`flux-bootstrap` смонтировал бы каталог вместо файла.
|
||||
2. **`gitea-init`** — одноразовый: заводит администратора (`gitea admin user
|
||||
create`), организацию и пустой репозиторий через API. Идемпотентен.
|
||||
3. **`flux-k8s-init`** — одноразовый: namespace `flux-system` и Service-мост до
|
||||
gitea (см. выше). Обязан отработать до bootstrap.
|
||||
4. **`vault` + `vault-init`** — Vault на file-хранилище. `vault-init` живёт
|
||||
постоянно: инициализирует Vault одним ключом, распечатывает его и включает
|
||||
`kv-v2` на пути `secrets/` (тот же путь, что в k8s-контурах). После ребута
|
||||
хоста Vault поднимается запечатанным — цикл распечатывает его сам.
|
||||
5. **`flux-bootstrap`** — одноразовый: `flux bootstrap git` ставит контроллеры в
|
||||
k3s и пушит их манифесты в gitea в `clusters/aero/flux-system`.
|
||||
|
||||
> **FluxCD не работает в docker-compose** — это контроллеры Kubernetes. В compose
|
||||
> живёт только установщик; после его успеха Flux работает внутри k3s.
|
||||
|
||||
Секреты подложки (`GITEA_ADMIN_PASSWORD`, `K3S_TOKEN`) генерируются так же, как
|
||||
остальные — в `aero/.secrets/<host>/`. Unseal-ключ и root-токен Vault лежат на
|
||||
отдельном docker-томе `sarex-vault-init` с правами `600` и **в git не попадают**.
|
||||
|
||||
#### Границы текущего этапа
|
||||
|
||||
Сделана только подложка. Осознанно **не** сделано:
|
||||
|
||||
- Репозиторий в gitea содержит лишь `clusters/aero/flux-system` — то, что запушил
|
||||
bootstrap. Наполнение (`apps/`, `infrastructure/`) и перенос прикладных сервисов
|
||||
из compose в k3s — следующий этап.
|
||||
- Vault поднят и распечатан, но **kubernetes auth не настроен**: для него нужен
|
||||
Vault Agent Injector внутри k3s, а он приедет уже через Flux. Пока в Vault
|
||||
можно только класть секреты, поды их ещё не читают.
|
||||
- Прикладной стек (`sarex_services`) не тронут и продолжает работать в compose.
|
||||
|
||||
### Развёртывание sarex-стека (роль `sarex_stack`)
|
||||
|
||||
Копирует `docker-compose.yaml`, `nginx/templates` и `backend/uwsgi.ini` в
|
||||
`/root/sarex`, рендерит `.env` из `.env.example` со **сгенерированными паролями**
|
||||
и доменами `*.sarex.local.lonsdaleites.ru`, генерирует самоподписанный
|
||||
TLS-сертификат на все три домена (`nginx/certs/selfsigned.{crt,key}`), логинится
|
||||
в реестр и (при `sarex_compose_up=true`) поднимает сервисы приложения.
|
||||
Роли/базы и MinIO-бакеты создаются одноразовыми `postgres-init`/`minio-init`.
|
||||
|
||||
```bash
|
||||
uv run ansible-playbook deploy.yml --check --diff # dry-run
|
||||
uv run ansible-playbook deploy.yml # подготовка файлов
|
||||
```
|
||||
|
||||
- Пароли генерируются один раз и персистятся на control-node в `aero/.secrets/`
|
||||
(gitignored) — повторный прогон не меняет `.env` (идемпотентно).
|
||||
- Только пароли и `.env`, без остального деплоя — отдельной командой:
|
||||
|
||||
```bash
|
||||
uv run poe gen-env # сгенерировать/обновить .env
|
||||
rm -rf .secrets/<host> && uv run poe gen-env # перегенерировать пароли заново
|
||||
```
|
||||
- Стек по умолчанию **не поднимается** (`sarex_compose_up: false`). Образы —
|
||||
приватные (`cr.yandex`), поэтому сперва `docker login cr.yandex` на хосте,
|
||||
затем `cd /root/sarex && docker compose up -d` (или прогон с
|
||||
`-e sarex_compose_up=true`).
|
||||
- Домены нужно завести в DNS/hosts, чтобы они резолвились на хост.
|
||||
|
||||
### Galaxy-коллекции (опционально)
|
||||
|
||||
Коллекции из `requirements.yml` (`community.docker` и др.) **не требуются** для
|
||||
работы роли — она использует только модули `ansible.builtin`. Ставятся при
|
||||
необходимости:
|
||||
|
||||
```bash
|
||||
uv run poe galaxy
|
||||
```
|
||||
|
||||
## Настройка
|
||||
|
||||
Хосты — в [`inventory.ini`](inventory.ini) (группа `docker_hosts`). Root — через
|
||||
`sudo` (`become`). Если `sudo` с паролем — добавьте `--ask-become-pass`:
|
||||
|
||||
```bash
|
||||
uv run poe play -- --ask-become-pass
|
||||
```
|
||||
|
||||
Переменные роли (`roles/docker/defaults/main.yml`):
|
||||
|
||||
| Переменная | По умолчанию | Назначение |
|
||||
| --------------------------- | ------------ | -------------------------------------------- |
|
||||
| `docker_update_packages` | `true` | Обновлять пакеты при старте |
|
||||
| `docker_upgrade_dist` | `false` | Полный `dist-upgrade` (только Debian) |
|
||||
| `docker_service_enabled` | `true` | Автозапуск службы docker |
|
||||
| `docker_service_state` | `started` | Состояние службы после прогона |
|
||||
| `docker_users` | `[]` | Пользователи в группу `docker` (без sudo) |
|
||||
| `docker_redhat_add_ce_repo` | `false` | Внешний репозиторий Docker CE (RHEL; RedOS не нужен) |
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
aero/
|
||||
├── pyproject.toml # окружение uv + poe-задачи
|
||||
├── ansible.cfg # настройки ansible (inventory, become)
|
||||
├── requirements.yml # galaxy-коллекции (опционально)
|
||||
├── inventory.ini # хосты
|
||||
├── site.yml # плейбук
|
||||
└── roles/docker/
|
||||
├── defaults/main.yml # переменные и списки пакетов по семействам
|
||||
├── tasks/
|
||||
│ ├── main.yml # диспетчер по пакетному менеджеру + общие шаги
|
||||
│ ├── debian.yml # ветка apt (Ubuntu/Debian)
|
||||
│ └── redhat.yml # ветка dnf (RedOS/RHEL)
|
||||
├── handlers/main.yml # restart docker
|
||||
└── meta/main.yml # метаданные и зависимости
|
||||
```
|
||||
@ -1,16 +0,0 @@
|
||||
[defaults]
|
||||
inventory = inventory.ini
|
||||
roles_path = roles
|
||||
host_key_checking = False
|
||||
retry_files_enabled = False
|
||||
interpreter_python = auto_silent
|
||||
deprecation_warnings = False
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
|
||||
[ssh_connection]
|
||||
# Keepalive, чтобы длинные задачи (dnf upgrade) не рвали соединение
|
||||
ssh_args = -o ControlMaster=auto -o ControlPersist=600s -o ServerAliveInterval=30 -o ServerAliveCountMax=20 -o TCPKeepAlive=yes
|
||||
pipelining = True
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: Развернуть sarex-стек на docker-хостах
|
||||
hosts: docker_hosts
|
||||
become: true
|
||||
roles:
|
||||
- sarex_stack
|
||||
@ -1,16 +0,0 @@
|
||||
# Инвентарь docker-хостов.
|
||||
# Подключение: SSH-ключ + пользователь + IP. Root — через sudo (become).
|
||||
[docker_hosts]
|
||||
aero-01 ansible_host=158.160.38.249
|
||||
|
||||
[docker_hosts:vars]
|
||||
ansible_user=emelinda
|
||||
# Ключ копируется в WSL-домашку с правами 600 (на /mnt/c ssh отвергает ключ
|
||||
# из-за слишком открытых прав). Исходник: C:\Users\user\.ssh\local\id_ed25519
|
||||
ansible_ssh_private_key_file=~/.ssh/id_ed25519
|
||||
ansible_python_interpreter=/usr/bin/python3
|
||||
|
||||
# Root через sudo -i (беспарольный sudo). Если sudo требует пароль —
|
||||
# запускайте плейбук с флагом --ask-become-pass.
|
||||
ansible_become=true
|
||||
ansible_become_method=sudo
|
||||
@ -1,102 +0,0 @@
|
||||
[project]
|
||||
name = "aero"
|
||||
version = "0.1.0"
|
||||
description = "Ansible-провижининг docker-хостов (docker, docker-compose, containerd)"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"ansible-core>=2.17",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ansible-lint>=24.0",
|
||||
"poethepoet>=0.29",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
package = false
|
||||
|
||||
# Общее окружение для всех poe-задач.
|
||||
# ANSIBLE_CONFIG задаётся явно: на /mnt/c (диск Windows) права 0777, и ansible
|
||||
# из соображений безопасности игнорирует ansible.cfg в world-writable каталоге.
|
||||
[tool.poe.env]
|
||||
ANSIBLE_CONFIG = "${POE_ROOT}/ansible.cfg"
|
||||
UV_LINK_MODE = "copy"
|
||||
|
||||
# Таск-раннер poethepoet. Запуск: uv run poe <task>
|
||||
[tool.poe.tasks]
|
||||
sync = "uv sync"
|
||||
galaxy = "ansible-galaxy collection install -r requirements.yml"
|
||||
ping = "ansible docker_hosts -m ping"
|
||||
# Провижининг хоста: базовые пакеты + docker/containerd + запуск службы
|
||||
provision = "ansible-playbook site.yml"
|
||||
check = "ansible-playbook site.yml --check --diff"
|
||||
# Деплой конфигурации: файлы, .env с паролями, сертификаты, docker login
|
||||
deploy = "ansible-playbook deploy.yml"
|
||||
deploy-check = "ansible-playbook deploy.yml --check --diff"
|
||||
# Деплой + поднять стек приложения (docker compose up -d)
|
||||
stack = "ansible-playbook deploy.yml -e sarex_compose_up=true"
|
||||
# Деплой + поднять GitOps-подложку: k3s + gitea + vault + bootstrap FluxCD.
|
||||
# Без --tags намеренно: подложке нужны .env, docker-compose.yaml и vault/config,
|
||||
# которые кладут нетегированные задачи роли (при --tags они были бы пропущены).
|
||||
platform = "ansible-playbook deploy.yml -e aero_platform_up=true"
|
||||
# Только генерация паролей и рендер .env на хосте (без копирования/сертификатов)
|
||||
gen-env = "ansible-playbook deploy.yml --tags env"
|
||||
# docker login в приватный реестр по ключу json_key
|
||||
login = "ansible-playbook deploy.yml --tags login"
|
||||
# Сгенерировать логин+пароль и создать Django-суперпользователя в backend
|
||||
superuser = "ansible-playbook deploy.yml -e sarex_create_superuser=true --tags superuser"
|
||||
lint = "ansible-lint"
|
||||
|
||||
# --- Операционные задачи на хосте (без полного деплоя) ----------------------
|
||||
# Поднять/пересоздать сервисы приложения (docker compose up -d sarex_services).
|
||||
# Только тег up: не трогает файлы/.env/сертификаты/login, лишь применяет стек.
|
||||
up = "ansible-playbook deploy.yml -e sarex_compose_up=true --tags up"
|
||||
|
||||
[tool.poe.tasks.ps]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose ps chdir=/root/sarex'"
|
||||
help = "Статус стека на хосте (docker compose ps)"
|
||||
|
||||
[tool.poe.tasks.flux-status]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose exec -T k3s-server kubectl -n flux-system get kustomizations,gitrepositories,pods chdir=/root/sarex'"
|
||||
help = "Состояние FluxCD в k3s (kustomizations, источники, поды)"
|
||||
|
||||
[tool.poe.tasks.vault-status]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose exec -T vault-init vault status chdir=/root/sarex'"
|
||||
help = "Состояние Vault (инициализирован / распечатан)"
|
||||
|
||||
[tool.poe.tasks.pull]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose pull ${service} chdir=/root/sarex'"
|
||||
help = "Стянуть образы: uv run poe pull [service]"
|
||||
[[tool.poe.tasks.pull.args]]
|
||||
name = "service"
|
||||
positional = true
|
||||
default = ""
|
||||
|
||||
[tool.poe.tasks.logs]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose logs --no-color --tail ${tail} ${service} chdir=/root/sarex'"
|
||||
help = "Логи сервиса(ов): uv run poe logs [service] [--tail N]"
|
||||
[[tool.poe.tasks.logs.args]]
|
||||
name = "service"
|
||||
positional = true
|
||||
default = ""
|
||||
[[tool.poe.tasks.logs.args]]
|
||||
name = "tail"
|
||||
options = ["--tail"]
|
||||
default = "80"
|
||||
|
||||
[tool.poe.tasks.restart]
|
||||
cmd = "ansible docker_hosts -m ansible.builtin.shell -a 'docker compose restart ${service} chdir=/root/sarex'"
|
||||
help = "Перезапустить сервис: uv run poe restart <service>"
|
||||
[[tool.poe.tasks.restart.args]]
|
||||
name = "service"
|
||||
positional = true
|
||||
required = true
|
||||
|
||||
# Подготовка окружения: uv sync + установка коллекций
|
||||
[tool.poe.tasks.setup]
|
||||
sequence = ["sync", "galaxy"]
|
||||
|
||||
# Установка с чистого листа: окружение → docker → деплой+стек → суперпользователь
|
||||
[tool.poe.tasks.install]
|
||||
sequence = ["sync", "galaxy", "provision", "stack", "superuser"]
|
||||
@ -1,8 +0,0 @@
|
||||
# Galaxy-зависимости роли. Установка: uv run ansible-galaxy collection install -r requirements.yml
|
||||
collections:
|
||||
- name: community.docker
|
||||
version: ">=3.10.0"
|
||||
- name: community.general
|
||||
version: ">=9.0.0"
|
||||
- name: ansible.posix
|
||||
version: ">=1.5.0"
|
||||
@ -1,4 +0,0 @@
|
||||
---
|
||||
# Базовые пакеты-утилиты, ставятся на все хосты
|
||||
base_packages:
|
||||
- vim
|
||||
@ -1,12 +0,0 @@
|
||||
---
|
||||
# apt не обновляет кэш сам — делаем это перед установкой (dnf обновляет по TTL)
|
||||
- name: Обновить кэш пакетов (apt)
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
|
||||
- name: Установить базовые пакеты
|
||||
ansible.builtin.package:
|
||||
name: "{{ base_packages }}"
|
||||
state: present
|
||||
@ -1,38 +0,0 @@
|
||||
---
|
||||
# Обновлять индекс пакетов и апгрейдить систему при старте роли
|
||||
docker_update_packages: true
|
||||
docker_upgrade_dist: false # true — выполнить полный dist-upgrade
|
||||
|
||||
# Официальный репозиторий Docker (Debian/Ubuntu)
|
||||
docker_apt_key_url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
|
||||
docker_apt_repo_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else ansible_architecture }}"
|
||||
|
||||
# RedHat-семейство (RedOS/RHEL). Для RedOS docker есть в родных репозиториях,
|
||||
# поэтому внешний репозиторий по умолчанию не подключается.
|
||||
docker_redhat_add_ce_repo: false
|
||||
docker_redhat_ce_repo_url: "https://download.docker.com/linux/centos/docker-ce.repo"
|
||||
|
||||
# Имена пакетов различаются между семействами ОС.
|
||||
# Debian/Ubuntu (официальный репозиторий Docker):
|
||||
docker_packages_debian:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
|
||||
# RedHat/RedOS (родные репозитории RedOS: containerd вместо containerd.io,
|
||||
# docker-compose вместо docker-compose-plugin; buildx в репах отсутствует):
|
||||
docker_packages_redhat:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd
|
||||
- docker-compose
|
||||
|
||||
# Служба docker
|
||||
docker_manage_service: true # false — не трогать службу (не включать/не запускать)
|
||||
docker_service_enabled: true
|
||||
docker_service_state: started
|
||||
|
||||
# Пользователи, добавляемые в группу docker (запуск без sudo)
|
||||
docker_users: []
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
- name: Restart docker
|
||||
ansible.builtin.systemd_service:
|
||||
name: docker
|
||||
state: restarted
|
||||
@ -1,33 +0,0 @@
|
||||
---
|
||||
galaxy_info:
|
||||
role_name: docker
|
||||
namespace: aero
|
||||
author: aero
|
||||
description: Установка Docker Engine, containerd и docker compose на Ubuntu/Debian/RedOS
|
||||
license: MIT
|
||||
min_ansible_version: "2.17"
|
||||
platforms:
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- jammy
|
||||
- noble
|
||||
- name: Debian
|
||||
versions:
|
||||
- bullseye
|
||||
- bookworm
|
||||
- name: EL
|
||||
versions:
|
||||
- "8"
|
||||
- "9"
|
||||
galaxy_tags:
|
||||
- docker
|
||||
- containerd
|
||||
- compose
|
||||
|
||||
# Galaxy-коллекции, от которых зависит роль
|
||||
collections:
|
||||
- community.docker
|
||||
- community.general
|
||||
- ansible.posix
|
||||
|
||||
dependencies: []
|
||||
@ -1,51 +0,0 @@
|
||||
---
|
||||
# --- Обновление пакетов при старте ---------------------------------------
|
||||
- name: Обновить индекс пакетов apt
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
when: docker_update_packages | bool
|
||||
|
||||
- name: Обновить установленные пакеты (upgrade)
|
||||
ansible.builtin.apt:
|
||||
upgrade: "{{ 'dist' if docker_upgrade_dist | bool else 'yes' }}"
|
||||
when: docker_update_packages | bool
|
||||
|
||||
# --- Подготовка репозитория Docker ---------------------------------------
|
||||
- name: Установить зависимости для apt-репозитория
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Создать каталог для ключей apt
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Добавить GPG-ключ Docker
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ docker_apt_key_url }}"
|
||||
dest: /etc/apt/keyrings/docker.asc
|
||||
mode: "0644"
|
||||
force: false
|
||||
|
||||
- name: Добавить apt-репозиторий Docker
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb [arch={{ docker_apt_repo_arch }} signed-by=/etc/apt/keyrings/docker.asc]
|
||||
https://download.docker.com/linux/{{ ansible_distribution | lower }}
|
||||
{{ ansible_distribution_release }} stable
|
||||
filename: docker
|
||||
state: present
|
||||
|
||||
# --- Установка Docker Engine + containerd + compose ----------------------
|
||||
- name: Установить Docker Engine, containerd и docker compose (apt)
|
||||
ansible.builtin.apt:
|
||||
name: "{{ docker_packages_debian }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
@ -1,38 +0,0 @@
|
||||
---
|
||||
- name: Определить семейство пакетного менеджера
|
||||
ansible.builtin.set_fact:
|
||||
docker_pkg_family: >-
|
||||
{{ 'debian' if ansible_pkg_mgr == 'apt'
|
||||
else 'redhat' if ansible_pkg_mgr in ['dnf', 'dnf5', 'yum']
|
||||
else 'unsupported' }}
|
||||
|
||||
- name: Проверить поддерживаемую ОС
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- docker_pkg_family != 'unsupported'
|
||||
fail_msg: >-
|
||||
Роль docker поддерживает Ubuntu/Debian (apt) и RedOS/RHEL (dnf).
|
||||
Обнаружено: {{ ansible_distribution }} {{ ansible_distribution_version }}
|
||||
(pkg_mgr={{ ansible_pkg_mgr }}).
|
||||
|
||||
- name: Установить Docker для текущего семейства ОС
|
||||
ansible.builtin.include_tasks: "{{ docker_pkg_family }}.yml"
|
||||
|
||||
# --- Общие шаги (systemd одинаков для всех семейств) ---------------------
|
||||
- name: Включить и запустить службу docker
|
||||
ansible.builtin.systemd_service:
|
||||
name: docker
|
||||
enabled: "{{ docker_service_enabled | bool }}"
|
||||
state: "{{ docker_service_state }}"
|
||||
when: docker_manage_service | bool
|
||||
# В check-режиме пакеты не ставятся, поэтому unit ещё не существует —
|
||||
# не роняем dry-run на этом шаге.
|
||||
ignore_errors: "{{ ansible_check_mode }}"
|
||||
|
||||
- name: Добавить пользователей в группу docker
|
||||
ansible.builtin.user:
|
||||
name: "{{ item }}"
|
||||
groups: docker
|
||||
append: true
|
||||
loop: "{{ docker_users }}"
|
||||
when: docker_users | length > 0
|
||||
@ -1,35 +0,0 @@
|
||||
---
|
||||
# --- Обновление пакетов при старте ---------------------------------------
|
||||
- name: Обновить кэш пакетов dnf
|
||||
ansible.builtin.dnf:
|
||||
update_cache: true
|
||||
when: docker_update_packages | bool
|
||||
|
||||
- name: Обновить установленные пакеты (upgrade)
|
||||
ansible.builtin.dnf:
|
||||
name: "*"
|
||||
state: latest
|
||||
update_only: true
|
||||
when: docker_update_packages | bool
|
||||
|
||||
# --- Репозиторий Docker CE ------------------------------------------------
|
||||
# RedOS поставляет docker-ce/containerd в родных репозиториях — внешний
|
||||
# репозиторий не нужен. Для прочих RHEL-совместимых включите
|
||||
# docker_redhat_add_ce_repo=true.
|
||||
- name: Установить dnf-plugins-core
|
||||
ansible.builtin.dnf:
|
||||
name: dnf-plugins-core
|
||||
state: present
|
||||
|
||||
- name: Добавить репозиторий Docker CE
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ docker_redhat_ce_repo_url }}"
|
||||
dest: /etc/yum.repos.d/docker-ce.repo
|
||||
mode: "0644"
|
||||
when: docker_redhat_add_ce_repo | bool
|
||||
|
||||
# --- Установка Docker Engine + containerd + compose ----------------------
|
||||
- name: Установить Docker Engine, containerd и docker compose (dnf)
|
||||
ansible.builtin.dnf:
|
||||
name: "{{ docker_packages_redhat }}"
|
||||
state: present
|
||||
@ -1,132 +0,0 @@
|
||||
---
|
||||
# Каталог развёртывания на хосте (домашка root)
|
||||
deploy_dir: /root/sarex
|
||||
|
||||
# Источник файлов — корень репозитория iac (playbook лежит в aero/)
|
||||
deploy_src_root: "{{ playbook_dir }}/.."
|
||||
|
||||
# Домены верхнего nginx (попадают в .env и в SAN сертификата)
|
||||
platform_domain: sarex.local.lonsdaleites.ru
|
||||
admin_domain: admin.sarex.local.lonsdaleites.ru
|
||||
minio_domain: minio.sarex.local.lonsdaleites.ru
|
||||
|
||||
# Самоподписанный TLS-сертификат
|
||||
cert_days: 365
|
||||
cert_dir: "{{ deploy_dir }}/nginx/certs"
|
||||
|
||||
# Переменные-пароли: им генерируются стойкие значения взамен слабых дефолтов.
|
||||
sarex_secret_vars:
|
||||
- K3S_TOKEN
|
||||
- GITEA_ADMIN_PASSWORD
|
||||
- SAREX_POSTGRES_PASSWORD
|
||||
- SAREX_DJANGO_DB_PASSWORD
|
||||
- SAREX_PROCESSING_DB_PASSWORD
|
||||
- SAREX_BIM_DB_PASSWORD
|
||||
- SAREX_WORKSPACE_DB_PASSWORD
|
||||
- SAREX_RABBITMQ_PASSWORD
|
||||
- SAREX_MINIO_ROOT_PASSWORD
|
||||
- SAREX_MINIO_APP_PASSWORD
|
||||
|
||||
secret_length: 24
|
||||
|
||||
# Хранилище секретов на control-node (persist + переиспользование). Gitignored.
|
||||
secrets_store: "{{ playbook_dir }}/.secrets"
|
||||
|
||||
# RSA-ключи JWT backend (RS512). Генерируются на control-node, persist в secrets_store.
|
||||
jwt_private_key_path: "{{ secrets_store }}/{{ inventory_hostname }}/jwt_private.pem"
|
||||
jwt_public_key_path: "{{ secrets_store }}/{{ inventory_hostname }}/jwt_public.pem"
|
||||
|
||||
# --- Приватный реестр образов и чартов (cr.yandex, аутентификация json_key) ---
|
||||
registry_host: cr.yandex
|
||||
registry_username: json_key
|
||||
|
||||
# Путь к ключу сервисного аккаунта НА CONTROL-NODE (ansible запускается из WSL,
|
||||
# поэтому диск C: виден как /mnt/c). Это машинно-зависимое значение —
|
||||
# переопределяйте, не редактируя роль:
|
||||
# uv run poe platform -- -e registry_key_src=/path/to/authorized_key.json
|
||||
registry_key_src: "/mnt/c/Users/user/Downloads/Telegram Desktop/authorized_key.json"
|
||||
|
||||
# Куда ключ кладётся на целевом хосте на время провижининга (удаляется после).
|
||||
registry_key_dest: "{{ deploy_dir }}/registry-key.json"
|
||||
|
||||
# Секреты в кластере. Namespace создаётся вместе с секретом — он нужен раньше,
|
||||
# чем чарт создаст его сам. Список пополняется по мере переезда компонентов.
|
||||
# * yc-cr-auth (flux-system) — Flux тянет им OCI-ЧАРТЫ. Обязателен.
|
||||
# * regcred — imagePullSecrets подов в namespace потребителя.
|
||||
registry_secrets:
|
||||
- {name: yc-cr-auth, namespace: flux-system}
|
||||
- {name: regcred, namespace: cert-manager}
|
||||
- {name: regcred, namespace: istio-system}
|
||||
- {name: regcred, namespace: kubernetes-dashboard}
|
||||
|
||||
# Поднимать стек (docker compose up -d). Требует запущенной службы docker и
|
||||
# docker login в cr.yandex — по умолчанию выключено.
|
||||
sarex_compose_up: false
|
||||
compose_cmd: "docker compose"
|
||||
|
||||
# --- GitOps-подложка контура (k3s + gitea + vault + flux) -------------------
|
||||
# Параметры gitea и Flux. Попадают в .env (их читает docker-compose) — менять
|
||||
# нужно здесь, а не в .env.example, иначе перезапишется при следующем деплое.
|
||||
gitea_admin_user: sarex
|
||||
gitea_admin_email: "{{ gitea_admin_user }}@{{ platform_domain }}"
|
||||
gitea_org: infra
|
||||
gitea_repo: iac
|
||||
# Ветка и путь, за которыми следит Flux внутри репозитория в gitea.
|
||||
aero_git_branch: master
|
||||
aero_flux_path: clusters/aero
|
||||
|
||||
# Поднимается отдельно от прикладного стека: образы публичные, docker login в
|
||||
# cr.yandex не нужен. По умолчанию выключено, включает `uv run poe platform`.
|
||||
aero_platform_up: false
|
||||
|
||||
# Волна 1: долгоживущие сервисы, которым нужно успеть стать healthy.
|
||||
# k3s-server при первом старте создаёт ./k3s/kubeconfig.yaml — его ждёт волна 2.
|
||||
aero_platform_services_wave1:
|
||||
- k3s-server
|
||||
- k3s-worker-1
|
||||
- k3s-worker-2
|
||||
- k3s-worker-3
|
||||
- gitea
|
||||
|
||||
# Волна 2: провижининг и bootstrap. gitea-init, flux-k8s-init и flux-bootstrap
|
||||
# одноразовые (restart: "no"), vault-init живёт постоянно и распечатывает Vault
|
||||
# после ребута хоста.
|
||||
aero_platform_services_wave2:
|
||||
- gitea-init
|
||||
- flux-k8s-init
|
||||
- vault
|
||||
- vault-init
|
||||
- flux-bootstrap
|
||||
|
||||
# Ноды k3s. Каждой нужен свой каталог PVC-хранилища на хосте: провижинер
|
||||
# local-path node-local, и PV навсегда привязывается к ноде через nodeAffinity.
|
||||
aero_k3s_nodes:
|
||||
- server
|
||||
- worker-1
|
||||
- worker-2
|
||||
- worker-3
|
||||
|
||||
# Сколько ждать появления kubeconfig от k3s-server, секунд.
|
||||
aero_kubeconfig_timeout: 180
|
||||
|
||||
# Сервисы приложения, поднимаемые при sarex_compose_up (depends_on тянет
|
||||
# зависимости и порядок). k3s/gitea намеренно не поднимаем.
|
||||
sarex_services:
|
||||
# k3s + провижининг DNS-моста (нужны engine'у до старта)
|
||||
- k3s-server
|
||||
- processing-k8s-init
|
||||
- postgres
|
||||
- postgres-init
|
||||
- redis
|
||||
- rabbitmq
|
||||
- minio
|
||||
- minio-init
|
||||
- measurements
|
||||
- s3-proxy
|
||||
- backend
|
||||
- celery
|
||||
- frontend
|
||||
- processing-api
|
||||
- processing-frontend
|
||||
- engine
|
||||
- nginx
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
# Пересоздание контейнеров при изменении их bind-mount конфигов.
|
||||
# docker compose up -d НЕ пересоздаёт контейнер, если поменялся только
|
||||
# смонтированный файл (шаблон nginx, production.py) — контент тома он не
|
||||
# отслеживает. Поэтому на изменение конфига форсим --force-recreate конкретного
|
||||
# сервиса. Срабатывает только когда стек реально поднимается (sarex_compose_up),
|
||||
# иначе на обычном deploy без up мы бы стартовали контейнеры.
|
||||
- name: Recreate nginx
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} up -d --force-recreate --no-deps nginx"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
when: sarex_compose_up | bool
|
||||
|
||||
- name: Recreate backend and celery
|
||||
# Оба монтируют ./backend/production.py (celery — ещё и через тот же файл),
|
||||
# поэтому пересоздаём вместе.
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} up -d --force-recreate --no-deps backend celery"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
when: sarex_compose_up | bool
|
||||
@ -1,222 +0,0 @@
|
||||
---
|
||||
# --- Каталоги и файлы ----------------------------------------------------
|
||||
- name: Создать каталог развёртывания
|
||||
ansible.builtin.file:
|
||||
path: "{{ deploy_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
tags: [env]
|
||||
|
||||
- name: Скопировать docker-compose.yaml
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/docker-compose.yaml"
|
||||
dest: "{{ deploy_dir }}/docker-compose.yaml"
|
||||
mode: "0640"
|
||||
|
||||
# nginx монтирует ./nginx/templates и ./nginx/certs — без шаблонов nginx не
|
||||
# стартует, поэтому копируем конфигурацию рядом с compose.
|
||||
# Изменение шаблона → handler пересоздаёт nginx (envsubst рендерит на старте).
|
||||
- name: Скопировать шаблоны nginx
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/nginx/templates/"
|
||||
dest: "{{ deploy_dir }}/nginx/templates/"
|
||||
mode: "0644"
|
||||
notify: Recreate nginx
|
||||
|
||||
# backend монтирует ./backend/uwsgi.ini (http-socket + 4 воркера) и
|
||||
# ./backend/production.py (классическая JWT-аутентификация).
|
||||
# Изменение конфигов → handler пересоздаёт backend и celery.
|
||||
- name: Скопировать конфиги backend (uwsgi.ini, production.py)
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/backend/"
|
||||
dest: "{{ deploy_dir }}/backend/"
|
||||
mode: "0644"
|
||||
notify: Recreate backend and celery
|
||||
|
||||
# k3s-манифесты DNS-моста (namespace processing + Service/Endpoints postgres/minio).
|
||||
# processing-k8s-init монтирует ./k3s/manifests/processing и применяет их kubectl'ом.
|
||||
- name: Скопировать k3s-манифесты (DNS-мост processing)
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/k3s/manifests/"
|
||||
dest: "{{ deploy_dir }}/k3s/manifests/"
|
||||
mode: "0644"
|
||||
|
||||
# engine монтирует ./engine/yc-s3-service-account.json (доступ Job-подов к S3).
|
||||
- name: Скопировать конфиги engine (S3 service-account)
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/engine/"
|
||||
dest: "{{ deploy_dir }}/engine/"
|
||||
mode: "0644"
|
||||
|
||||
# vault монтирует ./vault/config как :ro — без конфига сервер не стартует.
|
||||
- name: Скопировать конфигурацию Vault
|
||||
ansible.builtin.copy:
|
||||
src: "{{ deploy_src_root }}/vault/config/"
|
||||
dest: "{{ deploy_dir }}/vault/config/"
|
||||
mode: "0644"
|
||||
|
||||
# Каталоги PVC-данных k3s — по одному на ноду. Создаём заранее: иначе docker
|
||||
# создаст их от root с umask демона, а local-path пишет туда от имени подов.
|
||||
- name: Создать каталоги PVC-хранилища k3s (по ноде)
|
||||
ansible.builtin.file:
|
||||
path: "{{ deploy_dir }}/k3s-storage/{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop: "{{ aero_k3s_nodes }}"
|
||||
|
||||
# --- Секреты: генерация с персистом на control-node (идемпотентно) --------
|
||||
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
|
||||
ansible.builtin.set_fact:
|
||||
sarex_secrets: >-
|
||||
{{ sarex_secrets | default({}) | combine({
|
||||
item: lookup('password',
|
||||
secrets_store ~ '/' ~ inventory_hostname ~ '/' ~ item
|
||||
~ ' length=' ~ secret_length ~ ' chars=ascii_letters,digits')
|
||||
}) }}
|
||||
loop: "{{ sarex_secret_vars }}"
|
||||
no_log: true
|
||||
tags: [env]
|
||||
|
||||
# RSA-ключи JWT (RS512): генерируем на control-node, persist в secrets_store.
|
||||
- name: Сгенерировать приватный RSA-ключ JWT
|
||||
ansible.builtin.command: "openssl genrsa -out {{ jwt_private_key_path }} 4096"
|
||||
args:
|
||||
creates: "{{ jwt_private_key_path }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
tags: [env]
|
||||
|
||||
- name: Извлечь публичный RSA-ключ JWT
|
||||
ansible.builtin.command: "openssl rsa -in {{ jwt_private_key_path }} -pubout -out {{ jwt_public_key_path }}"
|
||||
args:
|
||||
creates: "{{ jwt_public_key_path }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
tags: [env]
|
||||
|
||||
- name: Собрать словарь переопределений для .env (пароли + домены + JWT)
|
||||
ansible.builtin.set_fact:
|
||||
env_overrides: >-
|
||||
{{ sarex_secrets | combine({
|
||||
'PLATFORM_DOMAIN': platform_domain,
|
||||
'ADMIN_DOMAIN': admin_domain,
|
||||
'MINIO_DOMAIN': minio_domain,
|
||||
'SAREX_MINIO_CONSOLE_URL': 'https://' ~ minio_domain,
|
||||
'GITEA_ADMIN_USER': gitea_admin_user,
|
||||
'GITEA_ADMIN_EMAIL': gitea_admin_email,
|
||||
'GITEA_ORG': gitea_org,
|
||||
'GITEA_REPO': gitea_repo,
|
||||
'AERO_GIT_BRANCH': aero_git_branch,
|
||||
'AERO_FLUX_PATH': aero_flux_path,
|
||||
'SAREX_JWT_PRIVATE_KEY': "'" ~ (lookup('file', jwt_private_key_path) | replace('\n', '\\n')) ~ "'",
|
||||
'SAREX_JWT_PUBLIC_KEY': "'" ~ (lookup('file', jwt_public_key_path) | replace('\n', '\\n')) ~ "'",
|
||||
}) }}
|
||||
no_log: true
|
||||
tags: [env]
|
||||
|
||||
- name: Отрендерить .env из .env.example с переопределениями
|
||||
ansible.builtin.template:
|
||||
src: env.j2
|
||||
dest: "{{ deploy_dir }}/.env"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
tags: [env]
|
||||
|
||||
# --- Самоподписанный TLS-сертификат для трёх доменов ----------------------
|
||||
- name: Создать каталог для сертификатов
|
||||
ansible.builtin.file:
|
||||
path: "{{ cert_dir }}"
|
||||
state: directory
|
||||
mode: "0750"
|
||||
|
||||
- name: Сгенерировать самоподписанный сертификат (SAN на все домены)
|
||||
ansible.builtin.shell:
|
||||
# umask 077 → приватный ключ создаётся сразу с правами 0600
|
||||
cmd: >-
|
||||
umask 077 && openssl req -x509 -nodes -newkey rsa:2048 -days {{ cert_days }}
|
||||
-keyout {{ cert_dir }}/selfsigned.key
|
||||
-out {{ cert_dir }}/selfsigned.crt
|
||||
-subj "/CN={{ platform_domain }}"
|
||||
-addext "subjectAltName=DNS:{{ platform_domain }},DNS:{{ admin_domain }},DNS:{{ minio_domain }}"
|
||||
creates: "{{ cert_dir }}/selfsigned.crt"
|
||||
|
||||
# --- Доступ к приватному реестру (docker на хосте + registries.yaml нод) ---
|
||||
# Обязательно ДО подъёма k3s: registries.yaml монтируется в ноды, и k3s читает
|
||||
# его только при старте.
|
||||
- name: Настроить доступ к приватному реестру
|
||||
ansible.builtin.include_tasks: registry.yml
|
||||
tags: [login, registry]
|
||||
|
||||
# --- GitOps-подложка: k3s + gitea + vault + Flux --------------------------
|
||||
# Отдельный тег и отдельный флаг: подложка поднимается публичными образами и
|
||||
# не зависит от docker login, поэтому её можно накатывать независимо от стека.
|
||||
- name: Поднять GitOps-подложку контура
|
||||
ansible.builtin.include_tasks: platform.yml
|
||||
when: aero_platform_up | bool
|
||||
tags: [platform]
|
||||
|
||||
# --- Поднять сервисы приложения ------------------------------------------
|
||||
- name: Поднять сервисы приложения (docker compose up -d)
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} up -d {{ sarex_services | join(' ') }}"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
when: sarex_compose_up | bool
|
||||
changed_when: true
|
||||
tags: [up]
|
||||
|
||||
# --- Django-суперпользователь: генерация логина+пароля, создание -----------
|
||||
# Только по явной команде (uv run poe superuser передаёт sarex_create_superuser=true),
|
||||
# чтобы обычный deploy не дёргал backend. Логин/пароль персистятся в secrets_store
|
||||
# (переиспользуются при повторе — идемпотентно).
|
||||
- name: Сгенерировать логин суперпользователя
|
||||
ansible.builtin.set_fact:
|
||||
superuser_name: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_NAME chars=ascii_lowercase,digits length=10') }}"
|
||||
when: sarex_create_superuser | default(false) | bool
|
||||
no_log: true
|
||||
tags: [superuser]
|
||||
|
||||
- name: Сгенерировать пароль суперпользователя
|
||||
ansible.builtin.set_fact:
|
||||
superuser_password: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_PASSWORD chars=ascii_letters,digits length=' ~ secret_length) }}"
|
||||
when: sarex_create_superuser | default(false) | bool
|
||||
no_log: true
|
||||
tags: [superuser]
|
||||
|
||||
- name: Создать/обновить Django-суперпользователя в backend
|
||||
when: sarex_create_superuser | default(false) | bool
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ compose_cmd.split()[0] }}"
|
||||
- exec
|
||||
- -e
|
||||
- "SU_NAME={{ superuser_name }}"
|
||||
- -e
|
||||
- "SU_PASS={{ superuser_password }}"
|
||||
- -e
|
||||
- "SU_EMAIL={{ superuser_name }}@{{ platform_domain }}"
|
||||
- sarex-backend
|
||||
- python
|
||||
- manage.py
|
||||
- shell
|
||||
- -c
|
||||
- >-
|
||||
import os;
|
||||
from django.contrib.auth import get_user_model;
|
||||
U = get_user_model();
|
||||
u, c = U.objects.get_or_create(username=os.environ['SU_NAME'], defaults={'email': os.environ['SU_EMAIL']});
|
||||
u.is_staff = True; u.is_superuser = True; u.set_password(os.environ['SU_PASS']); u.save();
|
||||
print('created' if c else 'updated')
|
||||
register: superuser_result
|
||||
changed_when: true
|
||||
no_log: true
|
||||
tags: [superuser]
|
||||
|
||||
- name: Показать учётные данные суперпользователя
|
||||
ansible.builtin.debug:
|
||||
msg: "Django superuser → login: {{ superuser_name }} password: {{ superuser_password }}"
|
||||
when: sarex_create_superuser | default(false) | bool
|
||||
tags: [superuser]
|
||||
@ -1,88 +0,0 @@
|
||||
---
|
||||
# Подъём GitOps-подложки контура: k3s + gitea + vault + bootstrap FluxCD.
|
||||
# Отделено от прикладного стека (sarex_services) намеренно: здесь только
|
||||
# публичные образы, docker login в приватный реестр не требуется.
|
||||
#
|
||||
# Порядок важен и поэтому разбит на две волны: flux-bootstrap монтирует
|
||||
# ./k3s/kubeconfig.yaml, который k3s-server создаёт только при первом старте.
|
||||
# Если поднять всё одной командой, docker может создать на месте отсутствующего
|
||||
# файла директорию, и bootstrap упадёт с невнятной ошибкой.
|
||||
|
||||
- name: Волна 1 — поднять k3s-server и gitea
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave1 | join(' ') }}"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
changed_when: true
|
||||
|
||||
- name: Дождаться kubeconfig от k3s-server
|
||||
ansible.builtin.wait_for:
|
||||
path: "{{ deploy_dir }}/k3s/kubeconfig.yaml"
|
||||
state: present
|
||||
timeout: "{{ aero_kubeconfig_timeout }}"
|
||||
|
||||
# Пустой файл означает, что k3s-server ещё дописывает kubeconfig. Без этой
|
||||
# проверки flux-bootstrap может стартовать с нулевым конфигом.
|
||||
- name: Убедиться, что kubeconfig не пустой
|
||||
ansible.builtin.wait_for:
|
||||
path: "{{ deploy_dir }}/k3s/kubeconfig.yaml"
|
||||
search_regex: "clusters:"
|
||||
timeout: 60
|
||||
|
||||
# Секреты реестра — до bootstrap: без yc-cr-auth в flux-system source-controller
|
||||
# не сможет скачать ни один OCI-чарт, и вся первая волна инфраструктуры встанет.
|
||||
- name: Создать секреты доступа к реестру в кластере
|
||||
ansible.builtin.include_tasks: registry-secrets.yml
|
||||
|
||||
- name: Волна 2 — gitea-init, vault(+init) и bootstrap Flux
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} up -d {{ aero_platform_services_wave2 | join(' ') }}"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
changed_when: true
|
||||
|
||||
# flux-bootstrap одноразовый: успех = код 0. Забираем его явно, иначе ошибка
|
||||
# bootstrap'а останется незамеченной — `compose up -d` о ней не сообщает.
|
||||
#
|
||||
# `docker compose wait` здесь не годится: для уже завершившегося контейнера он
|
||||
# возвращает rc=1 и "no containers for project". Так как `up -d` не дожидается
|
||||
# одноразового сервиса, состояние гоночное — поэтому опрашиваем `ps -a`,
|
||||
# который корректно отвечает и для running, и для exited.
|
||||
#
|
||||
# Формат обёрнут в {% raw %}: это Go-шаблон docker'а, и без raw Jinja попыталась
|
||||
# бы раскрыть {{.State.Status}} как свою переменную. Аргументы передаём списком —
|
||||
# у `command` нет шелла, и строка со скобками разбилась бы по пробелу.
|
||||
- name: Дождаться завершения flux-bootstrap
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ compose_cmd.split()[0] }}"
|
||||
- inspect
|
||||
- "-f"
|
||||
- "{% raw %}{{.State.Status}} {{.State.ExitCode}}{% endraw %}"
|
||||
- flux-bootstrap
|
||||
register: aero_flux_bootstrap
|
||||
changed_when: false
|
||||
retries: 30
|
||||
delay: 10
|
||||
until: aero_flux_bootstrap.stdout | trim is not match('^running')
|
||||
|
||||
- name: Показать логи flux-bootstrap при ошибке
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ compose_cmd }} logs --no-color --tail 50 flux-bootstrap"
|
||||
chdir: "{{ deploy_dir }}"
|
||||
register: aero_flux_logs
|
||||
changed_when: false
|
||||
when: aero_flux_bootstrap.stdout.split() | last != "0"
|
||||
|
||||
- name: Прервать деплой, если bootstrap не удался
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
flux bootstrap завершился с кодом {{ aero_flux_bootstrap.stdout.split() | last }}.
|
||||
Логи контейнера:
|
||||
{{ aero_flux_logs.stdout | default('(недоступны)') }}
|
||||
when: aero_flux_bootstrap.stdout.split() | last != "0"
|
||||
|
||||
- name: Итог
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "gitea: http://{{ ansible_host }}:3000 (пользователь {{ gitea_admin_user }}, пароль в aero/.secrets/{{ inventory_hostname }}/GITEA_ADMIN_PASSWORD)"
|
||||
- "Flux реконсилирует {{ gitea_org }}/{{ gitea_repo }} → {{ aero_flux_path }}"
|
||||
- "Проверка: docker compose exec k3s-server kubectl -n flux-system get kustomizations"
|
||||
@ -1,41 +0,0 @@
|
||||
---
|
||||
# Секреты доступа к приватному реестру внутри кластера.
|
||||
# Требуют поднятого k3s — включается из platform.yml после первой волны.
|
||||
#
|
||||
# Манифест собирается из шаблона и ключа сервисного аккаунта, применяется
|
||||
# kubectl'ом и сразу удаляется: в нём секрет в открытом виде.
|
||||
# Ключ уже прочитан в registry_key_content задачей из registry.yml.
|
||||
|
||||
- name: Отрендерить манифест секретов реестра
|
||||
ansible.builtin.template:
|
||||
src: registry-secret.yaml.j2
|
||||
dest: "{{ deploy_dir }}/k3s/registry-secret.yaml"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
|
||||
# ./k3s смонтирован в k3s-server как /output — отсюда и путь.
|
||||
- name: Применить секреты реестра в кластере
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ compose_cmd.split()[0] }}"
|
||||
- compose
|
||||
- exec
|
||||
- "-T"
|
||||
- k3s-server
|
||||
- kubectl
|
||||
- apply
|
||||
- "-f"
|
||||
- /output/registry-secret.yaml
|
||||
chdir: "{{ deploy_dir }}"
|
||||
register: registry_secret_apply
|
||||
changed_when: >-
|
||||
'created' in registry_secret_apply.stdout or
|
||||
'configured' in registry_secret_apply.stdout
|
||||
|
||||
# Удаляем всегда, в том числе если apply упал: файл содержит ключ.
|
||||
- name: Удалить манифест секретов с хоста
|
||||
ansible.builtin.file:
|
||||
path: "{{ deploy_dir }}/k3s/registry-secret.yaml"
|
||||
state: absent
|
||||
@ -1,112 +0,0 @@
|
||||
---
|
||||
# Доступ к приватному реестру cr.yandex (аутентификация json_key).
|
||||
#
|
||||
# Три независимых потребителя, каждому нужен свой способ:
|
||||
# 1. docker на хосте — образы сервисов compose (backend, frontend, ...)
|
||||
# 2. containerd на нодах — образы подов; /etc/rancher/k3s/registries.yaml
|
||||
# 3. source-controller Flux — OCI-чарты; Secret yc-cr-auth в flux-system
|
||||
#
|
||||
# Ключ читается с control-node и на целевой хост в открытом виде не кладётся
|
||||
# (кроме короткого окна для docker login, см. ниже).
|
||||
|
||||
- name: Проверить наличие ключа реестра на control-node
|
||||
ansible.builtin.stat:
|
||||
path: "{{ registry_key_src }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
register: registry_key_stat
|
||||
tags: [login, registry]
|
||||
|
||||
- name: Прервать деплой, если ключа нет
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
Не найден ключ сервисного аккаунта: {{ registry_key_src }}
|
||||
|
||||
Без него не поедет ни один компонент — все чарты и образы лежат
|
||||
в приватном реестре {{ registry_host }}.
|
||||
|
||||
Укажите актуальный путь:
|
||||
uv run poe platform -- -e registry_key_src=/path/to/authorized_key.json
|
||||
when: not registry_key_stat.stat.exists
|
||||
tags: [login, registry]
|
||||
|
||||
- name: Прочитать ключ реестра с control-node
|
||||
ansible.builtin.set_fact:
|
||||
registry_key_content: "{{ lookup('file', registry_key_src) }}"
|
||||
no_log: true
|
||||
tags: [login, registry]
|
||||
|
||||
# --- 1. docker на хосте ----------------------------------------------------
|
||||
- name: Проверить, выполнен ли вход в реестр
|
||||
ansible.builtin.command: grep -q "{{ registry_host }}" /root/.docker/config.json
|
||||
register: registry_login_state
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
tags: [login]
|
||||
|
||||
- name: Скопировать ключ реестра на хост (временно)
|
||||
ansible.builtin.copy:
|
||||
content: "{{ registry_key_content }}"
|
||||
dest: "{{ registry_key_dest }}"
|
||||
mode: "0600"
|
||||
when: registry_login_state.rc != 0
|
||||
no_log: true
|
||||
tags: [login]
|
||||
|
||||
- name: docker login в приватный реестр
|
||||
ansible.builtin.shell: >-
|
||||
set -o pipefail && cat {{ registry_key_dest | quote }}
|
||||
| docker login --username {{ registry_username }} --password-stdin {{ registry_host }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
when: registry_login_state.rc != 0
|
||||
register: registry_login_result
|
||||
changed_when: "'Login Succeeded' in registry_login_result.stdout"
|
||||
no_log: true
|
||||
tags: [login]
|
||||
|
||||
# helm на хосте может отсутствовать — он нужен только для ручной отладки.
|
||||
# Flux чарты тянет сам, по секрету yc-cr-auth, а не через helm CLI.
|
||||
- name: Проверить наличие helm на хосте
|
||||
ansible.builtin.command: which helm
|
||||
register: registry_helm_present
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
tags: [login]
|
||||
|
||||
- name: helm registry login (если helm установлен)
|
||||
ansible.builtin.shell: >-
|
||||
set -o pipefail && cat {{ registry_key_dest | quote }}
|
||||
| helm registry login {{ registry_host }} --username {{ registry_username }} --password-stdin
|
||||
args:
|
||||
executable: /bin/bash
|
||||
when:
|
||||
- registry_helm_present.rc == 0
|
||||
- registry_login_state.rc != 0
|
||||
register: registry_helm_login
|
||||
changed_when: "'Login Succeeded' in registry_helm_login.stdout"
|
||||
no_log: true
|
||||
tags: [login]
|
||||
|
||||
- name: Удалить временный ключ реестра с хоста
|
||||
ansible.builtin.file:
|
||||
path: "{{ registry_key_dest }}"
|
||||
state: absent
|
||||
tags: [login]
|
||||
|
||||
# --- 2. containerd на нодах k3s -------------------------------------------
|
||||
# Монтируется во все ноды (см. docker-compose.yaml). Изменение файла требует
|
||||
# перезапуска нод — k3s читает registries.yaml только на старте.
|
||||
- name: Отрендерить registries.yaml для нод k3s
|
||||
ansible.builtin.template:
|
||||
src: registries.yaml.j2
|
||||
dest: "{{ deploy_dir }}/k3s/registries.yaml"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
tags: [registry]
|
||||
|
||||
# Секреты доступа в самом кластере создаются отдельно (registry-secrets.yml):
|
||||
# они требуют уже поднятого k3s, поэтому включаются из platform.yml после
|
||||
# первой волны, а не здесь.
|
||||
@ -1,12 +0,0 @@
|
||||
#jinja2: trim_blocks:True, lstrip_blocks:True
|
||||
{# Рендер .env из .env.example: строки KEY=... из env_overrides заменяются, #}
|
||||
{# комментарии и структура сохраняются. Источник — файл на control-node. #}
|
||||
{% set example_lines = lookup('file', deploy_src_root ~ '/.env.example').split('\n') %}
|
||||
{% for line in example_lines %}
|
||||
{% set parts = line.split('=', 1) %}
|
||||
{% if not line.lstrip().startswith('#') and parts | length == 2 and parts[0].strip() in env_overrides %}
|
||||
{{ parts[0].strip() }}={{ env_overrides[parts[0].strip()] }}
|
||||
{% else %}
|
||||
{{ line }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@ -1,21 +0,0 @@
|
||||
#jinja2: trim_blocks:True, lstrip_blocks:True
|
||||
# Аутентификация containerd в приватном реестре — на уровне НОДЫ k3s.
|
||||
# Файл монтируется в /etc/rancher/k3s/registries.yaml на каждую ноду.
|
||||
#
|
||||
# Почему так, а не imagePullSecrets/regcred в каждом namespace: контур
|
||||
# однотенантный и реестр всего один, поэтому узловая настройка избавляет от
|
||||
# необходимости заводить секрет в каждом новом namespace. Манифесты из репозитория
|
||||
# при этом продолжают ссылаться на regcred — отсутствующий imagePullSecret
|
||||
# kubelet допускает: он логирует событие и тянет образ кредами ноды.
|
||||
#
|
||||
# ВНИМАНИЕ: файл содержит секрет. Рендерится с mode 0600, в git не попадает.
|
||||
mirrors:
|
||||
"{{ registry_host }}":
|
||||
endpoint:
|
||||
- "https://{{ registry_host }}"
|
||||
|
||||
configs:
|
||||
"{{ registry_host }}":
|
||||
auth:
|
||||
username: "{{ registry_username }}"
|
||||
password: {{ registry_key_content | to_json }}
|
||||
@ -1,43 +0,0 @@
|
||||
#jinja2: trim_blocks:True, lstrip_blocks:True
|
||||
{#
|
||||
Манифест секретов доступа к приватному реестру, собираемый из ключа
|
||||
сервисного аккаунта (registry_key_src) на control-node.
|
||||
|
||||
Секретов два и они РАЗНОГО назначения:
|
||||
* yc-cr-auth (flux-system) — им source-controller тянет OCI-ЧАРТЫ.
|
||||
Обязателен: без него не поедет ни один HelmRelease.
|
||||
* regcred (namespace потребителя) — imagePullSecrets подов. Продублирован
|
||||
из манифестов репозитория; на уровне ноды образы и так доступны через
|
||||
/etc/rancher/k3s/registries.yaml, но манифесты на него ссылаются.
|
||||
|
||||
Namespace создаётся здесь же: секрет нужен РАНЬШЕ, чем чарт создаст namespace.
|
||||
|
||||
ВНИМАНИЕ: файл содержит секрет в открытом виде. Рендерится с mode 0600
|
||||
во временный каталог и удаляется сразу после kubectl apply.
|
||||
#}
|
||||
{% set docker_config = {
|
||||
"auths": {
|
||||
registry_host: {
|
||||
"username": registry_username,
|
||||
"password": registry_key_content,
|
||||
"auth": (registry_username ~ ":" ~ registry_key_content) | b64encode
|
||||
}
|
||||
}
|
||||
}
|
||||
%}
|
||||
{% for s in registry_secrets %}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ s.namespace }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ s.name }}
|
||||
namespace: {{ s.namespace }}
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: {{ docker_config | to_json | b64encode }}
|
||||
{% endfor %}
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: Провижининг docker-хостов
|
||||
hosts: docker_hosts
|
||||
become: true
|
||||
roles:
|
||||
- base
|
||||
- docker
|
||||
880
aero/uv.lock
generated
880
aero/uv.lock
generated
@ -1,880 +0,0 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.11"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.14'",
|
||||
"python_full_version >= '3.12' and python_full_version < '3.14'",
|
||||
"python_full_version < '3.12'",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aero"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "ansible-core", version = "2.19.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
||||
{ name = "ansible-core", version = "2.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "ansible-lint" },
|
||||
{ name = "poethepoet" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "ansible-core", specifier = ">=2.17" }]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "ansible-lint", specifier = ">=24.0" },
|
||||
{ name = "poethepoet", specifier = ">=0.29" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansible-compat"
|
||||
version = "26.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "ansible-core", version = "2.19.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
||||
{ name = "ansible-core", version = "2.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
||||
{ name = "jsonschema" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "subprocess-tee" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/85/ff345c374486e6375f51e1e3629e2ebc28003229165b67cfcc93f24f5323/ansible_compat-26.6.0.tar.gz", hash = "sha256:ad00d3cff84a961165a7dd90f175fd9a4584e2e602e9d8af2062ce7c479dd350", size = 233940, upload-time = "2026-06-30T11:52:01.126Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/be/0945639296ee8ecb282dc495a7e1bed06de476a65fa30cf2c715e4b28e42/ansible_compat-26.6.0-py3-none-any.whl", hash = "sha256:739c4d10c791000c4b353f5e725e9ebafb6384dbeb00b94c7c8ac3ee2c172337", size = 29176, upload-time = "2026-06-30T11:51:59.379Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansible-core"
|
||||
version = "2.19.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.12'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "cryptography", marker = "python_full_version < '3.12'" },
|
||||
{ name = "jinja2", marker = "python_full_version < '3.12'" },
|
||||
{ name = "packaging", marker = "python_full_version < '3.12'" },
|
||||
{ name = "pyyaml", marker = "python_full_version < '3.12'" },
|
||||
{ name = "resolvelib", marker = "python_full_version < '3.12'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/59/db/7d3c7be76df6fc3707db05a151b530a298bb37080fc9ecc669dbd7e82b28/ansible_core-2.19.11.tar.gz", hash = "sha256:e8d541720050fc0a7ddb568cde779cce25a9cf470aa489e63ee10d1c94df4248", size = 3430025, upload-time = "2026-06-18T19:37:36.721Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/ad/a1b84d6e52ec1573456a6126bc1a127d8d5418b8bc9ef32a4fbf8daaaa78/ansible_core-2.19.11-py3-none-any.whl", hash = "sha256:c39612b1f55a3321445a09eaee43f59ca6c849483792088a4767b97d8fe8580f", size = 2426194, upload-time = "2026-06-18T19:37:35.292Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansible-core"
|
||||
version = "2.21.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.14'",
|
||||
"python_full_version >= '3.12' and python_full_version < '3.14'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "cryptography", marker = "python_full_version >= '3.12'" },
|
||||
{ name = "jinja2", marker = "python_full_version >= '3.12'" },
|
||||
{ name = "packaging", marker = "python_full_version >= '3.12'" },
|
||||
{ name = "pyyaml", marker = "python_full_version >= '3.12'" },
|
||||
{ name = "resolvelib", marker = "python_full_version >= '3.12'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/6d/14fbdae14e7d02fd8349e6a52a76c144a1f92a2df3236c46bd7030cafdce/ansible_core-2.21.2.tar.gz", hash = "sha256:c6139e662eda1bfb5af16029f12afa5edfc7f95f8cd44281b1bdb434a6d9dc70", size = 3388984, upload-time = "2026-07-13T19:39:08.347Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/0c/c3f6f78d0e28123bec95a7d1a0caf8042c51042ce71db2816a290448863b/ansible_core-2.21.2-py3-none-any.whl", hash = "sha256:c7d696c717da03109a32a569a5fe57925812a86734344eab775cba169bf57cf8", size = 2456273, upload-time = "2026-07-13T19:39:06.668Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansible-lint"
|
||||
version = "26.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "ansible-compat" },
|
||||
{ name = "ansible-core", version = "2.19.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
|
||||
{ name = "ansible-core", version = "2.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
|
||||
{ name = "black" },
|
||||
{ name = "cffi" },
|
||||
{ name = "cryptography" },
|
||||
{ name = "distro" },
|
||||
{ name = "filelock" },
|
||||
{ name = "jsonschema" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "referencing" },
|
||||
{ name = "ruamel-yaml" },
|
||||
{ name = "ruamel-yaml-clib", marker = "python_full_version < '3.14'" },
|
||||
{ name = "subprocess-tee" },
|
||||
{ name = "wcmatch" },
|
||||
{ name = "yamllint" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4c/e5/547e64cf118392fb4d02c179eb0cd86b06145bf7c8e18ab49cc6de5e9886/ansible_lint-26.6.0.tar.gz", hash = "sha256:790d08ff6ee56525244677411c90a17b374245d3913bc6a462b5d913ece6d615", size = 767696, upload-time = "2026-06-30T11:57:56.824Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/66/465f210bd0ac409143d5258516bd9db5376ac86ac61707e3e4ef65b27fc4/ansible_lint-26.6.0-py3-none-any.whl", hash = "sha256:162939615eae3b59f38bd829542642b586ccee17eefb0df8718ea4b092eee222", size = 341055, upload-time = "2026-06-30T11:57:55.144Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "26.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "26.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "platformdirs" },
|
||||
{ name = "pytokens" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/96/3c3e09f09f44a37aac36b178a279cd19aa7001bd796187a7b162a294c81f/black-26.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", size = 1970639, upload-time = "2026-05-18T17:05:11.461Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/ea/5ad117b9ee3ecd933c712bcbae610006e5b7cc9f41c526cd7ed3b6c4124c/black-26.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", size = 1792130, upload-time = "2026-05-18T17:05:12.983Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/3a/7c448bc623fcdfa96672531beb5a616ea5e64f6975955254d7731ffb0ad9/black-26.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", size = 1846134, upload-time = "2026-05-18T17:05:14.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/5b/0b39b3a5917f0657ac014ad2edb58c139553a478adfe7f817abf1622ff6e/black-26.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", size = 1478883, upload-time = "2026-05-18T17:05:16.542Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/48/dc222692e0f95030db1bbfb6c857e76858bad09058221ea7aae815255327/black-26.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", size = 1277776, upload-time = "2026-05-18T17:05:18.029Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/5c/c384363980e11e25ca6b93205949bb331fbf35f4e0dbec376dfa6326cec8/black-26.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", size = 2009020, upload-time = "2026-05-18T17:05:28.132Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/df/9f31c5e0babbfed77d505fc5d120beb98b21b33feaeded3924ea941fe360/black-26.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", size = 1813335, upload-time = "2026-05-18T17:05:31.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/24/8e7b9a2fa61b0afd82209efe937557d180a1fa055bd7f6161eb9defc3719/black-26.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", size = 1881614, upload-time = "2026-05-18T17:05:32.718Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/ad/b4e0d9365ba8ac34f6bbab62a4b1b2dd5d618fac3fa1b8db968c844201b5/black-26.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", size = 1488925, upload-time = "2026-05-18T17:05:34.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/4b/652b859bf5df88a751c30451b09338f7fd26a77d1271c666992f836b7711/black-26.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", size = 1289883, upload-time = "2026-05-18T17:05:36.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/16/a8da8eb208c51c7f4ce74609a45d0dcc6d8a2141e45e81ee5289d1bb0d59/black-26.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", size = 2004800, upload-time = "2026-05-18T17:05:38.182Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/8a/a479296a19e383b70a725882a6cf3d786540601ff03cabbaaf1cce864c5a/black-26.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", size = 1815576, upload-time = "2026-05-18T17:05:40.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/6b/cfaf3d39f25132c156a068f6b805576c9103a84086019507c70e1911ee7d/black-26.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", size = 1877927, upload-time = "2026-05-18T17:05:42.463Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/76/302e313964bcff7e28df329d39f84f5270095730d85ff0acc260610a0d82/black-26.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", size = 1511860, upload-time = "2026-05-18T17:05:43.943Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/4e/a3827e35e0e567f9f9ee59e2a0ab979267dca98718f25547ca8c6733afd4/black-26.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae", size = 1316632, upload-time = "2026-05-18T17:05:45.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bracex"
|
||||
version = "3.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ac/01/5f394b8bcd6e5b92f73130990960423bbb19711f906bd9fe9ea5557c667c/bracex-3.0.1.tar.gz", hash = "sha256:4e38e32392e4a4780fe15d644bfc7c8514057cfc3861e060b11814ce829c25e4", size = 44019, upload-time = "2026-07-20T13:43:00.335Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/8f/6f7273a7adb8d73fc8d21ede4376a3e475e52f98435c6007f69100dec8ca/bracex-3.0.1-py3-none-any.whl", hash = "sha256:6523ad83aeb5098a4ee597cff0f964442ff74e460bd3fafaffab6a013ff2288c", size = 11940, upload-time = "2026-07-20T13:42:59.268Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "2.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "49.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distro"
|
||||
version = "1.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.32.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c0/80/8232b582c4b318b817cf1274ba74976b07b34d35ef439b3eb948f98645a1/filelock-3.32.0.tar.gz", hash = "sha256:7be2ad23a14607ccc71808e68fe30848aeace7058ace17852f68e2a68e310402", size = 213757, upload-time = "2026-07-21T13:17:42.898Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/79/b4c714bef36bc4ec2beeae1e0c124f0223888cd8c6feb1cdc56038116920/filelock-3.32.0-py3-none-any.whl", hash = "sha256:d396bea984af47333ef05e50eae7eff88c84256de6112aea0ec48a233c064fe3", size = 97732, upload-time = "2026-07-21T13:17:41.55Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonschema"
|
||||
version = "4.26.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "jsonschema-specifications" },
|
||||
{ name = "referencing" },
|
||||
{ name = "rpds-py" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonschema-specifications"
|
||||
version = "2025.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "referencing" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pastel"
|
||||
version = "0.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/f1/4594f5e0fcddb6953e5b8fe00da8c317b8b41b547e2b3ae2da7512943c62/pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d", size = 7555, upload-time = "2020-09-16T19:21:12.43Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/18/a8444036c6dd65ba3624c63b734d3ba95ba63ace513078e1580590075d21/pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", size = 5955, upload-time = "2020-09-16T19:21:11.409Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "1.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.11.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/9b/560e4be8e26f6fd133a03630a8df0c663b9e8d61b4ade152b72005aec83b/platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0", size = 31953, upload-time = "2026-07-21T13:09:36.565Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74", size = 23247, upload-time = "2026-07-21T13:09:35.422Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "poethepoet"
|
||||
version = "0.48.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pastel" },
|
||||
{ name = "pyyaml" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5c/92/93a4af9511b8c7c647874521d9e6c904266be98067c2ee1eb2e74520d208/poethepoet-0.48.0.tar.gz", hash = "sha256:a06f49d244fadfc2e2e7faa78b54e64a9694727e4ce1d50e08f23cea3ded74f1", size = 148679, upload-time = "2026-07-05T21:48:30.106Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/59/8d/d7c9455b15f8d2d7ce57e7b71a8ef8d02d9992ae4283c9777120620c9022/poethepoet-0.48.0-py3-none-any.whl", hash = "sha256:98da6096d060f49b8d84034770265863fb7dc92a40233b7694b9d216ac68737d", size = 185808, upload-time = "2026-07-05T21:48:28.601Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytokens"
|
||||
version = "0.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "referencing"
|
||||
version = "0.37.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
{ name = "rpds-py" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolvelib"
|
||||
version = "1.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/14/4669927e06631070edb968c78fdb6ce8992e27c9ab2cde4b3993e22ac7af/resolvelib-1.2.1.tar.gz", hash = "sha256:7d08a2022f6e16ce405d60b68c390f054efcfd0477d4b9bd019cc941c28fad1c", size = 24575, upload-time = "2025-10-11T01:07:44.582Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/23/c941a0d0353681ca138489983c4309e0f5095dfd902e1357004f2357ddf2/resolvelib-1.2.1-py3-none-any.whl", hash = "sha256:fb06b66c8da04172d9e72a21d7d06186d8919e32ae5ab5cdf5b9d920be805ac2", size = 18737, upload-time = "2025-10-11T01:07:43.081Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpds-py"
|
||||
version = "2026.6.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/1f/a2dca5ffdbf1d475ffc4e80e4d5d720ff3a00f691795910116960ee12511/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", size = 342174, upload-time = "2026-06-30T07:14:54.821Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/dc/323d08583c0832911768663d1944f0107fcd4088704858d84b5e06d105a0/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", size = 345513, upload-time = "2026-06-30T07:14:56.515Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/2a/e31989834d18d2f26ec1d2774c5b1eb3331df4ea8ada525175294c94b48a/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", size = 373783, upload-time = "2026-06-30T07:14:57.736Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/fe/e80107ee3639585c9941c17d6a42cd65325022f656c023191fce78c324c8/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", size = 378316, upload-time = "2026-06-30T07:14:59.077Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/6f/81e3adf81acfb6fa694de2a6e4e7d8863121e3e0799e0a7725e6cf5679c4/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", size = 499423, upload-time = "2026-06-30T07:15:00.488Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/9a/41263969df0ce3d9af2a96d5005a288200af1989aed3354bfceb5fc0b21f/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", size = 386077, upload-time = "2026-06-30T07:15:01.911Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/19/7e98f468bd50346faff5b10e5297374b443bfdddacc8e9fbc65984539597/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", size = 371315, upload-time = "2026-06-30T07:15:03.317Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/3c/2b973b4d371906a134b03decfea7f5d9835a2c6d263454392e15b64b5b18/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", size = 383502, upload-time = "2026-06-30T07:15:04.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/2a/12e2799500af0a307bca76b63361c51f9fe479223561489c29eea1f2ee41/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", size = 402673, upload-time = "2026-06-30T07:15:05.856Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/e3/21e5872d165fe08be4f229e3d5ee9d90019c0bf0e5538de60dbd54009450/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", size = 549964, upload-time = "2026-06-30T07:15:07.159Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/d0/5ee0fe36844297de8123bee27bc12078c1a7416ad9f1b8a8ca18d6b0c0ac/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", size = 615446, upload-time = "2026-06-30T07:15:08.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/80/1ea5873cb683f2fbe5f21b23ea1f6d179ead19f3c5b249b7eb5dca568ef2/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", size = 576975, upload-time = "2026-06-30T07:15:09.97Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/e1/90ef639217a5ddb15b7f4f61b1c33911fd044ad03c311bafdd2bcab85582/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", size = 204453, upload-time = "2026-06-30T07:15:11.324Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/b7/b7a1695d7af36f521fb11e80d6d3adbd744f73b921859bd3c2a2c0dc706f/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", size = 223219, upload-time = "2026-06-30T07:15:12.476Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/a2/145afacf796e4506062825941176ad9445c2dcf2b3b6a1f13d3030a15e19/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", size = 219137, upload-time = "2026-06-30T07:15:13.631Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/9c/f0d19ac587fd0e4ab6b72cda355e9c5a6166b01ef7e064e437aef8eb9fef/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", size = 349791, upload-time = "2026-06-30T07:17:33.315Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/c7/1d49d204c9fd2ee6c537601dc4c1ba921e03363ca576bfab94a00254ac9a/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", size = 352842, upload-time = "2026-06-30T07:17:34.897Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/e5/c0b5dc93cd0d4c06ce1f438907649514e2ea077bcd911e3154a51e96c38e/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", size = 382094, upload-time = "2026-06-30T07:17:36.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/54/ec0e907b4ca8d541112db352409bd15f871c9b243e0c92c9b5a46ae96f01/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", size = 388662, upload-time = "2026-06-30T07:17:38.235Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f4/921c22a4fd0f1c1ac13a3996ffbf0aa67951e2c8ad0d1d9574938a2932e8/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", size = 504896, upload-time = "2026-06-30T07:17:39.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/1b/a114b972cefa1ab1cdb3c7bb177cd3844a12826c507c722d3a73516dbbaf/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", size = 391545, upload-time = "2026-06-30T07:17:41.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/98/af9b3db77d47fcbe6c8c1f36e2c2147ec70292819e99c325f871584a1c11/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", size = 380059, upload-time = "2026-06-30T07:17:42.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/ba/0efd8668b97c1d26a61566386c636a7a7a09829e474fdf807caa15a2c844/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", size = 393235, upload-time = "2026-06-30T07:17:44.637Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/90/8c139ee9690f73b0829f32647de6f40d826f8f443af6fa72644f96351aac/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", size = 413008, upload-time = "2026-06-30T07:17:46.225Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/97/0043896fdd7828ce09a1d9a8b06433714d0960fc4ff3fc4aa72b666b764e/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", size = 558118, upload-time = "2026-06-30T07:17:47.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/40/02355f0e134f783a8f9814c4680a1bd311d37671577a5964ea838573ff37/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", size = 623138, upload-time = "2026-06-30T07:17:49.355Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruamel-yaml"
|
||||
version = "0.19.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993", size = 142709, upload-time = "2026-01-02T16:50:31.84Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", size = 118102, upload-time = "2026-01-02T16:50:29.201Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruamel-yaml-clib"
|
||||
version = "0.2.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ea/97/60fda20e2fb54b83a61ae14648b0817c8f5d84a3821e40bfbdae1437026a/ruamel_yaml_clib-0.2.15.tar.gz", hash = "sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600", size = 225794, upload-time = "2025-11-16T16:12:59.761Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/80/8ce7b9af532aa94dd83360f01ce4716264db73de6bc8efd22c32341f6658/ruamel_yaml_clib-0.2.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c583229f336682b7212a43d2fa32c30e643d3076178fb9f7a6a14dde85a2d8bd", size = 147998, upload-time = "2025-11-16T16:13:13.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/09/de9d3f6b6701ced5f276d082ad0f980edf08ca67114523d1b9264cd5e2e0/ruamel_yaml_clib-0.2.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56ea19c157ed8c74b6be51b5fa1c3aff6e289a041575f0556f66e5fb848bb137", size = 132743, upload-time = "2025-11-16T16:13:14.265Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/f7/73a9b517571e214fe5c246698ff3ed232f1ef863c8ae1667486625ec688a/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5fea0932358e18293407feb921d4f4457db837b67ec1837f87074667449f9401", size = 731459, upload-time = "2025-11-16T20:22:44.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/a2/0dc0013169800f1c331a6f55b1282c1f4492a6d32660a0cf7b89e6684919/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef71831bd61fbdb7aa0399d5c4da06bea37107ab5c79ff884cc07f2450910262", size = 749289, upload-time = "2025-11-16T16:13:15.633Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/ed/3fb20a1a96b8dc645d88c4072df481fe06e0289e4d528ebbdcc044ebc8b3/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:617d35dc765715fa86f8c3ccdae1e4229055832c452d4ec20856136acc75053f", size = 777630, upload-time = "2025-11-16T16:13:16.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/50/6842f4628bc98b7aa4733ab2378346e1441e150935ad3b9f3c3c429d9408/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b45498cc81a4724a2d42273d6cfc243c0547ad7c6b87b4f774cb7bcc131c98d", size = 744368, upload-time = "2025-11-16T16:13:18.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/b0/128ae8e19a7d794c2e36130a72b3bb650ce1dd13fb7def6cf10656437dcf/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:def5663361f6771b18646620fca12968aae730132e104688766cf8a3b1d65922", size = 745233, upload-time = "2025-11-16T20:22:45.833Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/05/91130633602d6ba7ce3e07f8fc865b40d2a09efd4751c740df89eed5caf9/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:014181cdec565c8745b7cbc4de3bf2cc8ced05183d986e6d1200168e5bb59490", size = 770963, upload-time = "2025-11-16T16:13:19.344Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/4b/fd4542e7f33d7d1bc64cc9ac9ba574ce8cf145569d21f5f20133336cdc8c/ruamel_yaml_clib-0.2.15-cp311-cp311-win32.whl", hash = "sha256:d290eda8f6ada19e1771b54e5706b8f9807e6bb08e873900d5ba114ced13e02c", size = 102640, upload-time = "2025-11-16T16:13:20.498Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/eb/00ff6032c19c7537371e3119287999570867a0eafb0154fccc80e74bf57a/ruamel_yaml_clib-0.2.15-cp311-cp311-win_amd64.whl", hash = "sha256:bdc06ad71173b915167702f55d0f3f027fc61abd975bd308a0968c02db4a4c3e", size = 121996, upload-time = "2025-11-16T16:13:21.855Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/4b/5fde11a0722d676e469d3d6f78c6a17591b9c7e0072ca359801c4bd17eee/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cb15a2e2a90c8475df45c0949793af1ff413acfb0a716b8b94e488ea95ce7cff", size = 149088, upload-time = "2025-11-16T16:13:22.836Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/82/4d08ac65ecf0ef3b046421985e66301a242804eb9a62c93ca3437dc94ee0/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:64da03cbe93c1e91af133f5bec37fd24d0d4ba2418eaf970d7166b0a26a148a2", size = 134553, upload-time = "2025-11-16T16:13:24.151Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/cb/22366d68b280e281a932403b76da7a988108287adff2bfa5ce881200107a/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f6d3655e95a80325b84c4e14c080b2470fe4f33b6846f288379ce36154993fb1", size = 737468, upload-time = "2025-11-16T20:22:47.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/73/81230babf8c9e33770d43ed9056f603f6f5f9665aea4177a2c30ae48e3f3/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71845d377c7a47afc6592aacfea738cc8a7e876d586dfba814501d8c53c1ba60", size = 753349, upload-time = "2025-11-16T16:13:26.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/62/150c841f24cda9e30f588ef396ed83f64cfdc13b92d2f925bb96df337ba9/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e5499db1ccbc7f4b41f0565e4f799d863ea720e01d3e99fa0b7b5fcd7802c9", size = 788211, upload-time = "2025-11-16T16:13:27.441Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/93/e79bd9cbecc3267499d9ead919bd61f7ddf55d793fb5ef2b1d7d92444f35/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4b293a37dc97e2b1e8a1aec62792d1e52027087c8eea4fc7b5abd2bdafdd6642", size = 743203, upload-time = "2025-11-16T16:13:28.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/06/1eb640065c3a27ce92d76157f8efddb184bd484ed2639b712396a20d6dce/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:512571ad41bba04eac7268fe33f7f4742210ca26a81fe0c75357fa682636c690", size = 747292, upload-time = "2025-11-16T20:22:48.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/21/ee353e882350beab65fcc47a91b6bdc512cace4358ee327af2962892ff16/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5e9f630c73a490b758bf14d859a39f375e6999aea5ddd2e2e9da89b9953486a", size = 771624, upload-time = "2025-11-16T16:13:29.853Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/34/cc1b94057aa867c963ecf9ea92ac59198ec2ee3a8d22a126af0b4d4be712/ruamel_yaml_clib-0.2.15-cp312-cp312-win32.whl", hash = "sha256:f4421ab780c37210a07d138e56dd4b51f8642187cdfb433eb687fe8c11de0144", size = 100342, upload-time = "2025-11-16T16:13:31.067Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/e5/8925a4208f131b218f9a7e459c0d6fcac8324ae35da269cb437894576366/ruamel_yaml_clib-0.2.15-cp312-cp312-win_amd64.whl", hash = "sha256:2b216904750889133d9222b7b873c199d48ecbb12912aca78970f84a5aa1a4bc", size = 119013, upload-time = "2025-11-16T16:13:32.164Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/5e/2f970ce4c573dc30c2f95825f2691c96d55560268ddc67603dc6ea2dd08e/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dcec721fddbb62e60c2801ba08c87010bd6b700054a09998c4d09c08147b8fb", size = 147450, upload-time = "2025-11-16T16:13:33.542Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/03/a1baa5b94f71383913f21b96172fb3a2eb5576a4637729adbf7cd9f797f8/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:65f48245279f9bb301d1276f9679b82e4c080a1ae25e679f682ac62446fac471", size = 133139, upload-time = "2025-11-16T16:13:34.587Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/19/40d676802390f85784235a05788fd28940923382e3f8b943d25febbb98b7/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:46895c17ead5e22bea5e576f1db7e41cb273e8d062c04a6a49013d9f60996c25", size = 731474, upload-time = "2025-11-16T20:22:49.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/bb/6ef5abfa43b48dd55c30d53e997f8f978722f02add61efba31380d73e42e/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3eb199178b08956e5be6288ee0b05b2fb0b5c1f309725ad25d9c6ea7e27f962a", size = 748047, upload-time = "2025-11-16T16:13:35.633Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/5d/e4f84c9c448613e12bd62e90b23aa127ea4c46b697f3d760acc32cb94f25/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d1032919280ebc04a80e4fb1e93f7a738129857eaec9448310e638c8bccefcf", size = 782129, upload-time = "2025-11-16T16:13:36.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/4b/e98086e88f76c00c88a6bcf15eae27a1454f661a9eb72b111e6bbb69024d/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab0df0648d86a7ecbd9c632e8f8d6b21bb21b5fc9d9e095c796cacf32a728d2d", size = 736848, upload-time = "2025-11-16T16:13:37.952Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/5c/5964fcd1fd9acc53b7a3a5d9a05ea4f95ead9495d980003a557deb9769c7/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:331fb180858dd8534f0e61aa243b944f25e73a4dae9962bd44c46d1761126bbf", size = 741630, upload-time = "2025-11-16T20:22:51.718Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/1e/99660f5a30fceb58494598e7d15df883a07292346ef5696f0c0ae5dee8c6/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd4c928ddf6bce586285daa6d90680b9c291cfd045fc40aad34e445d57b1bf51", size = 766619, upload-time = "2025-11-16T16:13:39.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/2f/fa0344a9327b58b54970e56a27b32416ffbcfe4dcc0700605516708579b2/ruamel_yaml_clib-0.2.15-cp313-cp313-win32.whl", hash = "sha256:bf0846d629e160223805db9fe8cc7aec16aaa11a07310c50c8c7164efa440aec", size = 100171, upload-time = "2025-11-16T16:13:40.456Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/c4/c124fbcef0684fcf3c9b72374c2a8c35c94464d8694c50f37eef27f5a145/ruamel_yaml_clib-0.2.15-cp313-cp313-win_amd64.whl", hash = "sha256:45702dfbea1420ba3450bb3dd9a80b33f0badd57539c6aac09f42584303e0db6", size = 118845, upload-time = "2025-11-16T16:13:41.481Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/bd/ab8459c8bb759c14a146990bf07f632c1cbec0910d4853feeee4be2ab8bb/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:753faf20b3a5906faf1fc50e4ddb8c074cb9b251e00b14c18b28492f933ac8ef", size = 147248, upload-time = "2025-11-16T16:13:42.872Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/f2/c4cec0a30f1955510fde498aac451d2e52b24afdbcb00204d3a951b772c3/ruamel_yaml_clib-0.2.15-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:480894aee0b29752560a9de46c0e5f84a82602f2bc5c6cde8db9a345319acfdf", size = 133764, upload-time = "2025-11-16T16:13:43.932Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/c7/2480d062281385a2ea4f7cc9476712446e0c548cd74090bff92b4b49e898/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d3b58ab2454b4747442ac76fab66739c72b1e2bb9bd173d7694b9f9dbc9c000", size = 730537, upload-time = "2025-11-16T20:22:52.918Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/08/e365ee305367559f57ba6179d836ecc3d31c7d3fdff2a40ebf6c32823a1f/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bfd309b316228acecfa30670c3887dcedf9b7a44ea39e2101e75d2654522acd4", size = 746944, upload-time = "2025-11-16T16:13:45.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/5c/8b56b08db91e569d0a4fbfa3e492ed2026081bdd7e892f63ba1c88a2f548/ruamel_yaml_clib-0.2.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2812ff359ec1f30129b62372e5f22a52936fac13d5d21e70373dbca5d64bb97c", size = 778249, upload-time = "2025-11-16T16:13:46.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/1d/70dbda370bd0e1a92942754c873bd28f513da6198127d1736fa98bb2a16f/ruamel_yaml_clib-0.2.15-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7e74ea87307303ba91073b63e67f2c667e93f05a8c63079ee5b7a5c8d0d7b043", size = 737140, upload-time = "2025-11-16T16:13:48.349Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/87/822d95874216922e1120afb9d3fafa795a18fdd0c444f5c4c382f6dac761/ruamel_yaml_clib-0.2.15-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:713cd68af9dfbe0bb588e144a61aad8dcc00ef92a82d2e87183ca662d242f524", size = 741070, upload-time = "2025-11-16T20:22:54.151Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/17/4e01a602693b572149f92c983c1f25bd608df02c3f5cf50fd1f94e124a59/ruamel_yaml_clib-0.2.15-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:542d77b72786a35563f97069b9379ce762944e67055bea293480f7734b2c7e5e", size = 765882, upload-time = "2025-11-16T16:13:49.526Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/17/7999399081d39ebb79e807314de6b611e1d1374458924eb2a489c01fc5ad/ruamel_yaml_clib-0.2.15-cp314-cp314-win32.whl", hash = "sha256:424ead8cef3939d690c4b5c85ef5b52155a231ff8b252961b6516ed7cf05f6aa", size = 102567, upload-time = "2025-11-16T16:13:50.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/67/be582a7370fdc9e6846c5be4888a530dcadd055eef5b932e0e85c33c7d73/ruamel_yaml_clib-0.2.15-cp314-cp314-win_amd64.whl", hash = "sha256:ac9b8d5fa4bb7fd2917ab5027f60d4234345fd366fe39aa711d5dca090aa1467", size = 122847, upload-time = "2025-11-16T16:13:51.807Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subprocess-tee"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/22/991efbf35bc811dfe7edcd749253f0931d2d4838cf55176132633e1c82a7/subprocess_tee-0.4.2.tar.gz", hash = "sha256:91b2b4da3aae9a7088d84acaf2ea0abee3f4fd9c0d2eae69a9b9122a71476590", size = 14951, upload-time = "2024-06-17T19:51:51.249Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/ab/e3a3be062cd544b2803760ff707dee38f0b1cb5685b2446de0ec19be28d9/subprocess_tee-0.4.2-py3-none-any.whl", hash = "sha256:21942e976715af4a19a526918adb03a8a27a8edab959f2d075b777e3d78f532d", size = 5249, upload-time = "2024-06-17T19:51:15.949Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcmatch"
|
||||
version = "11.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "bracex" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/16/25/1da725838132221e33568973da484ff43813662ccc06ebf7f6e3abddfcd5/wcmatch-11.0.tar.gz", hash = "sha256:55d95c2447789712774b198ceec72939e88b5618f1f8f0a9b605bf7740b63b96", size = 141360, upload-time = "2026-07-10T05:50:24.183Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/28/12/f38b6fee116274d7221743caab07d765032e1370bb54cad8714f87aeb0e8/wcmatch-11.0-py3-none-any.whl", hash = "sha256:3a5977ace27e075eef67eb03d539563f1a19018b62881949a42932cf66926934", size = 42914, upload-time = "2026-07-10T05:50:22.995Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yamllint"
|
||||
version = "1.38.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pathspec" },
|
||||
{ name = "pyyaml" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/28/a0/8fc2d68e132cf918f18273fdc8a1b8432b60d75ac12fdae4b0ef5c9d2e8d/yamllint-1.38.0.tar.gz", hash = "sha256:09e5f29531daab93366bb061e76019d5e91691ef0a40328f04c927387d1d364d", size = 142446, upload-time = "2026-01-13T07:47:53.276Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/92/aed08e68de6e6a3d7c2328ce7388072cd6affc26e2917197430b646aed02/yamllint-1.38.0-py3-none-any.whl", hash = "sha256:fc394a5b3be980a4062607b8fdddc0843f4fa394152b6da21722f5d59013c220", size = 68940, upload-time = "2026-01-13T07:47:51.343Z" },
|
||||
]
|
||||
@ -49,10 +49,19 @@ spec:
|
||||
[ -f /vault/secrets/attachments-db ] && . /vault/secrets/attachments-db
|
||||
[ -f /vault/secrets/attachments-s3 ] && . /vault/secrets/attachments-s3
|
||||
set +a
|
||||
mkdir -p /etc/sarex/yc-s3-storage
|
||||
cat > /etc/sarex/yc-s3-storage/yc-s3-service-account.json <<EOF
|
||||
{
|
||||
"endpoint": "${YANDEX_S3_ENDPOINT_URL}",
|
||||
"access_key_id": "${YANDEX_S3_ACCESS_KEY_ID}",
|
||||
"secret_access_key": "${YANDEX_S3_SECRET_ACCESS_KEY}",
|
||||
"use_ssl": ${YANDEX_S3_USE_SSL}
|
||||
}
|
||||
EOF
|
||||
exec /opt/attachments/entrypoint.sh
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/attachments:feature_6238c882
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/att9:dev
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
service:
|
||||
@ -76,6 +85,9 @@ spec:
|
||||
- name: POSTGRES_POOL_SIZE
|
||||
value:
|
||||
_default: "10"
|
||||
- name: YANDEX_S3_ACCOUNT_PATH
|
||||
value:
|
||||
_default: "/etc/sarex/yc-s3-storage/yc-s3-service-account.json"
|
||||
- name: API_ADDRESS
|
||||
value:
|
||||
_default: 0.0.0.0:8000
|
||||
@ -103,7 +115,7 @@ spec:
|
||||
YANDEX_S3_ENDPOINT_URL=minio.minio:9000
|
||||
YANDEX_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YANDEX_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
YANDEX_S3_USE_SSL=false
|
||||
YANDEX_S3_USE_SSL=true
|
||||
YANDEX_S3_REGION=ru-central
|
||||
YANDEX_S3_VERIFY=false
|
||||
BUCKET_NAME=attachments
|
||||
|
||||
@ -22,14 +22,14 @@ spec:
|
||||
DATABASE_PASSWORD={{ index .Data.data "password" }}
|
||||
DATABASE_SSL_MODE=disable
|
||||
{{- end -}}
|
||||
# vault.hashicorp.com/agent-inject-secret-attachments-s3: secrets/data/minio/apps/attachments
|
||||
# vault.hashicorp.com/agent-inject-template-attachments-s3: |-
|
||||
# {{- with secret "secrets/data/minio/apps/attachments" -}}
|
||||
# YANDEX_S3_ENDPOINT_URL=minio.minio:9000
|
||||
# YANDEX_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
# YANDEX_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
# YANDEX_S3_USE_SSL=false
|
||||
# YANDEX_S3_REGION=ru-central
|
||||
# YANDEX_S3_VERIFY=false
|
||||
# BUCKET_NAME=attachments
|
||||
# {{- end -}}
|
||||
vault.hashicorp.com/agent-inject-secret-attachments-s3: secrets/data/minio/apps/attachments
|
||||
vault.hashicorp.com/agent-inject-template-attachments-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/attachments" -}}
|
||||
YANDEX_S3_ENDPOINT_URL=s3.uralmine.com
|
||||
YANDEX_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YANDEX_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
YANDEX_S3_USE_SSL=true
|
||||
YANDEX_S3_REGION=ru-central
|
||||
YANDEX_S3_VERIFY=false
|
||||
BUCKET_NAME=sarex-attachments-storage
|
||||
{{- end -}}
|
||||
|
||||
@ -42,7 +42,7 @@ spec:
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/bim-api:contour_f9f2a39
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/bim-api:contour_f9f2a39-dirty
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ spec:
|
||||
service:
|
||||
enabled: true
|
||||
name:
|
||||
_default: rfi-backend-api-svc
|
||||
_default: backend-svc
|
||||
type:
|
||||
_default: ClusterIP
|
||||
port:
|
||||
|
||||
@ -285,6 +285,9 @@ spec:
|
||||
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
AWS_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
AWS_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
AWS_STORAGE_BUCKET_NAME={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
|
||||
{{- end }}
|
||||
vault.hashicorp.com/agent-inject-secret-django-kafka: secrets/data/kafka/apps/django
|
||||
vault.hashicorp.com/agent-inject-template-django-kafka: |-
|
||||
|
||||
@ -62,6 +62,7 @@ data:
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
}
|
||||
|
||||
location ~^/api/pm/ {
|
||||
#rewrite /api/(.+) /$1 break;
|
||||
proxy_http_version 1.1;
|
||||
@ -70,11 +71,12 @@ data:
|
||||
proxy_pass http://backend-svc.pm.svc.cluster.local:8000;
|
||||
}
|
||||
|
||||
# location ~^/api/v1/documents/ {
|
||||
# #rewrite /api/(.+) /$1 break;
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_pass http://backend-filestream-svc.documentations.svc.cluster.local:80;
|
||||
# }
|
||||
location ~^/api/v1/documents/ {
|
||||
proxy_http_version 1.1;
|
||||
#rewrite /api/(.+) /$1 break;
|
||||
proxy_set_header Host $host;
|
||||
proxy_pass http://backend-filestream-svc.documentations.svc.cluster.local:80;
|
||||
}
|
||||
|
||||
location ~^/(api|admin)/ {
|
||||
proxy_http_version 1.1;
|
||||
@ -83,13 +85,54 @@ data:
|
||||
proxy_pass http://backend-svc.django.svc.cluster.local:80;
|
||||
}
|
||||
|
||||
location ~^/workspaces-v2/(.+).js {
|
||||
|
||||
location = /static/pdf-runtime/assets/mupdf-wasm.wasm {
|
||||
alias /opt/react_client/static/pdf-runtime/assets/mupdf-wasm.wasm;
|
||||
add_header Content-Type application/wasm always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
|
||||
}
|
||||
|
||||
location = /workspaces-v2/worker/static/viewer-pdf/mupdf-wasm.js {
|
||||
alias /opt/react_client/static/viewer-pdf/mupdf-wasm.js;
|
||||
add_header Content-Type application/javascript always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
|
||||
}
|
||||
|
||||
location = /workspaces-v2/worker/mupdf.worker-3.3.9.js {
|
||||
alias /opt/react_client/static/pdf-runtime/mupdf.worker-3.3.9.js;
|
||||
add_header Content-Type application/javascript always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
|
||||
}
|
||||
|
||||
location = /workspaces-v2/worker/static/viewer-pdf/mupdf.js {
|
||||
alias /opt/react_client/static/viewer-pdf/mupdf.js;
|
||||
add_header Content-Type application/javascript always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always;
|
||||
}
|
||||
|
||||
location = /workspaces-v2/worker/static/viewer-pdf/mupdf-wasm.wasm {
|
||||
add_header Content-Type application/wasm always;
|
||||
alias /opt/react_client/static/viewer-pdf/mupdf-wasm.wasm;
|
||||
}
|
||||
|
||||
location ~^/workspaces-v2/(.+).js {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
rewrite /workspaces-v2/(.+) /$1 break;
|
||||
proxy_pass http://frontend-svc.workspaces.svc.cluster.local:80;
|
||||
}
|
||||
|
||||
|
||||
location ~^/workspaces-v2/(.+)\.wasm$ {
|
||||
proxy_http_version 1.1;
|
||||
|
||||
@ -126,9 +126,13 @@ spec:
|
||||
- name: ZITADEL_HOST
|
||||
value:
|
||||
_default: https://sarex-login.uralmine.com
|
||||
# Включено вместе с message-hub: он консьюмер топика message-hub-stage
|
||||
# (SETTINGS_TOPICS в apps/message-hub/d8-ugmk-prod/message-hub.yaml),
|
||||
# а писать в этот топик должен django. Vault-шаблон django-kafka
|
||||
# и KAFKA_SSL_CAFILE уже есть в base — здесь только флаг.
|
||||
- name: SERVER_KAFKA_ENABLED
|
||||
value:
|
||||
_default: "False"
|
||||
_default: "True"
|
||||
- name: KAFKA_TOPICS
|
||||
value:
|
||||
_default: '{"planning": "message-hub-stage", "ams-sync": "ams-sync"}'
|
||||
@ -138,3 +142,17 @@ spec:
|
||||
- name: KC_USE_REDIRECT_LOGOUT
|
||||
value:
|
||||
_default: "False"
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-template-django-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/django" }}
|
||||
AWS_S3_ENDPOINT_URL=https://s3.uralmine.com
|
||||
S3_HOST=https://s3.uralmine.com
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
AWS_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
AWS_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
AWS_STORAGE_BUCKET_NAME={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
|
||||
{{- end }}
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: django
|
||||
resources:
|
||||
- ../base
|
||||
patches:
|
||||
- path: backend.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: zitadel-configmap.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: zitadel-configmap
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: django
|
||||
resources:
|
||||
- ../base
|
||||
patches:
|
||||
- path: backend.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: zitadel-configmap.yaml
|
||||
target:
|
||||
kind: ConfigMap
|
||||
name: zitadel-configmap
|
||||
- path: s3-proxy.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: s3-proxy
|
||||
31
apps/django/d8-ugmk-prod/s3-proxy.yaml
Normal file
31
apps/django/d8-ugmk-prod/s3-proxy.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
# Патч s3-proxy для контура УГМК.
|
||||
#
|
||||
# В base зашит AWS_API_ENDPOINT=https://minio.contour.infra.sarex.tech —
|
||||
# в закрытом контуре этот хост недоступен, прокси не достучится до MinIO
|
||||
# и маршрут /media/ (s3-proxy-virt-service в istio-config) вернёт ошибку.
|
||||
#
|
||||
# podAnnotations — map, мержится по ключам, поэтому переопределён только
|
||||
# agent-inject-template-s3; остальные vault-аннотации берутся из base.
|
||||
# Эндпоинт задан литералом, а не через .Data.data.client.endpoint: так же
|
||||
# сделано в apps/django/d8-ugmk-prod/backend.yaml:145 для того же секрета
|
||||
# secrets/data/minio/apps/django — держим один способ на весь ns.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: s3-proxy
|
||||
namespace: django
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
s3-proxy:
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-template-s3: |
|
||||
{{- with secret "secrets/data/minio/apps/django" }}
|
||||
AWS_API_ENDPOINT=https://s3.uralmine.com
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
AWS_S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}django{{ end }}
|
||||
AWS_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
AWS_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
{{- end }}
|
||||
139
apps/django/yc-ecp/frontend.yaml
Normal file
139
apps/django/yc-ecp/frontend.yaml
Normal file
@ -0,0 +1,139 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: django
|
||||
spec:
|
||||
interval: 5m
|
||||
timeout: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
frontend:
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/sarex-frontend-dev:cps_82ba823b
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: frontend
|
||||
|
||||
replicaCount:
|
||||
_default: 1
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu:
|
||||
_default: 25m
|
||||
memory:
|
||||
_default: 100Mi
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: frontend-service
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: true
|
||||
name:
|
||||
_default: dockerhub
|
||||
|
||||
# чарт прогоняет weight, key, operator и topologyKey через pluckEnv,
|
||||
# который читает только map вида {_default: …}; скаляры дают пустые значения
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight:
|
||||
_default: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key:
|
||||
_default: app
|
||||
operator:
|
||||
_default: In
|
||||
values:
|
||||
- frontend
|
||||
topologyKey:
|
||||
_default: kubernetes.io/hostname
|
||||
|
||||
# ConfigMap'ы nginx-configmap и robots-txt-config создаются вне этого
|
||||
# релиза — чарт только монтирует их
|
||||
volumes:
|
||||
_default:
|
||||
- name: nginx-configmap
|
||||
mountPath:
|
||||
_default: /etc/nginx/nginx.conf
|
||||
subPath:
|
||||
_default: nginx.conf
|
||||
configMap:
|
||||
name:
|
||||
_default: nginx-configmap
|
||||
items:
|
||||
- key: nginx.conf
|
||||
path:
|
||||
_default: nginx.conf
|
||||
|
||||
- name: robots-volume
|
||||
mountPath:
|
||||
_default: /opt/react_client/robots.txt
|
||||
subPath:
|
||||
_default: robots.txt
|
||||
configMap:
|
||||
name:
|
||||
_default: robots-txt-config
|
||||
items:
|
||||
- key: robots.txt
|
||||
path:
|
||||
_default: robots.txt
|
||||
9
apps/django/yc-ecp/kustomization.yaml
Normal file
9
apps/django/yc-ecp/kustomization.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: django
|
||||
resources:
|
||||
- frontend.yaml
|
||||
- s3-proxy.yaml
|
||||
- s3-proxy-bim.yaml
|
||||
# - namespace.yaml
|
||||
7
apps/django/yc-ecp/namespace.yaml
Normal file
7
apps/django/yc-ecp/namespace.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: django
|
||||
labels:
|
||||
istio-injection: enabled
|
||||
104
apps/django/yc-ecp/s3-proxy-bim.yaml
Normal file
104
apps/django/yc-ecp/s3-proxy-bim.yaml
Normal file
@ -0,0 +1,104 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: s3-proxy-bim
|
||||
namespace: django
|
||||
spec:
|
||||
interval: 5m
|
||||
timeout: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
s3-proxy-bim:
|
||||
enabled: true
|
||||
|
||||
# образ публичный, из Docker Hub — pull-секрет не нужен
|
||||
image:
|
||||
name:
|
||||
_default: pottava/s3-proxy
|
||||
pullPolicy:
|
||||
_default: Always
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: s3-proxy-bim
|
||||
|
||||
replicaCount:
|
||||
_default: 2
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: s3-bim-service
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: false
|
||||
|
||||
envs:
|
||||
- name: AWS_API_ENDPOINT
|
||||
value:
|
||||
_default: "https://storage.yandexcloud.net"
|
||||
|
||||
# ключи S3 лежат в Secret/s3-proxy-bim-secret, созданном вне этого релиза
|
||||
secretEnvs:
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
secretName:
|
||||
_default: "s3-proxy-bim-secret"
|
||||
secretKey: "login"
|
||||
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
secretName:
|
||||
_default: "s3-proxy-bim-secret"
|
||||
secretKey: "password"
|
||||
|
||||
- name: AWS_S3_BUCKET
|
||||
secretName:
|
||||
_default: "s3-proxy-bim-secret"
|
||||
secretKey: "bucket"
|
||||
105
apps/django/yc-ecp/s3-proxy.yaml
Normal file
105
apps/django/yc-ecp/s3-proxy.yaml
Normal file
@ -0,0 +1,105 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: s3-proxy
|
||||
namespace: django
|
||||
spec:
|
||||
interval: 5m
|
||||
timeout: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
s3-proxy:
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/s3-proxy:stable
|
||||
pullPolicy:
|
||||
_default: Always
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: s3-proxy
|
||||
|
||||
replicaCount:
|
||||
_default: 2
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: s3-service
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: true
|
||||
name:
|
||||
_default: dockerhub
|
||||
|
||||
envs:
|
||||
- name: AWS_API_ENDPOINT
|
||||
value:
|
||||
_default: "https://storage.yandexcloud.net"
|
||||
|
||||
# ключи S3 лежат в Secret/s3-proxy-secret, созданном вне этого релиза
|
||||
secretEnvs:
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
secretName:
|
||||
_default: "s3-proxy-secret"
|
||||
secretKey: "login"
|
||||
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
secretName:
|
||||
_default: "s3-proxy-secret"
|
||||
secretKey: "password"
|
||||
|
||||
- name: AWS_S3_BUCKET
|
||||
secretName:
|
||||
_default: "s3-proxy-secret"
|
||||
secretKey: "bucket"
|
||||
@ -3,7 +3,7 @@ apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: document-link
|
||||
namespace:
|
||||
|
||||
spec:
|
||||
interval: 10m
|
||||
@ -36,7 +36,7 @@ spec:
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/document-link-frontend:wb_cb2027ce
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/document-link-frontend:contour_d8c3481b
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
|
||||
@ -50,7 +50,7 @@ spec:
|
||||
_default: 1
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
_default: 3000
|
||||
|
||||
resources:
|
||||
requests:
|
||||
@ -78,7 +78,7 @@ spec:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
_default: 3000
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
@ -144,7 +144,7 @@ spec:
|
||||
_default: sarex.contour.infra.sarex.tech
|
||||
- name: DOCUMENTATION_URL
|
||||
value:
|
||||
_default: http://documentations-api.documentations.svc.cluster.local:80/
|
||||
_default: http://backend-api-svc.documentations.svc.cluster.local:80/
|
||||
- name: WORKFLOW_URL
|
||||
value:
|
||||
_default: http://backend-svc.processing.svc.cluster.local:80/
|
||||
|
||||
@ -68,7 +68,7 @@ spec:
|
||||
_default: sarex.uralmine.com
|
||||
- name: DOCUMENTATION_URL
|
||||
value:
|
||||
_default: http://documentations-api.documentations.svc.cluster.local:80/
|
||||
_default: http://backend-api-svc.documentations.svc.cluster.local:80/
|
||||
- name: WORKFLOW_URL
|
||||
value:
|
||||
_default: http://backend-svc.processing.svc.cluster.local:80/
|
||||
@ -95,7 +95,7 @@ spec:
|
||||
_default: http://marks-service:8000
|
||||
- name: PUBLIC_LINK_HOST
|
||||
value:
|
||||
_default: https://document-link-srx.wb.ru
|
||||
_default: https://sarex-document-link.uralmine.com
|
||||
- name: NAMESPACE
|
||||
value:
|
||||
_default: documentations
|
||||
|
||||
@ -92,7 +92,7 @@ spec:
|
||||
_default: http://marks-service:8000
|
||||
- name: PUBLIC_LINK_HOST
|
||||
value:
|
||||
_default: https://document-link-srx.wb.ru
|
||||
_default: https://sarex-document-link.uralmine.com
|
||||
- name: NAMESPACE
|
||||
value:
|
||||
_default: documentations
|
||||
|
||||
@ -167,11 +167,11 @@ spec:
|
||||
|
||||
- name: GATEWAY_URL
|
||||
value:
|
||||
_default: "http://pdm-api.documentations.svc.cluster.local:8080"
|
||||
_default: "http://pdm-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: RESOURCE_URL
|
||||
value:
|
||||
_default: "http://resources-service.resources.svc.cluster.local:8000"
|
||||
_default: "http://iam-backend.iam.svc.cluster.local:8000"
|
||||
|
||||
- name: SERVICE_HOST
|
||||
value:
|
||||
@ -199,7 +199,7 @@ spec:
|
||||
|
||||
- name: WORKFLOWS_HOST
|
||||
value:
|
||||
_default: "http://workflows-api-service.workflow.svc.cluster.local:8000/api/v1"
|
||||
_default: "http://backend-svc.processing.svc.cluster.local:80/api/v1"
|
||||
|
||||
- name: WORKFLOWS_TIMEOUT
|
||||
value:
|
||||
|
||||
@ -102,6 +102,23 @@ spec:
|
||||
name:
|
||||
_default: regcred
|
||||
|
||||
volumes:
|
||||
_default:
|
||||
- name: iam-zitadel-org-rules
|
||||
mountPath:
|
||||
_default: /config/zitadel/org-rules-prod.json
|
||||
subPath:
|
||||
_default: org-rules-prod.json
|
||||
readOnly:
|
||||
_default: true
|
||||
configMap:
|
||||
name:
|
||||
_default: iam-zitadel-org-rules
|
||||
items:
|
||||
- key: org-rules-prod.json
|
||||
path:
|
||||
_default: org-rules-prod.json
|
||||
|
||||
labels:
|
||||
monitoring: prometheus
|
||||
|
||||
@ -132,11 +149,11 @@ spec:
|
||||
|
||||
- name: ZITADEL_ENABLED
|
||||
value:
|
||||
_default: "false"
|
||||
_default: "true"
|
||||
|
||||
- name: ZITADEL_HOST
|
||||
value:
|
||||
_default: "https://login.sarex.io"
|
||||
_default: "https://sarex-login.uralmine.com"
|
||||
|
||||
- name: ZITADEL_ORG_RULES_FILE
|
||||
value:
|
||||
@ -187,10 +204,10 @@ spec:
|
||||
{{- with secret "secrets/data/apps/iam/postgres" -}}
|
||||
DB_DSN=postgres://{{ index .Data.data "username" }}:{{ index .Data.data "password" }}@{{ index .Data.data "host" }}:{{ index .Data.data "port" }}/{{ index .Data.data "database" }}
|
||||
{{- end -}}
|
||||
vault.hashicorp.com/agent-inject-secret-iam-zitadel: secrets/data/apps/iam/zitadel
|
||||
vault.hashicorp.com/agent-inject-secret-iam-zitadel: secrets/data/vault/common/django_auth
|
||||
vault.hashicorp.com/agent-inject-template-iam-zitadel: |-
|
||||
{{- with secret "secrets/data/apps/iam/zitadel" -}}
|
||||
ZITADEL_ACCESS_TOKEN={{ index .Data.data "access_token" }}
|
||||
{{- with secret "secrets/data/vault/common/django_auth" -}}
|
||||
ZITADEL_ACCESS_TOKEN={{ index .Data.data "django_zitadel_access_token" }}
|
||||
{{- end -}}
|
||||
vault.hashicorp.com/agent-inject-secret-iam-kafka: secrets/data/kafka/apps/iam
|
||||
vault.hashicorp.com/agent-inject-template-iam-kafka: |-
|
||||
|
||||
@ -5,3 +5,4 @@ namespace: iam
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- backend.yaml
|
||||
- zitadel-org-rules-configmap.yaml
|
||||
|
||||
12
apps/iam/base/zitadel-org-rules-configmap.yaml
Normal file
12
apps/iam/base/zitadel-org-rules-configmap.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: iam-zitadel-org-rules
|
||||
namespace: iam
|
||||
data:
|
||||
org-rules-prod.json: |
|
||||
{
|
||||
"default_org_id": "383923292894987370",
|
||||
"rules": []
|
||||
}
|
||||
78
apps/iam/d8-ugmk-prod/backend-s3.yaml
Normal file
78
apps/iam/d8-ugmk-prod/backend-s3.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: iam-backend
|
||||
namespace: iam
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
envs:
|
||||
- name: ENVIRONMENT
|
||||
value:
|
||||
_default: "prod"
|
||||
|
||||
- name: LOG_LEVEL
|
||||
value:
|
||||
_default: "debug"
|
||||
|
||||
- name: AUTH_ENABLED
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: HTTP_PORT
|
||||
value:
|
||||
_default: "8080"
|
||||
|
||||
- name: HTTP_READ_BUFFER_SIZE
|
||||
value:
|
||||
_default: "131072"
|
||||
|
||||
- name: DB_MIGRATIONS_PATH
|
||||
value:
|
||||
_default: "migrations"
|
||||
|
||||
- name: ZITADEL_ENABLED
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: ZITADEL_HOST
|
||||
value:
|
||||
_default: "https://sarex-login.uralmine.com"
|
||||
|
||||
- name: ZITADEL_ORG_RULES_FILE
|
||||
value:
|
||||
_default: "config/zitadel/org-rules-prod.json"
|
||||
|
||||
- name: S3_ENABLED
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: S3_ENDPOINT_URL
|
||||
value:
|
||||
_default: "https://s3.uralmine.com"
|
||||
|
||||
- name: S3_BUCKET_NAME
|
||||
value:
|
||||
_default: "sarex-media-storage"
|
||||
|
||||
- name: S3_REGION
|
||||
value:
|
||||
_default: "ru-central1"
|
||||
|
||||
- name: S3_PRESIGN_EXPIRES
|
||||
value:
|
||||
_default: "1h"
|
||||
|
||||
- name: KAFKA_ENABLED
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: KAFKA_SSL_CAFILE
|
||||
value:
|
||||
_default: "/etc/ca-certificates/Yandex/ca-cert"
|
||||
|
||||
- name: KAFKA_TOPIC_LEGACY_AMS_SYNC
|
||||
value:
|
||||
_default: "ams-sync"
|
||||
@ -3,4 +3,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: iam
|
||||
resources:
|
||||
- ../base
|
||||
- ../base
|
||||
patches:
|
||||
- path: backend-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: iam-backend
|
||||
@ -8,3 +8,5 @@ resources:
|
||||
- celery.yaml
|
||||
- frontend.yaml
|
||||
- production-configmap.yaml
|
||||
- redis-deployment.yaml
|
||||
- redis-service.yaml
|
||||
|
||||
@ -46,7 +46,7 @@ data:
|
||||
|
||||
WORKFLOWS_HOST = "http://workflows-api-service.workflow.svc.cluster.local:8000"
|
||||
WORKFLOWS_URL = "http://workflows-api-service.workflow.svc.cluster.local:8000"
|
||||
DOCUMENTATIONS_URL = "http://documentations-api.documentations.svc.cluster.local:8080"
|
||||
DOCUMENTATIONS_URL = "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
RESOURCES_API_HOST = os.getenv("RESOURCES_API_HOST", default="http://resources-service.resources.svc.cluster:8000")
|
||||
KAFKA_HOST = "wb-stage-kafka-bootstrap.kafka.svc.cluster.local:9093"
|
||||
KAFKA_USERNAME = "sarex"
|
||||
|
||||
27
apps/issues/base/redis-deployment.yaml
Normal file
27
apps/issues/base/redis-deployment.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: issues
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: cr.yandex/crp3ccidau046kdj8g9q/redis:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
protocol: TCP
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
13
apps/issues/base/redis-service.yaml
Normal file
13
apps/issues/base/redis-service.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: issues
|
||||
spec:
|
||||
selector:
|
||||
app: redis
|
||||
ports:
|
||||
- port: 6379
|
||||
targetPort: 6379
|
||||
protocol: TCP
|
||||
20
apps/issues/d8-ugmk-prod/backend-s3.yaml
Normal file
20
apps/issues/d8-ugmk-prod/backend-s3.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: issues
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-issues-s3: secrets/data/minio/apps/issues
|
||||
vault.hashicorp.com/agent-inject-template-issues-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/issues" -}}
|
||||
YC_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YC_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
YC_S3_BUCKET_NAME=sarex-issues
|
||||
YC_S3_ENDPOINT_URL=https://s3.uralmine.com
|
||||
{{- end -}}
|
||||
20
apps/issues/d8-ugmk-prod/celery-s3.yaml
Normal file
20
apps/issues/d8-ugmk-prod/celery-s3.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: celery
|
||||
namespace: issues
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
celery:
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-issues-s3: secrets/data/minio/apps/issues
|
||||
vault.hashicorp.com/agent-inject-template-issues-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/issues" -}}
|
||||
YC_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YC_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
YC_S3_BUCKET_NAME=sarex-issues
|
||||
YC_S3_ENDPOINT_URL=https://s3.uralmine.com
|
||||
{{- end -}}
|
||||
@ -8,3 +8,11 @@ patches:
|
||||
target:
|
||||
kind: Namespace
|
||||
name: issues
|
||||
- path: backend-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: celery-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: celery
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: measurements
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
- measurements.yaml
|
||||
- namespace.yaml
|
||||
111
apps/measurements/yc-ecp/measurements.yaml
Normal file
111
apps/measurements/yc-ecp/measurements.yaml
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: measurements
|
||||
namespace: measurements
|
||||
spec:
|
||||
interval: 5m
|
||||
timeout: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
backend:
|
||||
enabled: true
|
||||
|
||||
# в yc-ecp S3-настройки приходят из Secret, а не через Vault Agent,
|
||||
# поэтому serviceAccount, vault-аннотации и обёртка entrypoint не нужны
|
||||
serviceAccount:
|
||||
enabled:
|
||||
_default: false
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/measurements:prod_6070cd4d
|
||||
pullPolicy:
|
||||
_default: Always
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: measurement
|
||||
|
||||
replicaCount:
|
||||
_default: 2
|
||||
|
||||
port:
|
||||
_default: 8000
|
||||
|
||||
# entrypoint.sh запускает gunicorn без --access-logfile, поэтому
|
||||
# запросы не попадают в лог; подменяем команду целиком
|
||||
command:
|
||||
_default: ["/bin/bash", "-ec"]
|
||||
args:
|
||||
_default:
|
||||
- gunicorn -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000 --timeout 240 --access-logfile - --access-logformat '%(h)s "%(r)s" %(s)s %(b)s %(M)sms' measurements.main:app
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu:
|
||||
_default: 25m
|
||||
memory:
|
||||
_default: 128Mi
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: measurement-service
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 8000
|
||||
|
||||
targetPort:
|
||||
_default: 8000
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: true
|
||||
name:
|
||||
_default: dockerhub
|
||||
|
||||
|
||||
secretEnvs:
|
||||
- name: S3_JSON_SETTINGS
|
||||
secretName:
|
||||
_default: "s3-json-settings"
|
||||
secretKey: "S3_JSON_SETTINGS"
|
||||
7
apps/measurements/yc-ecp/namespace.yaml
Normal file
7
apps/measurements/yc-ecp/namespace.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: measurements
|
||||
labels:
|
||||
istio-injection: enabled
|
||||
@ -8,3 +8,7 @@ patches:
|
||||
target:
|
||||
kind: Namespace
|
||||
name: message-hub
|
||||
- path: message-hub.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: message-hub
|
||||
|
||||
120
apps/message-hub/d8-ugmk-prod/message-hub.yaml
Normal file
120
apps/message-hub/d8-ugmk-prod/message-hub.yaml
Normal file
@ -0,0 +1,120 @@
|
||||
---
|
||||
# Патч message-hub для контура УГМК.
|
||||
#
|
||||
# ВНИМАНИЕ: envs — список, kustomize заменяет его ЦЕЛИКОМ (JSON merge patch),
|
||||
# поэтому здесь продублирован весь набор из apps/message-hub/base/message-hub.yaml.
|
||||
# podAnnotations — map, мержится по ключам, поэтому переопределён только
|
||||
# agent-inject-template-message-hub-kafka; остальные берутся из base.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: message-hub
|
||||
namespace: message-hub
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
# base: production_24425472 от 15.02.2026 — 18 production-релизов назад.
|
||||
# Здесь актуальный production от 31.07.2026.
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/message-hub:production_e8010fe4
|
||||
|
||||
envs:
|
||||
- name: WORKER_TIMEOUT
|
||||
value:
|
||||
_default: "60"
|
||||
|
||||
- name: PYTHONPATH
|
||||
value:
|
||||
_default: "src"
|
||||
|
||||
- name: SETTINGS_MAX_RETRIES
|
||||
value:
|
||||
_default: "1"
|
||||
|
||||
# base: '{"planning": "pm", "assets": "assets_broadcast", "project_entity": "issues_broadcast"}'
|
||||
# Два исправления:
|
||||
# 1. ключ project_entity невалиден — TopicsType (src/enums.py) знает только
|
||||
# assets / planning / issues / resources_updated / resources_deleted,
|
||||
# на прочих валидатор check_topics_keys кидает ValueError при старте.
|
||||
# Консьюмер лежит в project_entity.py, но подписан на TopicsType.issues.
|
||||
# 2. planning был "pm", а django публикует в "message-hub-stage"
|
||||
# (KAFKA_TOPICS, apps/django/d8-ugmk-prod/backend.yaml) — продюсер
|
||||
# и консьюмер сидели на разных топиках.
|
||||
- name: SETTINGS_TOPICS
|
||||
value:
|
||||
_default: '{"planning": "message-hub-stage", "assets": "assets_broadcast", "issues": "issues_broadcast"}'
|
||||
|
||||
# В base нет, дефолт True. S3 контура (s3.uralmine.com) отдаёт
|
||||
# самоподписанный сертификат — тот же случай, что S3_VERIFY=False у pm.
|
||||
# Флаг общий: гасит проверку TLS сразу и для S3, и для всех HTTP-клиентов.
|
||||
- name: SETTINGS_VERIFY_SSL
|
||||
value:
|
||||
_default: "0"
|
||||
|
||||
# base: http://backend-service.pm.svc.cluster.local:8000 — сервис pm
|
||||
# называется backend-svc (apps/pm/base/backend.yaml:91).
|
||||
- name: SAREX_BASE_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.pm.svc.cluster.local:8000"
|
||||
|
||||
# В base нет. Без него ServiceConfig с префиксом PM_ уходит
|
||||
# в дефолт http://localhost:8001. В dsinv и brusnika задан.
|
||||
- name: PM_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.pm.svc.cluster.local:8000"
|
||||
|
||||
# Имена сверены с infrastructure/istio-config/d8-ugmk-prod/istio-config.yaml.
|
||||
- name: EAV_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.eav.svc.cluster.local:80"
|
||||
|
||||
- name: ISSUES_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.issues.svc.cluster.local:80"
|
||||
|
||||
- name: CACHE_HOST
|
||||
value:
|
||||
_default: "redis.pm.svc.cluster.local"
|
||||
|
||||
- name: CACHE_PORT
|
||||
value:
|
||||
_default: "6379"
|
||||
|
||||
- name: CACHE_SSL
|
||||
value:
|
||||
_default: "0"
|
||||
|
||||
# ВНИМАНИЕ: значение не подтверждено. В base было захардкожено
|
||||
# kafka-kafka-contour-controller-headless — имя из другого контура,
|
||||
# здесь HelmRelease называется kafka (infrastructure/kafka/d8-ugmk-prod).
|
||||
# Проверить: kubectl -n kafka get svc
|
||||
# Задано переменной, а не vault-шаблоном, специально: ошибка в шаблоне
|
||||
# блокирует старт пода (agent-init-first), ошибка в env — только логи.
|
||||
- name: KAFKA_HOST
|
||||
value:
|
||||
_default: "kafka-controller-headless.kafka.svc.cluster.local"
|
||||
|
||||
- name: KAFKA_PORT
|
||||
value:
|
||||
_default: "9092"
|
||||
|
||||
# listeners.client.protocol: SASL_SSL — без CA соединение не поднимется.
|
||||
- name: KAFKA_SSL_CAFILE
|
||||
value:
|
||||
_default: "/usr/local/share/ca-certificates/kafka.crt"
|
||||
|
||||
podAnnotations:
|
||||
_default:
|
||||
# Из base убраны KAFKA_HOST/KAFKA_PORT: файл /vault/secrets/message-hub-kafka
|
||||
# подгружается через `set -a; . file`, то есть переписывает переменные
|
||||
# окружения. Пока хост не подтверждён, держим его в envs.
|
||||
vault.hashicorp.com/agent-inject-secret-message-hub-kafka: secrets/data/kafka/apps/pm
|
||||
vault.hashicorp.com/agent-inject-template-message-hub-kafka: |-
|
||||
{{- with secret "secrets/data/kafka/apps/pm" -}}
|
||||
KAFKA_USERNAME={{ index .Data.data "username" }}
|
||||
KAFKA_PASSWORD={{ index .Data.data "password" }}
|
||||
KAFKA_SECURITY_PROTOCOL={{ index .Data.data.auth "security_protocol" }}
|
||||
KAFKA_SASL_MECHANISM={{ index .Data.data.auth "sasl_mechanism" }}
|
||||
{{- end -}}
|
||||
@ -246,7 +246,7 @@ spec:
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
S3_BUCKET={{- if gt (len $buckets) 0 -}}{{ index (index $buckets 0) "name" }}{{- else -}}pm-bucket{{- end -}}
|
||||
S3_BUCKET={{- if gt (len $buckets) 0 -}}{{ index (index $buckets 0) "name" }}{{- else -}}sarex-media-storage{{- end -}}
|
||||
S3_VERIFY=False
|
||||
{{- end -}}
|
||||
|
||||
|
||||
@ -228,7 +228,7 @@ spec:
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
S3_BUCKET={{- if gt (len $buckets) 0 -}}{{ index (index $buckets 0) "name" }}{{- else -}}pm-bucket{{- end -}}
|
||||
S3_BUCKET={{- if gt (len $buckets) 0 -}}{{ index (index $buckets 0) "name" }}{{- else -}}sarex-media-storage{{- end -}}
|
||||
S3_VERIFY=False
|
||||
{{- end -}}
|
||||
|
||||
|
||||
@ -8,3 +8,4 @@ resources:
|
||||
- celery.yaml
|
||||
- frontend.yaml
|
||||
- backend-configmap.yaml
|
||||
- resources-static.yaml
|
||||
|
||||
90
apps/pm/base/resources-static.yaml
Normal file
90
apps/pm/base/resources-static.yaml
Normal file
@ -0,0 +1,90 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: resources-static
|
||||
namespace: pm
|
||||
|
||||
spec:
|
||||
interval: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
resources-static:
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/resources-frontend:ugok_7f38a9ce
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: resources-static
|
||||
|
||||
replicaCount:
|
||||
_default: 1
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu:
|
||||
_default: 25m
|
||||
memory:
|
||||
_default: 100Mi
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: resources-static-svc
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: true
|
||||
name:
|
||||
_default: regcred
|
||||
170
apps/pm/d8-ugmk-prod/backend.yaml
Normal file
170
apps/pm/d8-ugmk-prod/backend.yaml
Normal file
@ -0,0 +1,170 @@
|
||||
---
|
||||
# Патч backend для контура УГМК.
|
||||
#
|
||||
# ВНИМАНИЕ: args — список, kustomize заменяет его ЦЕЛИКОМ (JSON merge patch),
|
||||
# поэтому здесь продублирован весь скрипт из apps/pm/base/backend.yaml.
|
||||
# При правке args в base их нужно продублировать и сюда.
|
||||
# podAnnotations — map, мержится по ключам, поэтому переопределён только
|
||||
# один ключ agent-inject-template-pm-s3; остальные vault-аннотации берутся из base.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: pm
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
# base: production_a889f6a3 (релиз 1.14.1, 13.07.2026).
|
||||
# Здесь 1.14.7 — pipeline 72144, зелёный.
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/pm-backend:production_fa0f1551
|
||||
|
||||
deployment:
|
||||
args:
|
||||
_default:
|
||||
- |
|
||||
set -a
|
||||
[ -f /vault/secrets/pm-db ] && . /vault/secrets/pm-db
|
||||
[ -f /vault/secrets/pm-rabbitmq ] && . /vault/secrets/pm-rabbitmq
|
||||
[ -f /vault/secrets/pm-s3 ] && . /vault/secrets/pm-s3
|
||||
set +a
|
||||
python manage.py makemigrations pm --noinput
|
||||
python manage.py migrate
|
||||
exec /opt/sarex/entrypoint.sh
|
||||
|
||||
# ВНИМАНИЕ: envs — список, kustomize заменяет его ЦЕЛИКОМ,
|
||||
# поэтому здесь продублирован весь набор из apps/pm/base/backend.yaml.
|
||||
# Отличия от base помечены комментариями.
|
||||
envs:
|
||||
- name: USERS_INTERNAL_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.django.svc.cluster.local:80"
|
||||
|
||||
- name: CELERY_REDIS_HOST
|
||||
value:
|
||||
_default: "redis.pm.svc.cluster.local"
|
||||
|
||||
- name: RESOURCES_INTERNAL_HOST
|
||||
value:
|
||||
_default: "http://iam-backend.iam.svc.cluster.local:8000"
|
||||
|
||||
- name: EAV_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.eav.svc.cluster.local:80"
|
||||
|
||||
- name: EAV_API_PREFIX
|
||||
value:
|
||||
_default: "/api/v0"
|
||||
|
||||
- name: EAV_API_PREFIX_V1
|
||||
value:
|
||||
_default: "/api/v1"
|
||||
|
||||
- name: TRACING_INSECURE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_ENABLE_SYNC_RESOURCES
|
||||
value:
|
||||
_default: "True"
|
||||
|
||||
- name: SERVER_DELETED_TASK_MAX_AGE_DAYS
|
||||
value:
|
||||
_default: "1"
|
||||
|
||||
- name: SERVER_EXPIRED_TASK_NOTIFICATION_HOUR
|
||||
value:
|
||||
_default: "17"
|
||||
|
||||
- name: LANG
|
||||
value:
|
||||
_default: "C.UTF-8"
|
||||
|
||||
- name: LC_ALL
|
||||
value:
|
||||
_default: "C.UTF-8"
|
||||
|
||||
- name: PYTHONUTF8
|
||||
value:
|
||||
_default: "1"
|
||||
|
||||
- name: CACHE_SSL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: CACHE_SSL_CA_CERTS
|
||||
value:
|
||||
_default: ""
|
||||
|
||||
# base: "False". При False CACHE_CLIENT = None (config/settings/base.py:190),
|
||||
# и GET /api/pm/msp/external-task-info/ падает с
|
||||
# AttributeError: 'NoneType' object has no attribute 'get' —
|
||||
# sarex/pm/utils/broker_producer.py:38 дёргает .get() без проверки на None.
|
||||
- name: CACHE_ENABLE
|
||||
value:
|
||||
_default: "True"
|
||||
|
||||
# Новые: в base их нет. Дефолт CacheSettings.host — localhost,
|
||||
# т.е. без них включённый кэш стучится в собственный под.
|
||||
# Redis разворачивается тут же — apps/pm/d8-ugmk-prod/redis.yaml.
|
||||
- name: CACHE_HOST
|
||||
value:
|
||||
_default: "redis.pm.svc.cluster.local"
|
||||
|
||||
- name: CACHE_PORT
|
||||
value:
|
||||
_default: "6379"
|
||||
|
||||
- name: CLICKHOUSE_ENABLE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: KAFKA_ENABLE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: AUTH_PUBLIC_TOKEN_URL
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com/api/token/public/"
|
||||
|
||||
- name: SERVER_HOST
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com"
|
||||
|
||||
- name: SERVER_API_HOST
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com"
|
||||
|
||||
- name: SERVER_DEBUG
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_ALLOWED_HOSTS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: SERVER_USE_OTEL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_VERIFY_SSL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_LOG_LEVEL
|
||||
value:
|
||||
_default: "INFO"
|
||||
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-template-pm-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/pm" -}}
|
||||
S3_HOST={{ index .Data.data.client "endpoint" }}
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
S3_VERIFY=False
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}sarex-media-storage{{ end }}
|
||||
{{- end -}}
|
||||
160
apps/pm/d8-ugmk-prod/celery.yaml
Normal file
160
apps/pm/d8-ugmk-prod/celery.yaml
Normal file
@ -0,0 +1,160 @@
|
||||
---
|
||||
# Патч celery для контура УГМК.
|
||||
#
|
||||
# ВНИМАНИЕ: envs — список, kustomize заменяет его ЦЕЛИКОМ (JSON merge patch),
|
||||
# поэтому здесь продублирован весь набор из apps/pm/base/celery.yaml.
|
||||
# При добавлении переменной в base её нужно продублировать и сюда.
|
||||
# podAnnotations — map, мержится по ключам, поэтому переопределён только
|
||||
# один ключ agent-inject-template-pm-s3; остальные vault-аннотации берутся из base.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: celery
|
||||
namespace: pm
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
celery:
|
||||
# Образ общий с backend — держать в одной версии обязательно,
|
||||
# иначе воркер разъедется с API по схеме задач и моделям.
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/pm-backend:production_fa0f1551
|
||||
|
||||
envs:
|
||||
# base: http://backend-service.sarex.svc.cluster.local:8000 — ns sarex не существует
|
||||
- name: USERS_INTERNAL_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.django.svc.cluster.local:80"
|
||||
|
||||
- name: CELERY_REDIS_HOST
|
||||
value:
|
||||
_default: "redis.pm.svc.cluster.local"
|
||||
|
||||
# base: http://sarex-resources-service.resources — ns resources не развёрнут в контуре
|
||||
- name: RESOURCES_INTERNAL_HOST
|
||||
value:
|
||||
_default: "http://iam-backend.iam.svc.cluster.local:8000"
|
||||
|
||||
# base: http://eav-service.eav — сервис называется backend-svc и слушает 80
|
||||
- name: EAV_HOST
|
||||
value:
|
||||
_default: "http://backend-svc.eav.svc.cluster.local:80"
|
||||
|
||||
- name: EAV_API_PREFIX
|
||||
value:
|
||||
_default: "/api/v0"
|
||||
|
||||
- name: EAV_API_PREFIX_V1
|
||||
value:
|
||||
_default: "/api/v1"
|
||||
|
||||
- name: TRACING_INSECURE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_ENABLE_SYNC_RESOURCES
|
||||
value:
|
||||
_default: "True"
|
||||
|
||||
- name: SERVER_DELETED_TASK_MAX_AGE_DAYS
|
||||
value:
|
||||
_default: "1"
|
||||
|
||||
- name: SERVER_EXPIRED_TASK_NOTIFICATION_HOUR
|
||||
value:
|
||||
_default: "17"
|
||||
|
||||
- name: LANG
|
||||
value:
|
||||
_default: "C.UTF-8"
|
||||
|
||||
- name: LC_ALL
|
||||
value:
|
||||
_default: "C.UTF-8"
|
||||
|
||||
- name: PYTHONUTF8
|
||||
value:
|
||||
_default: "1"
|
||||
|
||||
- name: CACHE_SSL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: CACHE_SSL_CA_CERTS
|
||||
value:
|
||||
_default: ""
|
||||
|
||||
# base: "False". Держим в одном значении с backend: при enable
|
||||
# config/celery.py включает периодическую синхронизацию ресурсов,
|
||||
# которая пишет ключи service_accounts / resources:* — их читает
|
||||
# backend в sarex/pm/utils/resources.py.
|
||||
- name: CACHE_ENABLE
|
||||
value:
|
||||
_default: "True"
|
||||
|
||||
# Новые: в base их нет, дефолт CacheSettings.host — localhost.
|
||||
- name: CACHE_HOST
|
||||
value:
|
||||
_default: "redis.pm.svc.cluster.local"
|
||||
|
||||
- name: CACHE_PORT
|
||||
value:
|
||||
_default: "6379"
|
||||
|
||||
- name: CLICKHOUSE_ENABLE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: KAFKA_ENABLE
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
# base: https://lk.sarex.io/api/token/public/
|
||||
- name: AUTH_PUBLIC_TOKEN_URL
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com/api/token/public/"
|
||||
|
||||
# base: https://lk.sarex.io
|
||||
- name: SERVER_HOST
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com"
|
||||
|
||||
# base: https://api.sarex.io
|
||||
- name: SERVER_API_HOST
|
||||
value:
|
||||
_default: "https://sarex.uralmine.com"
|
||||
|
||||
- name: SERVER_DEBUG
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_ALLOWED_HOSTS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: SERVER_USE_OTEL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_VERIFY_SSL
|
||||
value:
|
||||
_default: "False"
|
||||
|
||||
- name: SERVER_LOG_LEVEL
|
||||
value:
|
||||
_default: "INFO"
|
||||
|
||||
podAnnotations:
|
||||
_default:
|
||||
# base склеивал S3_BUCKET с S3_VERIFY: {{- end -}} съедал перевод строки.
|
||||
# S3_VERIFY поднят выше блока if, у {{ end }} убран хвостовой дефис.
|
||||
vault.hashicorp.com/agent-inject-template-pm-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/pm" -}}
|
||||
S3_HOST={{ index .Data.data.client "endpoint" }}
|
||||
S3_LOGIN={{ index .Data.data "access_key" }}
|
||||
S3_PASSWORD={{ index .Data.data "secret_key" }}
|
||||
S3_VERIFY=False
|
||||
{{- $buckets := index .Data.data "buckets" }}
|
||||
S3_BUCKET={{ if gt (len $buckets) 0 }}{{ index (index $buckets 0) "name" }}{{ else }}sarex-media-storage{{ end }}
|
||||
{{- end -}}
|
||||
22
apps/pm/d8-ugmk-prod/frontend.yaml
Normal file
22
apps/pm/d8-ugmk-prod/frontend.yaml
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
# Патч frontend для контура УГМК.
|
||||
#
|
||||
# ВНИМАНИЕ: тег обязан быть contour_*, НЕ production_*.
|
||||
# Сборка prod-варианта тянет remoteEntry.js модулей с https://modules.sarex.io,
|
||||
# который в закрытом контуре недоступен (configWebpack/config/endpoints.ts).
|
||||
# В contour-сборке пути к remoteEntry относительные — только она здесь работает.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: pm
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
frontend:
|
||||
# TODO(Дмитрий): подставить тег новой contour-сборки, когда pipeline
|
||||
# добежит. Пока продублирован тег из base (contour_e5c3d387,
|
||||
# 16.07.2026) — то есть патч сейчас ничего не меняет.
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/pm-frontend:contour_fc00e54f
|
||||
@ -3,8 +3,21 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../base
|
||||
- redis.yaml
|
||||
patches:
|
||||
- path: namespace.yaml
|
||||
target:
|
||||
kind: Namespace
|
||||
name: pm
|
||||
- path: backend.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: celery.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: celery
|
||||
- path: frontend.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: frontend
|
||||
|
||||
98
apps/pm/d8-ugmk-prod/redis.yaml
Normal file
98
apps/pm/d8-ugmk-prod/redis.yaml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
# Redis для celery в ns pm. В base его нет — там CELERY_REDIS_HOST указывает
|
||||
# на redis.pm.svc.cluster.local, но сам сервис не разворачивается.
|
||||
#
|
||||
# Имя Service обязано быть ровно "redis" (не redis-svc, как принято в остальных
|
||||
# релизах), иначе не сойдётся с CELERY_REDIS_HOST в backend.yaml и celery.yaml.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: pm
|
||||
|
||||
spec:
|
||||
interval: 10m
|
||||
|
||||
chart:
|
||||
spec:
|
||||
chart: universal-chart
|
||||
version: "0.1.9"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
interval: 10m
|
||||
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
|
||||
values:
|
||||
global:
|
||||
env: _default
|
||||
|
||||
services:
|
||||
redis:
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/redis:latest
|
||||
pullPolicy:
|
||||
_default: Always
|
||||
|
||||
deployment:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: redis
|
||||
|
||||
replicaCount:
|
||||
_default: 1
|
||||
|
||||
port:
|
||||
_default: 6379
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu:
|
||||
_default: 25m
|
||||
memory:
|
||||
_default: 64Mi
|
||||
|
||||
probes:
|
||||
liveness:
|
||||
enabled: false
|
||||
readiness:
|
||||
enabled: false
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
|
||||
name:
|
||||
_default: redis
|
||||
|
||||
type:
|
||||
_default: ClusterIP
|
||||
|
||||
port:
|
||||
_default: 6379
|
||||
|
||||
targetPort:
|
||||
_default: 6379
|
||||
|
||||
# НЕ http: чарт по умолчанию подставляет "http", и тогда Istio навесит
|
||||
# на 6379 HTTP-фильтры и сломает RESP. Префикс tcp- переводит порт
|
||||
# в режим обычного TCP-проксирования.
|
||||
portName:
|
||||
_default: tcp-redis
|
||||
|
||||
imagePullSecrets:
|
||||
enabled:
|
||||
_default: true
|
||||
name:
|
||||
_default: regcred
|
||||
@ -42,7 +42,8 @@ spec:
|
||||
|
||||
image:
|
||||
name:
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/workflows-engine:contour_3ef5b462
|
||||
_default: cr.yandex/crp3ccidau046kdj8g9q/workflows-engine:contour_a03d37da-dirty2
|
||||
|
||||
pullPolicy:
|
||||
_default: IfNotPresent
|
||||
|
||||
@ -161,23 +162,25 @@ spec:
|
||||
|
||||
- name: INTERNAL_PDM_URL
|
||||
value:
|
||||
_default: "http://documentations-api.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: INTERNAL_FILESTREAM_URL
|
||||
value:
|
||||
_default: "http://documentations-filestream.documentations.svc.cluster.local:8080"
|
||||
|
||||
_default: "http://backend-filestream-svc.documentations.svc.cluster.local:80"
|
||||
- name: IGNORE_TAINTS_AND_NODE_SELECTOR
|
||||
value:
|
||||
_default: "true"
|
||||
- name: EXTERNAL_PDM_URL
|
||||
value:
|
||||
_default: "http://documentations-api.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: EXTERNAL_FILESTREAM_URL
|
||||
value:
|
||||
_default: "http://documentations-filestream-service.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-filestream-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: RESOURCES_API_INTERNAL_HOST
|
||||
value:
|
||||
_default: "http://resources-service.resources.svc.cluster.local:8000"
|
||||
_default: "http://iam-backend.iam.svc.cluster.local:8000"
|
||||
|
||||
- name: ENABLE_SQL_QUERY
|
||||
value:
|
||||
|
||||
@ -165,7 +165,7 @@ spec:
|
||||
|
||||
- name: INTERNAL_FILESTREAM_URL
|
||||
value:
|
||||
_default: "http://documentations-filestream.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-filestream-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: EXTERNAL_PDM_URL
|
||||
value:
|
||||
|
||||
20
apps/rfi/d8-ugmk-prod/backend-s3.yaml
Normal file
20
apps/rfi/d8-ugmk-prod/backend-s3.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: rfi
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-rfi-s3: secrets/data/minio/apps/rfi
|
||||
vault.hashicorp.com/agent-inject-template-rfi-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/rfi" -}}
|
||||
YC_S3_ENDPOINT_URL=https://s3.uralmine.com
|
||||
YC_S3_BUCKET_NAME=sarex-rfi
|
||||
YC_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YC_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
{{- end -}}
|
||||
20
apps/rfi/d8-ugmk-prod/celery-s3.yaml
Normal file
20
apps/rfi/d8-ugmk-prod/celery-s3.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: celery
|
||||
namespace: rfi
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
celery:
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-rfi-s3: secrets/data/minio/apps/rfi
|
||||
vault.hashicorp.com/agent-inject-template-rfi-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/rfi" -}}
|
||||
YC_S3_ENDPOINT_URL=https://s3.uralmine.com
|
||||
YC_S3_BUCKET_NAME=sarex-rfi
|
||||
YC_S3_ACCESS_KEY_ID={{ index .Data.data "access_key" }}
|
||||
YC_S3_SECRET_ACCESS_KEY={{ index .Data.data "secret_key" }}
|
||||
{{- end -}}
|
||||
@ -9,3 +9,11 @@ patches:
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: frontend
|
||||
- path: backend-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: celery-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: celery
|
||||
|
||||
@ -50,7 +50,7 @@ spec:
|
||||
_default: 1
|
||||
|
||||
port:
|
||||
_default: 80
|
||||
_default: 8080
|
||||
|
||||
resources:
|
||||
requests:
|
||||
@ -78,7 +78,7 @@ spec:
|
||||
_default: 80
|
||||
|
||||
targetPort:
|
||||
_default: 80
|
||||
_default: 8080
|
||||
|
||||
portName:
|
||||
_default: http
|
||||
|
||||
@ -253,7 +253,7 @@ spec:
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://documentations-api.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
|
||||
@ -238,7 +238,7 @@ spec:
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://documentations-api.documentations.svc.cluster.local:8080"
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
|
||||
256
apps/transmittal/d8-ugmk-prod/backend-s3.yaml
Normal file
256
apps/transmittal/d8-ugmk-prod/backend-s3.yaml
Normal file
@ -0,0 +1,256 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: transmittal
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
backend:
|
||||
envs:
|
||||
- name: TRANSMITTAL_SERVICE_APP__NAME
|
||||
value:
|
||||
_default: "Transmittal Service"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__LOG_LEVEL
|
||||
value:
|
||||
_default: "ERROR"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend-svc.flows.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "30"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__HOST
|
||||
value:
|
||||
_default: "https://sarex.contour.infra.sarex.tech/transmittal"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__ENVIRONMENT
|
||||
value:
|
||||
_default: "prod"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_ORIGINS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_METHODS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_HEADERS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_CREDENTIALS
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__HOST
|
||||
value:
|
||||
_default: "0.0.0.0"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__PORT
|
||||
value:
|
||||
_default: "8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__ENABLE_AUTO_RELOAD
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__ENABLE
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__HOST
|
||||
value:
|
||||
_default: "http://signoz-otel-collector-external.signoz.svc.cluster.local:4317"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__SERVICE_NAME
|
||||
value:
|
||||
_default: "backend.transmittals-prod"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__INSECURE
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__SSL_MODE
|
||||
value:
|
||||
_default: "verify-full"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH
|
||||
value:
|
||||
_default: "/opt/.postgresql/root.crt"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__LOG_LEVEL
|
||||
value:
|
||||
_default: "info"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__NUM_WORKERS
|
||||
value:
|
||||
_default: "2"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__ROOT_PATH
|
||||
value:
|
||||
_default: ""
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__ENABLE_SSL
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RABBITMQ__HOST
|
||||
value:
|
||||
_default: "rabbitmq.rabbitmq.svc.cluster.local"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RABBITMQ__PORT
|
||||
value:
|
||||
_default: "5672"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend-svc.django.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://iam-backend.iam.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__MAX_POOL_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__CONNECT_TIMEOUT
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__READ_TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__REGION_NAME
|
||||
value:
|
||||
_default: "ru-central1"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__VERIFY
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__ENDPOINT
|
||||
value:
|
||||
_default: "s3.uralmine.com"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__USE_SSL
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__BASE_URL
|
||||
value:
|
||||
_default: "http://export-project-service.django.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__BASE_URL
|
||||
value:
|
||||
_default: "http://marks-service.documentations.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__BASE_URL
|
||||
value:
|
||||
_default: "https://api.mailgun.net/v3/mg.sarex.io"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__EMAIL
|
||||
value:
|
||||
_default: "hello@wb.io"
|
||||
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-transmittal-s3: secrets/data/minio/apps/transmittal
|
||||
vault.hashicorp.com/agent-inject-template-transmittal-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/transmittal" -}}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY={{ index .Data.data "access_key" }}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY={{ index .Data.data "secret_key" }}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__DEFAULT_BUCKET=sarex-tf-state
|
||||
{{- end -}}
|
||||
@ -8,3 +8,11 @@ patches:
|
||||
target:
|
||||
kind: Namespace
|
||||
name: transmittal
|
||||
- path: backend-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: backend
|
||||
- path: worker-s3.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: worker
|
||||
|
||||
256
apps/transmittal/d8-ugmk-prod/worker-s3.yaml
Normal file
256
apps/transmittal/d8-ugmk-prod/worker-s3.yaml
Normal file
@ -0,0 +1,256 @@
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: worker
|
||||
namespace: transmittal
|
||||
spec:
|
||||
values:
|
||||
services:
|
||||
worker:
|
||||
envs:
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend-svc.flows.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_FLOWS_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "30"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__NAME
|
||||
value:
|
||||
_default: "Transmittal Service"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__LOG_LEVEL
|
||||
value:
|
||||
_default: "ERROR"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__HOST
|
||||
value:
|
||||
_default: "https://lk.srx.wb.ru:30443/transmittal"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_APP__ENVIRONMENT
|
||||
value:
|
||||
_default: "prod"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_ORIGINS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_METHODS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_HEADERS
|
||||
value:
|
||||
_default: '["*"]'
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_CORS__ALLOW_CREDENTIALS
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__HOST
|
||||
value:
|
||||
_default: "0.0.0.0"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__PORT
|
||||
value:
|
||||
_default: "8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__ENABLE_AUTO_RELOAD
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__ENABLE
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__HOST
|
||||
value:
|
||||
_default: "http://signoz-otel-collector-external.signoz.svc.cluster.local:4317"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__SERVICE_NAME
|
||||
value:
|
||||
_default: "backend.transmittals-prod"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_OTEL__INSECURE
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__SSL_MODE
|
||||
value:
|
||||
_default: "verify-full"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__SSL_ROOT_CERT_PATH
|
||||
value:
|
||||
_default: "/opt/.postgresql/root.crt"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__LOG_LEVEL
|
||||
value:
|
||||
_default: "info"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__NUM_WORKERS
|
||||
value:
|
||||
_default: "2"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_UVICORN__ROOT_PATH
|
||||
value:
|
||||
_default: ""
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DATABASE__ENABLE_SSL
|
||||
value:
|
||||
_default: "false"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RABBITMQ__HOST
|
||||
value:
|
||||
_default: "rabbitmq.rabbitmq.svc.cluster.local"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RABBITMQ__PORT
|
||||
value:
|
||||
_default: "5672"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend.django.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_SAREX_BACKEND_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://resources-service.resources.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_RESOURCE_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__BASE_URL
|
||||
value:
|
||||
_default: "http://backend-api-svc.documentations.svc.cluster.local:80"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_DOCUMENTATIONS_REPOSITORY__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__MAX_POOL_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__CONNECT_TIMEOUT
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__READ_TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__REGION_NAME
|
||||
value:
|
||||
_default: "ru-central1"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__VERIFY
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__ENDPOINT
|
||||
value:
|
||||
_default: "s3.uralmine.com"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_S3_CLIENT__USE_SSL
|
||||
value:
|
||||
_default: "true"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__BASE_URL
|
||||
value:
|
||||
_default: "http://export-project-service.django.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_HTML_TO_PDF_CONVERTER__TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__BASE_URL
|
||||
value:
|
||||
_default: "http://marks-service.documentations.svc.cluster.local:8000"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MARKINGS__TIMEOUT
|
||||
value:
|
||||
_default: "50"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__BASE_URL
|
||||
value:
|
||||
_default: "https://api.mailgun.net/v3/mg.sarex.io"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__MAX_CONNECTIONS
|
||||
value:
|
||||
_default: "10"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__MAX_KEEPALIVE_CONNECTIONS
|
||||
value:
|
||||
_default: "5"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__TIMEOUT
|
||||
value:
|
||||
_default: "15"
|
||||
|
||||
- name: TRANSMITTAL_SERVICE_MAILGUN__EMAIL
|
||||
value:
|
||||
_default: "hello@wb.io"
|
||||
|
||||
podAnnotations:
|
||||
_default:
|
||||
vault.hashicorp.com/agent-inject-secret-transmittal-s3: secrets/data/minio/apps/transmittal
|
||||
vault.hashicorp.com/agent-inject-template-transmittal-s3: |-
|
||||
{{- with secret "secrets/data/minio/apps/transmittal" -}}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__ACCESS_KEY={{ index .Data.data "access_key" }}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__SECRET_KEY={{ index .Data.data "secret_key" }}
|
||||
TRANSMITTAL_SERVICE_S3_CLIENT__DEFAULT_BUCKET=sarex-tf-state
|
||||
{{- end -}}
|
||||
@ -1,141 +0,0 @@
|
||||
from .base import *
|
||||
|
||||
from logging.handlers import SysLogHandler
|
||||
|
||||
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
|
||||
|
||||
FILE_UPLOAD_PERMISSIONS = 0o644
|
||||
|
||||
DEBUG = False
|
||||
|
||||
CSRF_COOKIE_SECURE = True
|
||||
SESSION_COOKIE_SECURE = True
|
||||
SECURE_SSL_REDIRECT = False
|
||||
|
||||
# STATIC_ROOT = env('STATIC_ROOT')
|
||||
# MEDIA_ROOT = env('MEDIA_ROOT')
|
||||
|
||||
# --- Media / объектное хранилище S3 -----------------------------------------
|
||||
# Файлы (ортофото, облака точек, вложения) складываются в S3/MinIO кастомным
|
||||
# storage-бэкендом; иначе Django пишет их на локальный диск контейнера.
|
||||
DEFAULT_FILE_STORAGE = 'sarex.core.storages.CustomS3Boto3Storage'
|
||||
# CustomS3Boto3Storage.url() отдаёт абсолютный URL = HOST + MEDIA_URL + key.
|
||||
# В base.py HOST захардкожен на https://lk.sarex.io — переопределяем на наш
|
||||
# домен платформы (из SERVER_HOST env), иначе media-ссылки уйдут на чужой хост.
|
||||
# Верхний nginx проксирует /media/ в s3-proxy (тот отдаёт объекты из бакета).
|
||||
HOST = SERVER_HOST
|
||||
|
||||
# SECRET_KEY = env('SECRET_KEY')
|
||||
SECRET_KEY = 't2=9+($2f%7ptsdy4!rby$)mcfl1l%o2e@vs^d(g&(wwi&%k1v'
|
||||
|
||||
# DATABASE CONFIGURATION START
|
||||
# ------------------------------------------------------------------------------
|
||||
POSTGRES_DATABASE = env('DJANGO_POSTGRES_DATABASE')
|
||||
POSTGRES_USER = env('DJANGO_POSTGRES_USER')
|
||||
POSTGRES_PASSWORD = env('DJANGO_POSTGRES_PASSWORD')
|
||||
POSTGRES_HOST = env('DJANGO_POSTGRES_HOST')
|
||||
POSTGRES_PORTS = env('DJANGO_POSTGRES_PORTS', default="5432")
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django_prometheus.db.backends.postgresql',
|
||||
'NAME': POSTGRES_DATABASE,
|
||||
'USER': POSTGRES_USER,
|
||||
'PASSWORD': POSTGRES_PASSWORD,
|
||||
'HOST': POSTGRES_HOST,
|
||||
'PORT': POSTGRES_PORTS,
|
||||
}
|
||||
}
|
||||
|
||||
# DATABASE CONFIGURATION END
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '[contactor] %(levelname)s %(asctime)s %(message)s'
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
# Send all messages to console
|
||||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
# critical errors are logged to sentry
|
||||
'sentry': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'logging.StreamHandler',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
# This is the "catch all" logger
|
||||
'': {
|
||||
'handlers': ['console', 'sentry'],
|
||||
'level': 'DEBUG',
|
||||
'propagate': False,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
COMPARATOR_SECTION = env("COMPARATOR_SECTION", default="sarex-production-storage")
|
||||
|
||||
SIMPLE_JWT = {
|
||||
# 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
|
||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
|
||||
'ROTATE_REFRESH_TOKENS': True,
|
||||
'BLACKLIST_AFTER_ROTATION': False,
|
||||
'UPDATE_LAST_LOGIN': False,
|
||||
|
||||
'ALGORITHM': 'RS512',
|
||||
'SIGNING_KEY': env.str("JWT_PRIVATE_KEY").replace("\\n", "\n"),
|
||||
'VERIFYING_KEY': env.str("JWT_PUBLIC_KEY").replace("\\n", "\n"),
|
||||
'AUDIENCE': None,
|
||||
'ISSUER': SIMPLE_JWT_ISSUER,
|
||||
|
||||
'AUTH_HEADER_TYPES': ('Bearer',),
|
||||
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
|
||||
'USER_ID_FIELD': 'id',
|
||||
'USER_ID_CLAIM': 'user_id',
|
||||
|
||||
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
|
||||
'TOKEN_TYPE_CLAIM': 'token_type',
|
||||
|
||||
'JTI_CLAIM': 'jti',
|
||||
|
||||
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
|
||||
# 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
|
||||
'SLIDING_TOKEN_LIFETIME': timedelta(hours=1),
|
||||
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
|
||||
}
|
||||
|
||||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||||
|
||||
COMPARISON_API_URL = f"{WORKFLOWSSETTINGS.host}/comparisons"
|
||||
DOCUMENTATION_API_URL = f"{WORKFLOWSSETTINGS.host}/documentations"
|
||||
PDM_FILES_API_URL = f"{WORKFLOWSSETTINGS.host}/files"
|
||||
|
||||
# --- Override для self-hosted (auth_type=original) --------------------------
|
||||
# В base.py классическая SimpleJWT-аутентификация закомментирована (образ собран
|
||||
# под Zitadel), поэтому Bearer-токен от /api/token/ отвергается защищёнными
|
||||
# эндпоинтами. Возвращаем её первым классом; Session — для админки.
|
||||
REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"] = [
|
||||
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
||||
"rest_framework.authentication.SessionAuthentication",
|
||||
"rest_framework.authentication.BasicAuthentication",
|
||||
]
|
||||
|
||||
# --- Оставляем в сайдбаре только модуль «Съёмки» ----------------------------
|
||||
# Фронт показывает модуль, только если его uri есть в modules_list (= SAREX_MODULES).
|
||||
SAREX_MODULES = [
|
||||
{"name": "Съёмки", "uri": "/targets"},
|
||||
]
|
||||
@ -1,24 +0,0 @@
|
||||
[uwsgi]
|
||||
log-format = {"time": "%(time)", "method": "%(method)", "uri": "%(uri)", "status": "%(status)", "size": "%(size)", "addr": "%(addr)", "user": "%(user)", "proto": "%(proto)", "user_agent": "%(uagent)", "referer": "%(referer)", "trace_id": "%(trace_id)", "span_id": "%(span_id)"}
|
||||
module = config.wsgi:application
|
||||
DJANGO_SETTINGS_MODULE = config.settings.production
|
||||
# HTTP-протокол вместо uwsgi (nginx проксирует через proxy_pass, доступен напрямую)
|
||||
http-socket = 0.0.0.0:8000
|
||||
processes = 4
|
||||
master = true
|
||||
vacuum = true
|
||||
die-on-term = true
|
||||
enable-threads = true
|
||||
buffer-size = 65535
|
||||
stats = :3031
|
||||
stats-http = true
|
||||
memory-report = true
|
||||
lazy-apps = true
|
||||
listen = 1024
|
||||
disable-write-exception= 0
|
||||
harakiri = 300
|
||||
socket-timeout = 300
|
||||
chunked-input-timeout = 300
|
||||
http-timeout = 300
|
||||
worker-reload-mercy = 240
|
||||
mule-reload-mercy = 240
|
||||
@ -1,8 +0,0 @@
|
||||
# Слой 2: ресурсы, которым нужны CRD из слоя controllers.
|
||||
# Применяется только после того, как infra-controllers дошёл до Ready
|
||||
# (dependsOn в clusters/aero/infrastructure.yaml).
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
# Внутренний удостоверяющий центр контура: selfsigned → корневой CA → издатель.
|
||||
- ../../../infrastructure/cert-manager/aero/configs
|
||||
@ -1,18 +0,0 @@
|
||||
# Слой 1: чарты инфраструктуры. Только HelmRelease и Namespace — никаких
|
||||
# ресурсов, чьи CRD ставятся этими же чартами (см. clusters/aero/infrastructure.yaml).
|
||||
#
|
||||
# Порядок внутри слоя обеспечивают dependsOn в самих HelmRelease:
|
||||
# istiod и ingressgateway ждут istio-base, istio-config ждёт всех троих.
|
||||
#
|
||||
# local-path-provisioner намеренно НЕ подключён: в k3s он встроен и уже
|
||||
# обслуживает StorageClass local-path (по умолчанию). Чарт из репозитория
|
||||
# создал бы второй провижинер с тем же именем класса.
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../../infrastructure/cert-manager/aero
|
||||
- ../../../infrastructure/istio-base/aero
|
||||
- ../../../infrastructure/istio-pilot/aero
|
||||
- ../../../infrastructure/istio-gateway/aero
|
||||
- ../../../infrastructure/istio-config/aero
|
||||
- ../../../infrastructure/dashboard/aero
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
# This manifest was generated by flux. DO NOT EDIT.
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m0s
|
||||
ref:
|
||||
branch: master
|
||||
secretRef:
|
||||
name: flux-system
|
||||
url: http://gitea.flux-system.svc.cluster.local:3000/infra/iac.git
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
path: ./clusters/aero
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
@ -1,14 +0,0 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: yc-oci-charts
|
||||
namespace: flux-system
|
||||
spec:
|
||||
type: oci
|
||||
interval: 10m0s
|
||||
url: oci://cr.yandex/crp3ccidau046kdj8g9q/charts
|
||||
# Секрет создаёт роль sarex_stack из ключа сервисного аккаунта
|
||||
# (см. aero/roles/sarex_stack/templates/registry-secret.yaml.j2).
|
||||
secretRef:
|
||||
name: yc-cr-auth
|
||||
@ -1,41 +0,0 @@
|
||||
# Инфраструктура разделена на два слоя, и это не косметика.
|
||||
#
|
||||
# Flux делает dry-run всей Kustomization целиком перед применением. Если
|
||||
# положить cert-manager (который СТАВИТ CRD) и ClusterIssuer/Certificate
|
||||
# (которые ЭТИ CRD используют) в один слой, dry-run падает с
|
||||
# no matches for kind "Certificate" in version "cert-manager.io/v1"
|
||||
# и не применяется НИЧЕГО — включая сам cert-manager. Дедлок: CRD никогда не
|
||||
# появятся, потому что слой не может пройти проверку.
|
||||
#
|
||||
# Поэтому: controllers ставят чарты (и CRD), configs применяются после них
|
||||
# через dependsOn и содержат только пользовательские ресурсы.
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: infra-controllers
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
path: ./clusters/aero/controllers
|
||||
prune: true
|
||||
wait: true
|
||||
timeout: 10m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: infra-configs
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
path: ./clusters/aero/configs
|
||||
prune: true
|
||||
dependsOn:
|
||||
- name: infra-controllers
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
@ -1,7 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./flux-system
|
||||
- ./helm-repositories.yaml
|
||||
# Два слоя инфраструктуры с dependsOn — см. комментарий внутри файла.
|
||||
- ./infrastructure.yaml
|
||||
@ -9,15 +9,6 @@ spec:
|
||||
name: letsencrypt
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
solvers:
|
||||
- selector:
|
||||
dnsNames:
|
||||
- zitadel.test.sarex.brusnika.tech
|
||||
- grafana.test.sarex.brusnika.tech
|
||||
- openobserve.test.sarex.brusnika.tech
|
||||
- vmalert.test.sarex.brusnika.tech
|
||||
http01:
|
||||
ingress:
|
||||
class: istio
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
class: istio
|
||||
|
||||
@ -4,8 +4,9 @@ metadata:
|
||||
name: sarex-wildcard
|
||||
namespace: d8-ingress-istio
|
||||
spec:
|
||||
commonName: "*.uralmine.com"
|
||||
commonName: "*.sarex-k8s.uralmine.com"
|
||||
dnsNames:
|
||||
- "*.sarex-k8s.uralmine.com"
|
||||
- "*.uralmine.com"
|
||||
issuerRef:
|
||||
group: cert-manager.io
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: gitea-cert
|
||||
namespace: istio-system
|
||||
spec:
|
||||
dnsNames:
|
||||
- gitea.invest.cps.sarex.lonsdaleites.ru
|
||||
issuerRef:
|
||||
kind: ClusterIssuer
|
||||
name: letsencrypt-prod
|
||||
secretName: gitea-tls-secret
|
||||
---
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: gitea-gateway
|
||||
namespace: gateway
|
||||
spec:
|
||||
selector:
|
||||
istio: ingressgateway
|
||||
servers:
|
||||
- hosts:
|
||||
- gitea.invest.cps.sarex.lonsdaleites.ru
|
||||
port:
|
||||
name: http
|
||||
number: 80
|
||||
protocol: HTTP
|
||||
- hosts:
|
||||
- gitea.invest.cps.sarex.lonsdaleites.ru
|
||||
port:
|
||||
name: https
|
||||
number: 443
|
||||
protocol: HTTPS
|
||||
tls:
|
||||
credentialName: gitea-tls-secret
|
||||
mode: SIMPLE
|
||||
---
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: gitea-virt-service
|
||||
namespace: gitea
|
||||
spec:
|
||||
gateways:
|
||||
- gateway/gitea-gateway
|
||||
hosts:
|
||||
- gitea.invest.cps.sarex.lonsdaleites.ru
|
||||
http:
|
||||
- match:
|
||||
- uri:
|
||||
prefix: /
|
||||
route:
|
||||
- destination:
|
||||
host: gitea
|
||||
port:
|
||||
number: 3000
|
||||
@ -1,14 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../../infrastructure/vault
|
||||
- ./gitea-istio.yaml
|
||||
- ./vault-istio.yaml
|
||||
patches:
|
||||
- path: ./patches/vault.yaml
|
||||
target:
|
||||
group: helm.toolkit.fluxcd.io
|
||||
version: v2
|
||||
kind: HelmRelease
|
||||
name: vault
|
||||
namespace: vault
|
||||
@ -1,57 +0,0 @@
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: vault-cert
|
||||
namespace: istio-system
|
||||
spec:
|
||||
dnsNames:
|
||||
- vault.invest.cps.sarex.lonsdaleites.ru
|
||||
issuerRef:
|
||||
kind: ClusterIssuer
|
||||
name: letsencrypt-prod
|
||||
secretName: vault-tls
|
||||
---
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: Gateway
|
||||
metadata:
|
||||
name: vault-gateway
|
||||
namespace: gateway
|
||||
spec:
|
||||
selector:
|
||||
istio: ingressgateway
|
||||
servers:
|
||||
- hosts:
|
||||
- vault.invest.cps.sarex.lonsdaleites.ru
|
||||
port:
|
||||
name: http
|
||||
number: 80
|
||||
protocol: HTTP
|
||||
- hosts:
|
||||
- vault.invest.cps.sarex.lonsdaleites.ru
|
||||
port:
|
||||
name: https
|
||||
number: 443
|
||||
protocol: HTTPS
|
||||
tls:
|
||||
credentialName: vault-tls
|
||||
mode: SIMPLE
|
||||
---
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vault-virt-service
|
||||
namespace: vault
|
||||
spec:
|
||||
gateways:
|
||||
- gateway/vault-gateway
|
||||
hosts:
|
||||
- vault.invest.cps.sarex.lonsdaleites.ru
|
||||
http:
|
||||
- match:
|
||||
- uri:
|
||||
prefix: /
|
||||
route:
|
||||
- destination:
|
||||
host: vault-vault-contour.vault.svc.cluster.local
|
||||
port:
|
||||
number: 8200
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user