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.
199 lines
7.1 KiB
Go
199 lines
7.1 KiB
Go
// Package writers — генерация Go-файлов ресурсов и registry.go.
|
|
//
|
|
// Генерирует три типа файлов в internal/resources_gen/:
|
|
// - {id}_{service}_resource.go — основной CRUD инстанса
|
|
// - {id}_{service}_{sub}_resource.go — подресурсы
|
|
// - {id}_{service}_{action}_action.go — action-ресурсы (редко)
|
|
// - registry.go — AllResources() со списком всех ресурсов
|
|
//
|
|
// Каждый файл компилируется через text/template и форматируется через gofmt.
|
|
package writers
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"text/template"
|
|
|
|
"resource-generator/internal/helpers"
|
|
"resource-generator/internal/templates"
|
|
"resource-generator/internal/types"
|
|
)
|
|
|
|
// WriteInstanceResource генерирует nubes_{service} (CRUD инстанса).
|
|
func WriteInstanceResource(outDir string, svc types.GenResource) error {
|
|
fileName := fmt.Sprintf("%d_%s_resource.go", svc.ServiceID, svc.Name)
|
|
filePath := filepath.Join(outDir, fileName)
|
|
|
|
tpl, err := template.New("resource").Funcs(template.FuncMap{
|
|
"ToCamel": helpers.ToCamel,
|
|
"ToSnake": helpers.ToSnake,
|
|
"ParamType": helpers.ParamType,
|
|
"ParamDefaultExpr": helpers.ParamDefaultExpr,
|
|
"ParamFormat": helpers.ParamFormat,
|
|
"ParamParse": helpers.ParamParse,
|
|
"ParamDescription": helpers.ParamDescription,
|
|
"OutputType": helpers.OutputParamType,
|
|
"OutputIsMap": helpers.OutputParamIsMap,
|
|
"OutputIsList": helpers.OutputParamIsList,
|
|
"OutputSensitive": helpers.OutputParamSensitive,
|
|
"IsNested": helpers.IsNested,
|
|
"IsNestedList": helpers.IsNestedList,
|
|
"NestedModelName": helpers.NestedModelName,
|
|
"NestedTfType": helpers.NestedTfType,
|
|
"NestedSchemaType": helpers.NestedSchemaType,
|
|
"NestedSchemaBlock": helpers.NestedSchemaBlock,
|
|
"NestedSchemaEnd": helpers.NestedSchemaEnd,
|
|
"NestedJSONExpr": helpers.NestedJSONExpr,
|
|
"SubSchemaType": helpers.SubSchemaType,
|
|
"SubDefaultExpr": helpers.SubDefaultExpr,
|
|
"bt": func() string { return "`" },
|
|
}).Parse(templates.Instance)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tpl.Execute(&buf, svc); err != nil {
|
|
return err
|
|
}
|
|
|
|
formatted, err := helpers.FormatSourceOrWarn(filePath, buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(filePath, formatted, 0644)
|
|
}
|
|
|
|
// WriteSubresource генерирует nubes_{service}_{sub} (пользователи, базы, ...).
|
|
func WriteSubresource(outDir string, sr types.GenSubresource) error {
|
|
name := fmt.Sprintf("%s_%s", sr.ServiceName, sr.SubName)
|
|
fileName := fmt.Sprintf("%d_%s_resource.go", sr.ServiceID, name)
|
|
filePath := filepath.Join(outDir, fileName)
|
|
|
|
tpl, err := template.New("subresource").Funcs(template.FuncMap{
|
|
"ToCamel": helpers.ToCamel,
|
|
"ToSnake": helpers.ToSnake,
|
|
"ParamType": helpers.ParamType,
|
|
"ParamDefaultExpr": helpers.ParamDefaultExpr,
|
|
"ParamFormat": helpers.ParamFormat,
|
|
"ParamParse": helpers.ParamParse,
|
|
"ParamDescription": helpers.ParamDescription,
|
|
"PlanModifierType": helpers.PlanModifierType,
|
|
"PlanModifierExpr": helpers.PlanModifierExpr,
|
|
"bt": func() string { return "`" },
|
|
}).Parse(templates.Subresource)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tpl.Execute(&buf, sr); err != nil {
|
|
return err
|
|
}
|
|
|
|
formatted, err := helpers.FormatSourceOrWarn(filePath, buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(filePath, formatted, 0644)
|
|
}
|
|
|
|
// WriteActionResource генерирует action-ресурс (почти не используется).
|
|
func WriteActionResource(outDir string, act types.GenAction) error {
|
|
name := fmt.Sprintf("%s_%s", act.ServiceName, act.ActionName)
|
|
fileName := fmt.Sprintf("%d_%s_action.go", act.ServiceID, name)
|
|
filePath := filepath.Join(outDir, fileName)
|
|
|
|
tpl, err := template.New("action").Funcs(template.FuncMap{
|
|
"ToCamel": helpers.ToCamel,
|
|
"ToSnake": helpers.ToSnake,
|
|
"ParamType": helpers.ParamType,
|
|
"ParamDefaultExpr": helpers.ParamDefaultExpr,
|
|
"ParamFormat": helpers.ParamFormat,
|
|
"ParamParse": helpers.ParamParse,
|
|
"ParamDescription": helpers.ParamDescription,
|
|
"bt": func() string { return "`" },
|
|
}).Parse(templates.Action)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tpl.Execute(&buf, act); err != nil {
|
|
return err
|
|
}
|
|
|
|
formatted, err := helpers.FormatSourceOrWarn(filePath, buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(filePath, formatted, 0644)
|
|
}
|
|
|
|
// WriteModifierResource генерирует отдельный ресурс для parent-level modify.
|
|
func WriteModifierResource(outDir string, modifier types.GenModifier) error {
|
|
name := fmt.Sprintf("%s_%s", modifier.ServiceName, modifier.ModifierName)
|
|
fileName := fmt.Sprintf("%d_%s_modifier.go", modifier.ServiceID, name)
|
|
filePath := filepath.Join(outDir, fileName)
|
|
|
|
tpl, err := template.New("modifier").Funcs(template.FuncMap{
|
|
"ToCamel": helpers.ToCamel,
|
|
"ToSnake": helpers.ToSnake,
|
|
"ParamType": helpers.ParamType,
|
|
"ParamDefaultExpr": helpers.ParamDefaultExpr,
|
|
"ParamFormat": helpers.ParamFormat,
|
|
"ParamDescription": helpers.ParamDescription,
|
|
"bt": func() string { return "`" },
|
|
}).Parse(templates.Modifier)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tpl.Execute(&buf, modifier); err != nil {
|
|
return err
|
|
}
|
|
formatted, err := helpers.FormatSourceOrWarn(filePath, buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(filePath, formatted, 0644)
|
|
}
|
|
|
|
// WriteRegistry генерирует registry.go со списком всех ресурсов.
|
|
func WriteRegistry(outDir string, services []types.GenResource, subs []types.GenSubresource, actions []types.GenAction, modifiers []types.GenModifier) error {
|
|
var buf bytes.Buffer
|
|
buf.WriteString("package resources_gen\n\n")
|
|
buf.WriteString("import \"github.com/hashicorp/terraform-plugin-framework/resource\"\n\n")
|
|
buf.WriteString("// Code generated by TOOLS/resource-generator. DO NOT EDIT.\n")
|
|
buf.WriteString("func AllResources() []func() resource.Resource {\n")
|
|
buf.WriteString("\treturn []func() resource.Resource{\n")
|
|
for _, svc := range services {
|
|
buf.WriteString(fmt.Sprintf("\t\tNew%[1]sResource,\n", helpers.ToCamel(svc.Name)))
|
|
}
|
|
for _, sr := range subs {
|
|
buf.WriteString(fmt.Sprintf("\t\tNew%[1]sResource,\n", helpers.ToCamel(sr.ServiceName+"_"+sr.SubName)))
|
|
}
|
|
for _, act := range actions {
|
|
buf.WriteString(fmt.Sprintf("\t\tNew%[1]sResource,\n", helpers.ToCamel(act.ServiceName+"_"+act.ActionName)))
|
|
}
|
|
for _, modifier := range modifiers {
|
|
buf.WriteString(fmt.Sprintf("\t\tNew%[1]sResource,\n", helpers.ToCamel(modifier.ServiceName+"_"+modifier.ModifierName)))
|
|
}
|
|
buf.WriteString("\t}\n")
|
|
buf.WriteString("}\n")
|
|
|
|
regPath := filepath.Join(outDir, "registry.go")
|
|
formatted, err := helpers.FormatSourceOrWarn(regPath, buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(regPath, formatted, 0644)
|
|
}
|