From 897d9102956d1f75668dd642d84bf1859b30af13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Tue, 30 Jun 2026 15:43:27 +0400 Subject: [PATCH] add: generated resources batch 1/4 --- .../resources_gen/100_openwhisk_resource.go | 352 +++++++++++ .../resources_gen/110_dnszone_resource.go | 452 ++++++++++++++ .../resources_gen/111_dnsrecord_resource.go | 471 ++++++++++++++ .../resources_gen/112_tenant_resource.go | 352 +++++++++++ .../resources_gen/113_vc_complex_resource.go | 523 ++++++++++++++++ .../114_gitea_complex_resource.go | 305 ++++++++++ .../resources_gen/115_mariadb_resource.go | 576 ++++++++++++++++++ .../resources_gen/116_kafka_resource.go | 466 ++++++++++++++ .../resources_gen/1_dummy_redeploy_action.go | 128 ++++ .../resources_gen/1_dummy_resource.go | 504 +++++++++++++++ .../resources_gen/2_template_resource.go | 415 +++++++++++++ 11 files changed, 4544 insertions(+) create mode 100644 universal_rebuild/internal/resources_gen/100_openwhisk_resource.go create mode 100644 universal_rebuild/internal/resources_gen/110_dnszone_resource.go create mode 100644 universal_rebuild/internal/resources_gen/111_dnsrecord_resource.go create mode 100644 universal_rebuild/internal/resources_gen/112_tenant_resource.go create mode 100644 universal_rebuild/internal/resources_gen/113_vc_complex_resource.go create mode 100644 universal_rebuild/internal/resources_gen/114_gitea_complex_resource.go create mode 100644 universal_rebuild/internal/resources_gen/115_mariadb_resource.go create mode 100644 universal_rebuild/internal/resources_gen/116_kafka_resource.go create mode 100644 universal_rebuild/internal/resources_gen/1_dummy_redeploy_action.go create mode 100644 universal_rebuild/internal/resources_gen/1_dummy_resource.go create mode 100644 universal_rebuild/internal/resources_gen/2_template_resource.go diff --git a/universal_rebuild/internal/resources_gen/100_openwhisk_resource.go b/universal_rebuild/internal/resources_gen/100_openwhisk_resource.go new file mode 100644 index 0000000..a0c10df --- /dev/null +++ b/universal_rebuild/internal/resources_gen/100_openwhisk_resource.go @@ -0,0 +1,352 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: openwhisk +// Service ID: 100 + +var _ resource.Resource = &OpenwhiskResource{} +var _ resource.ResourceWithModifyPlan = &OpenwhiskResource{} +var _ resource.ResourceWithImportState = &OpenwhiskResource{} + +type OpenwhiskResource struct { + client *core.UniversalClient +} + +type OpenwhiskModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + ResourceRealm types.String `tfsdk:"resource_realm"` + Username types.String `tfsdk:"username"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewOpenwhiskResource() resource.Resource { + return &OpenwhiskResource{} +} + +func (r *OpenwhiskResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_openwhisk" +} + +func (r *OpenwhiskResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Ресурсная платформа Не изменяется после создания."}, + "username": schema.StringAttribute{Required: true, MarkdownDescription: "Имя пользователя Openwhisk Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *OpenwhiskResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *OpenwhiskModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *OpenwhiskModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan OpenwhiskModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.Username.IsNull() && !plan.Username.IsUnknown() && !state.Username.IsNull() && !state.Username.IsUnknown() { + if plan.Username.ValueString() != state.Username.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить username", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if config.Username.IsNull() || config.Username.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "username is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 64: resources_core.FormatString(config.Username), + 863: resources_core.FormatString(config.ResourceRealm), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 100, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *OpenwhiskResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data OpenwhiskModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if data.Username.IsNull() || data.Username.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "username is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 100, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 64: resources_core.FormatString(data.Username), + 863: resources_core.FormatString(data.ResourceRealm), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 100, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 100, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "username", Field: "Username", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *OpenwhiskResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state OpenwhiskModel + 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.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.ID.ValueString(), 100, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "username", Field: "Username", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *OpenwhiskResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan OpenwhiskModel + var state OpenwhiskModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 100, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "username", Field: "Username", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *OpenwhiskResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state OpenwhiskModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *OpenwhiskResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *OpenwhiskResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/110_dnszone_resource.go b/universal_rebuild/internal/resources_gen/110_dnszone_resource.go new file mode 100644 index 0000000..2b92e9f --- /dev/null +++ b/universal_rebuild/internal/resources_gen/110_dnszone_resource.go @@ -0,0 +1,452 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: dnszone +// Service ID: 110 + +var _ resource.Resource = &DnszoneResource{} +var _ resource.ResourceWithModifyPlan = &DnszoneResource{} +var _ resource.ResourceWithImportState = &DnszoneResource{} + +type DnszoneResource struct { + client *core.UniversalClient +} + +type DnszoneModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + ResourceRealm types.String `tfsdk:"resource_realm"` + ZoneEmail types.String `tfsdk:"zone_email"` + ZoneKind types.String `tfsdk:"zone_kind"` + ZoneMastersForSlave types.String `tfsdk:"zone_masters_for_slave"` + ZoneName types.String `tfsdk:"zone_name"` + ZoneTimeToExpire types.String `tfsdk:"zone_time_to_expire"` + ZoneTimeToLive types.String `tfsdk:"zone_time_to_live"` + ZoneTimeToRefresh types.String `tfsdk:"zone_time_to_refresh"` + ZoneTimeToRetry types.String `tfsdk:"zone_time_to_retry"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewDnszoneResource() resource.Resource { + return &DnszoneResource{} +} + +func (r *DnszoneResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dnszone" +} + +func (r *DnszoneResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "zone_email": schema.StringAttribute{Required: true, MarkdownDescription: "Контактный e-mail Не изменяется после создания."}, + "zone_kind": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("NATIVE"), MarkdownDescription: "Тип зоны Не изменяется после создания."}, + "zone_masters_for_slave": schema.StringAttribute{Optional: true, MarkdownDescription: "Использовать если выбран тип SLAVE. IP адреса в формате через пробел для настройки Master-серверов Не изменяется после создания."}, + "zone_name": schema.StringAttribute{Required: true, MarkdownDescription: "Имя зоны Не изменяется после создания."}, + "zone_time_to_expire": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("3600000"), MarkdownDescription: "Время в течение которого вторичный DNS будет пытаться завершить синхронизацию зоны с первичным Не изменяется после создания."}, + "zone_time_to_live": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("86400"), MarkdownDescription: "Время, в течение которого информация будет кешироваться другими DNS-серверами Не изменяется после создания."}, + "zone_time_to_refresh": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("86400"), MarkdownDescription: "Время ожидания ответа вторичного DNS перед запросом SOA-записи с первичных серверов Не изменяется после создания."}, + "zone_time_to_retry": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("7200"), MarkdownDescription: "Время в течение которого сервер повторно попробует синхронизировать информацию с первичных DNS-серверов Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *DnszoneResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *DnszoneModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *DnszoneModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan DnszoneModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneEmail.IsNull() && !plan.ZoneEmail.IsUnknown() && !state.ZoneEmail.IsNull() && !state.ZoneEmail.IsUnknown() { + if plan.ZoneEmail.ValueString() != state.ZoneEmail.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_email", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneKind.IsNull() && !plan.ZoneKind.IsUnknown() && !state.ZoneKind.IsNull() && !state.ZoneKind.IsUnknown() { + if plan.ZoneKind.ValueString() != state.ZoneKind.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_kind", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneMastersForSlave.IsNull() && !plan.ZoneMastersForSlave.IsUnknown() && !state.ZoneMastersForSlave.IsNull() && !state.ZoneMastersForSlave.IsUnknown() { + if plan.ZoneMastersForSlave.ValueString() != state.ZoneMastersForSlave.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_masters_for_slave", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneName.IsNull() && !plan.ZoneName.IsUnknown() && !state.ZoneName.IsNull() && !state.ZoneName.IsUnknown() { + if plan.ZoneName.ValueString() != state.ZoneName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneTimeToExpire.IsNull() && !plan.ZoneTimeToExpire.IsUnknown() && !state.ZoneTimeToExpire.IsNull() && !state.ZoneTimeToExpire.IsUnknown() { + if plan.ZoneTimeToExpire.ValueString() != state.ZoneTimeToExpire.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_time_to_expire", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneTimeToLive.IsNull() && !plan.ZoneTimeToLive.IsUnknown() && !state.ZoneTimeToLive.IsNull() && !state.ZoneTimeToLive.IsUnknown() { + if plan.ZoneTimeToLive.ValueString() != state.ZoneTimeToLive.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_time_to_live", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneTimeToRefresh.IsNull() && !plan.ZoneTimeToRefresh.IsUnknown() && !state.ZoneTimeToRefresh.IsNull() && !state.ZoneTimeToRefresh.IsUnknown() { + if plan.ZoneTimeToRefresh.ValueString() != state.ZoneTimeToRefresh.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_time_to_refresh", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneTimeToRetry.IsNull() && !plan.ZoneTimeToRetry.IsUnknown() && !state.ZoneTimeToRetry.IsNull() && !state.ZoneTimeToRetry.IsUnknown() { + if plan.ZoneTimeToRetry.ValueString() != state.ZoneTimeToRetry.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_time_to_retry", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if config.ZoneEmail.IsNull() || config.ZoneEmail.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_email is required.") + return + } + if config.ZoneName.IsNull() || config.ZoneName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_name is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 66: resources_core.FormatString(config.ZoneEmail), + 67: resources_core.FormatString(config.ZoneName), + 68: resources_core.FormatString(config.ZoneKind), + 69: resources_core.FormatString(config.ZoneMastersForSlave), + 70: resources_core.FormatString(config.ZoneTimeToRefresh), + 71: resources_core.FormatString(config.ZoneTimeToRetry), + 72: resources_core.FormatString(config.ZoneTimeToExpire), + 73: resources_core.FormatString(config.ZoneTimeToLive), + 284: resources_core.FormatString(config.ResourceRealm), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 110, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *DnszoneResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data DnszoneModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if data.ZoneEmail.IsNull() || data.ZoneEmail.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_email is required.") + return + } + if data.ZoneName.IsNull() || data.ZoneName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_name is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 110, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 66: resources_core.FormatString(data.ZoneEmail), + 67: resources_core.FormatString(data.ZoneName), + 68: resources_core.FormatString(data.ZoneKind), + 69: resources_core.FormatString(data.ZoneMastersForSlave), + 70: resources_core.FormatString(data.ZoneTimeToRefresh), + 71: resources_core.FormatString(data.ZoneTimeToRetry), + 72: resources_core.FormatString(data.ZoneTimeToExpire), + 73: resources_core.FormatString(data.ZoneTimeToLive), + 284: resources_core.FormatString(data.ResourceRealm), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 110, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 110, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "zoneEmail", Field: "ZoneEmail", Type: "string"}, + {Code: "zoneKind", Field: "ZoneKind", Type: "string"}, + {Code: "zoneMastersForSlave", Field: "ZoneMastersForSlave", Type: "string"}, + {Code: "zoneName", Field: "ZoneName", Type: "string"}, + {Code: "zoneTimeToExpire", Field: "ZoneTimeToExpire", Type: "string"}, + {Code: "zoneTimeToLive", Field: "ZoneTimeToLive", Type: "string"}, + {Code: "zoneTimeToRefresh", Field: "ZoneTimeToRefresh", Type: "string"}, + {Code: "zoneTimeToRetry", Field: "ZoneTimeToRetry", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DnszoneResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state DnszoneModel + 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.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.ID.ValueString(), 110, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "zoneEmail", Field: "ZoneEmail", Type: "string"}, + {Code: "zoneKind", Field: "ZoneKind", Type: "string"}, + {Code: "zoneMastersForSlave", Field: "ZoneMastersForSlave", Type: "string"}, + {Code: "zoneName", Field: "ZoneName", Type: "string"}, + {Code: "zoneTimeToExpire", Field: "ZoneTimeToExpire", Type: "string"}, + {Code: "zoneTimeToLive", Field: "ZoneTimeToLive", Type: "string"}, + {Code: "zoneTimeToRefresh", Field: "ZoneTimeToRefresh", Type: "string"}, + {Code: "zoneTimeToRetry", Field: "ZoneTimeToRetry", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *DnszoneResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan DnszoneModel + var state DnszoneModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 110, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "zoneEmail", Field: "ZoneEmail", Type: "string"}, + {Code: "zoneKind", Field: "ZoneKind", Type: "string"}, + {Code: "zoneMastersForSlave", Field: "ZoneMastersForSlave", Type: "string"}, + {Code: "zoneName", Field: "ZoneName", Type: "string"}, + {Code: "zoneTimeToExpire", Field: "ZoneTimeToExpire", Type: "string"}, + {Code: "zoneTimeToLive", Field: "ZoneTimeToLive", Type: "string"}, + {Code: "zoneTimeToRefresh", Field: "ZoneTimeToRefresh", Type: "string"}, + {Code: "zoneTimeToRetry", Field: "ZoneTimeToRetry", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DnszoneResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state DnszoneModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *DnszoneResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *DnszoneResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/111_dnsrecord_resource.go b/universal_rebuild/internal/resources_gen/111_dnsrecord_resource.go new file mode 100644 index 0000000..81d5f8f --- /dev/null +++ b/universal_rebuild/internal/resources_gen/111_dnsrecord_resource.go @@ -0,0 +1,471 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: dnsrecord +// Service ID: 111 + +var _ resource.Resource = &DnsrecordResource{} +var _ resource.ResourceWithModifyPlan = &DnsrecordResource{} +var _ resource.ResourceWithImportState = &DnsrecordResource{} + +type DnsrecordResource struct { + client *core.UniversalClient +} + +type DnsrecordModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + RecordInput types.String `tfsdk:"record_input"` + RecordName types.String `tfsdk:"record_name"` + RecordTTL types.Int64 `tfsdk:"record_t_t_l"` + RecordType types.String `tfsdk:"record_type"` + ZoneUid types.String `tfsdk:"zone_uid"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewDnsrecordResource() resource.Resource { + return &DnsrecordResource{} +} + +func (r *DnsrecordResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dnsrecord" +} + +func (r *DnsrecordResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "record_input": schema.StringAttribute{Required: true, MarkdownDescription: "Значение. Необходима валидация, в зависимости от типа записи. Должно быть заменено на UUID-внешнийIP"}, + "record_name": schema.StringAttribute{Required: true, MarkdownDescription: "Имя записи. Имя зоны в конце проставляется автоматически Не изменяется после создания."}, + "record_t_t_l": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(3600), MarkdownDescription: "Time-to-Leave записи. Раз в какое время запись будет обновлена Не изменяется после создания."}, + "record_type": schema.StringAttribute{Required: true, MarkdownDescription: "Тип DNS-записи Не изменяется после создания."}, + "zone_uid": schema.StringAttribute{Required: true, MarkdownDescription: "UUID экземпляра услуги DNS-зоны Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *DnsrecordResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *DnsrecordModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *DnsrecordModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan DnsrecordModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + planChanged := false + if !plan.ZoneUid.IsNull() && !plan.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, plan.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve zone_uid", err.Error()) + } else if resolvedZoneUid != "" && resolvedZoneUid != plan.ZoneUid.ValueString() { + plan.ZoneUid = types.StringValue(resolvedZoneUid) + planChanged = true + } + } + if planChanged { + resp.Diagnostics.Append(resp.Plan.Set(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.RecordName.IsNull() && !plan.RecordName.IsUnknown() && !state.RecordName.IsNull() && !state.RecordName.IsUnknown() { + if plan.RecordName.ValueString() != state.RecordName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить record_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.RecordTTL.IsNull() && !plan.RecordTTL.IsUnknown() && !state.RecordTTL.IsNull() && !state.RecordTTL.IsUnknown() { + if plan.RecordTTL.ValueInt64() != state.RecordTTL.ValueInt64() { + resp.Diagnostics.AddError("Нельзя изменить record_t_t_l", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.RecordType.IsNull() && !plan.RecordType.IsUnknown() && !state.RecordType.IsNull() && !state.RecordType.IsUnknown() { + if plan.RecordType.ValueString() != state.RecordType.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить record_type", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ZoneUid.IsNull() && !plan.ZoneUid.IsUnknown() && !state.ZoneUid.IsNull() && !state.ZoneUid.IsUnknown() { + if plan.ZoneUid.ValueString() != state.ZoneUid.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить zone_uid", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.RecordInput.IsNull() || config.RecordInput.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_input is required.") + return + } + if config.RecordName.IsNull() || config.RecordName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_name is required.") + return + } + if config.RecordType.IsNull() || config.RecordType.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_type is required.") + return + } + if config.ZoneUid.IsNull() || config.ZoneUid.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_uid is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + if !config.ZoneUid.IsNull() && !config.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, config.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve zone_uid", err.Error()) + } else if resolvedZoneUid != "" && resolvedZoneUid != config.ZoneUid.ValueString() { + config.ZoneUid = types.StringValue(resolvedZoneUid) + } + } + params := map[int]string{ + 75: resources_core.FormatString(config.ZoneUid), + 76: resources_core.FormatString(config.RecordType), + 77: resources_core.FormatString(config.RecordName), + 78: resources_core.FormatString(config.RecordInput), + 450: resources_core.FormatInt64(config.RecordTTL), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 111, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *DnsrecordResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data DnsrecordModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.RecordInput.IsNull() || data.RecordInput.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_input is required.") + return + } + if data.RecordName.IsNull() || data.RecordName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_name is required.") + return + } + if data.RecordType.IsNull() || data.RecordType.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "record_type is required.") + return + } + if data.ZoneUid.IsNull() || data.ZoneUid.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "zone_uid is required.") + return + } + if !data.ZoneUid.IsNull() && !data.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, data.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + if resolvedZoneUid != "" && resolvedZoneUid != data.ZoneUid.ValueString() { + data.ZoneUid = types.StringValue(resolvedZoneUid) + } + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 111, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 75: resources_core.FormatString(data.ZoneUid), + 76: resources_core.FormatString(data.RecordType), + 77: resources_core.FormatString(data.RecordName), + 78: resources_core.FormatString(data.RecordInput), + 450: resources_core.FormatInt64(data.RecordTTL), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 111, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 111, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "recordInput", Field: "RecordInput", Type: "string"}, + {Code: "recordName", Field: "RecordName", Type: "string"}, + {Code: "recordTTL", Field: "RecordTTL", Type: "int64"}, + {Code: "recordType", Field: "RecordType", Type: "string"}, + {Code: "zoneUid", Field: "ZoneUid", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + if !state.ZoneUid.IsNull() && !state.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, state.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve zone_uid", err.Error()) + } else if resolvedZoneUid != "" && resolvedZoneUid != state.ZoneUid.ValueString() { + state.ZoneUid = types.StringValue(resolvedZoneUid) + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DnsrecordResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state DnsrecordModel + 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.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.ID.ValueString(), 111, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "recordInput", Field: "RecordInput", Type: "string"}, + {Code: "recordName", Field: "RecordName", Type: "string"}, + {Code: "recordTTL", Field: "RecordTTL", Type: "int64"}, + {Code: "recordType", Field: "RecordType", Type: "string"}, + {Code: "zoneUid", Field: "ZoneUid", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + if !newState.ZoneUid.IsNull() && !newState.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, newState.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve zone_uid", err.Error()) + } else if resolvedZoneUid != "" && resolvedZoneUid != newState.ZoneUid.ValueString() { + newState.ZoneUid = types.StringValue(resolvedZoneUid) + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *DnsrecordResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan DnsrecordModel + var state DnsrecordModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + if !hasServiceParamChanges { + if plan.RecordInput.IsNull() != state.RecordInput.IsNull() || plan.RecordInput.IsUnknown() != state.RecordInput.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.RecordInput.IsNull() && !plan.RecordInput.IsUnknown() && !state.RecordInput.IsNull() && !state.RecordInput.IsUnknown() { + if plan.RecordInput.ValueString() != state.RecordInput.ValueString() { + hasServiceParamChanges = true + } + } + } + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{ + 256: resources_core.FormatString(plan.RecordInput), + } + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 111, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "recordInput", Field: "RecordInput", Type: "string"}, + {Code: "recordName", Field: "RecordName", Type: "string"}, + {Code: "recordTTL", Field: "RecordTTL", Type: "int64"}, + {Code: "recordType", Field: "RecordType", Type: "string"}, + {Code: "zoneUid", Field: "ZoneUid", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + if !state.ZoneUid.IsNull() && !state.ZoneUid.IsUnknown() { + resolvedZoneUid, err := r.client.ResolveRefSvcParamValue(ctx, 110, state.ZoneUid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve zone_uid", err.Error()) + } else if resolvedZoneUid != "" && resolvedZoneUid != state.ZoneUid.ValueString() { + state.ZoneUid = types.StringValue(resolvedZoneUid) + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DnsrecordResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state DnsrecordModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *DnsrecordResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *DnsrecordResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/112_tenant_resource.go b/universal_rebuild/internal/resources_gen/112_tenant_resource.go new file mode 100644 index 0000000..9ad6532 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/112_tenant_resource.go @@ -0,0 +1,352 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: tenant +// Service ID: 112 + +var _ resource.Resource = &TenantResource{} +var _ resource.ResourceWithModifyPlan = &TenantResource{} +var _ resource.ResourceWithImportState = &TenantResource{} + +type TenantResource struct { + client *core.UniversalClient +} + +type TenantModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + GrafanaOrgName types.String `tfsdk:"grafana_org_name"` + ResourceRealm types.String `tfsdk:"resource_realm"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewTenantResource() resource.Resource { + return &TenantResource{} +} + +func (r *TenantResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_tenant" +} + +func (r *TenantResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "grafana_org_name": schema.StringAttribute{Required: true, MarkdownDescription: "WZ-Код клиента Не изменяется после создания."}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *TenantResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *TenantModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *TenantModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan TenantModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.GrafanaOrgName.IsNull() && !plan.GrafanaOrgName.IsUnknown() && !state.GrafanaOrgName.IsNull() && !state.GrafanaOrgName.IsUnknown() { + if plan.GrafanaOrgName.ValueString() != state.GrafanaOrgName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить grafana_org_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.GrafanaOrgName.IsNull() || config.GrafanaOrgName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "grafana_org_name is required.") + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 239: resources_core.FormatString(config.GrafanaOrgName), + 240: resources_core.FormatString(config.ResourceRealm), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 112, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *TenantResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data TenantModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.GrafanaOrgName.IsNull() || data.GrafanaOrgName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "grafana_org_name is required.") + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 112, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 239: resources_core.FormatString(data.GrafanaOrgName), + 240: resources_core.FormatString(data.ResourceRealm), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 112, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 112, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "grafanaOrgName", Field: "GrafanaOrgName", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *TenantResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state TenantModel + 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.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.ID.ValueString(), 112, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "grafanaOrgName", Field: "GrafanaOrgName", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *TenantResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan TenantModel + var state TenantModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 112, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "grafanaOrgName", Field: "GrafanaOrgName", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *TenantResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state TenantModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *TenantResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *TenantResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/113_vc_complex_resource.go b/universal_rebuild/internal/resources_gen/113_vc_complex_resource.go new file mode 100644 index 0000000..fad5cf5 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/113_vc_complex_resource.go @@ -0,0 +1,523 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: vc_complex +// Service ID: 113 + +var _ resource.Resource = &VcComplexResource{} +var _ resource.ResourceWithModifyPlan = &VcComplexResource{} +var _ resource.ResourceWithImportState = &VcComplexResource{} + +type VcComplexResource struct { + client *core.UniversalClient +} + +type VcComplexModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + CpuAllocated types.String `tfsdk:"cpu_allocated"` + CpuGuaranteed types.Int64 `tfsdk:"cpu_guaranteed"` + IpSpaceName types.String `tfsdk:"ip_space_name"` + MemAllocated types.Int64 `tfsdk:"mem_allocated"` + MemGuaranteed types.Int64 `tfsdk:"mem_guaranteed"` + NeedEnableAVI types.Bool `tfsdk:"need_enable_a_v_i"` + NeedExternalAddressSNAT types.Bool `tfsdk:"need_external_address_s_n_a_t"` + ResourceRealm types.String `tfsdk:"resource_realm"` + SegroupName types.String `tfsdk:"segroup_name"` + StorageConfig types.String `tfsdk:"storage_config"` + VIPCount types.Int64 `tfsdk:"v_i_p_count"` + VappName types.String `tfsdk:"vapp_name"` + VdcNetworkPool types.String `tfsdk:"vdc_network_pool"` + VdcProviderGateway types.String `tfsdk:"vdc_provider_gateway"` + VirtualServicesCount types.String `tfsdk:"virtual_services_count"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewVcComplexResource() resource.Resource { + return &VcComplexResource{} +} + +func (r *VcComplexResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_vc_complex" +} + +func (r *VcComplexResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "cpu_allocated": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("1"), MarkdownDescription: "шт Не изменяется после создания."}, + "cpu_guaranteed": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(20), MarkdownDescription: "Не изменяется после создания."}, + "ip_space_name": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("internet-ipv4-v1"), MarkdownDescription: "Имя ip Space для внешнего IP. Целесообразнее брать самый дешёвый, так как это vip для исходящего трафика. Необходимо задавать если включен needExternalAddressSNAT Не изменяется после создания."}, + "mem_allocated": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(10), MarkdownDescription: "gb Не изменяется после создания."}, + "mem_guaranteed": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(20), MarkdownDescription: "Не изменяется после создания."}, + "need_enable_a_v_i": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "Включает AVI в Cloud Director Не изменяется после создания."}, + "need_external_address_s_n_a_t": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(true), MarkdownDescription: "Выделяет внешний IP на Edge. Используется для SNAT всего трафика Не изменяется после создания."}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "segroup_name": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("SEGROUP-SANDBOX-CL1-SHARED-01"), MarkdownDescription: "Наименование segroup, в котором будут выделяться пулы на AVI Не изменяется после создания."}, + "storage_config": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("[{\"name\": \"\", \"size\": 1024}]"), MarkdownDescription: "Описывается как массив объектов, где описывается имя политики и её размер Не изменяется после создания."}, + "v_i_p_count": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(0), MarkdownDescription: "ш Не изменяется после создания."}, + "vapp_name": schema.StringAttribute{Required: true, MarkdownDescription: "Имя vApp Не изменяется после создания."}, + "vdc_network_pool": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("nsxt-sandbox-geneve-np"), MarkdownDescription: "Не изменяется после создания."}, + "vdc_provider_gateway": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("sandbox-v1cl1-pvdc"), MarkdownDescription: "Взять из свойств ресурсной платформы.
Путь .vcd.providerVdc - взять KEY

providerGateway Cloud Director. Влияет ресурсы будут предоставлены. Является полем (List<String>) в свойствах рес. платформы ЛК, но сам параметр передаётся только как один String Не изменяется после создания."}, + "virtual_services_count": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("1"), MarkdownDescription: "Кол-во виртуальных сервисов, которые выделяются на AVI. Во избежании коллапса пока выделяется до 4 Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *VcComplexResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *VcComplexModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *VcComplexModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan VcComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.CpuAllocated.IsNull() && !plan.CpuAllocated.IsUnknown() && !state.CpuAllocated.IsNull() && !state.CpuAllocated.IsUnknown() { + if plan.CpuAllocated.ValueString() != state.CpuAllocated.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить cpu_allocated", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.CpuGuaranteed.IsNull() && !plan.CpuGuaranteed.IsUnknown() && !state.CpuGuaranteed.IsNull() && !state.CpuGuaranteed.IsUnknown() { + if plan.CpuGuaranteed.ValueInt64() != state.CpuGuaranteed.ValueInt64() { + resp.Diagnostics.AddError("Нельзя изменить cpu_guaranteed", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.IpSpaceName.IsNull() && !plan.IpSpaceName.IsUnknown() && !state.IpSpaceName.IsNull() && !state.IpSpaceName.IsUnknown() { + if plan.IpSpaceName.ValueString() != state.IpSpaceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить ip_space_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.MemAllocated.IsNull() && !plan.MemAllocated.IsUnknown() && !state.MemAllocated.IsNull() && !state.MemAllocated.IsUnknown() { + if plan.MemAllocated.ValueInt64() != state.MemAllocated.ValueInt64() { + resp.Diagnostics.AddError("Нельзя изменить mem_allocated", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.MemGuaranteed.IsNull() && !plan.MemGuaranteed.IsUnknown() && !state.MemGuaranteed.IsNull() && !state.MemGuaranteed.IsUnknown() { + if plan.MemGuaranteed.ValueInt64() != state.MemGuaranteed.ValueInt64() { + resp.Diagnostics.AddError("Нельзя изменить mem_guaranteed", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.NeedEnableAVI.IsNull() && !plan.NeedEnableAVI.IsUnknown() && !state.NeedEnableAVI.IsNull() && !state.NeedEnableAVI.IsUnknown() { + if plan.NeedEnableAVI.ValueBool() != state.NeedEnableAVI.ValueBool() { + resp.Diagnostics.AddError("Нельзя изменить need_enable_a_v_i", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.NeedExternalAddressSNAT.IsNull() && !plan.NeedExternalAddressSNAT.IsUnknown() && !state.NeedExternalAddressSNAT.IsNull() && !state.NeedExternalAddressSNAT.IsUnknown() { + if plan.NeedExternalAddressSNAT.ValueBool() != state.NeedExternalAddressSNAT.ValueBool() { + resp.Diagnostics.AddError("Нельзя изменить need_external_address_s_n_a_t", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.SegroupName.IsNull() && !plan.SegroupName.IsUnknown() && !state.SegroupName.IsNull() && !state.SegroupName.IsUnknown() { + if plan.SegroupName.ValueString() != state.SegroupName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить segroup_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.StorageConfig.IsNull() && !plan.StorageConfig.IsUnknown() && !state.StorageConfig.IsNull() && !state.StorageConfig.IsUnknown() { + if plan.StorageConfig.ValueString() != state.StorageConfig.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить storage_config", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.VIPCount.IsNull() && !plan.VIPCount.IsUnknown() && !state.VIPCount.IsNull() && !state.VIPCount.IsUnknown() { + if plan.VIPCount.ValueInt64() != state.VIPCount.ValueInt64() { + resp.Diagnostics.AddError("Нельзя изменить v_i_p_count", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.VappName.IsNull() && !plan.VappName.IsUnknown() && !state.VappName.IsNull() && !state.VappName.IsUnknown() { + if plan.VappName.ValueString() != state.VappName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить vapp_name", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.VdcNetworkPool.IsNull() && !plan.VdcNetworkPool.IsUnknown() && !state.VdcNetworkPool.IsNull() && !state.VdcNetworkPool.IsUnknown() { + if plan.VdcNetworkPool.ValueString() != state.VdcNetworkPool.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить vdc_network_pool", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.VdcProviderGateway.IsNull() && !plan.VdcProviderGateway.IsUnknown() && !state.VdcProviderGateway.IsNull() && !state.VdcProviderGateway.IsUnknown() { + if plan.VdcProviderGateway.ValueString() != state.VdcProviderGateway.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить vdc_provider_gateway", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.VirtualServicesCount.IsNull() && !plan.VirtualServicesCount.IsUnknown() && !state.VirtualServicesCount.IsNull() && !state.VirtualServicesCount.IsUnknown() { + if plan.VirtualServicesCount.ValueString() != state.VirtualServicesCount.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить virtual_services_count", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if config.VappName.IsNull() || config.VappName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "vapp_name is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 332: resources_core.FormatString(config.ResourceRealm), + 334: resources_core.FormatString(config.VappName), + 358: resources_core.FormatString(config.VdcProviderGateway), + 359: resources_core.FormatString(config.VirtualServicesCount), + 360: resources_core.FormatString(config.IpSpaceName), + 399: resources_core.FormatString(config.StorageConfig), + 400: resources_core.FormatString(config.VdcNetworkPool), + 401: resources_core.FormatInt64(config.CpuGuaranteed), + 402: resources_core.FormatInt64(config.MemGuaranteed), + 403: resources_core.FormatString(config.SegroupName), + 404: resources_core.FormatBool(config.NeedExternalAddressSNAT), + 405: resources_core.FormatBool(config.NeedEnableAVI), + 566: resources_core.FormatString(config.CpuAllocated), + 567: resources_core.FormatInt64(config.MemAllocated), + 568: resources_core.FormatInt64(config.VIPCount), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 113, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *VcComplexResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data VcComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if data.VappName.IsNull() || data.VappName.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "vapp_name is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 113, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 332: resources_core.FormatString(data.ResourceRealm), + 334: resources_core.FormatString(data.VappName), + 358: resources_core.FormatString(data.VdcProviderGateway), + 359: resources_core.FormatString(data.VirtualServicesCount), + 360: resources_core.FormatString(data.IpSpaceName), + 399: resources_core.FormatString(data.StorageConfig), + 400: resources_core.FormatString(data.VdcNetworkPool), + 401: resources_core.FormatInt64(data.CpuGuaranteed), + 402: resources_core.FormatInt64(data.MemGuaranteed), + 403: resources_core.FormatString(data.SegroupName), + 404: resources_core.FormatBool(data.NeedExternalAddressSNAT), + 405: resources_core.FormatBool(data.NeedEnableAVI), + 566: resources_core.FormatString(data.CpuAllocated), + 567: resources_core.FormatInt64(data.MemAllocated), + 568: resources_core.FormatInt64(data.VIPCount), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 113, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 113, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "cpuAllocated", Field: "CpuAllocated", Type: "string"}, + {Code: "cpuGuaranteed", Field: "CpuGuaranteed", Type: "int64"}, + {Code: "ipSpaceName", Field: "IpSpaceName", Type: "string"}, + {Code: "memAllocated", Field: "MemAllocated", Type: "int64"}, + {Code: "memGuaranteed", Field: "MemGuaranteed", Type: "int64"}, + {Code: "needEnableAVI", Field: "NeedEnableAVI", Type: "bool"}, + {Code: "needExternalAddressSNAT", Field: "NeedExternalAddressSNAT", Type: "bool"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "segroupName", Field: "SegroupName", Type: "string"}, + {Code: "storageConfig", Field: "StorageConfig", Type: "string"}, + {Code: "vIPCount", Field: "VIPCount", Type: "int64"}, + {Code: "vappName", Field: "VappName", Type: "string"}, + {Code: "vdcNetworkPool", Field: "VdcNetworkPool", Type: "string"}, + {Code: "vdcProviderGateway", Field: "VdcProviderGateway", Type: "string"}, + {Code: "virtualServicesCount", Field: "VirtualServicesCount", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *VcComplexResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state VcComplexModel + 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.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.ID.ValueString(), 113, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "cpuAllocated", Field: "CpuAllocated", Type: "string"}, + {Code: "cpuGuaranteed", Field: "CpuGuaranteed", Type: "int64"}, + {Code: "ipSpaceName", Field: "IpSpaceName", Type: "string"}, + {Code: "memAllocated", Field: "MemAllocated", Type: "int64"}, + {Code: "memGuaranteed", Field: "MemGuaranteed", Type: "int64"}, + {Code: "needEnableAVI", Field: "NeedEnableAVI", Type: "bool"}, + {Code: "needExternalAddressSNAT", Field: "NeedExternalAddressSNAT", Type: "bool"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "segroupName", Field: "SegroupName", Type: "string"}, + {Code: "storageConfig", Field: "StorageConfig", Type: "string"}, + {Code: "vIPCount", Field: "VIPCount", Type: "int64"}, + {Code: "vappName", Field: "VappName", Type: "string"}, + {Code: "vdcNetworkPool", Field: "VdcNetworkPool", Type: "string"}, + {Code: "vdcProviderGateway", Field: "VdcProviderGateway", Type: "string"}, + {Code: "virtualServicesCount", Field: "VirtualServicesCount", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *VcComplexResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan VcComplexModel + var state VcComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 113, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "cpuAllocated", Field: "CpuAllocated", Type: "string"}, + {Code: "cpuGuaranteed", Field: "CpuGuaranteed", Type: "int64"}, + {Code: "ipSpaceName", Field: "IpSpaceName", Type: "string"}, + {Code: "memAllocated", Field: "MemAllocated", Type: "int64"}, + {Code: "memGuaranteed", Field: "MemGuaranteed", Type: "int64"}, + {Code: "needEnableAVI", Field: "NeedEnableAVI", Type: "bool"}, + {Code: "needExternalAddressSNAT", Field: "NeedExternalAddressSNAT", Type: "bool"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "segroupName", Field: "SegroupName", Type: "string"}, + {Code: "storageConfig", Field: "StorageConfig", Type: "string"}, + {Code: "vIPCount", Field: "VIPCount", Type: "int64"}, + {Code: "vappName", Field: "VappName", Type: "string"}, + {Code: "vdcNetworkPool", Field: "VdcNetworkPool", Type: "string"}, + {Code: "vdcProviderGateway", Field: "VdcProviderGateway", Type: "string"}, + {Code: "virtualServicesCount", Field: "VirtualServicesCount", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *VcComplexResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state VcComplexModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *VcComplexResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *VcComplexResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/114_gitea_complex_resource.go b/universal_rebuild/internal/resources_gen/114_gitea_complex_resource.go new file mode 100644 index 0000000..c5d4586 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/114_gitea_complex_resource.go @@ -0,0 +1,305 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: gitea_complex +// Service ID: 114 + +var _ resource.Resource = &GiteaComplexResource{} +var _ resource.ResourceWithModifyPlan = &GiteaComplexResource{} +var _ resource.ResourceWithImportState = &GiteaComplexResource{} + +type GiteaComplexResource struct { + client *core.UniversalClient +} + +type GiteaComplexModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewGiteaComplexResource() resource.Resource { + return &GiteaComplexResource{} +} + +func (r *GiteaComplexResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_gitea_complex" +} + +func (r *GiteaComplexResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *GiteaComplexResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *GiteaComplexModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *GiteaComplexModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan GiteaComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{} + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 114, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *GiteaComplexResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data GiteaComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 114, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{} + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 114, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 114, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *GiteaComplexResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state GiteaComplexModel + 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.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.ID.ValueString(), 114, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *GiteaComplexResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan GiteaComplexModel + var state GiteaComplexModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 114, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *GiteaComplexResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state GiteaComplexModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *GiteaComplexResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *GiteaComplexResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/115_mariadb_resource.go b/universal_rebuild/internal/resources_gen/115_mariadb_resource.go new file mode 100644 index 0000000..31dda26 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/115_mariadb_resource.go @@ -0,0 +1,576 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: mariadb +// Service ID: 115 + +var _ resource.Resource = &MariadbResource{} +var _ resource.ResourceWithModifyPlan = &MariadbResource{} +var _ resource.ResourceWithImportState = &MariadbResource{} + +type MariadbResource struct { + client *core.UniversalClient +} + +type MariadbModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + AppVersion types.String `tfsdk:"app_version"` + AutoScale types.Bool `tfsdk:"auto_scale"` + AutoScalePercentage types.Int64 `tfsdk:"auto_scale_percentage"` + AutoScaleQuotaGb types.Int64 `tfsdk:"auto_scale_quota_gb"` + AutoScaleTechWindow types.Int64 `tfsdk:"auto_scale_tech_window"` + ExtBACKUPSCHEDULE types.String `tfsdk:"ext__b_a_c_k_u_p__s_c_h_e_d_u_l_e"` + IpSpaceNameMaster types.String `tfsdk:"ip_space_name_master"` + NeedExternalAddressMaster types.Bool `tfsdk:"need_external_address_master"` + ResourceCPU types.Int64 `tfsdk:"resource_c_p_u"` + ResourceDisk types.Int64 `tfsdk:"resource_disk"` + ResourceInstances types.Int64 `tfsdk:"resource_instances"` + ResourceMemory types.Int64 `tfsdk:"resource_memory"` + ResourceRealm types.String `tfsdk:"resource_realm"` + S3Uid types.String `tfsdk:"s3_uid"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewMariadbResource() resource.Resource { + return &MariadbResource{} +} + +func (r *MariadbResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_mariadb" +} + +func (r *MariadbResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "app_version": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("9.4.0"), MarkdownDescription: "Версия MySQL Не изменяется после создания."}, + "auto_scale": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "Включает автоскейлинг PV. При включении параметра необходимо настроить autoScalePercentage и autoScaleTechWindow. Алерт при срабатывании вызывает modify у текущей услуги"}, + "auto_scale_percentage": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(10), MarkdownDescription: "Требует включения autoScale. Позволяет указать в процентах расширение от текущего макс объема"}, + "auto_scale_quota_gb": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "Квота для autoScale"}, + "auto_scale_tech_window": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(0), MarkdownDescription: "Требует включения autoScale. Окно обновления (пока не реализовано). Указывается час в виде Integer (0 / 5 / 12 / 23)"}, + "ext__b_a_c_k_u_p__s_c_h_e_d_u_l_e": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("0 * * * *"), MarkdownDescription: "Не обязательный. Время запуска бекапа"}, + "ip_space_name_master": schema.StringAttribute{Optional: true, MarkdownDescription: "Имя ipSpace для публикации VIP master. Не может быть пустым, если включен needExternalAddressMaster"}, + "need_external_address_master": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "Выделяет внешний (белый) IP для доступа к master"}, + "resource_c_p_u": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(500), MarkdownDescription: "Квота ядра пода (milicores)"}, + "resource_disk": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "Квота диска (Указывается в GIGAbytes)"}, + "resource_instances": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "Количество узлов"}, + "resource_memory": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1024), MarkdownDescription: "Квота памяти пода (MBytes)"}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "s3_uid": schema.StringAttribute{Required: true, MarkdownDescription: "Экземпляр (учетная запись) S3 для резервного копирования. Резервное копирование обязательно Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(true)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *MariadbResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *MariadbModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *MariadbModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan MariadbModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + planChanged := false + if !plan.S3Uid.IsNull() && !plan.S3Uid.IsUnknown() { + resolvedS3Uid, err := r.client.ResolveRefSvcParamValue(ctx, 12, plan.S3Uid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve s3_uid", err.Error()) + } else if resolvedS3Uid != "" && resolvedS3Uid != plan.S3Uid.ValueString() { + plan.S3Uid = types.StringValue(resolvedS3Uid) + planChanged = true + } + } + if planChanged { + resp.Diagnostics.Append(resp.Plan.Set(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.AppVersion.IsNull() && !plan.AppVersion.IsUnknown() && !state.AppVersion.IsNull() && !state.AppVersion.IsUnknown() { + if plan.AppVersion.ValueString() != state.AppVersion.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить app_version", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.S3Uid.IsNull() && !plan.S3Uid.IsUnknown() && !state.S3Uid.IsNull() && !state.S3Uid.IsUnknown() { + if plan.S3Uid.ValueString() != state.S3Uid.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить s3_uid", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if config.S3Uid.IsNull() || config.S3Uid.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "s3_uid is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + if !config.S3Uid.IsNull() && !config.S3Uid.IsUnknown() { + resolvedS3Uid, err := r.client.ResolveRefSvcParamValue(ctx, 12, config.S3Uid.ValueString()) + if err != nil { + resp.Diagnostics.AddWarning("Failed to resolve s3_uid", err.Error()) + } else if resolvedS3Uid != "" && resolvedS3Uid != config.S3Uid.ValueString() { + config.S3Uid = types.StringValue(resolvedS3Uid) + } + } + params := map[int]string{ + 422: resources_core.FormatString(config.ResourceRealm), + 424: resources_core.FormatInt64(config.ResourceCPU), + 425: resources_core.FormatInt64(config.ResourceMemory), + 426: resources_core.FormatInt64(config.ResourceDisk), + 427: resources_core.FormatInt64(config.ResourceInstances), + 428: resources_core.FormatBool(config.NeedExternalAddressMaster), + 429: resources_core.FormatString(config.IpSpaceNameMaster), + 430: resources_core.FormatString(config.ExtBACKUPSCHEDULE), + 431: resources_core.FormatString(config.AppVersion), + 432: resources_core.FormatBool(config.AutoScale), + 433: resources_core.FormatInt64(config.AutoScalePercentage), + 434: resources_core.FormatInt64(config.AutoScaleTechWindow), + 435: resources_core.FormatInt64(config.AutoScaleQuotaGb), + 459: resources_core.FormatString(config.S3Uid), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 115, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *MariadbResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data MariadbModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + if data.S3Uid.IsNull() || data.S3Uid.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "s3_uid is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 115, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 422: resources_core.FormatString(data.ResourceRealm), + 424: resources_core.FormatInt64(data.ResourceCPU), + 425: resources_core.FormatInt64(data.ResourceMemory), + 426: resources_core.FormatInt64(data.ResourceDisk), + 427: resources_core.FormatInt64(data.ResourceInstances), + 428: resources_core.FormatBool(data.NeedExternalAddressMaster), + 429: resources_core.FormatString(data.IpSpaceNameMaster), + 430: resources_core.FormatString(data.ExtBACKUPSCHEDULE), + 431: resources_core.FormatString(data.AppVersion), + 432: resources_core.FormatBool(data.AutoScale), + 433: resources_core.FormatInt64(data.AutoScalePercentage), + 434: resources_core.FormatInt64(data.AutoScaleTechWindow), + 435: resources_core.FormatInt64(data.AutoScaleQuotaGb), + 459: resources_core.FormatString(data.S3Uid), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 115, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 115, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "appVersion", Field: "AppVersion", Type: "string"}, + {Code: "autoScale", Field: "AutoScale", Type: "bool"}, + {Code: "autoScalePercentage", Field: "AutoScalePercentage", Type: "int64"}, + {Code: "autoScaleQuotaGb", Field: "AutoScaleQuotaGb", Type: "int64"}, + {Code: "autoScaleTechWindow", Field: "AutoScaleTechWindow", Type: "int64"}, + {Code: "ext_BACKUP_SCHEDULE", Field: "ExtBACKUPSCHEDULE", Type: "string"}, + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *MariadbResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state MariadbModel + 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.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.ID.ValueString(), 115, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "appVersion", Field: "AppVersion", Type: "string"}, + {Code: "autoScale", Field: "AutoScale", Type: "bool"}, + {Code: "autoScalePercentage", Field: "AutoScalePercentage", Type: "int64"}, + {Code: "autoScaleQuotaGb", Field: "AutoScaleQuotaGb", Type: "int64"}, + {Code: "autoScaleTechWindow", Field: "AutoScaleTechWindow", Type: "int64"}, + {Code: "ext_BACKUP_SCHEDULE", Field: "ExtBACKUPSCHEDULE", Type: "string"}, + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *MariadbResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan MariadbModel + var state MariadbModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + if !hasServiceParamChanges { + if plan.ResourceCPU.IsNull() != state.ResourceCPU.IsNull() || plan.ResourceCPU.IsUnknown() != state.ResourceCPU.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceCPU.IsNull() && !plan.ResourceCPU.IsUnknown() && !state.ResourceCPU.IsNull() && !state.ResourceCPU.IsUnknown() { + if plan.ResourceCPU.ValueInt64() != state.ResourceCPU.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceMemory.IsNull() != state.ResourceMemory.IsNull() || plan.ResourceMemory.IsUnknown() != state.ResourceMemory.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceMemory.IsNull() && !plan.ResourceMemory.IsUnknown() && !state.ResourceMemory.IsNull() && !state.ResourceMemory.IsUnknown() { + if plan.ResourceMemory.ValueInt64() != state.ResourceMemory.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceInstances.IsNull() != state.ResourceInstances.IsNull() || plan.ResourceInstances.IsUnknown() != state.ResourceInstances.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceInstances.IsNull() && !plan.ResourceInstances.IsUnknown() && !state.ResourceInstances.IsNull() && !state.ResourceInstances.IsUnknown() { + if plan.ResourceInstances.ValueInt64() != state.ResourceInstances.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceDisk.IsNull() != state.ResourceDisk.IsNull() || plan.ResourceDisk.IsUnknown() != state.ResourceDisk.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceDisk.IsNull() && !plan.ResourceDisk.IsUnknown() && !state.ResourceDisk.IsNull() && !state.ResourceDisk.IsUnknown() { + if plan.ResourceDisk.ValueInt64() != state.ResourceDisk.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.NeedExternalAddressMaster.IsNull() != state.NeedExternalAddressMaster.IsNull() || plan.NeedExternalAddressMaster.IsUnknown() != state.NeedExternalAddressMaster.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.NeedExternalAddressMaster.IsNull() && !plan.NeedExternalAddressMaster.IsUnknown() && !state.NeedExternalAddressMaster.IsNull() && !state.NeedExternalAddressMaster.IsUnknown() { + if plan.NeedExternalAddressMaster.ValueBool() != state.NeedExternalAddressMaster.ValueBool() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.IpSpaceNameMaster.IsNull() != state.IpSpaceNameMaster.IsNull() || plan.IpSpaceNameMaster.IsUnknown() != state.IpSpaceNameMaster.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.IpSpaceNameMaster.IsNull() && !plan.IpSpaceNameMaster.IsUnknown() && !state.IpSpaceNameMaster.IsNull() && !state.IpSpaceNameMaster.IsUnknown() { + if plan.IpSpaceNameMaster.ValueString() != state.IpSpaceNameMaster.ValueString() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ExtBACKUPSCHEDULE.IsNull() != state.ExtBACKUPSCHEDULE.IsNull() || plan.ExtBACKUPSCHEDULE.IsUnknown() != state.ExtBACKUPSCHEDULE.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ExtBACKUPSCHEDULE.IsNull() && !plan.ExtBACKUPSCHEDULE.IsUnknown() && !state.ExtBACKUPSCHEDULE.IsNull() && !state.ExtBACKUPSCHEDULE.IsUnknown() { + if plan.ExtBACKUPSCHEDULE.ValueString() != state.ExtBACKUPSCHEDULE.ValueString() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.AutoScale.IsNull() != state.AutoScale.IsNull() || plan.AutoScale.IsUnknown() != state.AutoScale.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.AutoScale.IsNull() && !plan.AutoScale.IsUnknown() && !state.AutoScale.IsNull() && !state.AutoScale.IsUnknown() { + if plan.AutoScale.ValueBool() != state.AutoScale.ValueBool() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.AutoScalePercentage.IsNull() != state.AutoScalePercentage.IsNull() || plan.AutoScalePercentage.IsUnknown() != state.AutoScalePercentage.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.AutoScalePercentage.IsNull() && !plan.AutoScalePercentage.IsUnknown() && !state.AutoScalePercentage.IsNull() && !state.AutoScalePercentage.IsUnknown() { + if plan.AutoScalePercentage.ValueInt64() != state.AutoScalePercentage.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.AutoScaleTechWindow.IsNull() != state.AutoScaleTechWindow.IsNull() || plan.AutoScaleTechWindow.IsUnknown() != state.AutoScaleTechWindow.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.AutoScaleTechWindow.IsNull() && !plan.AutoScaleTechWindow.IsUnknown() && !state.AutoScaleTechWindow.IsNull() && !state.AutoScaleTechWindow.IsUnknown() { + if plan.AutoScaleTechWindow.ValueInt64() != state.AutoScaleTechWindow.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.AutoScaleQuotaGb.IsNull() != state.AutoScaleQuotaGb.IsNull() || plan.AutoScaleQuotaGb.IsUnknown() != state.AutoScaleQuotaGb.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.AutoScaleQuotaGb.IsNull() && !plan.AutoScaleQuotaGb.IsUnknown() && !state.AutoScaleQuotaGb.IsNull() && !state.AutoScaleQuotaGb.IsUnknown() { + if plan.AutoScaleQuotaGb.ValueInt64() != state.AutoScaleQuotaGb.ValueInt64() { + hasServiceParamChanges = true + } + } + } + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{ + 436: resources_core.FormatInt64(plan.ResourceCPU), + 437: resources_core.FormatInt64(plan.ResourceMemory), + 438: resources_core.FormatInt64(plan.ResourceInstances), + 439: resources_core.FormatInt64(plan.ResourceDisk), + 440: resources_core.FormatBool(plan.NeedExternalAddressMaster), + 441: resources_core.FormatString(plan.IpSpaceNameMaster), + 442: resources_core.FormatString(plan.ExtBACKUPSCHEDULE), + 443: resources_core.FormatBool(plan.AutoScale), + 444: resources_core.FormatInt64(plan.AutoScalePercentage), + 445: resources_core.FormatInt64(plan.AutoScaleTechWindow), + 446: resources_core.FormatInt64(plan.AutoScaleQuotaGb), + } + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 115, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "appVersion", Field: "AppVersion", Type: "string"}, + {Code: "autoScale", Field: "AutoScale", Type: "bool"}, + {Code: "autoScalePercentage", Field: "AutoScalePercentage", Type: "int64"}, + {Code: "autoScaleQuotaGb", Field: "AutoScaleQuotaGb", Type: "int64"}, + {Code: "autoScaleTechWindow", Field: "AutoScaleTechWindow", Type: "int64"}, + {Code: "ext_BACKUP_SCHEDULE", Field: "ExtBACKUPSCHEDULE", Type: "string"}, + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *MariadbResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state MariadbModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *MariadbResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *MariadbResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/116_kafka_resource.go b/universal_rebuild/internal/resources_gen/116_kafka_resource.go new file mode 100644 index 0000000..9174ad1 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/116_kafka_resource.go @@ -0,0 +1,466 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: kafka +// Service ID: 116 + +var _ resource.Resource = &KafkaResource{} +var _ resource.ResourceWithModifyPlan = &KafkaResource{} +var _ resource.ResourceWithImportState = &KafkaResource{} + +type KafkaResource struct { + client *core.UniversalClient +} + +type KafkaModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + IpSpaceNameMaster types.String `tfsdk:"ip_space_name_master"` + NeedExternalAddressMaster types.Bool `tfsdk:"need_external_address_master"` + ResourceCPU types.Int64 `tfsdk:"resource_c_p_u"` + ResourceDisk types.Int64 `tfsdk:"resource_disk"` + ResourceInstances types.Int64 `tfsdk:"resource_instances"` + ResourceMemory types.Int64 `tfsdk:"resource_memory"` + ResourceRealm types.String `tfsdk:"resource_realm"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewKafkaResource() resource.Resource { + return &KafkaResource{} +} + +func (r *KafkaResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_kafka" +} + +func (r *KafkaResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "ip_space_name_master": schema.StringAttribute{Optional: true, MarkdownDescription: "Если включен предыдущий параметр, то поле необходимо заполнить. Пример: `internet-no-antiddos-v1`"}, + "need_external_address_master": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "Флаг, определяющий, нужно ли выделять внешний IP для доступа к master-брокеру. Пример: `true` или `false`"}, + "resource_c_p_u": schema.Int64Attribute{Required: true, MarkdownDescription: "Пример: `2000`"}, + "resource_disk": schema.Int64Attribute{Required: true, MarkdownDescription: "Пример: `20`"}, + "resource_instances": schema.Int64Attribute{Required: true, MarkdownDescription: "Пример: `2`"}, + "resource_memory": schema.Int64Attribute{Required: true, MarkdownDescription: "Пример: `2048`"}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Выбрать платформу из списка Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(true)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *KafkaResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *KafkaModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *KafkaModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan KafkaModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceCPU.IsNull() || config.ResourceCPU.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_c_p_u is required.") + return + } + if config.ResourceDisk.IsNull() || config.ResourceDisk.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_disk is required.") + return + } + if config.ResourceInstances.IsNull() || config.ResourceInstances.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_instances is required.") + return + } + if config.ResourceMemory.IsNull() || config.ResourceMemory.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_memory is required.") + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 461: resources_core.FormatInt64(config.ResourceInstances), + 462: resources_core.FormatInt64(config.ResourceMemory), + 463: resources_core.FormatInt64(config.ResourceCPU), + 464: resources_core.FormatInt64(config.ResourceDisk), + 465: resources_core.FormatBool(config.NeedExternalAddressMaster), + 466: resources_core.FormatString(config.IpSpaceNameMaster), + 469: resources_core.FormatString(config.ResourceRealm), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 116, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *KafkaResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data KafkaModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceCPU.IsNull() || data.ResourceCPU.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_c_p_u is required.") + return + } + if data.ResourceDisk.IsNull() || data.ResourceDisk.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_disk is required.") + return + } + if data.ResourceInstances.IsNull() || data.ResourceInstances.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_instances is required.") + return + } + if data.ResourceMemory.IsNull() || data.ResourceMemory.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_memory is required.") + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 116, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 461: resources_core.FormatInt64(data.ResourceInstances), + 462: resources_core.FormatInt64(data.ResourceMemory), + 463: resources_core.FormatInt64(data.ResourceCPU), + 464: resources_core.FormatInt64(data.ResourceDisk), + 465: resources_core.FormatBool(data.NeedExternalAddressMaster), + 466: resources_core.FormatString(data.IpSpaceNameMaster), + 469: resources_core.FormatString(data.ResourceRealm), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 116, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 116, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *KafkaResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state KafkaModel + 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.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.ID.ValueString(), 116, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *KafkaResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan KafkaModel + var state KafkaModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + if !hasServiceParamChanges { + if plan.ResourceInstances.IsNull() != state.ResourceInstances.IsNull() || plan.ResourceInstances.IsUnknown() != state.ResourceInstances.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceInstances.IsNull() && !plan.ResourceInstances.IsUnknown() && !state.ResourceInstances.IsNull() && !state.ResourceInstances.IsUnknown() { + if plan.ResourceInstances.ValueInt64() != state.ResourceInstances.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceMemory.IsNull() != state.ResourceMemory.IsNull() || plan.ResourceMemory.IsUnknown() != state.ResourceMemory.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceMemory.IsNull() && !plan.ResourceMemory.IsUnknown() && !state.ResourceMemory.IsNull() && !state.ResourceMemory.IsUnknown() { + if plan.ResourceMemory.ValueInt64() != state.ResourceMemory.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceCPU.IsNull() != state.ResourceCPU.IsNull() || plan.ResourceCPU.IsUnknown() != state.ResourceCPU.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceCPU.IsNull() && !plan.ResourceCPU.IsUnknown() && !state.ResourceCPU.IsNull() && !state.ResourceCPU.IsUnknown() { + if plan.ResourceCPU.ValueInt64() != state.ResourceCPU.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceDisk.IsNull() != state.ResourceDisk.IsNull() || plan.ResourceDisk.IsUnknown() != state.ResourceDisk.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceDisk.IsNull() && !plan.ResourceDisk.IsUnknown() && !state.ResourceDisk.IsNull() && !state.ResourceDisk.IsUnknown() { + if plan.ResourceDisk.ValueInt64() != state.ResourceDisk.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.NeedExternalAddressMaster.IsNull() != state.NeedExternalAddressMaster.IsNull() || plan.NeedExternalAddressMaster.IsUnknown() != state.NeedExternalAddressMaster.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.NeedExternalAddressMaster.IsNull() && !plan.NeedExternalAddressMaster.IsUnknown() && !state.NeedExternalAddressMaster.IsNull() && !state.NeedExternalAddressMaster.IsUnknown() { + if plan.NeedExternalAddressMaster.ValueBool() != state.NeedExternalAddressMaster.ValueBool() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.IpSpaceNameMaster.IsNull() != state.IpSpaceNameMaster.IsNull() || plan.IpSpaceNameMaster.IsUnknown() != state.IpSpaceNameMaster.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.IpSpaceNameMaster.IsNull() && !plan.IpSpaceNameMaster.IsUnknown() && !state.IpSpaceNameMaster.IsNull() && !state.IpSpaceNameMaster.IsUnknown() { + if plan.IpSpaceNameMaster.ValueString() != state.IpSpaceNameMaster.ValueString() { + hasServiceParamChanges = true + } + } + } + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{ + 501: resources_core.FormatInt64(plan.ResourceInstances), + 502: resources_core.FormatInt64(plan.ResourceMemory), + 503: resources_core.FormatInt64(plan.ResourceCPU), + 504: resources_core.FormatInt64(plan.ResourceDisk), + 505: resources_core.FormatBool(plan.NeedExternalAddressMaster), + 506: resources_core.FormatString(plan.IpSpaceNameMaster), + } + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 116, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "ipSpaceNameMaster", Field: "IpSpaceNameMaster", Type: "string"}, + {Code: "needExternalAddressMaster", Field: "NeedExternalAddressMaster", Type: "bool"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *KafkaResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state KafkaModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *KafkaResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *KafkaResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/1_dummy_redeploy_action.go b/universal_rebuild/internal/resources_gen/1_dummy_redeploy_action.go new file mode 100644 index 0000000..5236732 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/1_dummy_redeploy_action.go @@ -0,0 +1,128 @@ +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" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: dummy +// Action: redeploy + +var _ resource.Resource = &DummyRedeployResource{} + +// DummyRedeployResource triggers a one-time action. +type DummyRedeployResource struct { + client *core.UniversalClient +} + +type DummyRedeployModel struct { + ID types.String `tfsdk:"id"` + DummyID types.String `tfsdk:"dummy_id"` + RunID types.String `tfsdk:"run_id"` + OperationTimeout types.String `tfsdk:"operation_timeout"` +} + +func NewDummyRedeployResource() resource.Resource { + return &DummyRedeployResource{} +} + +func (r *DummyRedeployResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dummy_redeploy" +} + +func (r *DummyRedeployResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "dummy_id": schema.StringAttribute{Required: true}, + "run_id": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + } + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *DummyRedeployResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan DummyRedeployModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + instanceUID := strings.TrimSpace(plan.DummyID.ValueString()) + runID := strings.TrimSpace(plan.RunID.ValueString()) + if instanceUID == "" || runID == "" { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра или run_id") + return + } + + params := map[string]string{} + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.RunOperationByCodeWithTimeout(ctx, r.client, instanceUID, "redeploy", params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = types.StringValue(resources_core.BuildActionID(instanceUID, "redeploy", runID)) + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *DummyRedeployResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state DummyRedeployModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DummyRedeployResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan DummyRedeployModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + instanceUID := strings.TrimSpace(plan.DummyID.ValueString()) + runID := strings.TrimSpace(plan.RunID.ValueString()) + if instanceUID == "" || runID == "" { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра или run_id") + return + } + + params := map[string]string{} + + if err := resources_core.RunOperationByCode(ctx, r.client, instanceUID, "redeploy", params); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = types.StringValue(resources_core.BuildActionID(instanceUID, "redeploy", runID)) + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *DummyRedeployResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + // No-op: removing the resource does not trigger a remote action. +} + +func (r *DummyRedeployResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/1_dummy_resource.go b/universal_rebuild/internal/resources_gen/1_dummy_resource.go new file mode 100644 index 0000000..3f461b3 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/1_dummy_resource.go @@ -0,0 +1,504 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: dummy +// Service ID: 1 + +var _ resource.Resource = &DummyResource{} +var _ resource.ResourceWithModifyPlan = &DummyResource{} +var _ resource.ResourceWithImportState = &DummyResource{} + +type DummyResource struct { + client *core.UniversalClient +} + +type DummyModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + ArrayMapFixedExample types.String `tfsdk:"array_map_fixed_example"` + Bodymessage types.String `tfsdk:"bodymessage"` + DurationMs types.Int64 `tfsdk:"duration_ms"` + FailAtStart types.Bool `tfsdk:"fail_at_start"` + FailInProgress types.Bool `tfsdk:"fail_in_progress"` + JsonExample types.String `tfsdk:"json_example"` + MapExample types.String `tfsdk:"map_example"` + MapFixed types.String `tfsdk:"map_fixed"` + NestedRefExample types.String `tfsdk:"nested_ref_example"` + ResourceRealm types.String `tfsdk:"resource_realm"` + WhereFail types.Int64 `tfsdk:"where_fail"` + YamlExample types.String `tfsdk:"yaml_example"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewDummyResource() resource.Resource { + return &DummyResource{} +} + +func (r *DummyResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dummy" +} + +func (r *DummyResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "array_map_fixed_example": schema.StringAttribute{Optional: true, MarkdownDescription: "Array of map-fixed Не изменяется после создания."}, + "bodymessage": schema.StringAttribute{Optional: true, MarkdownDescription: "Дата, уходящая в Vault"}, + "duration_ms": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(0), MarkdownDescription: "перед завершением подождать (sleep) столько миллисекунд"}, + "fail_at_start": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "если true, завершить джоб, ничего не записывая в cmdb"}, + "fail_in_progress": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false), MarkdownDescription: "если true, корректно начать выполнение джоба, но в процессе завершить аварийно, ничего не записывая в cmdb"}, + "json_example": schema.StringAttribute{Optional: true, MarkdownDescription: "Для тестирования интерфейса"}, + "map_example": schema.StringAttribute{Optional: true}, + "map_fixed": schema.StringAttribute{Optional: true, MarkdownDescription: "Новый тип поля Не изменяется после создания."}, + "nested_ref_example": schema.StringAttribute{Optional: true, MarkdownDescription: "Не изменяется после создания."}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "where_fail": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "принимает 1,2,3. Работает с failInProgress. 1 - упасть в prepare. 2 - упасть внутри блока Data fill. 3 - упасть после vault write"}, + "yaml_example": schema.StringAttribute{Optional: true, MarkdownDescription: "Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(true)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *DummyResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *DummyModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *DummyModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan DummyModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.ArrayMapFixedExample.IsNull() && !plan.ArrayMapFixedExample.IsUnknown() && !state.ArrayMapFixedExample.IsNull() && !state.ArrayMapFixedExample.IsUnknown() { + if plan.ArrayMapFixedExample.ValueString() != state.ArrayMapFixedExample.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить array_map_fixed_example", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.MapFixed.IsNull() && !plan.MapFixed.IsUnknown() && !state.MapFixed.IsNull() && !state.MapFixed.IsUnknown() { + if plan.MapFixed.ValueString() != state.MapFixed.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить map_fixed", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.NestedRefExample.IsNull() && !plan.NestedRefExample.IsUnknown() && !state.NestedRefExample.IsNull() && !state.NestedRefExample.IsUnknown() { + if plan.NestedRefExample.ValueString() != state.NestedRefExample.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить nested_ref_example", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.YamlExample.IsNull() && !plan.YamlExample.IsUnknown() && !state.YamlExample.IsNull() && !state.YamlExample.IsUnknown() { + if plan.YamlExample.ValueString() != state.YamlExample.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить yaml_example", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 198: resources_core.FormatInt64(config.DurationMs), + 199: resources_core.FormatBool(config.FailAtStart), + 200: resources_core.FormatBool(config.FailInProgress), + 201: resources_core.FormatInt64(config.WhereFail), + 242: resources_core.FormatString(config.ResourceRealm), + 286: resources_core.FormatString(config.Bodymessage), + 321: resources_core.FormatString(config.MapExample), + 322: resources_core.FormatString(config.JsonExample), + 396: resources_core.FormatString(config.NestedRefExample), + 447: resources_core.FormatString(config.YamlExample), + 647: resources_core.FormatString(config.MapFixed), + 654: resources_core.FormatString(config.ArrayMapFixedExample), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 1, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *DummyResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data DummyModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 1, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 198: resources_core.FormatInt64(data.DurationMs), + 199: resources_core.FormatBool(data.FailAtStart), + 200: resources_core.FormatBool(data.FailInProgress), + 201: resources_core.FormatInt64(data.WhereFail), + 242: resources_core.FormatString(data.ResourceRealm), + 286: resources_core.FormatString(data.Bodymessage), + 321: resources_core.FormatString(data.MapExample), + 322: resources_core.FormatString(data.JsonExample), + 396: resources_core.FormatString(data.NestedRefExample), + 447: resources_core.FormatString(data.YamlExample), + 647: resources_core.FormatString(data.MapFixed), + 654: resources_core.FormatString(data.ArrayMapFixedExample), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 1, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 1, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "arrayMapFixedExample", Field: "ArrayMapFixedExample", Type: "string"}, + {Code: "bodymessage", Field: "Bodymessage", Type: "string"}, + {Code: "durationMs", Field: "DurationMs", Type: "int64"}, + {Code: "failAtStart", Field: "FailAtStart", Type: "bool"}, + {Code: "failInProgress", Field: "FailInProgress", Type: "bool"}, + {Code: "jsonExample", Field: "JsonExample", Type: "string"}, + {Code: "mapExample", Field: "MapExample", Type: "string"}, + {Code: "mapFixed", Field: "MapFixed", Type: "string"}, + {Code: "nestedRefExample", Field: "NestedRefExample", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "whereFail", Field: "WhereFail", Type: "int64"}, + {Code: "yamlExample", Field: "YamlExample", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DummyResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state DummyModel + 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.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.ID.ValueString(), 1, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "arrayMapFixedExample", Field: "ArrayMapFixedExample", Type: "string"}, + {Code: "bodymessage", Field: "Bodymessage", Type: "string"}, + {Code: "durationMs", Field: "DurationMs", Type: "int64"}, + {Code: "failAtStart", Field: "FailAtStart", Type: "bool"}, + {Code: "failInProgress", Field: "FailInProgress", Type: "bool"}, + {Code: "jsonExample", Field: "JsonExample", Type: "string"}, + {Code: "mapExample", Field: "MapExample", Type: "string"}, + {Code: "mapFixed", Field: "MapFixed", Type: "string"}, + {Code: "nestedRefExample", Field: "NestedRefExample", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "whereFail", Field: "WhereFail", Type: "int64"}, + {Code: "yamlExample", Field: "YamlExample", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *DummyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan DummyModel + var state DummyModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + if !hasServiceParamChanges { + if plan.DurationMs.IsNull() != state.DurationMs.IsNull() || plan.DurationMs.IsUnknown() != state.DurationMs.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.DurationMs.IsNull() && !plan.DurationMs.IsUnknown() && !state.DurationMs.IsNull() && !state.DurationMs.IsUnknown() { + if plan.DurationMs.ValueInt64() != state.DurationMs.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.FailAtStart.IsNull() != state.FailAtStart.IsNull() || plan.FailAtStart.IsUnknown() != state.FailAtStart.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.FailAtStart.IsNull() && !plan.FailAtStart.IsUnknown() && !state.FailAtStart.IsNull() && !state.FailAtStart.IsUnknown() { + if plan.FailAtStart.ValueBool() != state.FailAtStart.ValueBool() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.FailInProgress.IsNull() != state.FailInProgress.IsNull() || plan.FailInProgress.IsUnknown() != state.FailInProgress.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.FailInProgress.IsNull() && !plan.FailInProgress.IsUnknown() && !state.FailInProgress.IsNull() && !state.FailInProgress.IsUnknown() { + if plan.FailInProgress.ValueBool() != state.FailInProgress.ValueBool() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.WhereFail.IsNull() != state.WhereFail.IsNull() || plan.WhereFail.IsUnknown() != state.WhereFail.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.WhereFail.IsNull() && !plan.WhereFail.IsUnknown() && !state.WhereFail.IsNull() && !state.WhereFail.IsUnknown() { + if plan.WhereFail.ValueInt64() != state.WhereFail.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.Bodymessage.IsNull() != state.Bodymessage.IsNull() || plan.Bodymessage.IsUnknown() != state.Bodymessage.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.Bodymessage.IsNull() && !plan.Bodymessage.IsUnknown() && !state.Bodymessage.IsNull() && !state.Bodymessage.IsUnknown() { + if plan.Bodymessage.ValueString() != state.Bodymessage.ValueString() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.MapExample.IsNull() != state.MapExample.IsNull() || plan.MapExample.IsUnknown() != state.MapExample.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.MapExample.IsNull() && !plan.MapExample.IsUnknown() && !state.MapExample.IsNull() && !state.MapExample.IsUnknown() { + if plan.MapExample.ValueString() != state.MapExample.ValueString() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.JsonExample.IsNull() != state.JsonExample.IsNull() || plan.JsonExample.IsUnknown() != state.JsonExample.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.JsonExample.IsNull() && !plan.JsonExample.IsUnknown() && !state.JsonExample.IsNull() && !state.JsonExample.IsUnknown() { + if plan.JsonExample.ValueString() != state.JsonExample.ValueString() { + hasServiceParamChanges = true + } + } + } + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{ + 287: resources_core.FormatInt64(plan.DurationMs), + 288: resources_core.FormatBool(plan.FailAtStart), + 289: resources_core.FormatBool(plan.FailInProgress), + 290: resources_core.FormatInt64(plan.WhereFail), + 291: resources_core.FormatString(plan.Bodymessage), + 373: resources_core.FormatString(plan.MapExample), + 374: resources_core.FormatString(plan.JsonExample), + } + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 1, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "arrayMapFixedExample", Field: "ArrayMapFixedExample", Type: "string"}, + {Code: "bodymessage", Field: "Bodymessage", Type: "string"}, + {Code: "durationMs", Field: "DurationMs", Type: "int64"}, + {Code: "failAtStart", Field: "FailAtStart", Type: "bool"}, + {Code: "failInProgress", Field: "FailInProgress", Type: "bool"}, + {Code: "jsonExample", Field: "JsonExample", Type: "string"}, + {Code: "mapExample", Field: "MapExample", Type: "string"}, + {Code: "mapFixed", Field: "MapFixed", Type: "string"}, + {Code: "nestedRefExample", Field: "NestedRefExample", Type: "string"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + {Code: "whereFail", Field: "WhereFail", Type: "int64"}, + {Code: "yamlExample", Field: "YamlExample", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *DummyResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state DummyModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *DummyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *DummyResource) 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 +} diff --git a/universal_rebuild/internal/resources_gen/2_template_resource.go b/universal_rebuild/internal/resources_gen/2_template_resource.go new file mode 100644 index 0000000..9567524 --- /dev/null +++ b/universal_rebuild/internal/resources_gen/2_template_resource.go @@ -0,0 +1,415 @@ +package resources_gen + +import ( + "context" + + "terraform-provider-nubes/internal/core" + "terraform-provider-nubes/internal/resources_core" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Code generated by tools/gen_v2. DO NOT EDIT. +// Service: template +// Service ID: 2 + +var _ resource.Resource = &TemplateResource{} +var _ resource.ResourceWithModifyPlan = &TemplateResource{} +var _ resource.ResourceWithImportState = &TemplateResource{} + +type TemplateResource struct { + client *core.UniversalClient +} + +type TemplateModel struct { + ID types.String `tfsdk:"id"` + ResourceName types.String `tfsdk:"resource_name"` + OperationTimeout types.String `tfsdk:"operation_timeout"` + Domain types.String `tfsdk:"domain"` + ResourceCPU types.Int64 `tfsdk:"resource_c_p_u"` + ResourceDisk types.Int64 `tfsdk:"resource_disk"` + ResourceInstances types.Int64 `tfsdk:"resource_instances"` + ResourceMemory types.Int64 `tfsdk:"resource_memory"` + ResourceRealm types.String `tfsdk:"resource_realm"` + SuspendOnDestroy types.Bool `tfsdk:"suspend_on_destroy"` + AdoptExistingOnCreate types.Bool `tfsdk:"adopt_existing_on_create"` + StateParams types.Map `tfsdk:"state_params"` + StateOut types.Map `tfsdk:"state_out"` + StateParamsFlat types.Map `tfsdk:"state_params_flat"` + StateOutFlat types.Map `tfsdk:"state_out_flat"` + VaultSecrets types.Map `tfsdk:"vault_secrets"` + VaultUrl types.String `tfsdk:"vault_url"` + VaultUserPath types.String `tfsdk:"vault_user_path"` + VaultFields types.List `tfsdk:"vault_fields"` +} + +func NewTemplateResource() resource.Resource { + return &TemplateResource{} +} + +func (r *TemplateResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_template" +} + +func (r *TemplateResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{Computed: true}, + "resource_name": schema.StringAttribute{Required: true}, + "operation_timeout": schema.StringAttribute{Optional: true}, + "domain": schema.StringAttribute{Optional: true, Computed: true, Default: stringdefault.StaticString("web01"), MarkdownDescription: "Если будет указан FQDN, то происходят проверки DNS на валидность А-записи, или будет добавлено в зону resourceRealm Не изменяется после создания."}, + "resource_c_p_u": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(100)}, + "resource_disk": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "Квота диска (Указывается в GIGAbytes)"}, + "resource_instances": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(1), MarkdownDescription: "Количество узлов"}, + "resource_memory": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(200)}, + "resource_realm": schema.StringAttribute{Required: true, MarkdownDescription: "Платформа для развертывания Не изменяется после создания."}, + "suspend_on_destroy": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(true)}, + "adopt_existing_on_create": schema.BoolAttribute{Optional: true, Computed: true, Default: booldefault.StaticBool(false)}, + "state_params": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_params_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "state_out_flat": schema.MapAttribute{Computed: true, ElementType: types.StringType}, + "vault_secrets": schema.MapAttribute{Computed: true, ElementType: types.StringType, Sensitive: true}, + "vault_url": schema.StringAttribute{Computed: true}, + "vault_user_path": schema.StringAttribute{Computed: true}, + "vault_fields": schema.ListAttribute{Computed: true, ElementType: types.StringType}, + } + + resp.Schema = schema.Schema{Attributes: attrs} +} + +func (r *TemplateResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { + if r.client == nil { + return + } + + var config *TemplateModel + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + if config == nil { + return + } + + var state *TemplateModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if req.State.Raw.IsNull() && req.Plan.Raw.IsNull() { + return + } + + if state != nil && !state.ID.IsNull() && !state.ID.IsUnknown() { + var plan TemplateModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + if !plan.ResourceName.IsNull() && !plan.ResourceName.IsUnknown() && !state.ResourceName.IsNull() && !state.ResourceName.IsUnknown() { + if plan.ResourceName.ValueString() != state.ResourceName.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_name", "Параметр resource_name задается при создании и не может быть изменен. Создайте новый ресурс с другим именем.") + return + } + } + if !plan.Domain.IsNull() && !plan.Domain.IsUnknown() && !state.Domain.IsNull() && !state.Domain.IsUnknown() { + if plan.Domain.ValueString() != state.Domain.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить domain", "Параметр задается при создании и не может быть изменен.") + return + } + } + if !plan.ResourceRealm.IsNull() && !plan.ResourceRealm.IsUnknown() && !state.ResourceRealm.IsNull() && !state.ResourceRealm.IsUnknown() { + if plan.ResourceRealm.ValueString() != state.ResourceRealm.ValueString() { + resp.Diagnostics.AddError("Нельзя изменить resource_realm", "Параметр задается при создании и не может быть изменен.") + return + } + } + return + } + if config.ResourceRealm.IsNull() || config.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + if config.ResourceName.IsNull() || config.ResourceName.IsUnknown() { + return + } + adoptExistingOnCreate := false + if !config.AdoptExistingOnCreate.IsNull() && !config.AdoptExistingOnCreate.IsUnknown() { + adoptExistingOnCreate = config.AdoptExistingOnCreate.ValueBool() + } + params := map[int]string{ + 202: resources_core.FormatInt64(config.ResourceCPU), + 203: resources_core.FormatInt64(config.ResourceMemory), + 204: resources_core.FormatInt64(config.ResourceDisk), + 205: resources_core.FormatInt64(config.ResourceInstances), + 206: resources_core.FormatString(config.ResourceRealm), + 207: resources_core.FormatString(config.Domain), + } + + resp.Diagnostics.Append(resources_core.PlanExistingResourceDiagnosticsWithParams(ctx, r.client, 2, config.ResourceName.ValueString(), adoptExistingOnCreate, params)...) +} + +func (r *TemplateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data TemplateModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.ResourceRealm.IsNull() || data.ResourceRealm.IsUnknown() { + resp.Diagnostics.AddError("Missing required attribute", "resource_realm is required.") + return + } + + resourceName := data.ResourceName.ValueString() + resp.Diagnostics.Append(resources_core.CreateExistingResourceDiagnostics(ctx, r.client, 2, resourceName, data.AdoptExistingOnCreate.ValueBool())...) + + params := map[int]string{ + 202: resources_core.FormatInt64(data.ResourceCPU), + 203: resources_core.FormatInt64(data.ResourceMemory), + 204: resources_core.FormatInt64(data.ResourceDisk), + 205: resources_core.FormatInt64(data.ResourceInstances), + 206: resources_core.FormatString(data.ResourceRealm), + 207: resources_core.FormatString(data.Domain), + } + + operationTimeout := "" + if !data.OperationTimeout.IsNull() && !data.OperationTimeout.IsUnknown() { + operationTimeout = data.OperationTimeout.ValueString() + } + id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, 2, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout) + if err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + data.ID = types.StringValue(id) + + state, diags := resources_core.RefreshResourceState(ctx, r.client, id, 2, data, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "domain", Field: "Domain", Type: "string"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *TemplateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state TemplateModel + 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.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.ID.ValueString(), 2, state, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "domain", Field: "Domain", Type: "string"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &newState)...) +} + +func (r *TemplateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan TemplateModel + var state TemplateModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + instanceID := state.ID + if instanceID.IsNull() || instanceID.IsUnknown() { + instanceID = plan.ID + } + if instanceID.IsNull() || instanceID.IsUnknown() { + resp.Diagnostics.AddError("Ошибка клиента", "отсутствует идентификатор экземпляра для modify") + return + } + + hasServiceParamChanges := false + if !hasServiceParamChanges { + if plan.ResourceCPU.IsNull() != state.ResourceCPU.IsNull() || plan.ResourceCPU.IsUnknown() != state.ResourceCPU.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceCPU.IsNull() && !plan.ResourceCPU.IsUnknown() && !state.ResourceCPU.IsNull() && !state.ResourceCPU.IsUnknown() { + if plan.ResourceCPU.ValueInt64() != state.ResourceCPU.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceMemory.IsNull() != state.ResourceMemory.IsNull() || plan.ResourceMemory.IsUnknown() != state.ResourceMemory.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceMemory.IsNull() && !plan.ResourceMemory.IsUnknown() && !state.ResourceMemory.IsNull() && !state.ResourceMemory.IsUnknown() { + if plan.ResourceMemory.ValueInt64() != state.ResourceMemory.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceDisk.IsNull() != state.ResourceDisk.IsNull() || plan.ResourceDisk.IsUnknown() != state.ResourceDisk.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceDisk.IsNull() && !plan.ResourceDisk.IsUnknown() && !state.ResourceDisk.IsNull() && !state.ResourceDisk.IsUnknown() { + if plan.ResourceDisk.ValueInt64() != state.ResourceDisk.ValueInt64() { + hasServiceParamChanges = true + } + } + } + if !hasServiceParamChanges { + if plan.ResourceInstances.IsNull() != state.ResourceInstances.IsNull() || plan.ResourceInstances.IsUnknown() != state.ResourceInstances.IsUnknown() { + hasServiceParamChanges = true + } else if !plan.ResourceInstances.IsNull() && !plan.ResourceInstances.IsUnknown() && !state.ResourceInstances.IsNull() && !state.ResourceInstances.IsUnknown() { + if plan.ResourceInstances.ValueInt64() != state.ResourceInstances.ValueInt64() { + hasServiceParamChanges = true + } + } + } + + if !hasServiceParamChanges { + plan.ID = instanceID + plan.StateParams = state.StateParams + plan.StateOut = state.StateOut + plan.StateParamsFlat = state.StateParamsFlat + plan.StateOutFlat = state.StateOutFlat + plan.VaultSecrets = state.VaultSecrets + plan.VaultUrl = state.VaultUrl + plan.VaultUserPath = state.VaultUserPath + plan.VaultFields = state.VaultFields + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + return + } + + params := map[int]string{ + 208: resources_core.FormatInt64(plan.ResourceCPU), + 209: resources_core.FormatInt64(plan.ResourceMemory), + 210: resources_core.FormatInt64(plan.ResourceDisk), + 211: resources_core.FormatInt64(plan.ResourceInstances), + } + + operationTimeout := "" + if !plan.OperationTimeout.IsNull() && !plan.OperationTimeout.IsUnknown() { + operationTimeout = plan.OperationTimeout.ValueString() + } + if err := resources_core.UpdateResourceWithTimeout(ctx, r.client, instanceID.ValueString(), params, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } + + plan.ID = instanceID + state, diags := resources_core.RefreshResourceState(ctx, r.client, instanceID.ValueString(), 2, plan, []resources_core.StateField{ + {Code: "state_params"}, + {Code: "state_out"}, + {Code: "state_params_flat"}, + {Code: "state_out_flat"}, + {Code: "vault_secrets"}, + {Code: "vault_url"}, + {Code: "vault_user_path"}, + {Code: "vault_fields"}, + }, []resources_core.InputField{ + {Code: "domain", Field: "Domain", Type: "string"}, + {Code: "resourceCPU", Field: "ResourceCPU", Type: "int64"}, + {Code: "resourceDisk", Field: "ResourceDisk", Type: "int64"}, + {Code: "resourceInstances", Field: "ResourceInstances", Type: "int64"}, + {Code: "resourceMemory", Field: "ResourceMemory", Type: "int64"}, + {Code: "resourceRealm", Field: "ResourceRealm", Type: "string"}, + }) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *TemplateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state TemplateModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + if state.ID.IsNull() || state.ID.IsUnknown() { + return + } + + deleteMode := "state_only" + if !state.SuspendOnDestroy.IsNull() && !state.SuspendOnDestroy.IsUnknown() && state.SuspendOnDestroy.ValueBool() { + deleteMode = "suspend" + } + + operationTimeout := "" + if !state.OperationTimeout.IsNull() && !state.OperationTimeout.IsUnknown() { + operationTimeout = state.OperationTimeout.ValueString() + } + if err := resources_core.DeleteResourceWithTimeout(ctx, r.client, state.ID.ValueString(), deleteMode, operationTimeout); err != nil { + resp.Diagnostics.AddError("Ошибка клиента", err.Error()) + return + } +} + +func (r *TemplateResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *TemplateResource) 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 +}