Files
tf_provider/TOOLS/yaml-generator/main.go
T

116 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// service_spec_gen — генератор YAML-спеков сервисов из API Nubes.
//
// Читает список сервисов, дёргает API, собирает операции/параметры/MAN,
// пишет один YAML на сервис в resources_yaml/.
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
"yaml-generator/internal/client"
"yaml-generator/internal/config"
"yaml-generator/internal/normalize"
"yaml-generator/internal/spec"
"yaml-generator/internal/types"
)
func main() {
cfg, err := config.Load()
if err != nil {
panic(err)
}
cli := client.New(cfg.APIEndpoint, cfg.APIToken)
services := cfg.Services
if cfg.SingleServiceID > 0 {
services = []config.ServiceRef{{ID: cfg.SingleServiceID, Name: cfg.SingleServiceName}}
}
outputDir := cfg.OutputDir
if outputDir == "" {
panic("NUBES_OUTPUT_DIR is required — generated files must go to generated/{stand}/resources_yaml/")
}
if err := spec.ValidateOutputDir(outputDir); err != nil {
panic(err)
}
if err := os.MkdirAll(outputDir, 0o755); err != nil {
panic(err)
}
for _, svc := range services {
if svc.ID <= 0 {
continue
}
fmt.Fprintf(os.Stderr, " service %d (%s): fetching...\n", svc.ID, svc.Name)
info, err := cli.GetService(svc.ID)
if err != nil {
fmt.Fprintf(os.Stderr, " ⚠ service %d (%s) skipped: %v\n", svc.ID, svc.Name, err)
continue
}
name := strings.TrimSpace(svc.Name)
if name == "" {
name = strings.TrimSpace(info.ShortName)
}
if name == "" {
name = strings.TrimSpace(info.DisplayName)
}
name = normalize.ServiceName(name)
if name == "" {
name = fmt.Sprintf("service_%d", svc.ID)
}
fmt.Fprintf(os.Stderr, " %d operations to fetch...\n", len(info.Operations))
// === Универсальная выгрузка из API (БЕЗ доменных знаний) ===
//
// CollectOperations возвращает операции сервиса ТАКИМИ, КАК ИХ ОТДАЁТ API:
// create/delete/modify/suspend/... с их настоящими действиями и параметрами.
// Здесь НЕЛЬЗЯ привносить доменную семантику (помечать операцию как
// "модификатор", задавать delete_strategy, delete_params и т.п.) — это
// сломало бы главный принцип: YAML должен быть ЧИСТОЙ, ПОЛНОЙ выгрузкой
// того, что доступно по API для сервиса, без каких-либо знаний о слое
// "модификаторов" провайдера.
//
// Раньше (до рефакторинга 2026-09-23) здесь стоял реестр
// `serviceSpecificModifiers`, который помечал отдельные modify как
// kind=modifier. Это было инвазивно: обычные ресурсы зависели от
// доменного реестра, а YAML переставал быть чистой выгрузкой.
// Модификаторы теперь живут ОТДЕЛЬНЫМ оверлеем (см. modifiers.yaml +
// второй проход), базовый YAML их не содержит и не знает о них.
ops, hasSuspend, _, _, err := cli.CollectOperations(info.Operations)
if err != nil {
panic(err)
}
specYAML := types.ServiceSpec{
Name: name,
ServiceID: svc.ID,
ServiceDisplayName: strings.TrimSpace(info.DisplayName),
ServiceShortName: strings.TrimSpace(info.ShortName),
ServiceMan: strings.TrimSpace(info.Man),
Lifecycle: types.Lifecycle{
SuspendOnDestroyDefault: hasSuspend,
AdoptExistingOnCreateDefault: false,
},
Outputs: types.OutputSection{Params: spec.DefaultOutputParams()},
Operations: ops,
}
outPath := filepath.Join(outputDir, fmt.Sprintf("%d_%s.yaml", svc.ID, name))
buf, err := yaml.Marshal(specYAML)
if err != nil {
panic(err)
}
if err := os.WriteFile(outPath, buf, 0o644); err != nil {
panic(err)
}
fmt.Printf("written %s\n", outPath)
}
}