- HOWTO_IMPLEMENT_NEW_CLOUD_SERVICE.md: rules for implementing new managed services (naming, params, map-fixed blocks, operations, subresources, validation, checklist) - HOWTO_ADD_NEW_SERVICE.md: how to add service to terraform provider pipeline - TEST_STAND/*/main.tf: version 5.0.57, api_endpoint -> lk-api-gateway-test - TEST_STAND/POSTGRES/resources.tf: rewritten for new map-fixed param structure
222 lines
8.8 KiB
Markdown
222 lines
8.8 KiB
Markdown
# Инструкция по добавлению нового сервиса в Terraform-провайдер Nubes
|
||
|
||
## 1. Где прописывать
|
||
|
||
Единственная точка входа — `devops/config/services_list.txt` (или профильный `profiles/{stand}/services_list.txt`).
|
||
|
||
Формат строки:
|
||
```
|
||
{service_id} {service_name} # Описание (опционально)
|
||
```
|
||
|
||
Пример:
|
||
```
|
||
90 postgres # Управляемая база данных PostgreSQL
|
||
```
|
||
|
||
- **service_id** — число, ID сервиса из API Nubes (`/services/{id}`)
|
||
- **service_name** — snake_case, латиница. Будет использоваться как имя ресурса `nubes_{name}`
|
||
|
||
Исключение сервиса — закомментировать строку `#`.
|
||
|
||
---
|
||
|
||
## 2. Что происходит после добавления в список
|
||
|
||
Пайплайн (3 шага):
|
||
|
||
```
|
||
services_list.txt
|
||
→ 01_generate_yamls.sh → запрос к API → resources_yaml/{id}_{name}.yaml
|
||
→ 02_generate_resources_and_docs_v2.sh → internal/resources_gen/{name}_resource.go + docs
|
||
→ 03_build_and_upload_provider.sh → сборка + S3
|
||
```
|
||
|
||
**Никаких ручных правок YAML или сгенерированного Go-кода.** Всё из API.
|
||
|
||
---
|
||
|
||
## 3. Структура YAML (что генерируется)
|
||
|
||
```yaml
|
||
name: postgres # snake_case, из services_list.txt
|
||
service_id: 90 # ID сервиса
|
||
service_display_name: PostgreSQL # человекочитаемое имя
|
||
service_short_name: postgres # краткое имя из API
|
||
service_man: "описание..." # MAN-руководство (HTML)
|
||
|
||
lifecycle:
|
||
suspend_on_destroy_default: true # есть ли операция suspend
|
||
adopt_existing_on_create_default: false
|
||
|
||
outputs:
|
||
params: # выходные параметры (всегда одинаковые)
|
||
- code: state_params; type: map
|
||
- code: state_out; type: map
|
||
- code: vault_secrets; type: map; sensitive: true
|
||
- code: vault_url; type: string
|
||
...
|
||
|
||
operations:
|
||
- name: create # имя операции из API (snake_case)
|
||
id: 19 # svcOperationId
|
||
kind: instance # instance | subresource | action
|
||
action: create # create | modify | delete | suspend | ...
|
||
man: "руководство" # описание операции
|
||
params:
|
||
- id: 788 # svcOperationCfsParamId
|
||
code: clusterConfiguration
|
||
data_type: map-fixed
|
||
required: true
|
||
sort: 20
|
||
is_modifiable: true
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Типы параметров (data_type)
|
||
|
||
| Тип | Пример | Когда использовать |
|
||
|---|---|---|
|
||
| `string` | `resourceRealm`, `domain`, `dbName` | Имена, домены, UUID, строки |
|
||
| `integer > 0` | `resourceCPU`, `resourceMemory` | Числовые значения больше нуля |
|
||
| `integer >= 0` | `autoScaleTechWindow` | Числовые, допускающие 0 |
|
||
| `boolean` | `enablePgPoolerMaster`, `allowNoSsl` | Флаги вкл/выкл |
|
||
| `uuid` | `s3Uid`, `vdcUid` | Ссылки на другие сервисы (ref) |
|
||
| `map-fixed` | `clusterConfiguration` | **Сложные K8s-сервисы**: JSON-объект с фиксированным набором полей |
|
||
| `array-map-fixed` | `postgresConf` | Массив JSON-объектов (доп. конфигурации) |
|
||
| `json` | `jsonEnv`, `jsonParameters` | Произвольный JSON |
|
||
| `map` | `state_params` | Только в outputs |
|
||
| `yaml` | — | YAML-строка (редко) |
|
||
|
||
---
|
||
|
||
## 5. Виды операций (kind)
|
||
|
||
### instance — управление жизненным циклом сервиса
|
||
|
||
| action | Terraform | Пример |
|
||
|---|---|---|
|
||
| `create` | `resource "nubes_X" "Y" {}` | Создание сервиса |
|
||
| `delete` | `terraform destroy` | Удаление |
|
||
| `modify` | изменение параметров → `apply` | Модификация |
|
||
| `suspend` | `suspend_on_destroy = true` | Остановка (без удаления) |
|
||
| `resume` | `adopt_existing_on_create = true` | Запуск остановленного |
|
||
|
||
**Правило**: если у сервиса есть `suspend` И `resume` → `suspend_on_destroy_default = true`.
|
||
|
||
### subresource — вложенные объекты
|
||
|
||
Стандартные subresource'ы:
|
||
- **user** → `nubes_{service}_user` (create/delete)
|
||
- Параметры: `username` (string, required), `role` (string, required, value_list)
|
||
- **database** → `nubes_{service}_database` (create/delete)
|
||
- Параметры: `dbName` (string, required, regex), `dbOwner` (string, required)
|
||
- **topic** → Kafka
|
||
- **backup** → S3, PostgreSQL
|
||
- **vdc** → vcOrg
|
||
|
||
**Правило**: subresource всегда ссылается на родительский ресурс через `{service}_id`.
|
||
|
||
### action — разовые операции
|
||
|
||
| action | Когда |
|
||
|---|---|
|
||
| `reconcile` | Синхронизация состояния (у 20 сервисов) |
|
||
| `redeploy` | Переразвёртывание (приложения: flask, nodejs, lucee, ...) |
|
||
| `restart` | Перезапуск (postgres, mariadb, ...) |
|
||
| `recovery` | Восстановление из бэкапа |
|
||
|
||
**Правило**: action-ресурсы используют trigger-поле (`run_id`/`nonce`) для идемпотентности.
|
||
|
||
---
|
||
|
||
## 6. Валидация параметров (автоматически из API)
|
||
|
||
| Механизм | Параметров | Пример |
|
||
|---|---|---|
|
||
| `regex` | 29 | `dbName: ^[A-Za-z0-9]+$` |
|
||
| `value_list` | 38 | `role: [app_user, ddl_user]` |
|
||
| `minlength`/`maxlength` | 87/74 | `username: min 2, max 62` |
|
||
| `minvalue`/`maxvalue` | — | `resourceCPU > 0` |
|
||
| `default` | 120 | `deleteS3Bucket: true` |
|
||
| `is_modifiable` | 106 | Можно менять после create |
|
||
| `is_sensitive` | 2 | `vault_secrets` |
|
||
|
||
---
|
||
|
||
## 7. Что запрещено
|
||
|
||
- ❌ **Править сгенерированные YAML вручную** — источник истины только API
|
||
- ❌ **Править `internal/resources_gen/*.go` вручную** — перезапишется при следующей генерации
|
||
- ❌ **Использовать кириллицу в `service_name`** — только латиница, snake_case
|
||
- ❌ **Менять `embed.go`** — генерируется автоматически
|
||
- ❌ **Пропускать сервис через комментарий без причины** — лучше явно указать причину в комментарии: `# 24 DEPRECATED ...`
|
||
|
||
---
|
||
|
||
## 8. Быстрый старт: добавляем новый сервис
|
||
|
||
```bash
|
||
# 1. Добавить строку в services_list.txt
|
||
echo "200 my_new_service # Моя новая услуга" >> devops/config/services_list.txt
|
||
|
||
# 2. Сгенерировать YAML (test-стенд)
|
||
devops/01_generate_yamls.sh --profile devops/profiles/test
|
||
|
||
# 3. Сгенерировать Go-код + доки
|
||
devops/02_generate_resources_and_docs_v2.sh --profile devops/profiles/test
|
||
|
||
# 4. Проверить что появился файл
|
||
ls devops/profiles/test/generated/resources_yaml/200_my_new_service.yaml
|
||
ls devops/profiles/test/generated/go/200_my_new_service_resource.go
|
||
|
||
# 5. Собрать и задеплоить провайдер
|
||
devops/03_build_and_upload_provider.sh --profile devops/profiles/test
|
||
|
||
# 6. Написать тестовый манифест в TEST_STAND/my_new_service/main.tf
|
||
# 7. terraform init && terraform plan && terraform apply
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Как писать тестовый манифест
|
||
|
||
### Простой сервис (flat-параметры)
|
||
|
||
```hcl
|
||
resource "nubes_s3bucket" "test" {
|
||
resource_name = "Мой бакет"
|
||
s3_user_uid = var.s3_uid
|
||
bucket_name = "test-bucket"
|
||
}
|
||
```
|
||
|
||
### Сложный сервис (map-fixed)
|
||
|
||
```hcl
|
||
resource "nubes_postgres" "test" {
|
||
resource_name = "pg-test"
|
||
|
||
cluster_configuration = jsonencode({
|
||
platform = "k8s-3.ext.nubes.ru"
|
||
instances = 1
|
||
memory = 512
|
||
cpu = 500
|
||
disk = "1"
|
||
})
|
||
|
||
startup_configuration = jsonencode({
|
||
appVersion = "17"
|
||
})
|
||
|
||
access_configuration = jsonencode({
|
||
needExternalAddressMaster = false
|
||
})
|
||
|
||
# ... остальные блоки
|
||
}
|
||
```
|
||
|
||
**JSON-ключи внутри map-fixed** — camelCase-версии старых плоских названий параметров. Точные имена полей смотри в сгенерированном YAML (поле `code` у параметров в `operations.params`) или в `generated/docs/{service}_params_create.md`.
|