package utilities
import (
"context"
"fmt"
"strconv"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/flipgroup"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/flipgroup/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status"
)
func CreateResourceFlipgroup ( ctx context . Context , plan * models . ResourceFLIPGroupModel , c * client . Client ) ( uint64 , diag . Diagnostics ) {
tflog . Info ( ctx , fmt . Sprintf ( "Start create ResourceFlipgroup: flipgroup_name %s" , plan . Name . ValueString ( ) ) )
diags := diag . Diagnostics { }
createReq := flipgroup . CreateRequest {
AccountID : uint64 ( plan . AccountID . ValueInt64 ( ) ) ,
Name : plan . Name . ValueString ( ) ,
NetType : plan . NetType . ValueString ( ) ,
NetID : uint64 ( plan . NetID . ValueInt64 ( ) ) ,
ClientType : plan . ClientType . ValueString ( ) ,
}
if ! plan . IP . IsUnknown ( ) { // IP is optional & computed
createReq . IP = plan . IP . ValueString ( )
}
if ! plan . Description . IsNull ( ) { // Description is optional
createReq . Description = plan . Description . ValueString ( )
}
tflog . Info ( ctx , "CreateResourceFlipgroup: before call CloudAPI().FLIPGroup().Create" , map [ string ] any { "req" : createReq } )
resp , err := c . CloudAPI ( ) . FLIPGroup ( ) . Create ( ctx , createReq )
if err != nil {
diags . AddError ( "CreateResourceFlipgroup: unable to create flipgroup" , err . Error ( ) )
return 0 , diags
}
tflog . Info ( ctx , "CreateResourceFlipgroup: flipgroup created" , map [ string ] any { "flipgroup_id" : resp . ID , "name" : plan . Name . ValueString ( ) } )
return resp . ID , nil
}
// AddClientsFlipgroup add computes in flipgroup for created resource.
// In case of failure returns warnings.
func AddClientsFlipgroup ( ctx context . Context , flipgroupID uint64 , plan * models . ResourceFLIPGroupModel , c * client . Client ) diag . Diagnostics {
diags := diag . Diagnostics { }
tflog . Info ( ctx , "AddClientsFlipgroup: start add clients" , map [ string ] any { "flipgroup_id" : flipgroupID } )
clientIDs := make ( [ ] int , 0 , len ( plan . ClientIDs . Elements ( ) ) )
diagsItem := plan . ClientIDs . ElementsAs ( ctx , & clientIDs , true )
if diagsItem . HasError ( ) {
tflog . Error ( ctx , fmt . Sprintf ( "AddClientsFlipgroup: cannot populate clientIDs with plan.ClientIDs list elements: %v" , diagsItem ) )
diags . AddWarning ( "AddClientsFlipgroup: Unable to read clientIDs for flipgroup" , fmt . Sprintf ( "%v" , diagsItem ) )
return diags
}
for _ , computeID := range clientIDs {
addClientsReq := flipgroup . ComputeAddRequest {
FLIPGroupID : flipgroupID ,
ComputeID : uint64 ( computeID ) ,
}
res , err := c . CloudAPI ( ) . FLIPGroup ( ) . ComputeAdd ( ctx , addClientsReq )
if err != nil {
diags . AddWarning ( "AddClientsFlipgroup: Unable to add compute for flipgroup" , err . Error ( ) )
}
tflog . Info ( ctx , "AddClientsFlipgroup: response from CloudAPI().FLIPGroup().ComputeAdd" , map [ string ] any {
"flipgroup_id" : flipgroupID ,
"response" : res } )
}
return diags
}
// FlipgroupReadStatus loads flipgroup resource by id, gets it current status
// In case of failure returns errors.
func FlipgroupReadStatus ( ctx context . Context , state * models . ResourceFLIPGroupModel , c * client . Client ) diag . Diagnostics {
tflog . Info ( ctx , "FlipgroupReadStatus: Read status flipgroup with ID" , map [ string ] any { "flipgroup_id" : state . ID . ValueString ( ) } )
diags := diag . Diagnostics { }
flipgroupId , err := strconv . ParseUint ( state . ID . ValueString ( ) , 10 , 64 )
if err != nil {
diags . AddError ( "FlipgroupReadStatus: Cannot parse flipgroup ID from state" , err . Error ( ) )
return diags
}
recordFG , diags := FlipgroupResourceCheckPresence ( ctx , flipgroupId , c )
if err != nil {
diags . AddError ( "FlipgroupReadStatus: Unable to Read/Update flipgroup before status check" , err . Error ( ) )
return diags
}
//check resource status
switch recordFG . Status {
case status . Modeled :
diags . AddError (
"FlipgroupReadStatus: flipgroup is in status Modeled" ,
"please, contact support for more information" ,
)
return diags
case status . Destroyed :
diags . AddError (
"FlipgroupReadStatus: flipgroup is in status Destroyed" ,
fmt . Sprintf ( "the resource with flipgroup_id %d cannot be read or updated because it has been destroyed" , flipgroupId ) ,
)
return diags
}
return nil
}
func FlipgroupResourceCheckPresence ( ctx context . Context , flipgroupId uint64 , c * client . Client ) ( * flipgroup . RecordFLIPGroup , diag . Diagnostics ) {
tflog . Info ( ctx , fmt . Sprintf ( "FlipgroupResourceCheckPresence: Get info about flipgroup with ID - %v" , flipgroupId ) )
diags := diag . Diagnostics { }
recordFG , err := c . CloudAPI ( ) . FLIPGroup ( ) . Get ( ctx , flipgroup . GetRequest { FLIPGroupID : flipgroupId } )
if err != nil {
diags . AddError ( fmt . Sprintf ( "Cannot get info about flipgroup with ID %v" , flipgroupId ) , err . Error ( ) )
return nil , diags
}
tflog . Info ( ctx , "FlipgroupResourceCheckPresence: response from CloudAPI().FLIPGroup().Get" , map [ string ] any { "flipgroup_id" : flipgroupId , "response" : recordFG } )
return recordFG , nil
}
func EditFlipgroup ( ctx context . Context , flipgroupId uint64 , plan , state * models . ResourceFLIPGroupModel , c * client . Client ) diag . Diagnostics {
tflog . Info ( ctx , fmt . Sprintf ( "EditFlipgroup: Start edit flipgroup with ID - %v" , flipgroupId ) )
diags := diag . Diagnostics { }
editReq := flipgroup . EditRequest {
FLIPGroupID : flipgroupId ,
}
if ! plan . Name . Equal ( state . Name ) {
editReq . Name = plan . Name . ValueString ( )
}
if ! plan . Description . IsNull ( ) && ! plan . Description . Equal ( state . Description ) {
editReq . Description = plan . Description . ValueString ( )
}
_ , err := c . CloudAPI ( ) . FLIPGroup ( ) . Edit ( ctx , editReq )
if err != nil {
diags . AddError ( "EditFlipgroup: cannot edit flipgroup" , err . Error ( ) )
return diags
}
tflog . Info ( ctx , fmt . Sprintf ( "EditFlipgroup: Finish edit flipgroup with ID - %v" , flipgroupId ) )
return nil
}
func UpdateClientIDsFlipgroup ( ctx context . Context , flipgroupId uint64 , plan , state * models . ResourceFLIPGroupModel , c * client . Client ) diag . Diagnostics {
tflog . Info ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: Start update flipgroup with ID - %v" , flipgroupId ) )
diags := diag . Diagnostics { }
clientIDsPlan := make ( [ ] int , 0 , len ( plan . ClientIDs . Elements ( ) ) )
diags . Append ( plan . ClientIDs . ElementsAs ( ctx , & clientIDsPlan , true ) ... )
if diags . HasError ( ) {
tflog . Error ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: cannot populate clientIDs with plan.ClientIDs list elements" ) )
return diags
}
clientIDsState := make ( [ ] int , 0 , len ( state . ClientIDs . Elements ( ) ) )
diags . Append ( state . ClientIDs . ElementsAs ( ctx , & clientIDsState , true ) ... )
if diags . HasError ( ) {
tflog . Error ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: cannot populate clientIDs with state.ClientIDs list elements" ) )
return diags
}
deleteIDs := difference ( clientIDsState , clientIDsPlan )
addIDs := difference ( clientIDsPlan , clientIDsState )
for _ , id := range deleteIDs {
tflog . Info ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: Start remove client with ID - %v" , id ) )
req := flipgroup . ComputeRemoveRequest {
FLIPGroupID : flipgroupId ,
ComputeID : id ,
}
res , err := c . CloudAPI ( ) . FLIPGroup ( ) . ComputeRemove ( ctx , req )
tflog . Info ( ctx , "UpdateClientIDsFlipgroup: response from CloudAPI().FLIPGroup().ComputeRemove" , map [ string ] any { "flipgroup_id" : plan . ID . ValueString ( ) , "response" : res } )
if err != nil {
diags . AddError ( "UpdateClientIDsFlipgroup: can not remove client for flipgroup" , err . Error ( ) )
}
}
for _ , id := range addIDs {
tflog . Info ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: Start add client with ID - %v" , id ) )
req := flipgroup . ComputeAddRequest {
FLIPGroupID : flipgroupId ,
ComputeID : id ,
}
res , err := c . CloudAPI ( ) . FLIPGroup ( ) . ComputeAdd ( ctx , req )
tflog . Info ( ctx , "UpdateClientIDsFlipgroup: response from CloudAPI().FLIPGroup().ComputeAdd" , map [ string ] any { "flipgroup_id" : plan . ID . ValueString ( ) , "response" : res } )
if err != nil {
diags . AddError ( "UpdateClientIDsFlipgroup: can not add client for flipgroup" , err . Error ( ) )
}
}
tflog . Info ( ctx , fmt . Sprintf ( "UpdateClientIDsFlipgroup: Finish update flipgroup with ID - %v" , flipgroupId ) )
return diags
}
func difference ( set , check [ ] int ) [ ] uint64 {
mapCheck := make ( map [ int ] struct { } )
for _ , id := range check {
mapCheck [ id ] = struct { } { }
}
var diff [ ] uint64
for _ , id := range set {
if _ , ok := mapCheck [ id ] ; ! ok {
diff = append ( diff , uint64 ( id ) )
}
}
return diff
}