From 7b63f123475e2844346588186ec4d6ba192aadab Mon Sep 17 00:00:00 2001 From: Repinoid Date: Fri, 2 Oct 2026 08:07:58 +0300 Subject: [PATCH] =?UTF-8?q?docs(crud):=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=20=C2=AB=D0=A7=D1=82=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D1=91=D1=82=20=D1=81=D0=B0=D0=BC=C2=BB=20+=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0=B0=20=D1=83=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=BC=D1=91=D0=BD=20=D0=97=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=D0=BB=D0=B0=D0=B4=D0=B5=D0=BB=D1=8C=D1=86?= =?UTF-8?q?=D0=B0:=20=D0=B2=20README=20=D0=BD=D0=B5=20=D0=B1=D1=8B=D0=BB?= =?UTF-8?q?=D0=BE=20=D0=B2=D0=B8=D0=B4=D0=BD=D0=BE,=20=D0=BA=D0=B0=D0=BA?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= =?UTF-8?q?=D1=8B=20=D1=8E=D0=B7=D0=B5=D1=80=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D1=91=D1=82=20=D0=A1=D0=92=D0=9E=D0=98=D0=9C=D0=98=20=D0=B7?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8,=20?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B5=20=D1=81=D0=BA=D0=B0=D0=B7=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=BF=D1=80=D0=BE=20=D1=83=D0=BD=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=B4=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B8=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=81=D0=B0.=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=20(=D1=81=D1=80=D0=B0=D0=B7=D1=83=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BB=D0=B5=20=C2=AB=D0=9A=D0=B0=D0=BA=20=D1=8D?= =?UTF-8?q?=D1=82=D0=BE=20=D1=83=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BD=D0=BE?= =?UTF-8?q?=C2=BB):=20-=20=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F:=20api=5Ftoken=20(pg+apps),=20realm=20(pg+apps,=20?= =?UTF-8?q?=D0=BE=D0=B4=D0=BD=D0=BE=20=D0=B8=20=D1=82=D0=BE=20=D0=B6=D0=B5?= =?UTF-8?q?),=20=20=20s3=5Fname=20(pg)=20+=20=D0=BA=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D0=BD=D0=B4=D1=8B=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20terraform.tfvars=20=D0=B2=20=D0=BE=D0=B1=D0=B5=D0=B8?= =?UTF-8?q?=D1=85=20=D0=BF=D0=B0=D0=BF=D0=BA=D0=B0=D1=85;=20-=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B0,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BD=D1=83=D0=B6=D0=BD=D0=BE=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=B4=D1=83=D0=BC=D0=B0=D1=82=D1=8C:=20pg=5Fresource=5Fn?= =?UTF-8?q?ame=20=D0=B8=20*=5Fresource=5Fname=20=D0=BF=D1=80=D0=B8=D0=BB?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B9=20=E2=80=94=20=20=20=D1=83?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B0=D1=85=20=D1=81=D1=82?= =?UTF-8?q?=D0=B5=D0=BD=D0=B4=D0=B0;=20pg=5Fusername/pg=5Fdb=5Fname=20?= =?UTF-8?q?=E2=80=94=20=D0=B2=20=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D1=85=20=D0=BA=D0=BB=D0=B0=D1=81=D1=82=D0=B5=D1=80=D0=B0=20=20?= =?UTF-8?q?=20(=D1=81=D0=BB=D1=83=D0=B6=D0=B5=D0=B1=D0=BD=D1=8B=D0=B5=20ad?= =?UTF-8?q?min/postgres/standby=20=D0=BF=D0=BB=D0=B0=D1=82=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=20=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D1=82);=20*=5Fdomain=20=E2=80=94=20=D1=83=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=20=20=20=D0=B2=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BB=D0=B0=D0=BA=D0=B5;=20-=20=D0=BF=D0=BE=D1=87=D0=B5?= =?UTF-8?q?=D0=BC=D1=83:=20adopt=5Fexisting=5Fon=5Fcreate=20=D0=B8=D1=89?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B8=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=81=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=B2=D0=BD?= =?UTF-8?q?=D1=83=D1=82=D1=80=D0=B8=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=20=20=20(provider/internal/resources=5Fcore/crud.go:171,?= =?UTF-8?q?=20provider/internal/core/refsvc=5Ffind.go:47),=20=20=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=8D=D1=82=D0=BE=D0=BC=D1=83=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BD=D1=8F=D1=82=D0=BE=D0=BC=20=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B0=D0=B9=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=20=D0=BD=D0=B5=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D1=91?= =?UTF-8?q?=D1=82=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=83=D1=80=D1=81,=20=D0=B0=20=D1=83=D1=81=D1=8B=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=20=20=20=D1=81=D1=83=D1=89=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D1=83=D1=8E=D1=89=D0=B8=D0=B9;=20=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=20adopt=20=E2=80=94=20=D0=BF=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=20=D1=81=20=C2=AB=D1=83=D0=B6=D0=B5=20=D1=81=D1=83?= =?UTF-8?q?=D1=89=D0=B5=D1=81=D1=82=D0=B2=D1=83=D0=B5=D1=82=C2=BB.=20?= =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80:=20tflucee/tfflask/=20=20?= =?UTF-8?q?=20tfnodejs=20=D0=B7=D0=B0=D0=BD=D1=8F=D1=82=D1=8B=20=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D1=8B=D0=BC=D0=B8=20=D0=B8=D0=BD=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D1=81=D0=B0=D0=BC=D0=B8=20(apps/locals.tf:45,57,68?= =?UTF-8?q?);=20-=20=D1=87=D1=82=D0=BE=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=B2=D0=B0=D1=82=D1=8C?= =?UTF-8?q?:=20=D0=BF=D0=B5=D1=80=D0=B5=D1=87=D0=B8=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B4=D0=B5=D1=84=D0=BE=D0=BB=D1=82=D1=8B=20pg/?= =?UTF-8?q?main.tf=20=D0=B8=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D1=8B?= =?UTF-8?q?=20=D0=B2=20apps/locals.tf.=20=D0=98=D0=B7=20=D1=88=D0=B0=D0=B3?= =?UTF-8?q?=D0=BE=D0=B2=201=20=D0=B8=203=20=D1=83=D0=B1=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D1=8B=20=D0=B4=D1=83=D0=B1=D0=BB=D0=B8=D1=80=D1=83=D1=8E=D1=89?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=8B=20?= =?UTF-8?q?=E2=80=94=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BB=D0=BA=D0=B0=20=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB,=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=B8=D0=B8=20=D0=B2=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD=D0=B4=D0=B0=D1=85=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20(=C2=AB=D1=81=D0=BC.=20=D1=82?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=83=20=D0=BD=D0=B8=D0=B6=D0=B5?= =?UTF-8?q?=C2=BB=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82=D0=B2=D1=83=D0=B5=D1=82).?= =?UTF-8?q?=20=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=B5=D0=BD=D0=BE:=2019?= =?UTF-8?q?0=20=D1=81=D1=82=D1=80=D0=BE=D0=BA,=2014=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=BA=20=D1=81=20=D0=B1=D0=BB=D0=BE=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=BA=D0=BE=D0=B4=D0=B0=20(=D1=87=D1=91=D1=82=D0=BD?= =?UTF-8?q?=D0=BE),=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TEST_STAND/CRUD/README.md | 63 +++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/TEST_STAND/CRUD/README.md b/TEST_STAND/CRUD/README.md index 650f1e1..e07afac 100644 --- a/TEST_STAND/CRUD/README.md +++ b/TEST_STAND/CRUD/README.md @@ -26,6 +26,51 @@ CRUD/ --- +## Что пользователь задаёт сам + +### Обязательные значения (без них `apply` не пройдёт) + +| Переменная | Где | Что это | +|---|---|---| +| `api_token` | `pg/terraform.tfvars` и `apps/terraform.tfvars` | токен Nubes: ЛК → Профиль → Токены → создать «Технический» | +| `realm` | там же, **одно и то же значение** | ресурсная платформа (кластер Kubernetes), например `k8s-4-sandbox-nubes-ru`; в `apps/` обязан совпасть с `pg/`, иначе приложения не увидят кластер с базой | +| `s3_name` | `pg/terraform.tfvars` | имя (или UUID) экземпляра S3 для бэкапов: ЛК → S3 | + +Файлы создаются из примеров и нужны в обеих папках: + +```bash +cd pg && cp terraform.tfvars.example terraform.tfvars +cd ../apps && cp terraform.tfvars.example terraform.tfvars +``` + +### Имена: придумать самому, и они обязаны быть уникальными + +| Имя | Где задаётся | Правило | +|---|---|---| +| `pg_resource_name` (кластер) | `pg/terraform.tfvars` | уникально **в пределах стенда** | +| `pg_username`, `pg_db_name` | `pg/terraform.tfvars` | уникальны в пределах кластера; служебные имена (`admin`, `postgres`, `standby`) платформа не примет | +| `lucee_resource_name`, `flask_resource_name`, `nodejs_resource_name` | `apps/locals.tf` | уникальны **в пределах стенда** | +| `lucee_domain`, `flask_domain`, `nodejs_domain` | `apps/locals.tf` | уникальны **в облаке** — один домен нельзя повесить на два инстанса | + +Почему это важно: все ресурсы создаются с `adopt_existing_on_create = true`, а провайдер ищет +инстанс **по имени внутри своего сервиса** (`provider/internal/resources_core/crud.go:171`, +`provider/internal/core/refsvc_find.go:47`). Если такое имя уже занято, он не станет создавать +новый ресурс, а **усыновит** существующий — то есть при занятом имени можно подцепить чужой или +старый инстанс. Если усыновление отключено, `apply` упадёт с «инстанс с resource_name … уже +существует». + +Живой пример: прежние имена `tflucee`, `tfflask`, `tfnodejs` заняты старыми инстансами, +поэтому в стенде взяты `lucee-crud`, `flask-crud`, `nodejs-crud` (`apps/locals.tf:45,57,68`). + +### Можно не задавать (есть значения по умолчанию) + +`pg/main.tf`: `pg_cpu=500`, `pg_memory=512`, `pg_replicas=1`, `pg_disk=10`, `pg_version="17"`, +`pg_retain=14`, `pg_schedule="0 0 * * *"`, `pg_timeout="11m"`, `pg_username="user4crudpg"`, +`pg_role="ddl_user"`, `pg_db_name="db4crudpg"`. Размеры приложений (`*_cpu`, `*_memory`, +`*_replicas`) — в `apps/locals.tf`. + +--- + ## Запуск — три шага ### 1. База данных (`pg/`) @@ -33,18 +78,15 @@ CRUD/ ```bash cd pg cp terraform.tfvars.example terraform.tfvars -# отредактировать terraform.tfvars (см. таблицу ниже) +# заполнить api_token, realm, s3_name (раздел «Что пользователь задаёт сам») terraform init terraform apply ``` Создадутся кластер (несколько минут), пользователь БД и база. -| Переменная (`pg/terraform.tfvars`) | Где взять | -|---|---| -| `api_token` | ЛК → Профиль → Токены → «Технический» | -| `realm` | ЛК → Кластеры (например `k8s-4-sandbox-nubes-ru`) | -| `s3_name` | ЛК → S3 → имя экземпляра (для бэкапов) | +Обязательные значения — `api_token`, `realm`, `s3_name`. Полный список и правила по именам — +в разделе «Что пользователь задаёт сам» выше. ### 2. Передать креды БД в `apps/` @@ -65,18 +107,15 @@ terraform output -json > ../apps/creds.json ```bash cd ../apps cp terraform.tfvars.example terraform.tfvars -# отредактировать terraform.tfvars (см. таблицу ниже) +# заполнить api_token и realm — те же, что в pg/ terraform init terraform apply ``` Создадутся три приложения, подключённые к общей БД. -| Что заполнить/проверить | Файл | Зачем | -|---|---|---| -| `api_token` | `apps/terraform.tfvars` | тот же, что в `pg/` | -| `realm` | `apps/terraform.tfvars` | должен совпадать с БД | -| `lucee_domain`, `flask_domain`, `nodejs_domain` | `apps/locals.tf` | имена доменов — должны быть **уникальны** в облаке | +Обязательные значения — `api_token` и `realm` (те же, что в `pg/`). Имена доменов нужно +придумать самому, они должны быть уникальны в облаке — см. раздел «Что пользователь задаёт сам». ---