You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
terraform-provider-dynamix/internal/service/cloudapi/kvmvm/utilities/utility_resource_compute_up...

1255 lines
52 KiB

package utilities
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/ic"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/models"
)
func ComputeResourceResize(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceResize: start resize compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceResize: cannot parsed ID compute from state", err.Error())
return diags
}
resizeReq := compute.ResizeRequest{
ComputeID: computeId,
CPU: 0,
RAM: 0,
Force: false,
}
if plan.ForceResize.ValueBool() {
resizeReq.Force = true
}
if !plan.CPU.Equal(state.CPU) && (state.CPU.ValueInt64() > plan.CPU.ValueInt64()) && !resizeReq.Force {
diags.AddError(fmt.Sprintf("Cannot resize compute ID %d: enable 'force_resize' to reduce compute vCPUs", computeId), "")
return diags
}
if !plan.CPU.Equal(state.CPU) {
resizeReq.CPU = uint64(plan.CPU.ValueInt64())
}
if !plan.RAM.Equal(state.RAM) {
resizeReq.RAM = uint64(plan.RAM.ValueInt64())
}
tflog.Info(ctx, fmt.Sprintf("ComputeResourceResize: changing CPU %d -> %d and/or RAM %d -> %d\"",
state.CPU.ValueInt64(), plan.CPU.ValueInt64(), state.RAM.ValueInt64(), plan.RAM.ValueInt64()))
tflog.Info(ctx, "ComputeResourceResize: before calling CloudAPI().Compute().Resize", map[string]any{"compute_id": computeId, "req": resizeReq})
res, err := c.CloudAPI().Compute().Resize(ctx, resizeReq)
tflog.Info(ctx, "ComputeResourceResize: response from CloudAPI().Compute().Resize", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceResize: Unable to resize Compute",
err.Error(),
)
return diags
}
tflog.Info(ctx, "ComputeResourceResize: compute is successfully resize", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceBootDiskResize(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceBootDiskResize: start resize boot disk size", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceBootDiskResize: cannot parsed ID compute from state", err.Error())
return diags
}
if state.BootDiskSize.ValueInt64() > plan.BootDiskSize.ValueInt64() {
diags.AddError(fmt.Sprintf("ComputeResourceBootDiskResize: compute ID %d - shrinking boot disk is not allowed", computeId), "")
return diags
}
req := compute.DiskResizeRequest{
ComputeID: computeId,
Size: uint64(plan.BootDiskSize.ValueInt64()),
}
if !state.BootDiskId.IsNull() {
req.DiskID = uint64(state.BootDiskId.ValueInt64())
} else {
bootDisk, diags := ComputeResourceBootDiskCheckPresence(ctx, state, c)
if diags.HasError() {
return diags
}
req.DiskID = bootDisk.ID
}
tflog.Info(ctx, fmt.Sprintf("ComputeResourceBootDiskResize: compute ID %d, boot disk ID %d resize %d -> %d",
computeId, req.DiskID, state.BootDiskSize.ValueInt64(), req.Size))
tflog.Info(ctx, "ComputeResourceBootDiskResize: before calling CloudAPI().Compute().DiskResize", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().DiskResize(ctx, req)
tflog.Info(ctx, "ComputeResourceBootDiskResize: response from CloudAPI().Compute().DiskResize", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceBootDiskResize: Unable to resize boot disk",
err.Error(),
)
return diags
}
tflog.Info(ctx, "ComputeResourceBootDiskResize: boot disk is successfully resize", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceExtraDiskUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: start update extra disk(s) list to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceExtraDiskUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
attachSet, detachSet := differenceSimpleType(state.ExtraDisks, plan.ExtraDisks)
for _, disk := range attachSet {
diskId := uint64(disk.(types.Int64).ValueInt64())
tflog.Info(ctx, fmt.Sprintf("ComputeResourceExtraDiskUpdate: Start attach extra disk with ID - %d to compute with ID - %d", diskId, computeId))
req := compute.DiskAttachRequest{
ComputeID: computeId,
DiskID: diskId,
}
res, err := c.CloudAPI().Compute().DiskAttach(ctx, req)
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: response from CloudAPI().Compute().DiskAttach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceExtraDiskUpdate: Cannot attach disk with ID - %d", diskId), err.Error())
}
}
if diags.HasError() {
return diags
}
if len(detachSet) > 0 {
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceExtraDiskUpdate: cannot stop compute", err.Error(),
)
return diags
}
}
for _, disk := range detachSet {
diskId := uint64(disk.(types.Int64).ValueInt64())
tflog.Info(ctx, fmt.Sprintf("ComputeResourceExtraDiskUpdate: Start detach extra disk with ID - %d from compute with ID - %d", diskId, computeId))
req := compute.DiskDetachRequest{
ComputeID: computeId,
DiskID: diskId,
}
res, err := c.CloudAPI().Compute().DiskDetach(ctx, req)
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: response from CloudAPI().Compute().DiskDetach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceExtraDiskUpdate: Cannot detach disk with ID - %d", diskId), err.Error())
}
}
if len(detachSet) > 0 && plan.Started.ValueBool() {
diags = ComputeResourceStartStop(ctx, plan, c)
}
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceExtraDiskUpdate: Errors occurred while managing disks")
return diags
}
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: extra disks is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourcePCIDeviceUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: start update PCI device(s) list to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourcePCIDeviceUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
attachSet, detachSet := differenceSimpleType(state.ExtraDisks, plan.ExtraDisks)
for _, pciDevice := range detachSet {
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
tflog.Info(ctx, fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Start detach PCI device with ID - %d from compute with ID - %d", pciDeviceId, computeId))
req := compute.DetachPCIDeviceRequest{
ComputeID: computeId,
DeviceID: uint64(pciDeviceId),
}
res, err := c.CloudAPI().Compute().DetachPCIDevice(ctx, req)
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: response from CloudAPI().Compute().DetachPCIDevice", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Cannot detach PCI device with ID - %d", pciDeviceId), err.Error())
}
}
for _, pciDevice := range attachSet {
pciDeviceId := pciDevice.(types.Int64).ValueInt64()
tflog.Info(ctx, fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Start attach PCI device with ID - %d to compute with ID - %d", pciDeviceId, computeId))
req := compute.AttachPCIDeviceRequest{
ComputeID: computeId,
DeviceID: uint64(pciDeviceId),
}
res, err := c.CloudAPI().Compute().AttachPCIDevice(ctx, req)
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: response from CloudAPI().Compute().AttachPCIDevice", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourcePCIDeviceUpdate: Cannot attach PCI device with ID - %d", pciDeviceId), err.Error())
}
}
if diags.HasError() {
tflog.Error(ctx, "ComputeResourcePCIDeviceUpdate: Errors occurred while managing PCI device(s)")
return diags
}
tflog.Info(ctx, "ComputeResourcePCIDeviceUpdate: PCI device(s) is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceNetworkUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start update network rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceNetworkUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
attachMap, changeIpMap, detachMap := differenceNetwork(state.Network, plan.Network)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start detach network(s) rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
for _, network := range detachMap {
req := compute.NetDetachRequest{
ComputeID: computeId,
IPAddr: network["ip_address"].(types.String).ValueString(),
MAC: network["mac"].(types.String).ValueString(),
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().NetDetach", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().NetDetach(ctx, req)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().NetDetach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to detach net ID %d from Compute ID %d",
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
}
}
if diags.HasError() {
return diags
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: start change IP network(s) rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
for _, network := range changeIpMap {
req := compute.ChangeIPRequest{
ComputeID: computeId,
NetType: network["net_type"].(types.String).ValueString(),
NetID: uint64(network["net_id"].(types.Int64).ValueInt64()),
IPAddr: network["ip_address"].(types.String).ValueString(),
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().ChangeIP", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().ChangeIP(ctx, req)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().ChangeIP", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to change IP net ID %d from Compute ID %d",
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
}
}
if diags.HasError() {
return diags
}
needStart := false
// need stop to attach first network
if len(detachMap) == len(state.Network.Elements()) || (len(state.Network.Elements()) < 1) && len(attachMap) > 0 || hasDPDKnetwork(attachMap) {
tflog.Info(ctx, "ComputeResourceNetworkUpdate: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceNetworkUpdate: cannot stop compute", err.Error(),
)
return diags
}
if plan.Started.ValueBool() {
needStart = true
}
}
sort.Slice(attachMap, func(i, j int) bool {
weightI := attachMap[i]["weight"].(types.Int64).ValueInt64()
weightJ := attachMap[j]["weight"].(types.Int64).ValueInt64()
if weightI == 0 {
return false
}
if weightJ == 0 {
return true
}
return weightI < weightJ
})
for _, network := range attachMap {
req := compute.NetAttachRequest{
ComputeID: computeId,
NetType: strings.ToUpper(network["net_type"].(types.String).ValueString()),
NetID: uint64(network["net_id"].(types.Int64).ValueInt64()),
}
if req.NetType == "DPDK" {
req.MTU = uint64(network["mtu"].(types.Int64).ValueInt64())
}
ipaddr, ipSet := network["ip_address"]
if ipSet {
req.IPAddr = ipaddr.(types.String).ValueString()
}
tflog.Info(ctx, "ComputeResourceNetworkUpdate: before calling CloudAPI().Compute().NetAttach", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().NetAttach(ctx, req)
tflog.Info(ctx, "ComputeResourceNetworkUpdate: response from CloudAPI().Compute().NetAttach", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceNetworkUpdate: failed to attach net ID %d from Compute ID %d",
network["net_id"].(types.Int64).ValueInt64(), computeId), err.Error())
}
}
if needStart {
diags = ComputeResourceStartStop(ctx, plan, c)
}
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceExtraDiskUpdate: Errors occurred while managing network(s)")
return diags
}
tflog.Info(ctx, "ComputeResourceExtraDiskUpdate: network(s) is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func hasDPDKnetwork(networkAttachMap []map[string]attr.Value) bool {
for _, elem := range networkAttachMap {
if elem["net_type"].(types.String).ValueString() == "DPDK" {
return true
}
}
return false
}
func ComputeResourceComputeUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceComputeUpdate: start update compute parameters", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceComputeUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
req := compute.UpdateRequest{
ComputeID: computeId,
}
if !plan.Name.Equal(state.Name) {
req.Name = plan.Name.ValueString()
}
if !plan.Description.IsUnknown() && !plan.Description.Equal(state.Description) {
req.Description = plan.Description.ValueString()
}
if !plan.NumaAffinity.Equal(state.NumaAffinity) {
req.NumaAffinity = plan.NumaAffinity.ValueString()
}
if !plan.CPUPin.Equal(state.CPUPin) {
req.CPUPin = plan.CPUPin.ValueBool()
} else if state.CPUPin.ValueBool() {
req.CPUPin = state.CPUPin.ValueBool()
}
if !plan.HPBacked.Equal(state.HPBacked) {
req.HPBacked = plan.HPBacked.ValueBool()
} else if state.HPBacked.ValueBool() {
req.HPBacked = state.HPBacked.ValueBool()
}
if !plan.Chipset.IsUnknown() && !plan.Chipset.Equal(state.Chipset) {
req.Chipset = plan.Chipset.ValueString()
}
// Note bene: numa_affinity, cpu_pin and hp_backed are not allowed to be changed for compute in STARTED tech status.
// If STARTED, we need to stop it before update
var isStopRequred bool
if !plan.NumaAffinity.Equal(state.NumaAffinity) || !plan.CPUPin.Equal(state.CPUPin) || !plan.HPBacked.Equal(state.HPBacked) {
isStopRequred = true
tflog.Info(ctx, "ComputeResourceComputeUpdate: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceComputeUpdate: cannot stop compute", err.Error(),
)
return diags
}
}
tflog.Info(ctx, "ComputeResourceComputeUpdate: before calling CloudAPI().Compute().Update", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().Update(ctx, req)
tflog.Info(ctx, "ComputeResourceComputeUpdate: response from CloudAPI().Compute().Update", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceComputeUpdate: Unable to update compute parameters",
err.Error(),
)
return diags
}
if isStopRequred && plan.Started.ValueBool() {
diags = ComputeResourceStartStop(ctx, plan, c)
}
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceExtraDiskUpdate: Errors occurred while managing network(s)")
return diags
}
tflog.Info(ctx, "ComputeResourceComputeUpdate: compute parameters is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceAffinityLabelUpdate(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: start resize boot disk size", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceAffinityLabelUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
if plan.AffinityLabel.ValueString() == "" {
req := compute.AffinityLabelRemoveRequest{
ComputeID: computeId,
}
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: before calling CloudAPI().Compute().AffinityLabelRemove", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AffinityLabelRemove(ctx, req)
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: response from CloudAPI().Compute().AffinityLabelRemove", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceAffinityLabelUpdate: Unable to remove affinity label",
err.Error(),
)
return diags
}
} else {
req := compute.AffinityLabelSetRequest{
ComputeID: computeId,
AffinityLabel: plan.AffinityLabel.ValueString(),
}
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: before calling CloudAPI().Compute().AffinityLabelSet", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AffinityLabelSet(ctx, req)
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: response from CloudAPI().Compute().AffinityLabelSet", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceAffinityLabelUpdate: Unable to set affinity label",
err.Error(),
)
return diags
}
}
tflog.Info(ctx, "ComputeResourceAffinityLabelUpdate: affinity label is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceAffinityRulesUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceAffinityRulesUpdate: start update affinity rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceAffinityRulesUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
if len(plan.AffinityRules.Elements()) == 0 {
req := compute.AffinityRulesClearRequest{
ComputeID: computeId,
}
tflog.Info(ctx, "ComputeResourceAffinityRulesUpdate: before calling CloudAPI().Compute().AffinityRulesClear", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AffinityRulesClear(ctx, req)
tflog.Info(ctx, "ComputeResourceAffinityRulesUpdate: response from CloudAPI().Compute().AffinityRulesClear", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceAffinityRulesUpdate: failed to clear affinity rules from Compute ID %d",
computeId), err.Error())
}
return diags
} else {
attachSet, detachSet := differenceAffinityRules(state.AffinityRules, plan.AffinityRules)
for _, affinityRules := range detachSet {
var itemAffinityRules models.ItemResourceRulesModel
objVal := affinityRules.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemAffinityRules, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceAffinityRulesUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourceAffinityRulesUpdate: Unable to set affinity rules for compute %d", computeId),
"cannot populate itemsAffinityRules with plan.AffinityRules List elements")
return diags
}
req := compute.AffinityRuleRemoveRequest{
ComputeID: computeId,
Topology: strings.ToLower(itemAffinityRules.Topology.ValueString()),
Policy: strings.ToUpper(itemAffinityRules.Policy.ValueString()),
Mode: strings.ToUpper(itemAffinityRules.Mode.ValueString()),
Key: itemAffinityRules.Key.ValueString(),
Value: itemAffinityRules.Value.ValueString(),
}
tflog.Info(ctx, "ComputeAffinityRules: before calling CloudAPI().Compute().AffinityRuleRemove", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AffinityRuleRemove(ctx, req)
tflog.Info(ctx, "ComputeAffinityRules: response from CloudAPI().Compute().AffinityRuleRemove", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeAffinityRules: Unable to AffinityRuleRemove for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, affinityRules := range attachSet {
var itemsAffinityRules models.ItemResourceRulesModel
objVal := affinityRules.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemsAffinityRules, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceAffinityRulesUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourceAffinityRulesUpdate: Unable to set affinity rules for compute %d", computeId),
"cannot populate itemsAffinityRules with plan.AffinityRules List elements")
return diags
}
req := compute.AffinityRuleAddRequest{
ComputeID: computeId,
Topology: strings.ToLower(itemsAffinityRules.Topology.ValueString()),
Policy: strings.ToUpper(itemsAffinityRules.Policy.ValueString()),
Mode: strings.ToUpper(itemsAffinityRules.Mode.ValueString()),
Key: itemsAffinityRules.Key.ValueString(),
Value: itemsAffinityRules.Value.ValueString(),
}
tflog.Info(ctx, "ComputeAffinityRules: before calling CloudAPI().Compute().AffinityRuleAdd", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AffinityRuleAdd(ctx, req)
tflog.Info(ctx, "ComputeAffinityRules: response from CloudAPI().Compute().AffinityRuleAdd", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeAffinityRules: Unable to AffinityRuleAdd for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
}
tflog.Info(ctx, "ComputeResourceAffinityRulesUpdate: affinity rules is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceAntiAffinityRulesUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceAntiAffinityRulesUpdate: start update affinity rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceAntiAffinityRulesUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
if len(plan.AntiAffinityRules.Elements()) == 0 {
req := compute.AntiAffinityRulesClearRequest{
ComputeID: computeId,
}
tflog.Info(ctx, "ComputeResourceAntiAffinityRulesUpdate: before calling CloudAPI().Compute().AntiAffinityRulesClear", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AntiAffinityRulesClear(ctx, req)
tflog.Info(ctx, "ComputeResourceAntiAffinityRulesUpdate: response from CloudAPI().Compute().AntiAffinityRulesClear", map[string]any{"compute_id": plan.ID.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("ComputeResourceAntiAffinityRulesUpdate: failed to clear affinity rules from Compute ID %d",
computeId), err.Error())
}
return diags
} else {
attachSet, detachSet := differenceAffinityRules(state.AntiAffinityRules, plan.AntiAffinityRules)
for _, antiAffinityRules := range detachSet {
var itemAntiAffinityRules models.ItemResourceRulesModel
objVal := antiAffinityRules.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemAntiAffinityRules, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceAntiAffinityRulesUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourceAntiAffinityRulesUpdate: Unable to set anti affinity rules for compute %d", computeId),
"cannot populate itemsAntiAntiAffinityRules with plan.AntiAntiAffinityRules List elements")
return diags
}
req := compute.AntiAffinityRuleRemoveRequest{
ComputeID: computeId,
Topology: strings.ToLower(itemAntiAffinityRules.Topology.ValueString()),
Policy: strings.ToUpper(itemAntiAffinityRules.Policy.ValueString()),
Mode: strings.ToUpper(itemAntiAffinityRules.Mode.ValueString()),
Key: itemAntiAffinityRules.Key.ValueString(),
Value: itemAntiAffinityRules.Value.ValueString(),
}
tflog.Info(ctx, "ComputeAntiAffinityRules: before calling CloudAPI().Compute().AntiAffinityRuleRemove", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AntiAffinityRuleRemove(ctx, req)
tflog.Info(ctx, "ComputeAntiAffinityRules: response from CloudAPI().Compute().AntiAffinityRuleRemove", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeAntiAffinityRules: Unable to AntiAffinityRuleRemove for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, antiAffinityRules := range attachSet {
var itemsAntiAffinityRules models.ItemResourceRulesModel
objVal := antiAffinityRules.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemsAntiAffinityRules, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceAntiAffinityRulesUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourceAntiAffinityRulesUpdate: Unable to set anti affinity rules for compute %d", computeId),
"cannot populate itemsAntiAffinityRules with plan.AntiAffinityRules List elements")
return diags
}
req := compute.AntiAffinityRuleAddRequest{
ComputeID: computeId,
Topology: strings.ToLower(itemsAntiAffinityRules.Topology.ValueString()),
Policy: strings.ToUpper(itemsAntiAffinityRules.Policy.ValueString()),
Mode: strings.ToUpper(itemsAntiAffinityRules.Mode.ValueString()),
Key: itemsAntiAffinityRules.Key.ValueString(),
Value: itemsAntiAffinityRules.Value.ValueString(),
}
tflog.Info(ctx, "ComputeAntiAffinityRules: before calling CloudAPI().Compute().AntiAffinityRuleAdd", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().AntiAffinityRuleAdd(ctx, req)
tflog.Info(ctx, "ComputeAntiAffinityRules: response from CloudAPI().Compute().AntiAffinityRuleAdd", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeAntiAffinityRules: Unable to AntiAffinityRuleAdd for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
}
tflog.Info(ctx, "ComputeResourceAntiAffinityRulesUpdate: affinity rules is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceTagsUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceTagsUpdate: start update tags to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceTagsUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
addedTags, deleteTags := differenceTags(state.Tags, plan.Tags)
for _, tags := range deleteTags {
req := compute.TagRemoveRequest{ComputeID: computeId}
objTag := tags.(types.Object)
tagMap := objTag.Attributes()
req.Key = tagMap["key"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceTags: before calling CloudAPI().Compute().TagRemove", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().TagRemove(ctx, req)
tflog.Info(ctx, "ComputeResourceTags: response from CloudAPI().Compute().TagRemove", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceTags: Unable to remove tags for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, tags := range addedTags {
req := compute.TagAddRequest{ComputeID: computeId}
objTag := tags.(types.Object)
tagMap := objTag.Attributes()
req.Key = tagMap["key"].(types.String).ValueString()
req.Value = tagMap["value"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceTags: before calling CloudAPI().Compute().TagAdd", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().TagAdd(ctx, req)
tflog.Info(ctx, "ComputeResourceTags: response from CloudAPI().Compute().TagAdd", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddWarning(
"ComputeResourceTags: Unable to add tags for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
tflog.Info(ctx, "ComputeResourceTagsUpdate: tags is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourcePortForwardingUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: start update port forwarding rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourcePortForwardingUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
addSet, delSet := differencePortForwarding(state.PortForwarding, plan.PortForwarding)
for _, pfw := range delSet {
var itemPortForwarding models.ItemPortForfardingModel
objVal := pfw.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemPortForwarding, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourcePortForwardingUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourcePortForwardingUpdate: Unable to set port forwarding rules for compute %d", computeId),
"cannot populate itemPortForwarding with plan.PortForwarding List elements")
return diags
}
req := compute.PFWDelRequest{
ComputeID: computeId,
PublicPortStart: uint64(itemPortForwarding.PublicPortStart.ValueInt64()),
Proto: strings.ToLower(itemPortForwarding.Proto.ValueString()),
}
if itemPortForwarding.PublicPortStart.ValueInt64() != 0 {
req.PublicPortStart = uint64(itemPortForwarding.PublicPortStart.ValueInt64())
}
if itemPortForwarding.LocalPort.ValueInt64() != 0 {
req.LocalBasePort = uint64(itemPortForwarding.LocalPort.ValueInt64())
}
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: before calling CloudAPI().Compute().PFWDel", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().PFWDel(ctx, req)
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: response from CloudAPI().Compute().PFWDel", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourcePortForwardingUpdate: Unable to port forwarding rules delete for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, pfw := range addSet {
var itemPortForwarding models.ItemPortForfardingModel
objVal := pfw.(attr.Value)
diags = objVal.(types.Object).As(ctx, &itemPortForwarding, basetypes.ObjectAsOptions{})
if diags.HasError() {
tflog.Error(ctx, "ComputeResourcePortForwardingUpdate Error converting object to struct")
diags.AddError(
fmt.Sprintf("ComputeResourcePortForwardingUpdate: Unable to set port forwarding rules for compute %d", computeId),
"cannot populate itemPortForwarding with plan.PortForwarding List elements")
return diags
}
req := compute.PFWAddRequest{
ComputeID: computeId,
PublicPortStart: uint64(itemPortForwarding.PublicPortStart.ValueInt64()),
Proto: strings.ToLower(itemPortForwarding.Proto.ValueString()),
}
if itemPortForwarding.PublicPortStart.ValueInt64() != 0 {
req.PublicPortStart = uint64(itemPortForwarding.PublicPortStart.ValueInt64())
}
if itemPortForwarding.LocalPort.ValueInt64() != 0 {
req.LocalBasePort = uint64(itemPortForwarding.LocalPort.ValueInt64())
}
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: before calling CloudAPI().Compute().PFWAdd", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().PFWAdd(ctx, req)
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: response from CloudAPI().Compute().PFWAdd", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourcePortForwardingUpdate: Unable to port forwarding rules add for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
tflog.Info(ctx, "ComputeResourcePortForwardingUpdate: port forwarding rules is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceUserAccessUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: start update user access rules to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceUserAccessUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
addedUserAccess, deleteUserAccess := differenceUserAccess(state.UserAccess, plan.UserAccess)
for _, userAccess := range deleteUserAccess {
req := compute.UserRevokeRequest{ComputeID: computeId}
objTag := userAccess.(types.Object)
tagMap := objTag.Attributes()
req.Username = tagMap["username"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: before calling CloudAPI().Compute().UserRevoke", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().UserRevoke(ctx, req)
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: response from CloudAPI().Compute().UserRevoke", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceUserAccessUpdate: Unable to revoke user access rules for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, userAccess := range addedUserAccess {
req := compute.UserGrantRequest{ComputeID: computeId}
objTag := userAccess.(types.Object)
tagMap := objTag.Attributes()
req.Username = tagMap["username"].(types.String).ValueString()
req.AccessType = tagMap["access_type"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: before calling CloudAPI().Compute().UserGrant", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().UserGrant(ctx, req)
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: response from CloudAPI().Compute().UserGrant", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceUserAccessUpdate: Unable to add user access rules for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: user access rules is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceSnapshotUpdate(ctx context.Context, state *models.ResourceComputeModel, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: start update snapshot(s) to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceSnapshotUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
addedLabel, deleteLabel := differenceSnapshot(state.Snapshot, plan.Snapshot)
for _, label := range deleteLabel {
req := compute.SnapshotDeleteRequest{ComputeID: computeId}
objTag := label.(types.Object)
tagMap := objTag.Attributes()
req.Label = tagMap["label"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: before calling CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotDelete(ctx, req)
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: response from CloudAPI().Compute().SnapshotDelete", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceSnapshotUpdate: Unable to delete snapshot for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
for _, label := range addedLabel {
req := compute.SnapshotCreateRequest{ComputeID: computeId}
objTag := label.(types.Object)
tagMap := objTag.Attributes()
req.Label = tagMap["label"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: before calling CloudAPI().Compute().SnapshotCreate", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotCreate(ctx, req)
tflog.Info(ctx, "ComputeResourceSnapshotUpdate: response from CloudAPI().Compute().SnapshotCreate", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceSnapshotUpdate: Unable to create snapshot for Compute",
err.Error(),
)
}
}
if diags.HasError() {
return diags
}
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: snapshot(s) is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceRollback(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceRollback: start rollback to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceRollback: cannot parsed ID compute from state", err.Error())
return diags
}
label := plan.Rollback.Attributes()["label"].(types.String).ValueString()
err = ic.ExistSnapshotInCompute(ctx, computeId, label, c)
if err != nil {
diags.AddError("ComputeResourceRollback: snapshot not found", err.Error())
return diags
}
tflog.Info(ctx, "ComputeResourceRollback: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceRollback: cannot stop compute", err.Error(),
)
return diags
}
req := compute.SnapshotRollbackRequest{ComputeID: computeId}
tagMap := plan.Rollback.Attributes()
req.Label = tagMap["label"].(types.String).ValueString()
tflog.Info(ctx, "ComputeResourceRollback: before calling CloudAPI().Compute().SnapshotRollback", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SnapshotRollback(ctx, req)
tflog.Info(ctx, "ComputeResourceRollback: response from CloudAPI().Compute().SnapshotRollback", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceRollback: Unable to rollback for Compute",
err.Error(),
)
return diags
}
if plan.Started.ValueBool() {
diags = ComputeResourceStartStop(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceRollback: cannot start compute")
return diags
}
}
tflog.Info(ctx, "ComputeResourceRollback: rollback is successfully", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceCDUpdate(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceCDUpdate: start update cd list to compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceCDUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
if plan.CD.IsNull() {
tflog.Info(ctx, "ComputeResourceCDUpdate: before calling CloudAPI().Compute().CDEject", map[string]any{"compute_id": computeId})
res, err := c.CloudAPI().Compute().CDEject(ctx, compute.CDEjectRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourceCDUpdate: response from CloudAPI().Compute().CDEject", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceCDUpdate: Unable to eject cd from Compute",
err.Error(),
)
return diags
}
} else {
req := compute.CDInsertRequest{ComputeID: computeId}
req.CDROMID = uint64(plan.CD.Attributes()["cdrom_id"].(types.Int64).ValueInt64())
tflog.Info(ctx, "ComputeResourceCDUpdate: before calling CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().CDInsert(ctx, req)
tflog.Info(ctx, "ComputeResourceCDUpdate: response from CloudAPI().Compute().CDInsert", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceCDUpdate: Unable to eject cd from Compute",
err.Error(),
)
}
}
tflog.Info(ctx, "ComputeResourceUserAccessUpdate: cd list is successfully update", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourcePinToStackUpdate(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourcePinToStackUpdate: Start pin/unpin to stack compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourcePinToStackUpdate: cannot parsed ID compute from plan", err.Error())
return diags
}
pinToStack := plan.PinToStack.ValueBool()
tflog.Info(ctx, "ComputeResourcePinToStackUpdate: compute to be pin to stack", map[string]any{
"compute_id": computeId,
"pin_to_stack": pinToStack})
if pinToStack {
_, err = c.CloudAPI().Compute().PinToStack(ctx, compute.PinToStackRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourcePinToStackUpdate: response from CloudAPI().Compute().PinToStack", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourcePinToStackUpdate: cannot pin to stack compute", err.Error(),
)
return diags
}
} else {
_, err = c.CloudAPI().Compute().UnpinFromStack(ctx, compute.UnpinFromStackRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourcePinToStackUpdate: response from CloudAPI().Compute().UnpinFromStack", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourcePinToStackUpdate: cannot unpin from stack compute", err.Error(),
)
return diags
}
}
tflog.Info(ctx, "ComputeResourcePinToStackUpdate: compute is successfully pin/unpin to stack", map[string]any{"compute_id": computeId, "pin_to_stack": pinToStack})
return nil
}
func ComputeResourcePauseResumeCompute(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: Start pause/resume compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourcePauseResumeCompute: cannot parsed ID compute from plan", err.Error())
return diags
}
pause := plan.Pause.ValueBool()
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: compute to pause/resume", map[string]any{
"compute_id": computeId,
"pause": pause})
if pause {
_, err = c.CloudAPI().Compute().Pause(ctx, compute.PauseRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: response from CloudAPI().Compute().Pause", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourcePauseResumeCompute: cannot pause compute", err.Error(),
)
return diags
}
} else {
_, err = c.CloudAPI().Compute().Resume(ctx, compute.ResumeRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: response from CloudAPI().Compute().Resume", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourcePauseResumeCompute: cannot resume compute", err.Error(),
)
return diags
}
}
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: compute is successfully pause/resume", map[string]any{"compute_id": computeId, "pause": pause})
return nil
}
func ComputeResourceResetCompute(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceResetCompute: Start reset compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceResetCompute: cannot parsed ID compute from plan", err.Error())
return diags
}
tflog.Info(ctx, "ComputeResourceResetCompute: before calling CloudAPI().Compute().Reset", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Reset(ctx, compute.ResetRequest{ComputeID: computeId})
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: response from CloudAPI().Compute().Reset", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourcePauseResumeCompute: cannot reset compute", err.Error(),
)
return diags
}
tflog.Info(ctx, "ComputeResourcePauseResumeCompute: compute is successfully reset", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceRedeploy(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceRedeploy: Start redeploy compute with ID", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceRedeploy: cannot parsed ID compute from plan", err.Error())
return diags
}
tflog.Info(ctx, "ComputeResourceRedeploy: stop compute", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Stop(ctx, compute.StopRequest{ComputeID: computeId})
if err != nil {
diags.AddError(
"ComputeResourceRedeploy: cannot stop compute", err.Error(),
)
return diags
}
req := compute.RedeployRequest{
ComputeID: computeId,
ImageID: uint64(plan.ImageID.ValueInt64()),
DataDisks: "detach",
}
if !plan.BootDiskSize.IsNull() {
req.DiskSize = uint64(plan.BootDiskSize.ValueInt64())
}
if !plan.DataDisks.IsNull() {
req.DataDisks = plan.DataDisks.ValueString()
}
if !plan.AutoStart.IsNull() {
req.AutoStart = plan.AutoStart.ValueBool()
}
if !plan.ForceStop.IsNull() {
req.ForceStop = plan.ForceStop.ValueBool()
}
tflog.Info(ctx, "ComputeResourceRedeploy: before calling CloudAPI().Compute().Redeploy", map[string]any{"compute_id": computeId})
_, err = c.CloudAPI().Compute().Redeploy(ctx, req)
tflog.Info(ctx, "ComputeResourceRedeploy: response from CloudAPI().Compute().Redeploy", map[string]any{"compute_id": computeId})
if err != nil {
diags.AddError(
"ComputeResourceRedeploy: cannot redeploy compute", err.Error(),
)
return diags
}
if plan.Started.ValueBool() {
diags = ComputeResourceStartStop(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "ComputeResourceRedeploy: cannot start compute")
return diags
}
}
tflog.Info(ctx, "ComputeResourceRedeploy: compute is successfully redeploy", map[string]any{"compute_id": computeId})
return nil
}
func ComputeResourceCustomFieldUpdate(ctx context.Context, plan *models.ResourceComputeModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: start update custom fields", map[string]any{"compute_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
computeId, err := strconv.ParseUint(plan.ID.ValueString(), 10, 64)
if err != nil {
diags.AddError("ComputeResourceCustomFieldUpdate: cannot parsed ID compute from state", err.Error())
return diags
}
if plan.CustomFields.ValueString() == "" {
req := compute.DeleteCustomFieldsRequest{
ComputeID: computeId,
}
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: before calling CloudAPI().Compute().DeleteCustomFields", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().DeleteCustomFields(ctx, req)
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: response from CloudAPI().Compute().DeleteCustomFields", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceCustomFieldUpdate: Unable to remove custom fields",
err.Error(),
)
return diags
}
} else {
customFields := plan.CustomFields.ValueString()
customFields = strings.ReplaceAll(customFields, "\\", "")
customFields = strings.ReplaceAll(customFields, "\n", "")
customFields = strings.ReplaceAll(customFields, "\t", "")
customFields = strings.TrimSpace(customFields)
req := compute.SetCustomFieldsRequest{
ComputeID: computeId,
CustomFields: customFields,
}
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: before calling CloudAPI().Compute().SetCustomFields", map[string]any{"compute_id": computeId, "req": req})
res, err := c.CloudAPI().Compute().SetCustomFields(ctx, req)
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: response from CloudAPI().Compute().SetCustomFields", map[string]any{"compute_id": computeId, "response": res})
if err != nil {
diags.AddError(
"ComputeResourceCustomFieldUpdate: Unable to set custom fields",
err.Error(),
)
return diags
}
}
tflog.Info(ctx, "ComputeResourceCustomFieldUpdate: custom fields is successfully update", map[string]any{"compute_id": computeId})
return nil
}