package utilities
import (
"context"
"fmt"
"strconv"
"time"
"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"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/rg/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status"
)
func CreateRequestResourceRG ( ctx context . Context , plan * models . ResourceRGModel ) ( rg . CreateRequest , diag . Diagnostics ) {
tflog . Info ( ctx , "Start CreateRequestResourceRG" , map [ string ] any {
"name" : plan . Name . ValueString ( ) ,
"account_id" : plan . AccountID . ValueInt64 ( ) ,
"gid" : plan . GID . ValueInt64 ( ) ,
} )
// set up required parameters in resource group create request
createReq := rg . CreateRequest {
Name : plan . Name . ValueString ( ) ,
AccountID : uint64 ( plan . AccountID . ValueInt64 ( ) ) ,
GID : uint64 ( plan . GID . ValueInt64 ( ) ) ,
MaxCPUCapacity : - 1 ,
MaxVDiskCapacity : - 1 ,
MaxMemoryCapacity : - 1 ,
MaxNetworkPeerTransfer : - 1 ,
MaxNumPublicIP : - 1 ,
}
// set up resource limits optional parameters
if ! plan . ResourceLimits . IsUnknown ( ) {
var resourceLimits models . ResourceLimitsModel
diags := plan . ResourceLimits . As ( ctx , & resourceLimits , basetypes . ObjectAsOptions { } )
if diags . HasError ( ) {
tflog . Error ( ctx , "CreateRequestResourceRG: cannot populate ResourceLimits with plan.ResourceLimits object element" )
return createReq , diags
}
if ! resourceLimits . CUM . IsUnknown ( ) {
createReq . MaxMemoryCapacity = int64 ( resourceLimits . CUM . ValueFloat64 ( ) )
}
if ! resourceLimits . CUDM . IsUnknown ( ) {
createReq . MaxVDiskCapacity = int64 ( resourceLimits . CUDM . ValueFloat64 ( ) )
}
if ! resourceLimits . CUC . IsUnknown ( ) {
createReq . MaxCPUCapacity = int64 ( resourceLimits . CUC . ValueFloat64 ( ) )
}
if ! resourceLimits . CUI . IsUnknown ( ) {
createReq . MaxNumPublicIP = int64 ( resourceLimits . CUI . ValueFloat64 ( ) )
}
if ! resourceLimits . CUNP . IsUnknown ( ) {
createReq . MaxNetworkPeerTransfer = int64 ( resourceLimits . CUNP . ValueFloat64 ( ) )
}
}
// set up defNet, owner, ipcidr, description, extNetId, extIp, registerComputes, uniqPools optional parameters
if ! plan . Owner . IsNull ( ) {
createReq . Owner = plan . Owner . ValueString ( )
}
if plan . DefNetType . IsNull ( ) {
createReq . DefNet = "PRIVATE" // default value
} else {
createReq . DefNet = plan . DefNetType . ValueString ( )
}
if ! plan . IPCIDR . IsNull ( ) {
//createReq.IPCIDR = plan.IPCIDR.ValueString()
}
if ! plan . Description . IsNull ( ) {
createReq . Description = plan . Description . ValueString ( )
}
if plan . ExtNetID . IsNull ( ) {
createReq . ExtNetID = 0 // default value 0
} else {
createReq . ExtNetID = uint64 ( plan . ExtNetID . ValueInt64 ( ) )
}
if ! plan . ExtIP . IsNull ( ) {
createReq . ExtIP = plan . ExtIP . ValueString ( )
}
if plan . RegisterComputes . IsNull ( ) {
createReq . RegisterComputes = false // default value
} else {
createReq . RegisterComputes = plan . RegisterComputes . ValueBool ( )
}
if ! plan . UniqPools . IsUnknown ( ) {
uniqPools := make ( [ ] string , 0 , len ( plan . UniqPools . Elements ( ) ) )
diags := plan . UniqPools . ElementsAs ( ctx , & uniqPools , true )
if diags . HasError ( ) {
tflog . Error ( ctx , "CreateRequestResourceRG: cannot populate UniqPools with plan.UniqPools object element" )
return createReq , diags
}
createReq . UniqPools = uniqPools
}
return createReq , nil
}
// RestoreRG performs resource group Restore request. Returns error in case of failures.
func RestoreRG ( ctx context . Context , rgId uint64 , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
restoreReq := rg . RestoreRequest { RGID : rgId }
tflog . Info ( ctx , "utilityRestoreRG: before calling CloudBroker().RG().Restore" , map [ string ] any { "rgId" : rgId , "req" : restoreReq } )
res , err := c . CloudBroker ( ) . RG ( ) . Restore ( ctx , restoreReq )
if err != nil {
diags . AddError (
"RestoreRG: cannot restore resource group" ,
err . Error ( ) ,
)
return diags
}
tflog . Info ( ctx , "utilityRestoreRG: response from CloudBroker().RG().Restore" , map [ string ] any { "rg_id" : rgId , "response" : res } )
return nil
}
// EnableRG performs resource group Enable request
func EnableRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) error {
enableReq := rg . EnableRequest { RGID : rgId }
tflog . Info ( ctx , "utilityEnableRG: before calling CloudBroker().RG().Enable" , map [ string ] any { "rg_id" : rgId , "req" : enableReq } )
res , err := c . CloudBroker ( ) . RG ( ) . Enable ( ctx , enableReq )
tflog . Info ( ctx , "utilityEnableRG: response from CloudBroker().RG().Enable" , map [ string ] any { "rg_id" : rgId , "response" : res } )
return err
}
// DisableRG performs resource group Disable request
func DisableRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) error {
disableReq := rg . DisableRequest { RGID : rgId }
tflog . Info ( ctx , "utilityDisableRG: before calling CloudBroker().RG().Disable" , map [ string ] any { "rg_id" : rgId , "req" : disableReq } )
res , err := c . CloudBroker ( ) . RG ( ) . Disable ( ctx , disableReq )
tflog . Info ( ctx , "utilityDisableRG: response from CloudBroker().RG().Disable" , map [ string ] any { "rg_id" : rgId , "response" : res } )
return err
}
// UpdateRG compares plan and state for resource group fields name, description, quota, register_computes.
// If any changes are detected, Update request is performed. If not, no update is performed.
func UpdateRG ( ctx context . Context , rgId uint64 , plan , state * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
var updateNeeded bool
var diags diag . Diagnostics
updateReq := rg . UpdateRequest {
RGID : rgId ,
}
if ! plan . Name . Equal ( state . Name ) {
updateReq . Name = plan . Name . ValueString ( )
tflog . Info ( ctx , "utilityUpdateRG: new name specified" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"name_plan" : plan . Name . ValueString ( ) ,
"name_state" : state . Name . ValueString ( ) } )
updateNeeded = true
}
if ! plan . Description . Equal ( state . Description ) {
updateReq . Description = plan . Description . ValueString ( )
tflog . Info ( ctx , "utilityUpdateRG: new description specified" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"description_plan" : plan . Description . ValueString ( ) ,
"description_state" : state . Description . ValueString ( ) } )
updateNeeded = true
}
if ! plan . RegisterComputes . Equal ( state . RegisterComputes ) {
if plan . RegisterComputes . IsNull ( ) {
updateReq . RegisterComputes = false // default value
} else {
updateReq . RegisterComputes = plan . RegisterComputes . ValueBool ( )
}
tflog . Info ( ctx , "utilityUpdateRG: new register_computes specified" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"register_computes_plan" : plan . RegisterComputes . ValueBool ( ) ,
"register_computes_state" : state . RegisterComputes . ValueBool ( ) } )
updateNeeded = true
}
var updResLimitsNeeded bool
var resLimitsPlan , resLimitsState models . ResourceLimitsModel
if ! plan . ResourceLimits . IsUnknown ( ) {
diags = plan . ResourceLimits . As ( ctx , & resLimitsPlan , basetypes . ObjectAsOptions { } )
if diags . HasError ( ) {
return diags
}
}
if ! state . ResourceLimits . IsNull ( ) {
diags = state . ResourceLimits . As ( ctx , & resLimitsState , basetypes . ObjectAsOptions { } )
if diags . HasError ( ) {
return diags
}
}
if ! plan . UniqPools . IsUnknown ( ) {
if ! plan . UniqPools . Equal ( state . UniqPools ) {
uniqPools := make ( [ ] string , 0 , len ( plan . UniqPools . Elements ( ) ) )
diags := plan . UniqPools . ElementsAs ( ctx , & uniqPools , true )
if diags . HasError ( ) {
tflog . Error ( ctx , "UpdateResourceRG: cannot populate UniqPools with plan.UniqPools object element" )
return diags
}
updateReq . UniqPools = uniqPools
}
}
if ! plan . ResourceLimits . IsUnknown ( ) {
if ! resLimitsPlan . CUM . Equal ( resLimitsState . CUM ) {
updateReq . MaxMemoryCapacity = int64 ( resLimitsPlan . CUM . ValueFloat64 ( ) )
updResLimitsNeeded = true
}
if ! resLimitsPlan . CUDM . Equal ( resLimitsState . CUDM ) {
updateReq . MaxVDiskCapacity = int64 ( resLimitsPlan . CUDM . ValueFloat64 ( ) )
updResLimitsNeeded = true
}
if ! resLimitsPlan . CUC . Equal ( resLimitsState . CUC ) {
updateReq . MaxCPUCapacity = int64 ( resLimitsPlan . CUC . ValueFloat64 ( ) )
updResLimitsNeeded = true
}
if ! resLimitsPlan . CUNP . Equal ( resLimitsState . CUNP ) {
updateReq . MaxNetworkPeerTransfer = int64 ( resLimitsPlan . CUNP . ValueFloat64 ( ) )
updResLimitsNeeded = true
}
if ! resLimitsPlan . CUI . Equal ( resLimitsState . CUI ) {
updateReq . MaxNumPublicIP = int64 ( resLimitsPlan . CUI . ValueFloat64 ( ) )
updResLimitsNeeded = true
}
}
if updResLimitsNeeded {
tflog . Info ( ctx , "utilityUpdateRG: new resource limits specified" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) } )
updateNeeded = true
}
if updateNeeded {
tflog . Info ( ctx , "utilityUpdateRG: before calling CloudBroker().RG().Update" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "req" : updateReq } )
res , err := c . CloudBroker ( ) . RG ( ) . Update ( ctx , updateReq )
tflog . Info ( ctx , "utilityUpdateRG: response from CloudBroker().RG().Update" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "response" : res } )
if err != nil {
diags . AddError ( "can not update RG" , err . Error ( ) )
return diags
}
}
if ! updateNeeded {
tflog . Info ( ctx , "utilityUpdateRG: call for CloudBroker().RG().Update was not needed" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) } )
}
return nil
}
// EnableDisableCreateRG performs Enable request is enable is true, and Disable request otherwise.
// In case of failure returns warnings.
func EnableDisableCreateRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
var enable bool
if plan . Enable . IsNull ( ) {
enable = true // default value
} else {
enable = plan . Enable . ValueBool ( )
}
tflog . Info ( ctx , "EnableDisableCreateRG: resource group to be enabled/disabled" , map [ string ] any {
"rg_id" : rgId ,
"enable" : enable } )
if enable {
err := EnableRG ( ctx , rgId , plan , c )
if err != nil {
diags . AddWarning (
"EnableDisableCreateRG: cannot enable rg" ,
err . Error ( ) ,
)
return diags
}
}
if ! enable {
err := DisableRG ( ctx , rgId , plan , c )
if err != nil {
diags . AddWarning (
"EnableDisableCreateRG: cannot disable rg" ,
err . Error ( ) ,
)
return diags
}
}
tflog . Info ( ctx , "EnableDisableCreateRG: resource group is successfully enabled/disabled" , map [ string ] any { "rg_id" : rgId , "enable" : enable } )
return nil
}
// EnableDisableUpdateRG performs Enable request is enable is true, and Disable request otherwise.
// In case of failure returns errors.
func EnableDisableUpdateRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
var enable bool
if plan . Enable . IsNull ( ) {
enable = true // default value
} else {
enable = plan . Enable . ValueBool ( )
}
tflog . Info ( ctx , "EnableDisableUpdateRG: resource group to be enabled/disabled" , map [ string ] any {
"rg_id" : rgId ,
"enable" : enable } )
if enable {
err := EnableRG ( ctx , rgId , plan , c )
if err != nil {
diags . AddError (
"EnableDisableUpdateRG: cannot enable rg" ,
err . Error ( ) ,
)
return diags
}
}
if ! enable {
err := DisableRG ( ctx , rgId , plan , c )
if err != nil {
diags . AddError (
"EnableDisableUpdateRG: cannot disable rg" ,
err . Error ( ) ,
)
return diags
}
}
tflog . Info ( ctx , "EnableDisableUpdateRG: resource group is successfully enabled/disabled" , map [ string ] any { "rg_id" : rgId , "enable" : enable } )
return nil
}
// AccessUpdateRG compares plan and state for resource group field access.
// If changes are detected, AccessRevoke request is performed for each deleted access user and AccessGrant request is
// performed for each added access user. If no changes are detected, no requests performed.
// Returns errors in case of failures.
func AccessUpdateRG ( ctx context . Context , rgId uint64 , plan , state * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
itemsAccessPlan := make ( [ ] models . AccessModel , 0 , len ( plan . Access . Elements ( ) ) )
diags = plan . Access . ElementsAs ( ctx , & itemsAccessPlan , false )
if diags . HasError ( ) {
tflog . Error ( ctx , "AccessUpdateRG: cannot populate itemsAccess with plan.Access List elements" )
return diags
}
itemsAccessState := make ( [ ] models . AccessModel , 0 , len ( state . Access . Elements ( ) ) )
diags = state . Access . ElementsAs ( ctx , & itemsAccessState , false )
if diags . HasError ( ) {
tflog . Error ( ctx , "AccessUpdateRG: cannot populate itemsAccess with state.Access List elements" )
return diags
}
// define accesses to be revoked and revoke them
var deletedAccess [ ] models . AccessModel
for _ , accessStateElem := range itemsAccessState {
if ! accessStateElem . Contains ( itemsAccessPlan ) {
deletedAccess = append ( deletedAccess , accessStateElem )
}
}
if len ( deletedAccess ) == 0 {
tflog . Info ( ctx , "AccessUpdateRG: no access needs to be revoked" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) } )
}
if len ( deletedAccess ) > 0 {
tflog . Info ( ctx , "AccessUpdateRG: access needs to be revoked" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"deleted_access" : deletedAccess } )
for _ , deletedAccessItem := range deletedAccess {
revokeReq := rg . AccessRevokeRequest {
RGID : rgId ,
User : deletedAccessItem . User . ValueString ( ) ,
}
tflog . Info ( ctx , "AccessUpdateRG: before calling CloudBroker().RG().AccessRevoke" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "req" : revokeReq } )
res , err := c . CloudBroker ( ) . RG ( ) . AccessRevoke ( ctx , revokeReq )
tflog . Info ( ctx , "AccessUpdateRG: response from CloudBroker().RG().AccessRevoke" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "response" : res } )
if err != nil {
diags . AddError (
"AccessUpdateRG: cannot revoke access for rg" ,
err . Error ( ) )
}
}
}
// define accesses to be granted and grant them
var addedAccess [ ] models . AccessModel
for _ , accessPlanElem := range itemsAccessPlan {
if ! accessPlanElem . Contains ( itemsAccessState ) {
addedAccess = append ( addedAccess , accessPlanElem )
}
}
if len ( addedAccess ) == 0 {
tflog . Info ( ctx , "AccessUpdateRG: no access need to be granted" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) } )
}
if len ( addedAccess ) > 0 {
tflog . Info ( ctx , "AccessUpdateRG: access needs to be granted" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"added_access" : addedAccess } )
for _ , addedAccessItem := range addedAccess {
grantReq := rg . AccessGrantRequest {
RGID : rgId ,
User : addedAccessItem . User . ValueString ( ) ,
Right : addedAccessItem . Right . ValueString ( ) ,
}
tflog . Info ( ctx , "AccessUpdateRG: before calling CloudBroker().RG().AccessGrant" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "req" : grantReq } )
res , err := c . CloudBroker ( ) . RG ( ) . AccessGrant ( ctx , grantReq )
tflog . Info ( ctx , "AccessUpdateRG: response from CloudBroker().RG().AccessGrant" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "response" : res } )
if err != nil {
diags . AddError (
"AccessUpdateRG: cannot grant access for rg" ,
err . Error ( ) )
}
}
}
return diags
}
// AccessCreateRG grants access to users specified in access field for created resource.
// In case of failure returns warnings.
func AccessCreateRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
if len ( plan . Access . Elements ( ) ) != 0 {
tflog . Info ( ctx , "AccessCreateRG: access needs to be granted" , map [ string ] any {
"rg_id" : rgId ,
"access_plan" : plan . Access . Elements ( ) } )
itemsAccessPlan := make ( [ ] models . AccessModel , 0 , len ( plan . Access . Elements ( ) ) )
diagsItem := plan . Access . ElementsAs ( ctx , & itemsAccessPlan , false )
if diagsItem . HasError ( ) {
tflog . Warn ( ctx , "cannot populate itemsAccess with plan.Access List elements" )
diags . AddWarning ( fmt . Sprintf ( "AccessCreateRG: Unable to get access info for RG %d" , rgId ) ,
"cannot populate itemsAccess with plan.Access List elements" ,
)
return diags
}
for _ , addedAccessItem := range itemsAccessPlan {
grantReq := rg . AccessGrantRequest {
RGID : rgId ,
User : addedAccessItem . User . ValueString ( ) ,
Right : addedAccessItem . Right . ValueString ( ) ,
}
tflog . Info ( ctx , "AccessCreateRG: before calling CloudBroker().RG().AccessGrant" , map [ string ] any {
"rg_id" : rgId ,
"req" : grantReq } )
res , err := c . CloudBroker ( ) . RG ( ) . AccessGrant ( ctx , grantReq )
if err != nil {
diags . AddWarning ( "AccessCreateRG: Unable to grant access for RG" ,
err . Error ( ) )
}
tflog . Info ( ctx , "AccessCreateRG: response from CloudBroker().RG().AccessGrant" , map [ string ] any {
"rg_id" : rgId ,
"response" : res } )
}
}
if len ( plan . Access . Elements ( ) ) == 0 {
tflog . Info ( ctx , "AccessCreateRG: no access need to be granted" , map [ string ] any {
"rg_id" : rgId ,
"access_plan" : plan . Access . Elements ( ) } )
}
return diags
}
// SetDefNetUpdateRG compares plan and state for resource group update field def_net.
// If any changes are detected, SetDefNet request is performed. If not, no SetDefNet is performed.
// Returns error in case of failures.
func SetDefNetUpdateRG ( ctx context . Context , rgId uint64 , plan , state * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
var setDefNetNeeded bool
setDefNetReq := rg . SetDefNetRequest {
RGID : rgId ,
}
var itemDefNetPlan , itemDefNetState models . DefNetModel
if ! plan . DefNet . IsNull ( ) {
diags . Append ( plan . DefNet . As ( ctx , & itemDefNetPlan , basetypes . ObjectAsOptions { } ) ... )
if diags . HasError ( ) {
tflog . Error ( ctx , "SetDefNetUpdateRG: cannot populate defNet with plan.DefNet object element" )
return diags
}
}
if ! state . DefNet . IsNull ( ) {
diags . Append ( state . DefNet . As ( ctx , & itemDefNetState , basetypes . ObjectAsOptions { } ) ... )
if diags . HasError ( ) {
tflog . Error ( ctx , "SetDefNetUpdateRG: cannot populate defNet with state.DefNet object element" )
return diags
}
}
if ! plan . DefNet . IsNull ( ) && ! state . DefNet . IsNull ( ) {
if ! itemDefNetPlan . NetId . Equal ( itemDefNetState . NetId ) {
setDefNetNeeded = true
}
if ! itemDefNetPlan . NetType . Equal ( itemDefNetState . NetType ) {
setDefNetNeeded = true
}
} else if ! plan . DefNet . IsNull ( ) {
setDefNetNeeded = true
}
if setDefNetNeeded {
tflog . Info ( ctx , "utilitySetDefNetUpdateRG: new def_net specified" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"def_net_plan" : plan . DefNet ,
"def_net_state" : state . DefNet } )
setDefNetReq . NetType = itemDefNetPlan . NetType . ValueString ( )
if itemDefNetPlan . NetId . IsNull ( ) {
setDefNetReq . NetID = 0 // default value
} else {
setDefNetReq . NetID = uint64 ( itemDefNetPlan . NetId . ValueInt64 ( ) )
}
tflog . Info ( ctx , "utilitySetDefNetUpdateRG: before calling CloudBroker().RG().SetDefNet" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "req" : setDefNetReq } )
res , err := c . CloudBroker ( ) . RG ( ) . SetDefNet ( ctx , setDefNetReq )
if err != nil {
diags . AddError (
"SetDefNetUpdateRG: can not set defNet for rg" ,
err . Error ( ) )
return diags
}
tflog . Info ( ctx , "utilitySetDefNetUpdateRG: response from CloudBroker().RG().SetDefNet" , map [ string ] any { "rg_id" : plan . Id . ValueString ( ) , "response" : res } )
}
if ! setDefNetNeeded {
tflog . Info ( ctx , "utilitySetDefNetUpdateRG: call for CloudBroker().RG().SetDefNet was not needed" , map [ string ] any {
"rg_id" : plan . Id . ValueString ( ) ,
"def_net_plan" : plan . DefNet ,
"def_net_state" : state . DefNet } )
}
return nil
}
// SetDefNetCreateRG performs SetDefNet request if def_net field is not empty. Otherwise, no SetDefNet request is performed.
// In case of failure returns warnings.
func SetDefNetCreateRG ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
setDefNetReq := rg . SetDefNetRequest { RGID : rgId }
var itemDefNetPlan models . DefNetModel
if ! plan . DefNet . IsNull ( ) {
tflog . Info ( ctx , "SetDefNetCreateRG: new def_net specified" , map [ string ] any {
"rg_id" : rgId ,
"def_net_plan" : plan . DefNet } )
diagItem := plan . DefNet . As ( ctx , & itemDefNetPlan , basetypes . ObjectAsOptions { } )
if diagItem . HasError ( ) {
diags . AddWarning (
fmt . Sprintf ( "SetDefNetCreateRG: Unable to setDefNet for RG %d" , rgId ) ,
"cannot populate defNet with plan.DefNet object element for rg" ,
)
return diags
}
setDefNetReq . NetType = itemDefNetPlan . NetType . ValueString ( )
if itemDefNetPlan . NetId . IsNull ( ) {
setDefNetReq . NetID = 0 // default value
} else {
setDefNetReq . NetID = uint64 ( itemDefNetPlan . NetId . ValueInt64 ( ) )
}
tflog . Info ( ctx , "SetDefNetCreateRG: before calling CloudBroker().RG().SetDefNet" , map [ string ] any { "rg_id" : rgId , "req" : setDefNetReq } )
res , err := c . CloudBroker ( ) . RG ( ) . SetDefNet ( ctx , setDefNetReq )
tflog . Info ( ctx , "SetDefNetCreateRG: response from CloudBroker().RG().SetDefNet" , map [ string ] any { "rg_id" : rgId , "response" : res } )
if err != nil {
diags . AddWarning (
"SetDefNetCreateRG: Unable to setDefNet for RG" ,
err . Error ( ) ,
)
return diags
}
}
if plan . DefNet . IsNull ( ) {
tflog . Info ( ctx , "SetDefNetCreateRG: call for CloudBroker().RG().SetDefNet was not needed" , map [ string ] any {
"rg_id" : rgId ,
"def_net_plan" : plan . DefNet } )
}
return nil
}
// UpdateComputeFeature performs С omputeFeatureUpdate request if compute_feature field is not empty and need update.
// In case of failure returns error.
func UpdateComputeFeature ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
req := rg . UpdateComputeFeaturesRequest { RGID : rgId }
computeFeatures := make ( [ ] string , 0 , len ( plan . ComputeFeatures . Elements ( ) ) )
diags = plan . ComputeFeatures . ElementsAs ( ctx , & computeFeatures , true )
if diags . HasError ( ) {
tflog . Error ( ctx , "UpdateComputeFeature: cannot populate ComputeFeature with plan.ComputeFeatures object element" )
return diags
}
req . ComputeFeatures = computeFeatures
tflog . Info ( ctx , "UpdateComputeFeature: before call CloudBroker().LB().UpdateComputeFeatures" , map [ string ] any { "req" : req } )
_ , err := c . CloudBroker ( ) . RG ( ) . UpdateComputeFeatures ( ctx , req )
if err != nil {
diags . AddError ( "UpdateComputeFeature: unable to update compute features" , err . Error ( ) )
return diags
}
tflog . Info ( ctx , "UpdateComputeFeature: compute features updated" )
return nil
}
// UpdateCpuAllocationParameter performs setCpuAllocationParameter request if cpu_allocation_parameter field is not empty and need update.
// In case of failure returns error.
func UpdateCpuAllocationParameter ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
req := rg . SetCPUAllocationParameterRequest {
RGID : rgId ,
StrictLoose : plan . CPUAllocationParameter . ValueString ( ) ,
}
tflog . Info ( ctx , "UpdateCpuAllocationParameter: before call CloudBroker().LB().SetCPUAllocationParameter" , map [ string ] any { "req" : req } )
_ , err := c . CloudBroker ( ) . RG ( ) . SetCPUAllocationParameter ( ctx , req )
if err != nil {
diags . AddError ( "UpdateCpuAllocationParameter: unable to update cpu allocation parameter" , err . Error ( ) )
return diags
}
tflog . Info ( ctx , "UpdateCpuAllocationParameter: cpu allocation parameter updated" )
return nil
}
// UpdateCpuAllocationRatio performs setCpuAllocationRatio request if ratio field is not empty and need update.
// In case of failure returns error.
func UpdateCpuAllocationRatio ( ctx context . Context , rgId uint64 , plan * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
req := rg . SetCPUAllocationRatioRequest {
RGID : rgId ,
Ratio : plan . CPUAllocationRatio . ValueFloat64 ( ) ,
}
tflog . Info ( ctx , "UpdateCpuAllocationRatio: before call CloudBroker().LB().SetCPUAllocationRatio" , map [ string ] any { "req" : req } )
_ , err := c . CloudBroker ( ) . RG ( ) . SetCPUAllocationRatio ( ctx , req )
if err != nil {
diags . AddError ( "UpdateCpuAllocationRatio: unable to update cpu allocation ratio" , err . Error ( ) )
return diags
}
tflog . Info ( ctx , "UpdateCpuAllocationRatio: cpu allocation ratio updated" )
return nil
}
// RGReadStatus loads rg resource by ids id, gets it current status. Performs restore and enable if needed for
// Deleted status.
// In case of failure returns errors.
func RGReadStatus ( ctx context . Context , state * models . ResourceRGModel , c * client . Client ) diag . Diagnostics {
tflog . Info ( ctx , "RGReadStatus: Read status rg with ID" , map [ string ] any { "rg_id" : state . Id . ValueString ( ) } )
diags := diag . Diagnostics { }
rgId , err := strconv . ParseUint ( state . Id . ValueString ( ) , 10 , 64 )
if err != nil {
diags . AddError ( "RGReadStatus: Cannot parse resource group ID from state" , err . Error ( ) )
return diags
}
recordRG , err := RGCheckPresence ( ctx , rgId , c )
if err != nil {
diags . AddError ( "RGReadStatus: Unable to Read RG before status check" , err . Error ( ) )
return diags
}
tflog . Info ( ctx , "RGReadStatus: resource group values before status check" , map [ string ] any {
"rg_id" : recordRG . ID ,
"updated_recordRG" : recordRG } )
// check resource status
switch recordRG . Status {
case status . Modeled :
diags . AddError (
"RG is in status Modeled" ,
"please, contact support for more information" ,
)
return diags
case status . Deleted :
tflog . Info ( ctx , "RGReadStatus: resource group with status.Deleted is being checked" , map [ string ] any {
"rg_id" : recordRG . ID ,
"status" : recordRG . Status } )
// restore and enable resource group in case it is required
if state . Restore . IsNull ( ) || state . Restore . ValueBool ( ) { // default true or user set-up true
diags . Append ( RestoreRG ( ctx , rgId , c ) ... )
if diags . HasError ( ) {
tflog . Error ( ctx , "RGReadStatus: cannot restore rg" )
return diags
}
tflog . Info ( ctx , "RGReadStatus: resource group restored successfully" , map [ string ] any { "rg_id" : recordRG . ID } )
state . LastUpdated = types . StringValue ( time . Now ( ) . Format ( time . RFC850 ) )
if state . Enable . IsNull ( ) || state . Enable . ValueBool ( ) { // default true or user set-up true
err := EnableRG ( ctx , rgId , state , c )
if err != nil {
diags . AddError (
"RGReadStatus: Unable to Enable RG" ,
err . Error ( ) ,
)
return diags
}
tflog . Info ( ctx , "RGReadStatus: resource group enabled successfully" , map [ string ] any { "rg_id" : recordRG . ID } )
}
}
case status . Destroyed :
diags . AddError (
"RGReadStatus: RG is in status Destroyed" ,
fmt . Sprintf ( "the resource with rg_id %d cannot be read because it has been destroyed" , recordRG . ID ) ,
)
return diags
}
return nil
}