package utilities import ( "context" "fmt" "strconv" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/lb" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/lb/models" "repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status" ) func CreateResourceLB(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) (uint64, diag.Diagnostics) { tflog.Info(ctx, fmt.Sprintf("Start create ResourceLB: name %s", plan.Name.ValueString())) diags := diag.Diagnostics{} createReq := lb.CreateRequest{ Name: plan.Name.ValueString(), RGID: uint64(plan.RGID.ValueInt64()), ExtNetID: plan.ExtNetID.ValueInt64(), VINSID: uint64(plan.VINSID.ValueInt64()), Start: plan.Start.ValueBool(), } if plan.HAMode.IsUnknown() { // HAMode is optional & computed createReq.HighlyAvailable = false } else { createReq.HighlyAvailable = plan.HAMode.ValueBool() } if !plan.Description.IsNull() { // Description is optional & computed createReq.Description = plan.Description.ValueString() } if !plan.SysctlParams.IsNull() { result := make([]map[string]interface{}, 0, len(plan.SysctlParams.Elements())) for _, val := range plan.SysctlParams.Elements() { objVal := val.(types.Object) valMap := objVal.Attributes() mapKey := valMap["key"].(types.String).ValueString() mapVal := valMap["value"].(types.String).ValueString() tempMap := make(map[string]interface{}) tempMap[mapKey] = mapVal result = append(result, tempMap) } createReq.SysctlParams = result } tflog.Info(ctx, "CreateResourceLB: before call CloudBroker().LB().Create", map[string]any{"req": createReq}) lbId, err := c.CloudBroker().LB().Create(ctx, createReq) if err != nil { diags.AddError("CreateResourceLB: unable to create LB", err.Error()) return 0, diags } tflog.Info(ctx, "CreateResourceLB: LB created", map[string]any{"lb_id": lbId, "name": plan.Name.ValueString()}) return lbId, nil } func LBResourceCheckPresence(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) (*lb.RecordLB, diag.Diagnostics) { tflog.Info(ctx, fmt.Sprintf("LBCheckPresence: Get info about LB with ID - %v", plan.ID.ValueString())) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return nil, diags } lbItem, err := c.CloudBroker().LB().Get(ctx, lb.GetRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot get info about lb with ID %v", lbId), err.Error()) return nil, diags } return lbItem, nil } func LBEnableDisable(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "EnableDisable lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } if plan.Enable.IsNull() || plan.Enable.ValueBool() { tflog.Info(ctx, "Enable lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) _, err := c.CloudBroker().LB().Enable(ctx, lb.EnableRequest{LBID: lbId}) if err != nil { diags.AddError("EnableDisableLB: error to enable LB", err.Error()) return diags } } else { tflog.Info(ctx, "Disable lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) _, err := c.CloudBroker().LB().Disable(ctx, lb.DisableRequest{LBID: lbId}) if err != nil { diags.AddError("EnableDisableLB: error to disable LB", err.Error()) return diags } } return diags } func LBReadStatus(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Read status lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } lbItem, err := c.CloudBroker().LB().Get(ctx, lb.GetRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot get info about lb with ID %v", lbItem), err.Error()) return diags } switch lbItem.Status { case status.Modeled: diags.AddError("Error:", fmt.Sprintf("The lb is in status: %s, please, contact support for more information", lbItem.Status)) return diags case status.Deleted: if plan.Restore.ValueBool() || plan.Restore.IsNull() { diags = LBRestore(ctx, plan, c) if diags.HasError() { tflog.Error(ctx, "Error restore lb", map[string]any{"lb_id": plan.ID.ValueString()}) return diags } } else { diags.AddError("LB in status Deleted:", "please clean state, or restore lb") return diags } if plan.Enable.ValueBool() || plan.Enable.IsNull() { diags = LBEnableDisable(ctx, plan, c) if diags.HasError() { tflog.Error(ctx, "Error enable/disable lb", map[string]any{"lb_id": plan.ID.ValueString()}) return diags } if plan.Start.ValueBool() || plan.Start.IsNull() { diags = LBStartStop(ctx, plan, c) if diags.HasError() { tflog.Error(ctx, "Error start/stop lb", map[string]any{"lb_id": plan.ID.ValueString()}) return diags } } } case status.Destroying: diags.AddError("Error:", fmt.Sprintf("The lb is in progress with status: %s", lbItem.Status)) return diags case status.Destroyed: diags.AddError("Error:", "The resource cannot be updated because it has been destroyed") return diags } tflog.Info(ctx, "Read status lb successfully", map[string]any{"lb_id": plan.ID.ValueString()}) return diags } func LBRestore(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Restore lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } _, err = c.CloudBroker().LB().Restore(ctx, lb.RestoreRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot restore lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Restore lb successfully", map[string]any{"lb_id": plan.ID.ValueString()}) return diags } func LBStartStop(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "StartStop lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } if plan.Enable.IsNull() || plan.Enable.ValueBool() { if plan.Start.ValueBool() || plan.Start.IsNull() { tflog.Info(ctx, "Start lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) _, err := c.CloudBroker().LB().Start(ctx, lb.StartRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot start lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } } else { tflog.Info(ctx, "Stop lb with ID", map[string]any{"lb_id": plan.ID.ValueString()}) _, err := c.CloudBroker().LB().Stop(ctx, lb.StopRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot stop lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } } } return diags } func LBUpdateHaMode(ctx context.Context, state *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Update ha mode from lb with ID", map[string]any{"id": state.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(state.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } _, err = c.CloudBroker().LB().HighlyAvailable(ctx, lb.HighlyAvailableRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot update ha mode from lb with ID - %s", state.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Update ha mode from LB with ID successfully", map[string]any{"id": state.ID.ValueString()}) return diags } func LBUpdateSysctlParams(ctx context.Context, plan *models.ResourceLBModel, state *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Update sysctl parameters from LB with ID", map[string]any{"id": state.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(state.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } sysctlParams := make([]map[string]interface{}, 0, len(plan.SysctlParams.Elements())) for _, val := range plan.SysctlParams.Elements() { objVal := val.(types.Object) valMap := objVal.Attributes() mapKey := valMap["key"].(types.String).ValueString() mapVal := valMap["value"].(types.String).ValueString() tempMap := make(map[string]interface{}) tempMap[mapKey] = mapVal sysctlParams = append(sysctlParams, tempMap) } req := lb.UpdateSysctParamsRequest{ LBID: lbId, SysctlParams: sysctlParams, } _, err = c.CloudBroker().LB().UpdateSysctlParams(ctx, req) if err != nil { diags.AddError(fmt.Sprintf("Cannot update sysctl parameters from LB with ID - %s", state.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Update sysctl parameters from LB with ID successfully", map[string]any{"id": state.ID.ValueString()}) return diags } func LBUpdateDescription(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Update description from lb with ID", map[string]any{"id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } _, err = c.CloudBroker().LB().Update(ctx, lb.UpdateRequest{LBID: lbId, Description: plan.Description.ValueString()}) if err != nil { diags.AddError(fmt.Sprintf("Cannot update description from lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Update description from LB with ID successfully", map[string]any{"id": plan.ID.ValueString()}) return diags } func LBRestart(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Restart lb with ID", map[string]any{"id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } req := lb.RestartRequest{ LBID: lbId, Safe: false, } if plan.Safe.ValueBool() || plan.Safe.IsNull() { req.Safe = true } _, err = c.CloudBroker().LB().Restart(ctx, req) if err != nil { diags.AddError(fmt.Sprintf("Cannot restart lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Restart LB with ID successfully", map[string]any{"id": plan.ID.ValueString()}) return diags } func LBConfigReset(ctx context.Context, plan *models.ResourceLBModel, c *client.Client) diag.Diagnostics { tflog.Info(ctx, "Reset config from lb with ID", map[string]any{"id": plan.ID.ValueString()}) diags := diag.Diagnostics{} lbId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64) if err != nil { diags.AddError("Cannot parsed ID lb from state", err.Error()) return diags } _, err = c.CloudBroker().LB().ConfigReset(ctx, lb.ConfigResetRequest{LBID: lbId}) if err != nil { diags.AddError(fmt.Sprintf("Cannot reset config from lb with ID - %s", plan.ID.ValueString()), err.Error()) return diags } tflog.Info(ctx, "Reset config from LB with ID successfully", map[string]any{"id": plan.ID.ValueString()}) return diags }