Validate required modifier parameters, refresh modifier state from parent state_params, preserve operation timeout and log level during update, and normalize nested modifier payloads as JSON. Document the modifier contract, vcOrg/vcNsxt usage, and the intentionally unsupported rollback semantics.
162 lines
8.0 KiB
Go
162 lines
8.0 KiB
Go
package templates
|
|
|
|
const Modifier = `package resources_gen
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"terraform-provider-nubes/internal/core"
|
|
"terraform-provider-nubes/internal/resources_core"
|
|
|
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
|
{{- if .NeedsBoolDefault }}
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
|
{{- end }}
|
|
{{- if .NeedsInt64Default }}
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default"
|
|
{{- end }}
|
|
{{- if .NeedsStringDefault }}
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
|
|
{{- end }}
|
|
{{- if .NeedsJsonPlanMod }}
|
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
|
{{- end }}
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
)
|
|
|
|
// Code generated by TOOLS/resource-generator. DO NOT EDIT.
|
|
// Modifier: {{.ServiceName}}.{{.ModifierName}}
|
|
|
|
var _ resource.Resource = &{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource{}
|
|
|
|
type {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource struct {
|
|
client *core.UniversalClient
|
|
}
|
|
|
|
type {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model struct {
|
|
ID types.String ` + "`" + `tfsdk:"id"` + "`" + `
|
|
{{ToCamel .ServiceName}}ID types.String ` + "`" + `tfsdk:"{{ToSnake .ServiceName}}_id"` + "`" + `
|
|
OperationTimeout types.String ` + "`" + `tfsdk:"operation_timeout"` + "`" + `
|
|
LogLevel types.String ` + "`" + `tfsdk:"log_level"` + "`" + `
|
|
{{- range .SchemaParams }}
|
|
{{ToCamel .Code}} {{ParamType .}} ` + "`" + `tfsdk:"{{ToSnake .Code}}"` + "`" + `
|
|
{{- end }}
|
|
}
|
|
|
|
func New{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource() resource.Resource {
|
|
return &{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource{}
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
|
resp.TypeName = req.ProviderTypeName + "_{{.ServiceName}}_{{.ModifierName}}"
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
|
attrs := map[string]schema.Attribute{
|
|
"id": schema.StringAttribute{Computed: true},
|
|
"{{ToSnake .ServiceName}}_id": schema.StringAttribute{Required: true},
|
|
"operation_timeout": schema.StringAttribute{Optional: true},
|
|
"log_level": schema.StringAttribute{Optional: true},
|
|
{{- range .SchemaParams }}
|
|
"{{ToSnake .Code}}": schema.{{if eq (ParamType .) "types.Bool"}}Bool{{else if eq (ParamType .) "types.Int64"}}Int64{{else}}String{{end}}Attribute{
|
|
{{- if and .Required (eq (ParamDefaultExpr .) "") }}Required: true,{{else}}Optional: true,{{end}}
|
|
{{- if ne (ParamDefaultExpr .) "" }}Computed: true, Default: {{ParamDefaultExpr .}},{{- end }}
|
|
{{- if ne (ParamDescription .) "" }}MarkdownDescription: {{ParamDescription .}},{{end}}
|
|
{{- if .Sensitive }}Sensitive: true,{{end}}
|
|
{{- if .IsJson }}PlanModifiers: []planmodifier.String{resources_core.JsonNormalize()},{{end}}
|
|
},
|
|
{{- end }}
|
|
}
|
|
resp.Schema = schema.Schema{Attributes: attrs}
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
|
var plan {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model
|
|
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
|
if resp.Diagnostics.HasError() { return }
|
|
{{- range .SchemaParams }}
|
|
{{- if and .Required (eq (ParamDefaultExpr .) "") }}
|
|
if plan.{{ToCamel .Code}}.IsNull() || plan.{{ToCamel .Code}}.IsUnknown() {
|
|
resp.Diagnostics.AddError("Missing required attribute", "{{ToSnake .Code}} is required.")
|
|
return
|
|
}
|
|
{{- end }}
|
|
{{- end }}
|
|
instanceUID := strings.TrimSpace(plan.{{ToCamel .ServiceName}}ID.ValueString())
|
|
if instanceUID == "" { resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра"); return }
|
|
params := resources_core.CompactParams(map[string]string{
|
|
{{- range .SchemaParams }}
|
|
"{{.Code}}": {{ParamFormat . (printf "plan.%s" (ToCamel .Code))}},
|
|
{{- end }}
|
|
})
|
|
operationTimeout := ""
|
|
if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { operationTimeout = plan.OperationTimeout.ValueString() }
|
|
if !plan.LogLevel.IsNull() && !plan.LogLevel.IsUnknown() { ctx = core.CtxWithLogLevel(ctx, plan.LogLevel.ValueString()) }
|
|
if err := resources_core.RunOperationByCodeWithTimeout(ctx, r.client, instanceUID, "{{.OperationName}}", params, operationTimeout); err != nil {
|
|
resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return
|
|
}
|
|
plan.ID = types.StringValue(resources_core.BuildActionID(instanceUID, "{{.OperationName}}", "{{.ModifierName}}"))
|
|
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
|
var state {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model
|
|
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
|
|
if resp.Diagnostics.HasError() { return }
|
|
if state.ID.IsNull() || state.ID.IsUnknown() { return }
|
|
if r.client != nil {
|
|
remove, err := resources_core.ShouldRemoveFromState(ctx, r.client, state.{{ToCamel .ServiceName}}ID.ValueString())
|
|
if err != nil { resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return }
|
|
if remove { resp.State.RemoveResource(ctx); return }
|
|
}
|
|
newState, diags := resources_core.RefreshResourceState(ctx, r.client, state.{{ToCamel .ServiceName}}ID.ValueString(), {{.ServiceID}}, state, nil, []resources_core.InputField{
|
|
{{- range .SchemaParams }}
|
|
{Code: "{{.Code}}", Field: "{{ToCamel .Code}}", Type: "{{.Type}}"},
|
|
{{- end }}
|
|
})
|
|
resp.Diagnostics.Append(diags...)
|
|
if resp.Diagnostics.HasError() { return }
|
|
resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...)
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
|
var plan {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model
|
|
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
|
if resp.Diagnostics.HasError() { return }
|
|
{{- range .SchemaParams }}
|
|
{{- if and .Required (eq (ParamDefaultExpr .) "") }}
|
|
if plan.{{ToCamel .Code}}.IsNull() || plan.{{ToCamel .Code}}.IsUnknown() {
|
|
resp.Diagnostics.AddError("Missing required attribute", "{{ToSnake .Code}} is required.")
|
|
return
|
|
}
|
|
{{- end }}
|
|
{{- end }}
|
|
instanceUID := strings.TrimSpace(plan.{{ToCamel .ServiceName}}ID.ValueString())
|
|
params := resources_core.CompactParams(map[string]string{
|
|
{{- range .SchemaParams }}
|
|
"{{.Code}}": {{ParamFormat . (printf "plan.%s" (ToCamel .Code))}},
|
|
{{- end }}
|
|
})
|
|
operationTimeout := ""
|
|
if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { operationTimeout = plan.OperationTimeout.ValueString() }
|
|
if !plan.LogLevel.IsNull() && !plan.LogLevel.IsUnknown() { ctx = core.CtxWithLogLevel(ctx, plan.LogLevel.ValueString()) }
|
|
if err := resources_core.RunOperationByCodeWithTimeout(ctx, r.client, instanceUID, "{{.OperationName}}", params, operationTimeout); err != nil {
|
|
resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return
|
|
}
|
|
plan.ID = types.StringValue(resources_core.BuildActionID(instanceUID, "{{.OperationName}}", "{{.ModifierName}}"))
|
|
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
|
// No-op: no confirmed inverse payload exists for this modifier.
|
|
}
|
|
|
|
func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
|
if req.ProviderData == nil { return }
|
|
client, ok := req.ProviderData.(*core.UniversalClient)
|
|
if !ok { resp.Diagnostics.AddError("Error", "Invalid client type"); return }
|
|
r.client = client
|
|
}
|
|
` |