package flattens import ( "context" "encoding/json" "fmt" "strconv" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" decort "repository.basistech.ru/BASIS/decort-golang-sdk" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/disks" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/disks/models" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/disks/utilities" ) // DiskResource flattens resource for disk. // Return error in case resource is not found on the platform. // Flatten errors are added to tflog. func DiskResource(ctx context.Context, plan *models.ResourceDiskModel, c *decort.DecortClient) diag.Diagnostics { tflog.Info(ctx, "Start flattens.DiskResource") diags := diag.Diagnostics{} diskId, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64) if err != nil { diags.AddError("flattens.DiskResource: Cannot parse disk ID from state", err.Error()) return diags } recordDisk, err := utilities.DiskCheckPresence(ctx, diskId, c) if err != nil { diags.AddError(fmt.Sprintf("Cannot get info about disk with ID %v", diskId), err.Error()) return diags } tflog.Info(ctx, "flattens.DiskResource: before flatten", map[string]any{"disk_id": diskId, "recordDisk": recordDisk}) diskAcl, _ := json.Marshal(recordDisk.ACL) *plan = models.ResourceDiskModel{ // required fields AccountID: types.Int64Value(int64(recordDisk.AccountID)), DiskName: types.StringValue(recordDisk.Name), SizeMax: types.Int64Value(int64(recordDisk.SizeMax)), GID: types.Int64Value(int64(recordDisk.GID)), // optional fields Description: plan.Description, Pool: plan.Pool, SEPID: plan.SEPID, Type: plan.Type, Detach: plan.Detach, Permanently: plan.Permanently, Shareable: plan.Shareable, Timeouts: plan.Timeouts, // computed fields LastUpdated: plan.LastUpdated, Id: types.StringValue(strconv.Itoa(int(recordDisk.ID))), DiskId: types.Int64Value(int64(recordDisk.ID)), AccountName: types.StringValue(recordDisk.AccountName), ACL: types.StringValue(string(diskAcl)), Computes: flattenComputes(ctx, recordDisk.Computes), CreatedTime: types.Int64Value(int64(recordDisk.CreatedTime)), DeletedTime: types.Int64Value(int64(recordDisk.DeletedTime)), DestructionTime: types.Int64Value(int64(recordDisk.DestructionTime)), DeviceName: types.StringValue(recordDisk.DeviceName), ImageID: types.Int64Value(int64(recordDisk.ImageID)), Order: types.Int64Value(int64(recordDisk.Order)), Params: types.StringValue(recordDisk.Params), ParentID: types.Int64Value(int64(recordDisk.ParentID)), PCISlot: types.Int64Value(int64(recordDisk.PCISlot)), PurgeTime: types.Int64Value(int64(recordDisk.PurgeTime)), ResID: types.StringValue(recordDisk.ResID), ResName: types.StringValue(recordDisk.ResName), Role: types.StringValue(recordDisk.Role), SepType: types.StringValue(recordDisk.SepType), SizeUsed: types.Float64Value(recordDisk.SizeUsed), Snapshots: flattenSnapshots(ctx, recordDisk.Snapshots), Status: types.StringValue(recordDisk.Status), TechStatus: types.StringValue(recordDisk.TechStatus), VMID: types.Int64Value(int64(recordDisk.VMID)), } plan.Images, diags = types.ListValueFrom(ctx, types.StringType, recordDisk.Images) if diags != nil { tflog.Error(ctx, fmt.Sprint("flattens.DiskResource: cannot flatten recordDisk.Images to plan.Images", diags)) } plan.PresentTo, diags = types.ListValueFrom(ctx, types.Int64Type, recordDisk.PresentTo) if diags != nil { tflog.Error(ctx, fmt.Sprint("flattens.DiskResource: cannot flatten recordDisk.PresentTo to plan.PresentTo", diags)) } if plan.Description.IsUnknown() { plan.Description = types.StringValue(recordDisk.Description) } if plan.Pool.IsUnknown() { plan.Pool = types.StringValue(recordDisk.Pool) } if plan.SEPID.IsUnknown() { plan.SEPID = types.Int64Value(int64(recordDisk.SepID)) } if plan.Shareable.IsUnknown() { plan.Shareable = types.BoolValue(recordDisk.Shareable) } if plan.Type.IsUnknown() { plan.Type = types.StringValue(recordDisk.Type) } iotune := models.IOTuneModel{ ReadBytesSec: types.Int64Value(int64(recordDisk.IOTune.ReadBytesSec)), ReadBytesSecMax: types.Int64Value(int64(recordDisk.IOTune.ReadBytesSecMax)), ReadIOPSSec: types.Int64Value(int64(recordDisk.IOTune.ReadIOPSSec)), ReadIOPSSecMax: types.Int64Value(int64(recordDisk.IOTune.ReadIOPSSecMax)), SizeIOPSSec: types.Int64Value(int64(recordDisk.IOTune.SizeIOPSSec)), TotalBytesSec: types.Int64Value(int64(recordDisk.IOTune.TotalBytesSec)), TotalBytesSecMax: types.Int64Value(int64(recordDisk.IOTune.TotalBytesSecMax)), TotalIOPSSec: types.Int64Value(int64(recordDisk.IOTune.TotalIOPSSec)), TotalIOPSSecMax: types.Int64Value(int64(recordDisk.IOTune.TotalIOPSSecMax)), WriteBytesSec: types.Int64Value(int64(recordDisk.IOTune.WriteBytesSec)), WriteBytesSecMax: types.Int64Value(int64(recordDisk.IOTune.WriteBytesSecMax)), WriteIOPSSec: types.Int64Value(int64(recordDisk.IOTune.WriteIOPSSec)), WriteIOPSSecMax: types.Int64Value(int64(recordDisk.IOTune.WriteIOPSSecMax)), } obj, diags := types.ObjectValueFrom(ctx, models.ItemIOTune, iotune) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattens.DiskResource iotune struct to obj", diags)) } plan.IOTune = obj tflog.Info(ctx, "flattens.DiskResource: after flatten", map[string]any{"disk_id": plan.Id.ValueString()}) tflog.Info(ctx, "End flattens.DiskResource") return nil } func flattenComputes(ctx context.Context, items map[string]string) types.List { tflog.Info(ctx, "Start flattenComputes") tempSlice := make([]types.Object, 0, len(items)) for id, name := range items { temp := models.ItemComputeModel{ ComputeId: types.StringValue(id), ComputeName: types.StringValue(name), } obj, diags := types.ObjectValueFrom(ctx, models.ItemCompute, temp) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenComputes struct to obj", diags)) } tempSlice = append(tempSlice, obj) } res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemCompute}, tempSlice) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenComputes", diags)) } tflog.Info(ctx, "End flattenComputes") return res } func flattenSnapshots(ctx context.Context, snapshots disks.ListSnapshots) types.List { tflog.Info(ctx, "Start flattenSnapshots") tempSlice := make([]types.Object, 0, len(snapshots)) for _, item := range snapshots { temp := models.ItemSnapshotModel{ GUID: types.StringValue(item.GUID), Label: types.StringValue(item.Label), ResID: types.StringValue(item.ResID), SnapSetGUID: types.StringValue(item.SnapSetGUID), SnapSetTime: types.Int64Value(int64(item.SnapSetTime)), TimeStamp: types.Int64Value(int64(item.TimeStamp)), } obj, diags := types.ObjectValueFrom(ctx, models.ItemSnapshot, temp) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenSnapshots struct to obj", diags)) } tempSlice = append(tempSlice, obj) } res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemSnapshot}, tempSlice) if diags != nil { tflog.Error(ctx, fmt.Sprint("Error flattenSnapshots", diags)) } tflog.Info(ctx, "End flattenSnapshots") return res }