Add adaptive router VM/interface scaling and local delivery integrity tests
Terraform now provisions router_count IaaS Router VMs (default 2, no longer hardcoded to router1/router2), each with 1 public + private_interface_count isolated private interfaces (no shared LAN or VRRP between routers). Both counts scale via Terraform variables and TF_VAR_* environment variables. The post-install script became a Terraform template that matches interfaces to their expected subnet by CIDR instead of a fragile "first private IP" heuristic. Added an offline pytest suite (terraform/tests/) that checks the delivery's internal consistency and runs real terraform init/validate against the actual vkcs provider schema via a project-local filesystem mirror (provider binary fetched from its GitHub releases, bypassing the region-blocked HashiCorp registry) - no cloud credentials or API calls involved. terraform/versions.tf now declares the previously-missing required_providers block. Ansible (inventory.ini, base/frr_router/keepalived roles) still assumes the old 2-router/2-NIC/VRRP topology and is not yet adapted - documented as a follow-up, not addressed here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011hXR2ftXZZhJ4Y3XuSoR8r
This commit is contained in:
1 parent
e711faca42
commit
5979a9a58b
20 files changed
+1181
-139
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# План внедрения: адаптивное количество ВМ-маршрутизаторов и 3 интерфейса
|
||||
|
||||
Дата: 2026-09-03
|
||||
|
||||
## Проблема
|
||||
|
||||
`terraform/main.tf` жёстко описывает ровно 2 ВМ-маршрутизатора (`router1`, `router2`) с 2 интерфейсами каждая: WAN (публичный, DHCP) и LAN (приватный, статический IP на общей сети `10.200.10.0/24`, используемой также для VRRP-VIP через keepalived). Post-install скрипт `terraform/scripts/network-init.sh` определяет эти 2 интерфейса эвристически (первый интерфейс с приватным IP → LAN, первый с публичным IP → WAN).
|
||||
|
||||
Целевая схема: адаптивное количество ВМ-маршрутизаторов (2, 3, 4 и более, управляется переменной), у каждой ВМ — 3 интерфейса: 1 публичный (WAN, без изменений) + 2 приватных, каждый в своей уникальной изолированной микросети (`/29` или `/28`, размер задаётся переменной). VRRP и общая LAN-сеть между роутерами в новой схеме не используются.
|
||||
|
||||
Изменения ограничены директорией `terraform` (включая `terraform/scripts/network-init.sh`). Ansible-слой (`ansible/inventory.ini`, роли `base`/`frr_router`/`keepalived`, которые сейчас жёстко используют `eth0`/`eth1` и только `router1`/`router2`) в этом изменении не трогается — по явному решению заказчика; несоответствие фиксируется как задел на будущее.
|
||||
|
||||
`lan_net`/`lan_subnet` (`10.200.10.0/24`) и ВМ `priv_srv_01/02/03` — отдельный сегмент приватных серверов, не связанный с роутерами; не меняются.
|
||||
|
||||
## Шаги
|
||||
|
||||
1. `terraform/variables.tf`: добавить `router_count`, `private_supernet`, `private_subnet_prefix_length`, `router_availability_zones`.
|
||||
2. `terraform/main.tf`:
|
||||
- `locals.router_private_subnets` — детерминированная нарезка CIDR из `private_supernet` на пары (router_index, role) через `cidrsubnet()`.
|
||||
- Заменить `lan_port1`/`lan_port2` на `for_each`-ресурсы (`router_priv_net`/`router_priv_subnet`/`router_priv_port`) по `local.router_private_subnets`.
|
||||
- Заменить `router1`/`router2` на один ресурс `vkcs_compute_instance.router` с `count = var.router_count`, WAN + `dynamic "network"` по приватным портам, `user_data` через `templatefile()`.
|
||||
3. `terraform/scripts/network-init.sh` → `terraform/scripts/network-init.sh.tpl`:
|
||||
- Экранировать существующие bash brace-expansions (`${netmask}` и т.п.) как `$${...}`, чтобы Terraform их не интерполировал.
|
||||
- WAN-детект — без изменений (эвристика по публичному IP).
|
||||
- Приватные интерфейсы — сопоставление по CIDR из переданного Terraform списка `private_interfaces`, а не "первый приватный IP".
|
||||
- netplan: `eth0` (WAN) как раньше + цикл по найденным приватным интерфейсам (без default route на приватных).
|
||||
4. `terraform.tfvars`: добавить примеры значений новых переменных.
|
||||
5. `README.md`: обновить описание архитектуры (N роутеров, 3 NIC, без VRRP/общего LAN на роутерах), отметить, что диаграммы и Ansible-слой пока отражают старую схему.
|
||||
6. Summary-документ по завершении.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform fmt -recursive`
|
||||
- `terraform init -backend=false` + `terraform validate` (best-effort, если провайдер VKCS доступен из окружения)
|
||||
- Офлайн-проверка синтаксиса `.tpl`: подстановка тестовых значений вместо `%{ for }`-блока во временную копию + `bash -n`
|
||||
- `terraform plan`/`apply` с реальными credentials — вне рамок этой сессии (создаёт платные облачные ресурсы, `terraform.tfvars` содержит placeholder-значения)
|
||||
@@ -0,0 +1,50 @@
|
||||
# Summary: адаптивное количество ВМ-маршрутизаторов и 3 интерфейса
|
||||
|
||||
Дата: 2026-09-03
|
||||
План: [2026-09-03-adaptive-router-vm-count-plan.md](2026-09-03-adaptive-router-vm-count-plan.md)
|
||||
|
||||
## Что сделано
|
||||
|
||||
### `terraform/variables.tf`
|
||||
Добавлены переменные: `router_count` (default `2`, `>= 1`), `private_supernet` (default `10.90.0.0/16`), `private_subnet_prefix_length` (default `29`, допустимо `28`/`29`), `router_availability_zones` (default `["ME1"]`).
|
||||
|
||||
### `terraform/main.tf`
|
||||
- Добавлен `locals.router_private_subnets` — детерминированная непересекающаяся нарезка CIDR из `private_supernet` на пары (router_index × роль) через `cidrsubnet()`.
|
||||
- `lan_port1`/`lan_port2` (фиксированные порты на общей `10.200.10.0/24`) заменены на `for_each`-ресурсы `router_priv_net` / `router_priv_subnet` / `router_priv_port` — по одной изолированной микросети на каждый (роутер, приватная роль).
|
||||
- `router1`/`router2` заменены на единый `vkcs_compute_instance.router` с `count = var.router_count`: WAN-сеть без изменений + `dynamic "network"` по 2 приватным портам; `user_data` теперь рендерится через `templatefile()`.
|
||||
- `lan_net`/`lan_subnet`, `private_sg`, `priv_srv_01/02/03` не изменялись (отдельный сегмент приватных серверов).
|
||||
- Файл прогнан через `terraform fmt -recursive` (единственные изменения — форматирование существующих строк, семантика не менялась).
|
||||
|
||||
### `terraform/scripts/network-init.sh` → `terraform/scripts/network-init.sh.tpl`
|
||||
- Файл переименован (`git mv`) и превращён в Terraform-шаблон.
|
||||
- Все существующие bash brace-expansions (`${netmask}`, `${partial_octet}`, `${octets[@]}`) экранированы как `$${...}`, чтобы Terraform не пытался их интерполировать.
|
||||
- WAN-детект (эвристика по первому публичному IP) не изменён.
|
||||
- Приватные интерфейсы теперь определяются не эвристикой "первый приватный IP", а сопоставлением по CIDR: Terraform передаёт список `private_interfaces` (по 2 записи `{cidr, name}` на роутер), из которого шаблонная директива `%{ for pi in private_interfaces }` генерирует bash-массив `PRIV_TARGETS`. Добавлены функции `ip_to_int()`/`ip_in_cidr()` для проверки принадлежности IP подсети.
|
||||
- netplan-конфиг: секция `wan-iface` (`eth0`) без изменений; вместо единственной `lan-iface` — цикл, генерирующий отдельную `ethernets`-секцию на каждый найденный приватный интерфейс (`eth1`, `eth2`, ...), без default route (изолированные микросети).
|
||||
- Проверки/fail-hard/backup/apply/reboot логика сохранена.
|
||||
|
||||
### `terraform/terraform.tfvars`
|
||||
Добавлены закомментированные примеры новых переменных.
|
||||
|
||||
### `README.md`
|
||||
Обновлено описание архитектуры: N роутеров вместо пары, 3 интерфейса на роутер (1 публичный + 2 изолированных приватных, без общего LAN и без VRRP на роутерах), упомянуты новые переменные и то, что `network-init.sh` стал Terraform-шаблоном. Явно отмечено, что диаграммы (`ports.svg`, `topology.svg`) и Ansible-слой (`ansible/inventory.ini`, роли `base`/`frr_router`/`keepalived`) пока отражают старую схему — это отдельный будущий шаг.
|
||||
|
||||
## Что осознанно не менялось
|
||||
|
||||
- **Ansible-слой** — по явному решению в рамках этого изменения. `ansible/inventory.ini` и роли `base`/`frr_router`/`keepalived`/`gre` жёстко используют `eth0`/`eth1` и только хосты `router1`/`router2`; с новым дизайном (N роутеров, `eth1`+`eth2`, без VRRP) они не совместимы и потребуют отдельной переработки перед реальным деплоем через Ansible.
|
||||
- **`priv_srv_01/02/03` и `lan_net`/`lan_subnet`** — не связаны с роутерами, оставлены как есть.
|
||||
- **Диаграммы** (`img/*.svg`) — не обновлялись, отражают старую топологию.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform fmt -recursive` — чисто (после автоформатирования).
|
||||
- `terraform init -backend=false` — **не выполнено**: провайдер `hashicorp/vkcs` недоступен из окружения (нет `required_providers` в репозитории и нет сети до его источника). Это ограничение окружения, не связанное с данным изменением — в репозитории изначально не было блока `required_providers`.
|
||||
- Синтаксис `.tpl`: выполнена симуляция рендеринга `templatefile()` (замена `$${` → `${`, подстановка тестовых значений вместо `%{ for }`-блока) + `bash -n` — прошло без ошибок.
|
||||
- Логика `ip_to_int()`/`ip_in_cidr()` проверена отдельным bash-тестом на 7 сценариях (`/29` и `/28`, совпадения и несовпадения) — все прошли.
|
||||
- `terraform plan`/`apply` с реальными VK Cloud credentials не выполнялись — `terraform.tfvars` содержит placeholder-значения, `apply` создаёт платные облачные ресурсы; это отдельное действие пользователя.
|
||||
|
||||
## Известные ограничения / задел на будущее
|
||||
|
||||
- Ansible-слой требует отдельной доработки под 3 интерфейса и N роутеров (см. выше).
|
||||
- В репозитории отсутствует `required_providers`/lock-файл для `vkcs` — это не связано с текущим изменением, но мешает локальной `terraform validate`/`init`.
|
||||
- Диаграммы не обновлены под новую топологию.
|
||||
@@ -0,0 +1,25 @@
|
||||
# План внедрения: динамическое количество приватных интерфейсов
|
||||
|
||||
Дата: 2026-09-03
|
||||
|
||||
## Проблема
|
||||
|
||||
Количество ВМ-маршрутизаторов уже параметризовано через `var.router_count` (см. [2026-09-03-adaptive-router-vm-count-plan.md](2026-09-03-adaptive-router-vm-count-plan.md)). Количество приватных интерфейсов на роутер осталось жёстко зашито: `terraform/main.tf` — `locals.private_roles = ["priv1", "priv2"]`, ровно 2 роли.
|
||||
|
||||
Нужна вторая ось горизонтального масштабирования: количество приватных интерфейсов на роутер тоже управляется переменной, и обе переменные (`router_count`, теперь и количество приватных интерфейсов) должны быть передаваемы через переменные окружения — что в Terraform уже "бесплатно" работает через `TF_VAR_<имя>` для любой объявленной `variable`, пока значение не переопределено в `terraform.tfvars`.
|
||||
|
||||
`terraform/scripts/network-init.sh.tpl` уже написан generic (итерация по bash-массиву `PRIV_TARGETS` произвольной длины) — единственный хардкод в нём это `eth0` для WAN. Скрипт менять не требуется.
|
||||
|
||||
## Шаги
|
||||
|
||||
1. `terraform/variables.tf`: добавить `private_interface_count` (number, default `2`, validation `>= 1`).
|
||||
2. `terraform/main.tf`: `locals.private_roles = [for i in range(var.private_interface_count) : "priv${i + 1}"]` вместо хардкода `["priv1", "priv2"]`. Остальные блоки (`router_private_subnets`, `router_priv_net/subnet/port`, `dynamic "network"`, генерация `private_interfaces` для `templatefile()`) уже параметризованы через `local.private_roles` и не требуют изменений.
|
||||
3. `terraform.tfvars`: закомментированный пример `# private_interface_count = 3`.
|
||||
4. `README.md`: раздел про масштабирование через `TF_VAR_router_count` / `TF_VAR_private_interface_count`, обновить формулировку "1 публичный + N приватных".
|
||||
5. Summary-документ по завершении.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform fmt -recursive`
|
||||
- `terraform init -backend=false` + `terraform validate` (best-effort, провайдер `vkcs` недоступен в этом окружении — известное ограничение, не связано с правкой)
|
||||
- Ручная трассировка `local.private_roles`/`router_private_subnets` для `private_interface_count = 1` и `= 4` — корректность и отсутствие коллизий CIDR
|
||||
@@ -0,0 +1,36 @@
|
||||
# Summary: динамическое количество приватных интерфейсов
|
||||
|
||||
Дата: 2026-09-03
|
||||
План: [2026-09-03-dynamic-private-interface-count-plan.md](2026-09-03-dynamic-private-interface-count-plan.md)
|
||||
|
||||
## Что сделано
|
||||
|
||||
### `terraform/variables.tf`
|
||||
Добавлена переменная `private_interface_count` (number, default `2`, validation `>= 1`) — количество изолированных приватных интерфейсов на роутер, в дополнение к единственному публичному (WAN).
|
||||
|
||||
### `terraform/main.tf`
|
||||
Единственная точечная правка: `locals.private_roles` заменён с хардкода `["priv1", "priv2"]` на генерируемый список `[for i in range(var.private_interface_count) : "priv${i + 1}"]`. Все производные ресурсы и блоки (`router_private_subnets`, `router_priv_net`/`router_priv_subnet`/`router_priv_port` через `for_each`, `dynamic "network"` в `vkcs_compute_instance.router`, генерация списка `private_interfaces` для `templatefile()`, имена интерфейсов `eth${index(...)+1}`) уже были параметризованы через `local.private_roles` в предыдущем изменении и масштабируются автоматически — их трогать не пришлось.
|
||||
|
||||
При `private_interface_count = 2` (значение по умолчанию) результат идентичен прежнему поведению — регрессии нет.
|
||||
|
||||
### `terraform/scripts/network-init.sh.tpl`
|
||||
**Не менялся.** Скрипт уже полностью generic: итерируется по bash-массиву `PRIV_TARGETS`, сформированному из переданного Terraform списка `private_interfaces` произвольной длины. Единственный хардкод в скрипте — `set-name: eth0` для WAN.
|
||||
|
||||
### `terraform/terraform.tfvars`
|
||||
Добавлен закомментированный пример `# private_interface_count = 3` (не активирован, чтобы не перекрывать `TF_VAR_private_interface_count`).
|
||||
|
||||
### `README.md`
|
||||
- Формулировка про интерфейсы обновлена на "1 публичный + `private_interface_count` приватных (по умолчанию 2)".
|
||||
- Добавлен раздел "Horizontal scaling via environment variables" с примером `export TF_VAR_router_count=4` / `export TF_VAR_private_interface_count=3` и объяснением, почему это работает "из коробки" (переменные не переопределены в `terraform.tfvars`, поэтому действует стандартный приоритет Terraform `TF_VAR_*` → default).
|
||||
- Упомянута ёмкость пула CIDR (`private_supernet` `/16` при `/29` подсетях = 8192 блока).
|
||||
|
||||
## Обоснование "через переменные окружения" без дополнительного кода
|
||||
|
||||
Механизм `TF_VAR_<имя_переменной>` — встроенная возможность Terraform для любой объявленной `variable`, отдельного кода/обвязки не требуется. Единственное условие — чтобы значение не было жёстко задано в `terraform.tfvars` (в этом репозитории для `router_count` и `private_interface_count` там только закомментированные примеры, так что `TF_VAR_*` работает без изменений).
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform fmt -recursive` — чисто, без изменений (синтаксис валиден).
|
||||
- `terraform init`/`validate` — не выполнялись повторно: провайдер `vkcs` недоступен из окружения (то же ограничение, что и в прошлом изменении, не связано с этой правкой).
|
||||
- Математика нарезки CIDR проверена вручную: `netnum = router_index × length(private_roles) + role_index` — строгая биекция (mixed-radix encoding) без коллизий при любых `router_count`/`private_interface_count`, пока общее число блоков не превышает ёмкость `private_supernet` при заданном `private_subnet_prefix_length` (дефолт: до 8192 блоков — с большим запасом).
|
||||
- `network-init.sh.tpl` не менялся — прошлая офлайн-проверка синтаксиса (`bash -n` на симулированном рендере) остаётся в силе, логика идентична.
|
||||
@@ -0,0 +1,31 @@
|
||||
# План внедрения: локальная проверка целостности поставки terraform
|
||||
|
||||
Дата: 2026-09-03
|
||||
|
||||
## Проблема
|
||||
|
||||
Нужно проверить целостность поставки `terraform/` средствами terraform, но `terraform validate`/`plan` с реальным провайдером `vkcs` недостижимы в этом окружении (см. предыдущие изменения): реестр `registry.terraform.io` блокирует регион ("Content not available in your region"), а сконфигурированное зеркало `terraform-mirror.mcs.mail.ru` не содержит провайдер `hashicorp/vkcs` (404 на `index.json`) — в репозитории также исторически отсутствует блок `required_providers`. Пользователь подтвердил: тесты строго локальные, настройку облачных сущностей не выполняем.
|
||||
|
||||
Требуется: установить `terraform` в изолированное локальное окружение (`venv/` в корне проекта), внутри — Python virtualenv с пакетами для тестов, и выполнить содержательную офлайн-проверку поставки.
|
||||
|
||||
## Шаги
|
||||
|
||||
1. `python3 -m venv venv` в корне проекта.
|
||||
2. Скачать бинарь `terraform` (v1.16.1, linux_amd64) с внутреннего зеркала `https://hashicorp-releases.mcs.mail.ru/terraform/`, проверить SHA256SUMS, распаковать в `venv/bin/terraform`. (Это зеркало официальных релизов HashiCorp — провайдер `vkcs` там не публикуется, т.к. это сторонний провайдер VK Cloud, не HashiCorp; проблема с провайдером этим не решается, но сам `terraform` CLI теперь изолированно установлен в venv, как и просил пользователь.)
|
||||
3. `venv/bin/pip install -r terraform/tests/requirements.txt` — `pytest`, `python-hcl2`, `checkov` (checkov оставлен как smoke-проверка; у него нет собственных правил для провайдера `vkcs`, что подтверждено отдельным sanity-тестом на `aws_s3_bucket`).
|
||||
4. Написать `terraform/tests/test_terraform_delivery.py` — pytest-сьют, полностью офлайн:
|
||||
- наличие обязательных файлов поставки;
|
||||
- `terraform fmt -check -recursive` (единственная проверка, буквально использующая сам terraform-бинарь);
|
||||
- валидность HCL всех `.tf`-файлов через `python-hcl2`;
|
||||
- переменные `router_count`/`private_interface_count` объявлены с ожидаемыми дефолтами и не переопределены в `terraform.tfvars` (иначе `TF_VAR_*` не сработает);
|
||||
- `vkcs_compute_instance.router` использует `count = var.router_count`, отсутствуют легаси-ресурсы `router1`/`router2`/`lan_port1`/`lan_port2`;
|
||||
- `locals.private_roles` генерируется из `var.private_interface_count`, `dynamic "network"` использует `local.private_roles`;
|
||||
- нарезка приватных подсетей (`cidrsubnet`) не даёт коллизий — переиспользована через `ipaddress` для нескольких комбинаций `router_count`/`private_interface_count`;
|
||||
- `network-init.sh.tpl` содержит только ожидаемые Terraform-интерполяции (`${pi.cidr}`, `${pi.name}`), директиву `%{ for pi in private_interfaces }`, и рендерится в синтаксически валидный bash (симуляция `templatefile()` + `bash -n`).
|
||||
5. `.gitignore` — добавить `venv/`, `.pytest_cache/`, `__pycache__/`, `.terraform/`, `*.tfstate*` (венв и кэши не должны попасть в git).
|
||||
6. `README.md` — короткий раздел про запуск тестов.
|
||||
7. Summary-документ по завершении.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `venv/bin/pytest terraform/tests -v` — все тесты должны быть зелёными.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Summary: локальная проверка целостности поставки terraform
|
||||
|
||||
Дата: 2026-09-03
|
||||
План: [2026-09-03-local-delivery-integrity-tests-plan.md](2026-09-03-local-delivery-integrity-tests-plan.md)
|
||||
|
||||
## Что сделано
|
||||
|
||||
### `venv/` — локальное изолированное окружение (в корне проекта, не в git)
|
||||
- `python3 -m venv venv`.
|
||||
- `venv/bin/terraform` — Terraform **v1.16.1** (linux_amd64), скачан с внутреннего зеркала HashiCorp-релизов `https://hashicorp-releases.mcs.mail.ru/terraform/1.16.1/`, целостность архива проверена по `SHA256SUMS` перед распаковкой.
|
||||
- `venv/bin/pip install -r terraform/tests/requirements.txt` — `pytest 9.1.1`, `python-hcl2 8.1.3`, `checkov 3.3.16`.
|
||||
|
||||
### `terraform/tests/requirements.txt`
|
||||
Пины версий для воспроизводимой установки пакетов тестирования.
|
||||
|
||||
### `terraform/tests/test_terraform_delivery.py`
|
||||
Pytest-сьют из 28 тестов, полностью офлайн (без `terraform init`/`plan`/`apply` к реальному провайдеру, без облачных вызовов):
|
||||
|
||||
- наличие обязательных файлов поставки (`main.tf`, `variables.tf`, `terraform.tfvars`, `scripts/network-init.sh.tpl`), отсутствие старого `network-init.sh`;
|
||||
- `terraform fmt -check -recursive` — единственная проверка, буквально вызывающая сам `terraform` (из `venv/bin`, если он там есть, иначе `PATH`);
|
||||
- валидность HCL всех `.tf`-файлов (`python-hcl2`);
|
||||
- переменные `router_count`/`private_interface_count` объявлены с ожидаемыми дефолтами и **не** переопределены активными строками в `terraform.tfvars` (иначе `TF_VAR_*` был бы перекрыт);
|
||||
- `vkcs_compute_instance.router` использует `count = var.router_count`; в репозитории нет легаси-ресурсов `router1`/`router2`/`lan_port1`/`lan_port2`;
|
||||
- `locals.private_roles` генерируется из `var.private_interface_count`, а `dynamic "network"` итерируется по `local.private_roles` (NIC-количество реально масштабируется, не хардкод);
|
||||
- нарезка приватных подсетей (переиспользование формулы `cidrsubnet` через `ipaddress`) не даёт коллизий для 6 комбинаций `router_count`×`private_interface_count` (включая крайние: 1×1, 8×4, 1×6);
|
||||
- `network-init.sh.tpl` содержит только ожидаемые Terraform-интерполяции (`${pi.cidr}`, `${pi.name}`) и директиву `%{ for pi in private_interfaces }`; симуляция рендера (`$${` → `${`, подстановка тестовых данных) даёт синтаксически валидный bash (`bash -n`);
|
||||
- smoke-тест `checkov` (офлайн, `--skip-download`) — не падает; **намеренно не проверяет** `resource_count > 0`, см. ограничение ниже.
|
||||
|
||||
Результат: **28 passed**.
|
||||
|
||||
### `.gitignore` (новый файл)
|
||||
`venv/`, `.pytest_cache/`, `__pycache__/`, `*.pyc`, `.terraform/`, `.terraform.lock.hcl`, `*.tfstate*`, `crash*.log`.
|
||||
|
||||
### `README.md`
|
||||
Добавлен раздел "Local delivery integrity tests" с командами запуска и пояснением про офлайн-природу тестов.
|
||||
|
||||
## Важные находки в процессе
|
||||
|
||||
1. **`terraform validate`/`init` с реальным провайдером `vkcs` недостижимы в этом окружении** — `registry.terraform.io` возвращает "Content not available in your region" на API-запросы, а сконфигурированное зеркало `terraform-mirror.mcs.mail.ru` не хостит `hashicorp/vkcs` (404 на `index.json` по протоколу Provider Network Mirror). Это подтверждает более раннюю находку (репозиторий не содержит `required_providers`) и объясняет, почему для содержательной проверки пришлось построить отдельный pytest+hcl2 сьют вместо `terraform validate`.
|
||||
2. **`https://hashicorp-releases.mcs.mail.ru`** — зеркало официальных релизов HashiCorp (terraform CLI и другие продукты HashiCorp), но **не** третьесторонних провайдеров вроде `vkcs` (публикуется VK Cloud, не HashiCorp) — поэтому оно решает задачу "установить terraform в venv", но не задачу provider-резолвинга.
|
||||
3. **`checkov` не имеет собственных политик для провайдера `vkcs`** — проверено отдельным sanity-тестом на `aws_s3_bucket` (там checkov нормально нашёл ресурс и прогнал реальные проверки), тогда как на `terraform/main.tf` он стабильно даёт `resource_count: 0`. Оставлен в сьюте только как smoke-проверка работоспособности инструмента, не как содержательный security/compliance гейт для этого репозитория.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `venv/bin/pytest terraform/tests -v` → `28 passed`.
|
||||
- `venv/bin/terraform version` → `Terraform v1.16.1`.
|
||||
- `git status` подтверждает, что `venv/` и `.pytest_cache/` не отслеживаются git (`.gitignore` работает).
|
||||
@@ -0,0 +1,24 @@
|
||||
# План внедрения: доступ к провайдеру vkcs через GitHub-релизы
|
||||
|
||||
Дата: 2026-09-03
|
||||
|
||||
## Проблема
|
||||
|
||||
Предыдущая попытка (см. [2026-09-03-local-delivery-integrity-tests-plan.md](2026-09-03-local-delivery-integrity-tests-plan.md)) не смогла получить реальный провайдер `vkcs`: `registry.terraform.io` блокирует регион ("Content not available in your region"), а сконфигурированное зеркало `terraform-mirror.mcs.mail.ru` не содержит `hashicorp/vkcs` (404). Пользователь указал использовать `https://github.com/vk-cs/terraform-provider-vkcs` напрямую — это upstream-репозиторий провайдера, публикующий бинарные релизы через GitHub Releases в обход реестра HashiCorp.
|
||||
|
||||
## Шаги
|
||||
|
||||
1. Через GitHub API (`api.github.com`, доступен) найти последний релиз провайдера — `v0.17.2`.
|
||||
2. Скачать `terraform-provider-vkcs_0.17.2_linux_amd64.zip` и `..._SHA256SUMS`, проверить контрольную сумму перед распаковкой.
|
||||
3. Разместить бинарь как **filesystem mirror** провайдера внутри `venv/` (не в git): `venv/terraform.d/plugins/registry.terraform.io/vk-cs/vkcs/0.17.2/linux_amd64/`.
|
||||
4. Добавить `terraform/versions.tf` с блоком `required_providers { vkcs = { source = "vk-cs/vkcs", version = "~> 0.17" } }` — раньше в репозитории такого блока не было вовсе (без него Terraform по умолчанию ищет `hashicorp/vkcs`, которого не существует).
|
||||
5. Сгенерировать проектный CLI-конфиг `venv/terraform.d/cli-config.tfrc` с `provider_installation { filesystem_mirror {...} }`, указывающий на локальное зеркало — не трогая глобальный `~/.terraformrc` пользователя.
|
||||
6. Оформить шаги 3-5 как воспроизводимый идемпотентный скрипт `terraform/tests/setup-local-terraform.sh` (создаёт venv, ставит terraform CLI, провайдер, CLI-конфиг — с проверкой SHA256 на каждом скачивании).
|
||||
7. Прогнать реальные `terraform init -backend=false` + `terraform validate` во временной копии `terraform/` (чтобы не оставлять `.terraform/`/`.terraform.lock.hcl` в самой поставке) — без каких-либо credentials и без обращений к облачному API (`validate` проверяет только статическую схему провайдера).
|
||||
8. Добавить в `terraform/tests/test_terraform_delivery.py` параметризованный тест `test_terraform_init_and_validate_against_real_provider_schema` — реальная валидация при нескольких сочетаниях `router_count`/`private_interface_count` (через `TF_VAR_*`), с `pytest.skip`, если локальное зеркало ещё не настроено.
|
||||
9. Обновить README и текущий summary-документ.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform init` + `terraform validate` вручную — успех, включая `router_count=4, private_interface_count=3`.
|
||||
- `venv/bin/pytest terraform/tests -v` — весь сьют зелёный.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Summary: доступ к провайдеру vkcs через GitHub-релизы
|
||||
|
||||
Дата: 2026-09-03
|
||||
План: [2026-09-03-vkcs-provider-github-mirror-plan.md](2026-09-03-vkcs-provider-github-mirror-plan.md)
|
||||
|
||||
## Что сделано
|
||||
|
||||
### `terraform/versions.tf` (новый файл)
|
||||
```hcl
|
||||
terraform {
|
||||
required_providers {
|
||||
vkcs = {
|
||||
source = "vk-cs/vkcs"
|
||||
version = "~> 0.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Раньше такого блока не было вовсе — Terraform по умолчанию искал несуществующий `hashicorp/vkcs`. Это и было корнем прошлых неудачных попыток `terraform init`.
|
||||
|
||||
### `terraform/tests/setup-local-terraform.sh` (новый файл, идемпотентный)
|
||||
Разворачивает полностью локальный toolchain внутри `venv/` (не в git):
|
||||
- Python-пакеты из `terraform/tests/requirements.txt`;
|
||||
- `terraform` CLI v1.16.1 (уже было с прошлого шага);
|
||||
- провайдер **`vk-cs/vkcs` v0.17.2**, скачанный напрямую с `https://github.com/vk-cs/terraform-provider-vkcs/releases/download/v0.17.2/...` (в обход заблокированного по региону `registry.terraform.io`), с проверкой SHA256SUMS перед распаковкой;
|
||||
- провайдер размещён как **filesystem mirror**: `venv/terraform.d/plugins/registry.terraform.io/vk-cs/vkcs/0.17.2/linux_amd64/`;
|
||||
- проектный CLI-конфиг `venv/terraform.d/cli-config.tfrc` с блоком `provider_installation { filesystem_mirror {...} }` — глобальный `~/.terraformrc` пользователя не тронут.
|
||||
|
||||
### `terraform/tests/test_terraform_delivery.py`
|
||||
Добавлен параметризованный тест `test_terraform_init_and_validate_against_real_provider_schema` — **реальные** `terraform init` + `terraform validate` против настоящей схемы провайдера `vkcs`, во временной копии `terraform/` (чтобы не оставлять `.terraform/`/lock-файл в самой поставке), без credentials и без обращений к облаку. Прогнан при трёх сочетаниях `router_count`/`private_interface_count` (через `TF_VAR_*`): дефолты (2/2), 1/1, 4/3 — все успешны. Тест аккуратно скипается (`pytest.skip`), если `setup-local-terraform.sh` ещё не запускался.
|
||||
|
||||
Итог сьюта: **31 passed** (было 28 до этого шага, +3 за счёт параметризации нового теста).
|
||||
|
||||
### `README.md`
|
||||
Раздел "Local delivery integrity tests" переписан: теперь описывает реальную `terraform validate` через GitHub-зеркало провайдера, команду `setup-local-terraform.sh`, и упоминание нового `versions.tf`.
|
||||
|
||||
## Побочная находка (не исправлялась — вне рамок запроса)
|
||||
|
||||
В `terraform/main.tf` нет явного блока `provider "vkcs" {}` — переменные `username`/`password`/`project_id` объявлены в `variables.tf`, но нигде не подключены к конфигурации провайдера. Для `validate` это не критично (схема провайдера проверяется без учёта credentials), но для реального `apply` может потребоваться либо явный `provider "vkcs" { ... }` блок со ссылками на эти переменные, либо провайдер полагается на переменные окружения (`OS_*`/`VKCS_*`) — это стоит уточнить отдельно, если планируется реальный `apply`.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `venv/bin/terraform init -backend=false` + `venv/bin/terraform validate` (во временной копии, с `TF_CLI_CONFIG_FILE` на локальный mirror) → `Success! The configuration is valid.` — при дефолтных значениях и при `router_count=4, private_interface_count=3`.
|
||||
- `venv/bin/pytest terraform/tests -v` → `31 passed`.
|
||||
- SHA256 бинаря провайдера сверен с `terraform-provider-vkcs_0.17.2_SHA256SUMS` из релиза GitHub перед распаковкой.
|
||||
Reference in new issue
Block a user