|  |  |  | @ -40,6 +40,7 @@ import ( | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	log "github.com/sirupsen/logrus" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/disks" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmppc" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmx86" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants" | 
			
		
	
	
		
			
				
					|  |  |  | @ -47,12 +48,16 @@ import ( | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/dc" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/statefuncs" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/status" | 
			
		
	
		
			
				
					|  |  |  |  | 	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/validators" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | 
			
		
	
		
			
				
					|  |  |  |  | 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | 
			
		
	
		
			
				
					|  |  |  |  | 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | 
			
		
	
		
			
				
					|  |  |  |  | ) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // DiskKey is custom string type to set up context Key for Disk ID
 | 
			
		
	
		
			
				
					|  |  |  |  | type DiskKey string | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { | 
			
		
	
		
			
				
					|  |  |  |  | 	log.Debugf("resourceComputeCreate: called for Compute name %q, RG ID %d", d.Get("name").(string), d.Get("rg_id").(int)) | 
			
		
	
		
			
				
					|  |  |  |  | 	c := m.(*controller.ControllerCfg) | 
			
		
	
	
		
			
				
					|  |  |  | @ -307,11 +312,13 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 						req.ImageID = uint64(diskConv["image_id"].(int)) | 
			
		
	
		
			
				
					|  |  |  |  | 					} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 					_, err := c.CloudAPI().Compute().DiskAdd(ctx, req) | 
			
		
	
		
			
				
					|  |  |  |  | 					diskId, err := c.CloudAPI().Compute().DiskAdd(ctx, req) | 
			
		
	
		
			
				
					|  |  |  |  | 					if err != nil { | 
			
		
	
		
			
				
					|  |  |  |  | 						cleanup = true | 
			
		
	
		
			
				
					|  |  |  |  | 						return diag.FromErr(err) | 
			
		
	
		
			
				
					|  |  |  |  | 					} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 					ctx = context.WithValue(ctx, DiskKey(strconv.Itoa(int(diskId))), diskConv["permanently"].(bool)) | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
	
		
			
				
					|  |  |  | @ -541,7 +548,7 @@ func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interfac | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if err = flattenCompute(d, computeRec); err != nil { | 
			
		
	
		
			
				
					|  |  |  |  | 	if err = flattenCompute(ctx, d, computeRec); err != nil { | 
			
		
	
		
			
				
					|  |  |  |  | 		return diag.FromErr(err) | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -747,14 +754,23 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 	if d.HasChange("disks") { | 
			
		
	
		
			
				
					|  |  |  |  | 		deletedDisks := make([]interface{}, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 		addedDisks := make([]interface{}, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 		updatedDisks := make([]interface{}, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 		resizedDisks := make([]interface{}, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 		renamedDisks := make([]interface{}, 0) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// save permanently in disks based on disk_id to context
 | 
			
		
	
		
			
				
					|  |  |  |  | 		for _, diskItemInterface := range d.Get("disks").([]interface{}) { | 
			
		
	
		
			
				
					|  |  |  |  | 			diskItem := diskItemInterface.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 			diskId := diskItem["disk_id"].(int) | 
			
		
	
		
			
				
					|  |  |  |  | 			permanently := diskItem["permanently"].(bool) | 
			
		
	
		
			
				
					|  |  |  |  | 			ctx = context.WithValue(ctx, DiskKey(strconv.Itoa(diskId)), permanently) | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		oldDisks, newDisks := d.GetChange("disks") | 
			
		
	
		
			
				
					|  |  |  |  | 		oldConv := oldDisks.([]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		newConv := newDisks.([]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		for _, el := range oldConv { | 
			
		
	
		
			
				
					|  |  |  |  | 			if !isContainsDisk(newConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if !isContainsDisk(newConv, el) && !isRenameDisk(newConv, el) && !isResizeDisk(newConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 				flag := false | 
			
		
	
		
			
				
					|  |  |  |  | 				extraDisks := d.Get("extra_disks").(*schema.Set).List() | 
			
		
	
		
			
				
					|  |  |  |  | 				delDisk := el.(map[string]interface{}) | 
			
		
	
	
		
			
				
					|  |  |  | @ -778,10 +794,12 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 		for _, el := range newConv { | 
			
		
	
		
			
				
					|  |  |  |  | 			if !isContainsDisk(oldConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 				addedDisks = append(addedDisks, el) | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				if isChangeDisk(oldConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 					updatedDisks = append(updatedDisks, el) | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			if isResizeDisk(oldConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 				resizedDisks = append(resizedDisks, el) | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			if isRenameDisk(oldConv, el) { | 
			
		
	
		
			
				
					|  |  |  |  | 				renamedDisks = append(renamedDisks, el) | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -850,15 +868,17 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 				if diskConv["image_id"].(int) != 0 { | 
			
		
	
		
			
				
					|  |  |  |  | 					req.ImageID = uint64(diskConv["image_id"].(int)) | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				_, err := c.CloudAPI().Compute().DiskAdd(ctx, req) | 
			
		
	
		
			
				
					|  |  |  |  | 				diskId, err := c.CloudAPI().Compute().DiskAdd(ctx, req) | 
			
		
	
		
			
				
					|  |  |  |  | 				if err != nil { | 
			
		
	
		
			
				
					|  |  |  |  | 					return diag.FromErr(err) | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				ctx = context.WithValue(ctx, DiskKey(strconv.Itoa(int(diskId))), diskConv["permanently"].(bool)) | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if len(updatedDisks) > 0 { | 
			
		
	
		
			
				
					|  |  |  |  | 			for _, disk := range updatedDisks { | 
			
		
	
		
			
				
					|  |  |  |  | 		if len(resizedDisks) > 0 { | 
			
		
	
		
			
				
					|  |  |  |  | 			for _, disk := range resizedDisks { | 
			
		
	
		
			
				
					|  |  |  |  | 				diskConv := disk.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 				if diskConv["disk_type"].(string) == "B" { | 
			
		
	
		
			
				
					|  |  |  |  | 					continue | 
			
		
	
	
		
			
				
					|  |  |  | @ -875,6 +895,22 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if len(renamedDisks) > 0 { | 
			
		
	
		
			
				
					|  |  |  |  | 			for _, disk := range renamedDisks { | 
			
		
	
		
			
				
					|  |  |  |  | 				diskConv := disk.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				req := disks.RenameRequest{ | 
			
		
	
		
			
				
					|  |  |  |  | 					DiskID: uint64(diskConv["disk_id"].(int)), | 
			
		
	
		
			
				
					|  |  |  |  | 					Name:   diskConv["disk_name"].(string), | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				_, err := c.CloudAPI().Disks().Rename(ctx, req) | 
			
		
	
		
			
				
					|  |  |  |  | 				if err != nil { | 
			
		
	
		
			
				
					|  |  |  |  | 					return diag.FromErr(err) | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if d.HasChange("started") { | 
			
		
	
	
		
			
				
					|  |  |  | @ -1398,7 +1434,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf | 
			
		
	
		
			
				
					|  |  |  |  | 	return warnings.Get() | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | func isChangeDisk(els []interface{}, el interface{}) bool { | 
			
		
	
		
			
				
					|  |  |  |  | func isResizeDisk(els []interface{}, el interface{}) bool { | 
			
		
	
		
			
				
					|  |  |  |  | 	for _, elOld := range els { | 
			
		
	
		
			
				
					|  |  |  |  | 		elOldConv := elOld.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		elConv := el.(map[string]interface{}) | 
			
		
	
	
		
			
				
					|  |  |  | @ -1410,11 +1446,23 @@ func isChangeDisk(els []interface{}, el interface{}) bool { | 
			
		
	
		
			
				
					|  |  |  |  | 	return false | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | func isRenameDisk(els []interface{}, el interface{}) bool { | 
			
		
	
		
			
				
					|  |  |  |  | 	for _, elOld := range els { | 
			
		
	
		
			
				
					|  |  |  |  | 		elOldConv := elOld.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		elConv := el.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		if elOldConv["disk_id"].(int) == elConv["disk_id"].(int) && | 
			
		
	
		
			
				
					|  |  |  |  | 			elOldConv["disk_name"].(string) != elConv["disk_name"].(string) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return true | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	return false | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | func isContainsDisk(els []interface{}, el interface{}) bool { | 
			
		
	
		
			
				
					|  |  |  |  | 	for _, elOld := range els { | 
			
		
	
		
			
				
					|  |  |  |  | 		elOldConv := elOld.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		elConv := el.(map[string]interface{}) | 
			
		
	
		
			
				
					|  |  |  |  | 		if elOldConv["disk_name"].(string) == elConv["disk_name"].(string) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if elOldConv["disk_id"].(int) == elConv["disk_id"].(int) { | 
			
		
	
		
			
				
					|  |  |  |  | 			return true | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
	
		
			
				
					|  |  |  | @ -1505,7 +1553,7 @@ func disksSubresourceSchemaMake() map[string]*schema.Schema { | 
			
		
	
		
			
				
					|  |  |  |  | 		"permanently": { | 
			
		
	
		
			
				
					|  |  |  |  | 			Type:        schema.TypeBool, | 
			
		
	
		
			
				
					|  |  |  |  | 			Optional:    true, | 
			
		
	
		
			
				
					|  |  |  |  | 			Default:     true, | 
			
		
	
		
			
				
					|  |  |  |  | 			Default:     false, | 
			
		
	
		
			
				
					|  |  |  |  | 			Description: "Disk deletion status", | 
			
		
	
		
			
				
					|  |  |  |  | 		}, | 
			
		
	
		
			
				
					|  |  |  |  | 		"disk_id": { | 
			
		
	
	
		
			
				
					|  |  |  | @ -1634,10 +1682,13 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema { | 
			
		
	
		
			
				
					|  |  |  |  | 			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.", | 
			
		
	
		
			
				
					|  |  |  |  | 			Type:     schema.TypeInt, | 
			
		
	
		
			
				
					|  |  |  |  | 			Required: true, | 
			
		
	
		
			
				
					|  |  |  |  | 			ValidateFunc: validation.All( | 
			
		
	
		
			
				
					|  |  |  |  | 				validation.IntAtLeast(constants.MinRamPerCompute), | 
			
		
	
		
			
				
					|  |  |  |  | 				validators.DivisibleBy(constants.RAMDivisibility), | 
			
		
	
		
			
				
					|  |  |  |  | 			), | 
			
		
	
		
			
				
					|  |  |  |  | 			Description: "Amount of RAM in MB to allocate to this compute instance.", | 
			
		
	
		
			
				
					|  |  |  |  | 		}, | 
			
		
	
		
			
				
					|  |  |  |  | 		"image_id": { | 
			
		
	
		
			
				
					|  |  |  |  | 			Type:     schema.TypeInt, | 
			
		
	
	
		
			
				
					|  |  |  | @ -1686,7 +1737,7 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema { | 
			
		
	
		
			
				
					|  |  |  |  | 					}, | 
			
		
	
		
			
				
					|  |  |  |  | 					"value": { | 
			
		
	
		
			
				
					|  |  |  |  | 						Type:        schema.TypeString, | 
			
		
	
		
			
				
					|  |  |  |  | 						Required:    true, | 
			
		
	
		
			
				
					|  |  |  |  | 						Optional:    true, | 
			
		
	
		
			
				
					|  |  |  |  | 						Description: "value that must match the key to be taken into account when analyzing this rule", | 
			
		
	
		
			
				
					|  |  |  |  | 					}, | 
			
		
	
		
			
				
					|  |  |  |  | 				}, | 
			
		
	
	
		
			
				
					|  |  |  | @ -1722,7 +1773,7 @@ func ResourceComputeSchemaMake() map[string]*schema.Schema { | 
			
		
	
		
			
				
					|  |  |  |  | 					}, | 
			
		
	
		
			
				
					|  |  |  |  | 					"value": { | 
			
		
	
		
			
				
					|  |  |  |  | 						Type:        schema.TypeString, | 
			
		
	
		
			
				
					|  |  |  |  | 						Required:    true, | 
			
		
	
		
			
				
					|  |  |  |  | 						Optional:    true, | 
			
		
	
		
			
				
					|  |  |  |  | 						Description: "value that must match the key to be taken into account when analyzing this rule", | 
			
		
	
		
			
				
					|  |  |  |  | 					}, | 
			
		
	
		
			
				
					|  |  |  |  | 				}, | 
			
		
	
	
		
			
				
					|  |  |  | 
 |