gos_tech_4.4.3
Nikita Sorokin 1 year ago
parent 712f8edf9e
commit 6932f9d305

@ -1,4 +1,4 @@
## Version 4.3.4 ## Version 4.3.5
## Bugfixes ## Feature
- Fixed bug with resource decort_cb_extnet: extnet did not switct status to "ENABLED" if field enable=true while resource create. - Added state upgrader for custom_fields field upgrade in kvmvm resource

@ -7,7 +7,7 @@ ZIPDIR = ./zip
BINARY=${NAME} BINARY=${NAME}
WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH} WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH}
MAINPATH = ./cmd/decort/ MAINPATH = ./cmd/decort/
VERSION=4.3.4 VERSION=4.3.5
OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH) OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH)
FILES = ${BINARY}_${VERSION}_darwin_amd64\ FILES = ${BINARY}_${VERSION}_darwin_amd64\

@ -637,10 +637,10 @@ func dataSourceComputeSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
// "custom_fields": { "custom_fields": {
// Type: schema.TypeString, Type: schema.TypeString,
// Computed: true, Computed: true,
// }, },
"deleted_by": { "deleted_by": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,

@ -154,10 +154,10 @@ func itemComputeSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
// "custom_fields": { //NEED "custom_fields": { //NEED
// Type: schema.TypeString, Type: schema.TypeString,
// Computed: true, Computed: true,
// }, },
"deleted_by": { "deleted_by": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,

@ -150,7 +150,7 @@ func flattenListACL(listAcl compute.ListACL) []map[string]interface{} {
func flattenComputeList(computes *compute.ListComputes) []map[string]interface{} { func flattenComputeList(computes *compute.ListComputes) []map[string]interface{} {
res := make([]map[string]interface{}, 0) res := make([]map[string]interface{}, 0)
for _, compute := range computes.Data { for _, compute := range computes.Data {
// customFields, _ := json.Marshal(compute.CustomFields) customFields, _ := json.Marshal(compute.CustomFields)
devices, _ := json.Marshal(compute.Devices) devices, _ := json.Marshal(compute.Devices)
temp := map[string]interface{}{ temp := map[string]interface{}{
"acl": flattenListACL(compute.ACL), "acl": flattenListACL(compute.ACL),
@ -169,44 +169,44 @@ func flattenComputeList(computes *compute.ListComputes) []map[string]interface{}
"cpus": compute.CPU, "cpus": compute.CPU,
"created_by": compute.CreatedBy, "created_by": compute.CreatedBy,
"created_time": compute.CreatedTime, "created_time": compute.CreatedTime,
// "custom_fields": string(customFields), "custom_fields": string(customFields),
"deleted_by": compute.DeletedBy, "deleted_by": compute.DeletedBy,
"deleted_time": compute.DeletedTime, "deleted_time": compute.DeletedTime,
"desc": compute.Description, "desc": compute.Description,
"devices": string(devices), "devices": string(devices),
"disks": flattenDisks(compute.Disks), "disks": flattenDisks(compute.Disks),
"driver": compute.Driver, "driver": compute.Driver,
"gid": compute.GID, "gid": compute.GID,
"guid": compute.GUID, "guid": compute.GUID,
"compute_id": compute.ID, "compute_id": compute.ID,
"image_id": compute.ImageID, "image_id": compute.ImageID,
"interfaces": flattenInterfaces(compute.Interfaces), "interfaces": flattenInterfaces(compute.Interfaces),
"lock_status": compute.LockStatus, "lock_status": compute.LockStatus,
"manager_id": compute.ManagerID, "manager_id": compute.ManagerID,
"manager_type": compute.ManagerType, "manager_type": compute.ManagerType,
"migrationjob": compute.MigrationJob, "migrationjob": compute.MigrationJob,
"milestones": compute.Milestones, "milestones": compute.Milestones,
"name": compute.Name, "name": compute.Name,
"pinned": compute.Pinned, "pinned": compute.Pinned,
"ram": compute.RAM, "ram": compute.RAM,
"reference_id": compute.ReferenceID, "reference_id": compute.ReferenceID,
"registered": compute.Registered, "registered": compute.Registered,
"res_name": compute.ResName, "res_name": compute.ResName,
"rg_id": compute.RGID, "rg_id": compute.RGID,
"rg_name": compute.RGName, "rg_name": compute.RGName,
"snap_sets": flattenSnapSets(compute.SnapSets), "snap_sets": flattenSnapSets(compute.SnapSets),
"stateless_sep_id": compute.StatelessSepID, "stateless_sep_id": compute.StatelessSepID,
"stateless_sep_type": compute.StatelessSepType, "stateless_sep_type": compute.StatelessSepType,
"status": compute.Status, "status": compute.Status,
"tags": flattenTags(compute.Tags), "tags": flattenTags(compute.Tags),
"tech_status": compute.TechStatus, "tech_status": compute.TechStatus,
"total_disk_size": compute.TotalDiskSize, "total_disk_size": compute.TotalDiskSize,
"updated_by": compute.UpdatedBy, "updated_by": compute.UpdatedBy,
"updated_time": compute.UpdatedTime, "updated_time": compute.UpdatedTime,
"user_managed": compute.UserManaged, "user_managed": compute.UserManaged,
"vgpus": compute.VGPUs, "vgpus": compute.VGPUs,
"vins_connected": compute.VINSConnected, "vins_connected": compute.VINSConnected,
"virtual_image_id": compute.VirtualImageID, "virtual_image_id": compute.VirtualImageID,
} }
res = append(res, temp) res = append(res, temp)
} }
@ -316,6 +316,7 @@ func flattenCompute(d *schema.ResourceData, computeRec compute.RecordCompute) er
d.Set("computeci_id", computeRec.ComputeCIID) d.Set("computeci_id", computeRec.ComputeCIID)
d.Set("created_by", computeRec.CreatedBy) d.Set("created_by", computeRec.CreatedBy)
d.Set("created_time", computeRec.CreatedTime) d.Set("created_time", computeRec.CreatedTime)
// d.Set("custom_fields", flattenCustomFields(computeRec.CustomFields))
d.Set("deleted_by", computeRec.DeletedBy) d.Set("deleted_by", computeRec.DeletedBy)
d.Set("deleted_time", computeRec.DeletedTime) d.Set("deleted_time", computeRec.DeletedTime)
d.Set("description", computeRec.Description) d.Set("description", computeRec.Description)
@ -541,7 +542,7 @@ func flattenDataCompute(d *schema.ResourceData, computeRec compute.RecordCompute
d.Set("cpus", computeRec.CPU) d.Set("cpus", computeRec.CPU)
d.Set("created_by", computeRec.CreatedBy) d.Set("created_by", computeRec.CreatedBy)
d.Set("created_time", computeRec.CreatedTime) d.Set("created_time", computeRec.CreatedTime)
// d.Set("custom_fields", flattenCustomFields(computeRec.CustomFields)) d.Set("custom_fields", flattenCustomFields(computeRec.CustomFields))
d.Set("deleted_by", computeRec.DeletedBy) d.Set("deleted_by", computeRec.DeletedBy)
d.Set("deleted_time", computeRec.DeletedTime) d.Set("deleted_time", computeRec.DeletedTime)
d.Set("desc", computeRec.Description) d.Set("desc", computeRec.Description)

@ -0,0 +1,550 @@
package kvmvm
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/statefuncs"
)
func resourceComputeResourceV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of this compute. Compute names are case sensitive and must be unique in the resource group.",
},
"rg_id": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(1),
Description: "ID of the resource group where this compute should be deployed.",
},
"driver": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: statefuncs.StateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"SVA_KVM_X86", "KVM_X86", "KVM_PPC"}, false), // observe case while validating
Description: "Hardware architecture of this compute instance.",
},
"cpu": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, constants.MaxCpusPerCompute),
Description: "Number of CPUs to allocate to this compute instance.",
},
"ram": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(constants.MinRamPerCompute),
Description: "Amount of RAM in MB to allocate to this compute instance.",
},
"image_id": {
Type: schema.TypeInt,
Required: true,
//ForceNew: true, //REDEPLOY
Description: "ID of the OS image to base this compute instance on.",
},
"boot_disk_size": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "This compute instance boot disk size in GB. Make sure it is large enough to accomodate selected OS image.",
},
"affinity_label": {
Type: schema.TypeString,
Optional: true,
Description: "Set affinity label for compute",
},
"affinity_rules": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topology": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"node", "compute"}, false),
Description: "compute or node, for whom rule applies",
},
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"RECOMMENDED", "REQUIRED"}, false),
Description: "RECOMMENDED or REQUIRED, the degree of 'strictness' of this rule",
},
"mode": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"EQ", "NE", "ANY"}, false),
Description: "EQ or NE or ANY - the comparison mode is 'value', recorded by the specified 'key'",
},
"key": {
Type: schema.TypeString,
Required: true,
Description: "key that are taken into account when analyzing this rule will be identified",
},
"value": {
Type: schema.TypeString,
Required: true,
Description: "value that must match the key to be taken into account when analyzing this rule",
},
},
},
},
"anti_affinity_rules": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topology": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"node", "compute"}, false),
Description: "compute or node, for whom rule applies",
},
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"RECOMMENDED", "REQUIRED"}, false),
Description: "RECOMMENDED or REQUIRED, the degree of 'strictness' of this rule",
},
"mode": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"EQ", "NE", "ANY"}, false),
Description: "EQ or NE or ANY - the comparison mode is 'value', recorded by the specified 'key'",
},
"key": {
Type: schema.TypeString,
Required: true,
Description: "key that are taken into account when analyzing this rule will be identified",
},
"value": {
Type: schema.TypeString,
Required: true,
Description: "value that must match the key to be taken into account when analyzing this rule",
},
},
},
},
"disks": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: disksSubresourceSchemaMake(),
},
},
"custom_fields": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
},
"val": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"stateless": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Compute will be stateless (SVA_KVM_X86) if set to True",
},
"with_default_vins": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Create compute with default resgroup ViNS (true) or without any interfaces (false). This parameter is ignored if network block is specified",
},
"boot_disk": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: disksSubresourceSchemaMake(),
},
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
Description: "ID of SEP to create bootDisk on. Uses image's sepId if not set.",
},
"pool": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
Description: "Pool to use if sepId is set, can be also empty if needed to be chosen by system.",
},
"extra_disks": {
Type: schema.TypeSet,
Optional: true,
MaxItems: constants.MaxExtraDisksPerCompute,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "Optional list of IDs of extra disks to attach to this compute. You may specify several extra disks.",
},
"network": {
Type: schema.TypeSet,
Optional: true,
MinItems: 1,
MaxItems: constants.MaxNetworksPerCompute,
Elem: &schema.Resource{
Schema: networkSubresourceSchemaMake(),
},
Description: "Optional network connection(s) for this compute. You may specify several network blocks, one for each connection.",
},
"tags": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: tagsSubresourceSchemaMake(),
},
},
"port_forwarding": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: portForwardingSubresourceSchemaMake(),
},
},
"user_access": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: userAccessSubresourceSchemaMake(),
},
},
"snapshot": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: snapshotSubresourceSchemaMake(),
},
},
"rollback": {
Type: schema.TypeSet,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: snapshotRollbackSubresourceSchemaMake(),
},
},
"cd": {
Type: schema.TypeSet,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: cdSubresourceSchemaMake(),
},
},
"pin_to_stack": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "Optional text description of this compute instance.",
},
"cloud_init": {
Type: schema.TypeString,
Optional: true,
Description: "Optional cloud_init parameters. Applied when creating new compute instance only, ignored in all other cases.",
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "If true - enable compute, else - disable",
},
"pause": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"reset": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"auto_start": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Flag for redeploy compute",
},
"force_stop": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Flag for redeploy compute",
},
"data_disks": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"KEEP", "DETACH", "DESTROY"}, false),
Default: "DETACH",
Description: "Flag for redeploy compute",
},
"started": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Is compute started.",
},
"detach_disks": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"is": {
Type: schema.TypeString,
Optional: true,
Description: "system name",
},
"ipa_type": {
Type: schema.TypeString,
Optional: true,
Description: "compute purpose",
},
// The rest are Compute properties, which are "computed" once it is created
"account_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the account this compute instance belongs to.",
},
"account_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the account this compute instance belongs to.",
},
"affinity_weight": {
Type: schema.TypeInt,
Computed: true,
},
"arch": {
Type: schema.TypeString,
Computed: true,
},
"boot_order": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"boot_disk_id": {
Type: schema.TypeInt,
Computed: true,
Description: "This compute instance boot disk ID.",
},
"clone_reference": {
Type: schema.TypeInt,
Computed: true,
},
"clones": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"computeci_id": {
Type: schema.TypeInt,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"devices": {
Type: schema.TypeString,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"interfaces": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeInterfacesSchemaMake(),
},
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"manager_id": {
Type: schema.TypeInt,
Computed: true,
},
"manager_type": {
Type: schema.TypeString,
Computed: true,
},
"migrationjob": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"natable_vins_id": {
Type: schema.TypeInt,
Computed: true,
},
"natable_vins_ip": {
Type: schema.TypeString,
Computed: true,
},
"natable_vins_name": {
Type: schema.TypeString,
Computed: true,
},
"natable_vins_network": {
Type: schema.TypeString,
Computed: true,
},
"natable_vins_network_name": {
Type: schema.TypeString,
Computed: true,
},
"os_users": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: osUsersSubresourceSchemaMake(),
},
Description: "Guest OS users provisioned on this compute instance.",
},
"pinned": {
Type: schema.TypeBool,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"registered": {
Type: schema.TypeBool,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the resource group where this compute instance is located.",
},
"snap_sets": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeSnapSetsSchemaMake(),
},
},
"stateless_sep_id": {
Type: schema.TypeInt,
Computed: true,
},
"stateless_sep_type": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"user_managed": {
Type: schema.TypeBool,
Computed: true,
},
"vgpus": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"virtual_image_id": {
Type: schema.TypeInt,
Computed: true,
},
"virtual_image_name": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

@ -192,6 +192,16 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
createReqX86.Driver = driver createReqX86.Driver = driver
if custom_fields, ok := d.GetOk("custom_fields"); ok {
val := custom_fields.(string)
val = strings.ReplaceAll(val, "\\", "")
val = strings.ReplaceAll(val, "\n", "")
val = strings.ReplaceAll(val, "\t", "")
val = strings.TrimSpace(val)
createReqX86.CustomFields = val
}
log.Debugf("resourceComputeCreate: creating Compute of type KVM VM x86") log.Debugf("resourceComputeCreate: creating Compute of type KVM VM x86")
apiResp, err := c.CloudAPI().KVMX86().Create(ctx, createReqX86) apiResp, err := c.CloudAPI().KVMX86().Create(ctx, createReqX86)
if err != nil { if err != nil {
@ -247,13 +257,13 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
if enabled, ok := d.GetOk("enabled"); ok { if enabled, ok := d.GetOk("enabled"); ok {
if enabled.(bool) { if enabled.(bool) {
req := compute.EnableRequest{ComputeID: computeId} req := compute.EnableRequest{ComputeID: computeId}
log.Debugf("resourceComputeCreate: enable=%t Compute ID %d after completing its resource configuration", computeId, enabled) log.Debugf("resourceComputeCreate: enable=%t Compute ID %d after completing its resource configuration", enabled, computeId)
if _, err := c.CloudAPI().Compute().Enable(ctx, req); err != nil { if _, err := c.CloudAPI().Compute().Enable(ctx, req); err != nil {
warnings.Add(err) warnings.Add(err)
} }
} else { } else {
req := compute.DisableRequest{ComputeID: computeId} req := compute.DisableRequest{ComputeID: computeId}
log.Debugf("resourceComputeCreate: enable=%t Compute ID %d after completing its resource configuration", computeId, enabled) log.Debugf("resourceComputeCreate: enable=%t Compute ID %d after completing its resource configuration", enabled, computeId)
if _, err := c.CloudAPI().Compute().Disable(ctx, req); err != nil { if _, err := c.CloudAPI().Compute().Disable(ctx, req); err != nil {
warnings.Add(err) warnings.Add(err)
} }
@ -574,11 +584,11 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
switch networkData["net_type"].(string) { switch networkData["net_type"].(string) {
case "VINS": case "VINS":
if vinsId, ok := existVinsId(ctx, m, networkData["net_id"].(int)); !ok { if vinsId, ok := existVinsId(ctx, m, networkData["net_id"].(int)); !ok {
return diag.Errorf("resourceComputeCreate: can't create compute because vins ID %d is not allowed or does not exist", vinsId) return diag.Errorf("resourceComputeCreate: can't update compute because vins ID %d is not allowed or does not exist", vinsId)
} }
case "EXTNET": case "EXTNET":
if extNetId, ok := existExtNetId(ctx, m, networkData["net_id"].(int)); !ok { if extNetId, ok := existExtNetId(ctx, m, networkData["net_id"].(int)); !ok {
return diag.Errorf("resourceComputeCreate: can't create compute because extnet ID %d is not allowed or does not exist", extNetId) return diag.Errorf("resourceComputeCreate: can't update compute because extnet ID %d is not allowed or does not exist", extNetId)
} }
default: default:
@ -1335,6 +1345,35 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
} }
} }
if d.HasChange("custom_fields") {
val := d.Get("custom_fields").(string)
val = strings.ReplaceAll(val, "\\", "")
val = strings.ReplaceAll(val, "\n", "")
val = strings.ReplaceAll(val, "\t", "")
val = strings.TrimSpace(val)
if len(val) > 0 {
req := compute.SetCustomFieldsRequest{
ComputeID: computeRec.ID,
CustomFields: val,
}
_, err := c.CloudAPI().Compute().SetCustomFields(ctx, req)
if err != nil {
return diag.FromErr(err)
}
} else {
req := compute.DeleteCustomFieldsRequest{
ComputeID: computeRec.ID,
}
_, err := c.CloudAPI().Compute().DeleteCustomFields(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
// we may reuse dataSourceComputeRead here as we maintain similarity // we may reuse dataSourceComputeRead here as we maintain similarity
// between Compute resource and Compute data source schemas // between Compute resource and Compute data source schemas
defer resourceComputeRead(ctx, d, m) defer resourceComputeRead(ctx, d, m)
@ -1678,6 +1717,11 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema {
Schema: disksSubresourceSchemaMake(), Schema: disksSubresourceSchemaMake(),
}, },
}, },
"custom_fields": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"stateless": { "stateless": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
@ -2075,7 +2119,7 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema {
func ResourceCompute() *schema.Resource { func ResourceCompute() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
SchemaVersion: 1, SchemaVersion: 2,
CreateContext: resourceComputeCreate, CreateContext: resourceComputeCreate,
ReadContext: resourceComputeRead, ReadContext: resourceComputeRead,
@ -2095,5 +2139,12 @@ func ResourceCompute() *schema.Resource {
}, },
Schema: ResourceComputeSchemaMake(), Schema: ResourceComputeSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceComputeResourceV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourceCompueteStateUpgradeV1,
Version: 1,
},
},
} }
} }

@ -0,0 +1,33 @@
package kvmvm
import (
"context"
"fmt"
"strings"
log "github.com/sirupsen/logrus"
)
func resourceCompueteStateUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourceCompueteStateUpgradeV1: upgrading state")
customFields, ok := rawState["custom_fields"]
if !ok || customFields == nil {
rawState["custom_fields"] = "{}"
return rawState, nil
}
b := &strings.Builder{}
b.WriteString("{")
oldCustomFieldsSlice := customFields.([]interface{})
for i := range oldCustomFieldsSlice {
oldCustomFields := oldCustomFieldsSlice[i].(map[string]interface{})
b.WriteString(fmt.Sprintf(`"%s":"%s"`, oldCustomFields["key"], oldCustomFields["val"]))
if i < len(oldCustomFieldsSlice)-1 {
b.WriteString(",")
}
}
b.WriteString("}")
rawState["custom_fields"] = b.String()
return rawState, nil
}

@ -165,6 +165,7 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
Force: true, Force: true,
} }
log.Debugf("utilityComputeNetworksConfigure: stopping compute %d", computeID)
_, err := c.CloudAPI().Compute().Stop(ctx, req) _, err := c.CloudAPI().Compute().Stop(ctx, req)
if err != nil { if err != nil {
return err return err
@ -255,6 +256,7 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
startReq := compute.StartRequest{ComputeID: computeID} startReq := compute.StartRequest{ComputeID: computeID}
log.Debugf("utilityComputeNetworksConfigure: starting compute %d", computeID)
_, err = c.CloudAPI().Compute().Start(ctx, startReq) _, err = c.CloudAPI().Compute().Start(ctx, startReq)
if err != nil { if err != nil {
apiErrCount++ apiErrCount++
@ -279,7 +281,7 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
computeRecord, err := c.CloudAPI().Compute().Get(ctx, req) computeRecord, err := c.CloudAPI().Compute().Get(ctx, req)
if err != nil { if err != nil {
return *computeRecord, err return compute.RecordCompute{}, err
} }
return *computeRecord, nil return *computeRecord, nil

Loading…
Cancel
Save