Introduce the modifier YAML kind for delayed parent-level modify operations and generate dedicated Terraform resources with typed parameters. Keep modifier parameters out of the ordinary instance CRUD resource, register modifiers separately, and leave delete as a no-op until an inverse API payload is confirmed. Mark vcOrg and vcNsxt modify operations during YAML generation so the contract survives regeneration.
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
// 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))
|
|
|
|
ops, hasSuspend, _, _, err := cli.CollectOperations(info.Operations)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for idx := range ops {
|
|
if strings.EqualFold(ops[idx].Action, "modify") && svc.ID == 19 {
|
|
ops[idx].Kind = "modifier"
|
|
ops[idx].Modifier = "ip_space"
|
|
}
|
|
if strings.EqualFold(ops[idx].Action, "modify") && svc.ID == 22 {
|
|
ops[idx].Kind = "modifier"
|
|
ops[idx].Modifier = "network"
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|