package templates const Modifier = `package resources_gen import ( "context" "fmt" "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 {{bt}}tfsdk:"id"{{bt}} {{ToCamel .ServiceName}}ID types.String {{bt}}tfsdk:"{{ToSnake .ServiceName}}_id"{{bt}} OperationTimeout types.String {{bt}}tfsdk:"operation_timeout"{{bt}} LogLevel types.String {{bt}}tfsdk:"log_level"{{bt}} {{- range .SchemaParams }} {{ToCamel .Code}} {{ParamType .}} {{bt}}tfsdk:"{{ToSnake .Code}}"{{bt}} {{- 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 } if err := r.reconcile(ctx, &plan, nil); err != nil { resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return } 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 } if err := r.reconcile(ctx, &plan, nil); err != nil { resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return } resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } // reconcile — единый путь apply для модификатора (полный payload, досылка в core). // override — обратные значения (wire-строки), используются только Delete=inverse. func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) reconcile(ctx context.Context, model *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model, override map[string]string) error { instanceUID := strings.TrimSpace(model.{{ToCamel .ServiceName}}ID.ValueString()) if instanceUID == "" { return fmt.Errorf("отсутствует идентификатор экземпляра") } params := map[string]string{} {{- range .SchemaParams }} {{- if .Required }} if model.{{ToCamel .Code}}.IsNull() || model.{{ToCamel .Code}}.IsUnknown() { return fmt.Errorf("{{ToSnake .Code}} is required") } params["{{.Code}}"] = {{ParamFormat . (printf "model.%s" (ToCamel .Code))}} {{- else }} if !model.{{ToCamel .Code}}.IsNull() && !model.{{ToCamel .Code}}.IsUnknown() { params["{{.Code}}"] = {{ParamFormat . (printf "model.%s" (ToCamel .Code))}} } {{- end }} {{- end }} for k, v := range override { params[k] = v } operationTimeout := "" if !model.OperationTimeout.IsNull() && !model.OperationTimeout.IsUnknown() { operationTimeout = model.OperationTimeout.ValueString() } if !model.LogLevel.IsNull() && !model.LogLevel.IsUnknown() { ctx = core.CtxWithLogLevel(ctx, model.LogLevel.ValueString()) } {{- if eq .Idempotency "check_before_run" }} if err := resources_core.RunOperationByCodeIdempotent(ctx, r.client, instanceUID, "{{.OperationName}}", params, operationTimeout); err != nil { return err } {{- else }} if err := resources_core.RunOperationByCodeWithTimeout(ctx, r.client, instanceUID, "{{.OperationName}}", params, operationTimeout); err != nil { return err } {{- end }} model.ID = types.StringValue(resources_core.BuildActionID(instanceUID, "{{.OperationName}}", "{{.ModifierName}}")) return nil } func (r *{{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { var state {{ToCamel (printf "%s_%s" .ServiceName .ModifierName)}}Model resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return } {{- if eq .DeleteStrategy "error" }} resp.Diagnostics.AddError("Запрещено удалять", "Модификатор {{.ServiceName}}.{{.ModifierName}} нельзя удалять: эффект необратим. Обратитесь в техническую поддержку.") return {{- else if eq .DeleteStrategy "inverse" }} override := map[string]string{ {{- range .DeleteParams }} "{{.Code}}": {{printf "%q" .Value}}, {{- end }} } if err := r.reconcile(ctx, &state, override); err != nil { resp.Diagnostics.AddError("Ошибка клиента", err.Error()); return } {{- else }} resp.Diagnostics.AddWarning("Эффект остаётся на платформе", "Удаление модификатора {{.ServiceName}}.{{.ModifierName}} снимает его из state, но его эффект на платформе остаётся. Откатите вручную при необходимости.") {{- end }} } 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 } `