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.
1255 lines
52 KiB
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
|
|
}
|