This commit is contained in:
asteam
2024-08-23 16:55:50 +03:00
parent 6f40af6a5f
commit 003e4d656e
524 changed files with 43376 additions and 432 deletions

View File

@@ -0,0 +1,91 @@
package cbVFpool
import (
"context"
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/schemas"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &dataSourceVFPool{}
)
func NewDataSourceVFPool() datasource.DataSource {
return &dataSourceVFPool{}
}
// dataSourceVFPool is the data source implementation.
type dataSourceVFPool struct {
client *decort.DecortClient
}
func (d *dataSourceVFPool) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Read Terraform configuration data into the model
var state models.ItemVFPoolModel
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPool: Error get state")
return
}
id := uint64(state.VFPoolID.ValueInt64())
tflog.Info(ctx, "Read dataSourceVFPool: got state successfully", map[string]any{"vfpool_id": id})
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout30s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPool: Error set timeout")
return
}
tflog.Info(ctx, "Read dataSourceVFPool: set timeouts successfully", map[string]any{
"vfpool_id": id,
"readTimeout": readTimeout})
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
// Map response body to schema
resp.Diagnostics.Append(flattens.VFPoolDataSource(ctx, &state, d.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPool: Error flatten data source")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPool: Error set state")
return
}
tflog.Info(ctx, "End read vfpool", map[string]any{"vfpool_id": id})
}
func (d *dataSourceVFPool) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaDataSourceVFPool(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx),
},
}
}
func (d *dataSourceVFPool) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_vfpool"
}
// Configure adds the provider configured client to the data source.
func (d *dataSourceVFPool) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure dataSourceVFPool")
d.client = client.DataSource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure dataSourceVFPool successfully")
}

View File

@@ -0,0 +1,89 @@
package cbVFpool
import (
"context"
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/schemas"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &dataSourceVFPoolList{}
)
func NewDataSourceVFPoolList() datasource.DataSource {
return &dataSourceVFPoolList{}
}
// dataSourceVFPoolList is the data source implementation.
type dataSourceVFPoolList struct {
client *decort.DecortClient
}
func (d *dataSourceVFPoolList) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Read Terraform configuration data into the model
var state models.ListVFPoolModel
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPoolList: Error get state")
return
}
tflog.Info(ctx, "Read dataSourceVFPoolList: got state successfully")
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout30s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPoolList: Error set timeout")
return
}
tflog.Info(ctx, "Read dataSourceVFPoolList: set timeouts successfully", map[string]any{
"readTimeout": readTimeout})
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
// Map response body to schema
resp.Diagnostics.Append(flattens.VFPoolListDataSource(ctx, &state, d.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPoolList: Error flatten data source")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceVFPoolList: Error set state")
return
}
tflog.Info(ctx, "End read vfpool list")
}
func (d *dataSourceVFPoolList) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaDataSourceVFPoolList(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx),
},
}
}
func (d *dataSourceVFPoolList) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_vfpool_list"
}
// Configure adds the provider configured client to the data source.
func (d *dataSourceVFPoolList) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure dataSourceVFPoolList")
d.client = client.DataSource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure dataSourceVFPoolList successfully")
}

View File

@@ -0,0 +1,92 @@
package flattens
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/utilities"
)
// VFPoolDataSource flattens data source for vfpool.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func VFPoolDataSource(ctx context.Context, state *models.ItemVFPoolModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.VFPoolDataSource")
diags := diag.Diagnostics{}
vfPoolID := uint64(state.VFPoolID.ValueInt64())
record, err := utilities.VFPoolCheckPresence(ctx, vfPoolID, c)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about VFpool with ID %v", vfPoolID), err.Error())
return diags
}
tflog.Info(ctx, "flattens.VFPoolDataSource: before flatten", map[string]any{"record": record})
*state = models.ItemVFPoolModel{
//required fields
VFPoolID: state.VFPoolID,
//optional fields
Timeouts: state.Timeouts,
//compute fields
AccountAccess: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, record.AccountAccess),
CreatedTime: types.Int64Value(int64(record.CreatedTime)),
Description: types.StringValue(record.Description),
GID: types.Int64Value(int64(record.GID)),
GUID: types.Int64Value(int64(record.GUID)),
Name: types.StringValue(record.Name),
RGAccess: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, record.RGAccess),
Status: types.StringValue(record.Status),
UpdatedTime: types.Int64Value(int64(record.UpdatedTime)),
}
items := make([]models.VFSModel, 0, len(record.VFS))
for _, vfsItem := range record.VFS {
i := models.VFSModel{
NodeID: types.Int64Value(int64(vfsItem.NodeID)),
}
vfList := make([]models.VFItemModel, 0, len(vfsItem.VFList))
for _, vfItem := range vfsItem.VFList {
vfI := models.VFItemModel{
NicName: types.StringValue(vfItem.NicName),
}
vfInfoList := make([]models.VFSInfoItemModel, 0, len(vfItem.VFSInfo))
for _, vfsInfoItem := range vfItem.VFSInfo {
vfsInfoI := models.VFSInfoItemModel{
ID: types.Int64Value(int64(vfsInfoItem.ID)),
Claimed: types.BoolValue(vfsInfoItem.Claimed),
VMID: types.Int64Value(int64(vfsInfoItem.VMID)),
}
vfInfoList = append(vfInfoList, vfsInfoI)
}
vfI.VFSInfo = vfInfoList
vfList = append(vfList, vfI)
}
i.VFList = vfList
items = append(items, i)
}
state.VFS = items
tflog.Info(ctx, "flattens.VFPoolDataSource: after flatten")
tflog.Info(ctx, "End flattens.VFPoolDataSource")
return nil
}

View File

@@ -0,0 +1,104 @@
package flattens
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/utilities"
)
// VFPoolListDataSource flattens data source for vfpool list.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func VFPoolListDataSource(ctx context.Context, state *models.ListVFPoolModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.VFPoolListDataSource")
diags := diag.Diagnostics{}
record, err := utilities.VFPoolListCheckPresence(ctx, state, c)
if err != nil {
diags.AddError("Cannot get info about fvpool list", err.Error())
return diags
}
tflog.Info(ctx, "flattens.VFPoolListDataSource: before flatten", map[string]any{"record": record})
*state = models.ListVFPoolModel{
//optional fields
Timeouts: state.Timeouts,
ByID: state.ByID,
Name: state.Name,
Description: state.Description,
Status: state.Status,
AccountAccess: state.AccountAccess,
RgAccess: state.RgAccess,
SortBy: state.SortBy,
Page: state.Page,
Size: state.Size,
//compute fields
EntryCount: types.Int64Value(int64(record.EntryCount)),
}
data := make([]models.ItemVFPoolListModel, 0, len(record.Data))
for _, item := range record.Data {
i := models.ItemVFPoolListModel{
VFPoolID: types.Int64Value(int64(item.ID)),
AccountAccess: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, item.AccountAccess),
CreatedTime: types.Int64Value(int64(item.CreatedTime)),
Description: types.StringValue(item.Description),
GID: types.Int64Value(int64(item.GID)),
GUID: types.Int64Value(int64(item.GUID)),
Name: types.StringValue(item.Name),
RGAccess: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, item.RGAccess),
Status: types.StringValue(item.Status),
UpdatedTime: types.Int64Value(int64(item.UpdatedTime)),
}
items := make([]models.VFSListModel, 0, len(item.VFS))
for _, item := range item.VFS {
i := models.VFSListModel{
NodeID: types.Int64Value(int64(item.NodeID)),
}
vfList := make([]models.VFItemListModel, 0, len(item.VFList))
for _, vfItem := range item.VFList {
vfI := models.VFItemListModel{
NicName: types.StringValue(vfItem.NicName),
}
vfInfoList := make([]models.VFSInfoItemListModel, 0, len(vfItem.VFSInfo))
for _, vfInfoItem := range vfItem.VFSInfo {
vfInfoI := models.VFSInfoItemListModel{
ID: types.Int64Value(int64(vfInfoItem.ID)),
Claimed: types.BoolValue(vfInfoItem.Claimed),
VMID: types.Int64Value(int64(vfInfoItem.VMID)),
}
vfInfoList = append(vfInfoList, vfInfoI)
}
vfI.VFSInfo = vfInfoList
vfList = append(vfList, vfI)
}
i.VFList = vfList
items = append(items, i)
}
i.VFS = items
data = append(data, i)
}
state.Items = data
tflog.Info(ctx, "flattens.VFPoolListDataSource: after flatten")
tflog.Info(ctx, "End flattens.VFPoolListDataSource")
return nil
}

View File

@@ -0,0 +1,146 @@
package flattens
import (
"context"
"fmt"
"strconv"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vfpool"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/utilities"
)
// VFPoolResource flattens data source for vfpool.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func VFPoolResource(ctx context.Context, state *models.ResourceItemVFPoolModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.VFPoolResource")
diags := diag.Diagnostics{}
vfPoolID := uint64(state.VFPoolID.ValueInt64())
if vfPoolID == 0 {
id, err := strconv.Atoi(state.ID.ValueString())
if err != nil {
diags.AddError(
"flattens.VFPoolResource: cannot parse resource ID from state",
err.Error())
return diags
}
vfPoolID = uint64(id)
}
record, err := utilities.ResourceVFPoolCheckPresence(ctx, vfPoolID, c)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about VFpool with ID %v", vfPoolID), err.Error())
return diags
}
tflog.Info(ctx, "flattens.VFPoolResource: before flatten", map[string]any{"record": record})
*state = models.ResourceItemVFPoolModel{
//required fields
Name: state.Name,
//optional fields
Description: state.Description,
AccountAccess: state.AccountAccess,
RGAccess: state.RGAccess,
Config: state.Config,
Enable: state.Enable,
Timeouts: state.Timeouts,
//compute fields
VFPoolID: types.Int64Value(int64(record.ID)),
CreatedTime: types.Int64Value(int64(record.CreatedTime)),
GID: types.Int64Value(int64(record.GID)),
GUID: types.Int64Value(int64(record.GUID)),
Status: types.StringValue(record.Status),
UpdatedTime: types.Int64Value(int64(record.UpdatedTime)),
VFS: flattenVFS(ctx, record.VFS),
ID: types.StringValue(strconv.Itoa(int(vfPoolID))),
}
tflog.Info(ctx, "flattens.VFPoolResource: after flatten")
tflog.Info(ctx, "End flattens.VFPoolResource")
return nil
}
func flattenVFS(ctx context.Context, items []vfpool.VFS) types.List {
tflog.Info(ctx, "Start flattenVFS")
tempSlice := make([]types.Object, 0, len(items))
for _, v := range items {
temp := models.ResourceIVFSModel{
NodeID: types.Int64Value(int64(v.NodeID)),
VFList: flattenVFList(ctx, v.VFList),
}
obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFS, temp)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFS struct to obj", diags))
}
tempSlice = append(tempSlice, obj)
}
res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ResourceIVFS}, tempSlice)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFS", diags))
}
tflog.Info(ctx, "End flattenVFS")
return res
}
func flattenVFList(ctx context.Context, items vfpool.VFList) types.List {
tflog.Info(ctx, "Start flattenVFList")
tempSlice := make([]types.Object, 0, len(items))
for _, v := range items {
temp := models.ResourceIVFItemModel{
NicName: types.StringValue(v.NicName),
VFSInfo: flattenVFSInfo(ctx, v.VFSInfo),
}
obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFItem, temp)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFList struct to obj", diags))
}
tempSlice = append(tempSlice, obj)
}
res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ResourceIVFItem}, tempSlice)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFList", diags))
}
tflog.Info(ctx, "End flattenVFList")
return res
}
func flattenVFSInfo(ctx context.Context, items vfpool.VFSInfoList) types.List {
tflog.Info(ctx, "Start flattenVFSInfo")
tempSlice := make([]types.Object, 0, len(items))
for _, v := range items {
temp := models.ResourceIVFSInfoItemModel{
ID: types.Int64Value(int64(v.ID)),
Claimed: types.BoolValue(v.Claimed),
VMID: types.Int64Value(int64(v.VMID)),
}
obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFSInfoItem, temp)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFSInfo struct to obj", diags))
}
tempSlice = append(tempSlice, obj)
}
res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ResourceIVFSInfoItem}, tempSlice)
if diags != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenVFSInfo", diags))
}
tflog.Info(ctx, "End flattenVFSInfo")
return res
}

View File

@@ -0,0 +1,40 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type ItemVFPoolModel struct {
//required and optional fields
VFPoolID types.Int64 `tfsdk:"vfpool_id"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// computed fields
AccountAccess types.List `tfsdk:"account_access"`
CreatedTime types.Int64 `tfsdk:"created_time"`
Description types.String `tfsdk:"description"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
Name types.String `tfsdk:"name"`
RGAccess types.List `tfsdk:"rg_access"`
Status types.String `tfsdk:"status"`
UpdatedTime types.Int64 `tfsdk:"updated_time"`
VFS []VFSModel `tfsdk:"vfs"`
}
type VFSModel struct {
NodeID types.Int64 `tfsdk:"node_id"`
VFList []VFItemModel `tfsdk:"vf_list"`
}
type VFItemModel struct {
NicName types.String `tfsdk:"nic_name"`
VFSInfo []VFSInfoItemModel `tfsdk:"vfs_info"`
}
type VFSInfoItemModel struct {
ID types.Int64 `tfsdk:"id"`
Claimed types.Bool `tfsdk:"claimed"`
VMID types.Int64 `tfsdk:"vm_id"`
}

View File

@@ -0,0 +1,55 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type ListVFPoolModel struct {
// optional fields
ByID types.Int64 `tfsdk:"by_id"`
GID types.Int64 `tfsdk:"gid"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
Status types.String `tfsdk:"status"`
AccountAccess types.Int64 `tfsdk:"account_access"`
RgAccess types.Int64 `tfsdk:"rg_access"`
SortBy types.String `tfsdk:"sort_by"`
Page types.Int64 `tfsdk:"page"`
Size types.Int64 `tfsdk:"size"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// compute fields
Items []ItemVFPoolListModel `tfsdk:"items"`
EntryCount types.Int64 `tfsdk:"entry_count"`
}
type ItemVFPoolListModel struct {
VFPoolID types.Int64 `tfsdk:"vfpool_id"`
AccountAccess types.List `tfsdk:"account_access"`
CreatedTime types.Int64 `tfsdk:"created_time"`
Description types.String `tfsdk:"description"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
Name types.String `tfsdk:"name"`
RGAccess types.List `tfsdk:"rg_access"`
Status types.String `tfsdk:"status"`
UpdatedTime types.Int64 `tfsdk:"updated_time"`
VFS []VFSListModel `tfsdk:"vfs"`
}
type VFSListModel struct {
NodeID types.Int64 `tfsdk:"node_id"`
VFList []VFItemListModel `tfsdk:"vf_list"`
}
type VFItemListModel struct {
NicName types.String `tfsdk:"nic_name"`
VFSInfo []VFSInfoItemListModel `tfsdk:"vfs_info"`
}
type VFSInfoItemListModel struct {
ID types.Int64 `tfsdk:"id"`
Claimed types.Bool `tfsdk:"claimed"`
VMID types.Int64 `tfsdk:"vm_id"`
}

View File

@@ -0,0 +1,72 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type ResourceItemVFPoolModel struct {
//required and optional fields
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
AccountAccess types.List `tfsdk:"account_access"`
RGAccess types.List `tfsdk:"rg_access"`
Config types.List `tfsdk:"config"`
Enable types.Bool `tfsdk:"enable"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// computed fields
ID types.String `tfsdk:"id"`
VFPoolID types.Int64 `tfsdk:"vfpool_id"`
CreatedTime types.Int64 `tfsdk:"created_time"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
Status types.String `tfsdk:"status"`
UpdatedTime types.Int64 `tfsdk:"updated_time"`
VFS types.List `tfsdk:"vfs"`
}
type ResourceItemVFPoolConfigModel struct {
NodeID types.Int64 `tfsdk:"node_id"`
NicName types.String `tfsdk:"nic_name"`
VFIDs types.List `tfsdk:"vf_ids"`
}
var ResourceItemVFPoolConfig = map[string]attr.Type{
"node_id": types.Int64Type,
"nic_name": types.StringType,
"vf_ids": types.ListType{ElemType: types.Int64Type},
}
type ResourceIVFSModel struct {
NodeID types.Int64 `tfsdk:"node_id"`
VFList types.List `tfsdk:"vf_list"`
}
var ResourceIVFS = map[string]attr.Type{
"node_id": types.Int64Type,
"vf_list": types.ListType{ElemType: types.ObjectType{AttrTypes: ResourceIVFItem}},
}
type ResourceIVFItemModel struct {
NicName types.String `tfsdk:"nic_name"`
VFSInfo types.List `tfsdk:"vfs_info"`
}
var ResourceIVFItem = map[string]attr.Type{
"nic_name": types.StringType,
"vfs_info": types.ListType{ElemType: types.ObjectType{AttrTypes: ResourceIVFSInfoItem}},
}
type ResourceIVFSInfoItemModel struct {
ID types.Int64 `tfsdk:"id"`
Claimed types.Bool `tfsdk:"claimed"`
VMID types.Int64 `tfsdk:"vm_id"`
}
var ResourceIVFSInfoItem = map[string]attr.Type{
"id": types.Int64Type,
"claimed": types.BoolType,
"vm_id": types.Int64Type,
}

View File

@@ -0,0 +1,294 @@
package cbVFpool
import (
"context"
"fmt"
"strconv"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vfpool"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/schemas"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/utilities"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &resourceVFPool{}
_ resource.ResourceWithImportState = &resourceVFPool{}
)
// NewresourceVFPool is a helper function to simplify the provider implementation.
func NewResourceVFPool() resource.Resource {
return &resourceVFPool{}
}
// resourceVFPool is the resource implementation.
type resourceVFPool struct {
client *decort.DecortClient
}
// Create creates the resource and sets the initial Terraform state.
func (r *resourceVFPool) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
// Get plan to create resource group
var plan models.ResourceItemVFPoolModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Create resourceVFPool: Error receiving the plan")
return
}
contextCreateMap := map[string]any{
"name": plan.Name.ValueString(),
}
tflog.Info(ctx, "Create resourceVFPool: got plan successfully", contextCreateMap)
tflog.Info(ctx, "Create resourceVFPool: start creating", contextCreateMap)
// Set timeouts
createTimeout, diags := plan.Timeouts.Create(ctx, constants.Timeout600s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Create resourceVFPool: Error set timeout")
return
}
tflog.Info(ctx, "Create resourceVFPool: set timeouts successfully", map[string]any{
"name": plan.Name.ValueString(),
"createTimeout": createTimeout})
ctx, cancel := context.WithTimeout(ctx, createTimeout)
defer cancel()
// Make create request and get response
id, diags := utilities.VFpoolResourceCreate(ctx, &plan, r.client)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
plan.ID = types.StringValue(strconv.Itoa(int(*id)))
tflog.Info(ctx, "VFPoolResourceCreatee: VFPool created", map[string]any{"vfpool_id": id})
tflog.Info(ctx, "VFPoolResourceCreatee: resource creation is completed", map[string]any{"vfpool_id": id})
// Map response body to schema and populate Computed attribute values
resp.Diagnostics.Append(flattens.VFPoolResource(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
return
}
// Set state to fully populated data
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
if resp.Diagnostics.HasError() {
return
}
}
// Read refreshes the Terraform state with the latest data.
func (r *resourceVFPool) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
// Get current state
var state models.ResourceItemVFPoolModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceVFPool: Error get state")
return
}
tflog.Info(ctx, "Read resourceVFPool: got state successfully", map[string]any{"vfpool_id": state.ID.ValueString()})
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceVFPool: Error set timeout")
return
}
tflog.Info(ctx, "Read resourceVFPool: set timeouts successfully", map[string]any{
"vfpool_id": state.ID.ValueString(),
"readTimeout": readTimeout})
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
// Overwrite items with refreshed state
resp.Diagnostics.Append(flattens.VFPoolResource(ctx, &state, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceVFPool: Error flatten")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceVFPool: Error set state")
return
}
tflog.Info(ctx, "End read resourceVFPool")
}
// Update updates the resource and sets the updated Terraform state on success.
func (r *resourceVFPool) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
// Retrieve values from plan
var plan models.ResourceItemVFPoolModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceVFPool: Error receiving the plan")
return
}
logMap := map[string]any{"vfpool_id": plan.ID.ValueString()}
tflog.Info(ctx, "Update resourceVFPool: got plan successfully", logMap)
// Retrieve values from state
var state models.ResourceItemVFPoolModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceVFPool: Error receiving the state")
return
}
tflog.Info(ctx, "Update resourceVFPool: got state successfully", logMap)
// Set timeouts
updateTimeout, diags := plan.Timeouts.Update(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceVFPool: Error set timeout")
return
}
tflog.Info(ctx, "Update resourceVFPool: set timeouts successfully", map[string]any{
"vfpool_id": state.ID.ValueString(),
"updateTimeout": updateTimeout})
ctx, cancel := context.WithTimeout(ctx, updateTimeout)
defer cancel()
_, err := strconv.Atoi(state.ID.ValueString())
if err != nil {
resp.Diagnostics.AddError("Update resourceVFPool: Cannot parse ID from state", err.Error())
return
}
if !plan.Name.Equal(state.Name) || !plan.Description.Equal(state.Description) || !plan.AccountAccess.Equal(state.AccountAccess) || !plan.RGAccess.Equal(state.RGAccess) || !plan.Config.Equal(state.Config) {
resp.Diagnostics.Append(utilities.UpdateVFpool(ctx, &state, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceVFPool: Error update VFPool")
return
}
}
if !plan.Enable.Equal(state.Enable) {
resp.Diagnostics.Append(utilities.EnableDisableVFpool(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceVFPool: Error enabling/disabling VFPool")
return
}
}
tflog.Info(ctx, "Update resourceVFPool: VFPool update is completed", logMap)
// Map response body to schema and populate Computed attribute values
resp.Diagnostics.Append(flattens.VFPoolResource(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
return
}
// Set state to fully populated data
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
if resp.Diagnostics.HasError() {
return
}
}
// Delete deletes the resource and removes the Terraform state on success.
func (r *resourceVFPool) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
// Get current state
var state models.ResourceItemVFPoolModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Delete resourceVFPool: Error get state")
return
}
tflog.Info(ctx, "Delete resourceVFPool: got state successfully", map[string]any{"serice_id": state.ID.ValueString()})
// Set timeouts
deleteTimeout, diags := state.Timeouts.Delete(ctx, constants.Timeout300s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Delete resourceVFPool: Error set timeout")
return
}
tflog.Info(ctx, "Delete resourceVFPool: set timeouts successfully", map[string]any{
"vfpool_id": state.ID.ValueString(),
"deleteTimeout": deleteTimeout})
ctx, cancel := context.WithTimeout(ctx, deleteTimeout)
defer cancel()
ID, err := strconv.Atoi(state.ID.ValueString())
if err != nil {
resp.Diagnostics.AddError("Delete resourceVFPool: Cannot parse ID from state", err.Error())
return
}
if state.Status.ValueString() == "ENABLED" || state.Status.ValueString() == "CREATED" {
reqDisable := vfpool.DisableRequest{
VFPoolID: uint64(ID),
}
tflog.Info(ctx, fmt.Sprintf("resourceVFPool Delete: need to disable vfPool with ID: %d, after delete", ID))
_, err = r.client.CloudBroker().VFPool().Disable(ctx, reqDisable)
if err != nil {
resp.Diagnostics.AddError("Delete resourceVFPool: Error disable VFPool with error: ", err.Error())
return
}
tflog.Info(ctx, fmt.Sprintf("resourceVFPoolDelete: disable vfPool with ID: %d, complete", ID))
}
delReq := vfpool.DeleteRequest{
VFPoolID: uint64(ID),
}
tflog.Info(ctx, "Delete resourceVFPool: before call cloudbroker().VFPool().Delete", map[string]any{"req": delReq})
_, err = r.client.CloudBroker().VFPool().Delete(ctx, delReq)
if err != nil {
resp.Diagnostics.AddError("Delete resourceVFPool: Error deleting VFPool with error: ", err.Error())
return
}
tflog.Info(ctx, "End delete resourceVFPool", map[string]any{"vfpool_id": state.ID.ValueString()})
}
// Schema defines the schema for the resource.
func (r *resourceVFPool) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaResourceVFPool(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx, timeouts.Opts{Create: true, Read: true, Update: true, Delete: true}),
},
}
}
// Metadata returns the resource type name.
func (r *resourceVFPool) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_vfpool"
}
// Configure adds the provider configured client to the resource.
func (r *resourceVFPool) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure resourceVFPool")
r.client = client.Resource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure resourceVFPool successfully")
}
func (r *resourceVFPool) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
// Retrieve import ID and save to id attribute
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}

View File

@@ -0,0 +1,79 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaDataSourceVFPool() map[string]schema.Attribute {
return map[string]schema.Attribute{
"vfpool_id": schema.Int64Attribute{
Required: true,
},
"account_access": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"created_time": schema.Int64Attribute{
Computed: true,
},
"description": schema.StringAttribute{
Computed: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
},
"rg_access": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
"updated_time": schema.Int64Attribute{
Computed: true,
},
"vfs": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"node_id": schema.Int64Attribute{
Computed: true,
},
"vf_list": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"nic_name": schema.StringAttribute{
Computed: true,
},
"vfs_info": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"id": schema.Int64Attribute{
Computed: true,
},
"claimed": schema.BoolAttribute{
Computed: true,
},
"vm_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
},
},
},
},
},
},
}
}

View File

@@ -0,0 +1,119 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaDataSourceVFPoolList() map[string]schema.Attribute {
return map[string]schema.Attribute{
"by_id": schema.Int64Attribute{
Optional: true,
},
"gid": schema.Int64Attribute{
Optional: true,
},
"name": schema.StringAttribute{
Optional: true,
},
"description": schema.StringAttribute{
Optional: true,
},
"status": schema.StringAttribute{
Optional: true,
},
"account_access": schema.Int64Attribute{
Optional: true,
},
"rg_access": schema.Int64Attribute{
Optional: true,
},
"sort_by": schema.StringAttribute{
Optional: true,
},
"page": schema.Int64Attribute{
Optional: true,
},
"size": schema.Int64Attribute{
Optional: true,
},
"items": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"account_access": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"created_time": schema.Int64Attribute{
Computed: true,
},
"description": schema.StringAttribute{
Computed: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"vfpool_id": schema.Int64Attribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
},
"rg_access": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
"updated_time": schema.Int64Attribute{
Computed: true,
},
"vfs": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"node_id": schema.Int64Attribute{
Computed: true,
},
"vf_list": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"nic_name": schema.StringAttribute{
Computed: true,
},
"vfs_info": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"id": schema.Int64Attribute{
Computed: true,
},
"claimed": schema.BoolAttribute{
Computed: true,
},
"vm_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
},
},
},
},
},
},
},
},
},
"entry_count": schema.Int64Attribute{
Computed: true,
},
}
}

View File

@@ -0,0 +1,107 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaResourceVFPool() map[string]schema.Attribute {
return map[string]schema.Attribute{
"name": schema.StringAttribute{
Required: true,
},
"description": schema.StringAttribute{
Optional: true,
},
"account_access": schema.ListAttribute{
Optional: true,
ElementType: types.Int64Type,
},
"rg_access": schema.ListAttribute{
Optional: true,
ElementType: types.Int64Type,
},
"config": schema.ListNestedAttribute{
Optional: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"node_id": schema.Int64Attribute{
Required: true,
},
"nic_name": schema.StringAttribute{
Required: true,
},
"vf_ids": schema.ListAttribute{
Required: true,
ElementType: types.Int64Type,
},
},
},
},
"enable": schema.BoolAttribute{
Optional: true,
},
"created_time": schema.Int64Attribute{
Computed: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"vfpool_id": schema.Int64Attribute{
Computed: true,
},
"status": schema.StringAttribute{
Computed: true,
},
"updated_time": schema.Int64Attribute{
Computed: true,
},
"vfs": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"node_id": schema.Int64Attribute{
Computed: true,
},
"vf_list": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"nic_name": schema.StringAttribute{
Computed: true,
},
"vfs_info": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"id": schema.Int64Attribute{
Computed: true,
},
"claimed": schema.BoolAttribute{
Computed: true,
},
"vm_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
},
},
},
},
},
},
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
}
}

View File

@@ -0,0 +1,25 @@
package utilities
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vfpool"
)
func VFPoolCheckPresence(ctx context.Context, vfPoolID uint64, c *decort.DecortClient) (*vfpool.RecordVFPool,
error) {
req := vfpool.GetRequest{VFPoolID: vfPoolID}
tflog.Info(ctx, "VFPoolCheckPresence: before call CloudBroker().VFPool().Get", map[string]any{"req": req})
vfPool, err := c.CloudBroker().VFPool().Get(ctx, req)
if err != nil {
return nil, fmt.Errorf("VFPoolCheckPresence: cannot get info about vfpool")
}
tflog.Info(ctx, "VFPoolCheckPresence: response from CloudBroker().VFPool().Get", map[string]any{"response": vfPool})
return vfPool, err
}

View File

@@ -0,0 +1,57 @@
package utilities
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vfpool"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
)
func VFPoolListCheckPresence(ctx context.Context, plan *models.ListVFPoolModel, c *decort.DecortClient) (*vfpool.ListVFPool,
error) {
req := vfpool.ListRequest{}
if !plan.ByID.IsNull() {
req.ByID = uint64(plan.ByID.ValueInt64())
}
if !plan.GID.IsNull() {
req.GID = uint64(plan.GID.ValueInt64())
}
if !plan.Name.IsNull() {
req.Name = plan.Name.ValueString()
}
if !plan.Description.IsNull() {
req.Description = plan.Description.ValueString()
}
if !plan.Status.IsNull() {
req.Status = plan.Status.ValueString()
}
if !plan.AccountAccess.IsNull() {
req.AccountAccess = uint64(plan.AccountAccess.ValueInt64())
}
if !plan.RgAccess.IsNull() {
req.RGAccess = uint64(plan.RgAccess.ValueInt64())
}
if !plan.SortBy.IsNull() {
req.SortBy = plan.SortBy.ValueString()
}
if !plan.Page.IsNull() {
req.Page = uint64(plan.Page.ValueInt64())
}
if !plan.Size.IsNull() {
req.Size = uint64(plan.Size.ValueInt64())
}
tflog.Info(ctx, "VFPoolListCheckPresence: before call CloudBroker().VFPool().List", map[string]any{"req": req})
vfPool, err := c.CloudBroker().VFPool().List(ctx, req)
if err != nil {
return nil, fmt.Errorf("VFPoolListCheckPresence: cannot get info about vfpool list")
}
tflog.Info(ctx, "VFPoolListCheckPresence: response from CloudBroker().VFPool().Get", map[string]any{"response": vfPool})
return vfPool, err
}

View File

@@ -0,0 +1,294 @@
package utilities
import (
"context"
"fmt"
"strconv"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vfpool"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/ic"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vfpool/models"
)
func ResourceVFPoolCheckPresence(ctx context.Context, vfPoolID uint64, c *decort.DecortClient) (*vfpool.RecordVFPool,
error) {
req := vfpool.GetRequest{VFPoolID: vfPoolID}
tflog.Info(ctx, "ResourceVFPoolCheckPresence: before call CloudBroker().VFPool().Get", map[string]any{"req": req})
vfPool, err := c.CloudBroker().VFPool().Get(ctx, req)
if err != nil {
return nil, fmt.Errorf("VFPoolCheckPresence: cannot get info about vfpool")
}
tflog.Info(ctx, "ResourceVFPoolCheckPresence: response from CloudBroker().VFPool().Get", map[string]any{"response": vfPool})
return vfPool, err
}
func VFpoolResourceCreate(ctx context.Context, plan *models.ResourceItemVFPoolModel, c *decort.DecortClient) (*uint64, diag.Diagnostics) {
tflog.Info(ctx, "Start VFpoolResourceCreate", map[string]any{"name": plan.Name.ValueString()})
diags := diag.Diagnostics{}
req := vfpool.CreateRequest{
Name: plan.Name.ValueString(),
}
if !plan.Description.IsNull() {
req.Description = plan.Description.ValueString()
}
if !plan.AccountAccess.IsNull() {
accountAccessList := make([]uint64, len(plan.AccountAccess.Elements()))
diags.Append(plan.AccountAccess.ElementsAs(ctx, &accountAccessList, true)...)
if diags.HasError() {
tflog.Error(ctx, "VFpoolResourceCreate: cannot populate VFpoolResourceCreate with plan.AccountAccess object element")
return nil, diags
}
req.AccountAccess = accountAccessList
}
if !plan.RGAccess.IsNull() {
RGAccessList := make([]uint64, len(plan.RGAccess.Elements()))
diags.Append(plan.RGAccess.ElementsAs(ctx, &RGAccessList, true)...)
if diags.HasError() {
tflog.Error(ctx, "VFpoolResourceCreate: cannot populate VFpoolResourceCreate with plan.RGAccess object element")
return nil, diags
}
req.RGAccess = RGAccessList
}
diags.Append(checkParamsExistence(ctx, req.AccountAccess, req.RGAccess, c)...)
if diags.HasError() {
tflog.Error(ctx, "VFpoolResourceCreate: RGAccess or AccountAccess does not exist")
return nil, diags
}
if !plan.Config.IsNull() {
configList := make([]models.ResourceItemVFPoolConfigModel, 0, len(plan.Config.Elements()))
diags.Append(plan.Config.ElementsAs(ctx, &configList, true)...)
if diags.HasError() {
tflog.Error(ctx, "VFpoolResourceCreate: cannot populate VFpoolResourceCreate with v.Config object element")
return nil, diags
}
config := make([]vfpool.Config, 0, len(configList))
for _, v := range configList {
vfIDs := make([]uint64, 0, len(v.VFIDs.Elements()))
diags.Append(v.VFIDs.ElementsAs(ctx, &vfIDs, true)...)
if diags.HasError() {
tflog.Error(ctx, "VFpoolResourceCreate: cannot populate UpdateVFpool with vfIDs object element")
return nil, diags
}
item := vfpool.Config{
NodeID: uint64(v.NodeID.ValueInt64()),
NicName: v.NicName.ValueString(),
VFIDs: vfIDs}
config = append(config, item)
}
req.Config = config
}
vfPoolID, err := c.CloudBroker().VFPool().Create(ctx, req)
if err != nil {
tflog.Error(ctx, "Error response for create VFpool", map[string]any{"error": err.Error()})
diags.AddError("Unable to Create VFpool", err.Error())
return nil, diags
}
plan.ID = types.StringValue(strconv.Itoa(int(vfPoolID)))
if !plan.Enable.IsNull() {
EnableDisableVFpool(ctx, plan, c)
}
tflog.Info(ctx, "End VFpoolResourceCreate", map[string]any{"vfpool_id": vfPoolID})
return &vfPoolID, diags
}
// EnableDisableVFpool performs VFpool Enable/Disable request.
// Returns error in case of failures.
func EnableDisableVFpool(ctx context.Context, plan *models.ResourceItemVFPoolModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start EnableDisableVFpool", map[string]any{"vfpool_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
ID, err := strconv.Atoi(plan.ID.ValueString())
if err != nil {
diags.AddError("EnableDisableVFpool: Cannot parse ID from state", err.Error())
return diags
}
if plan.Enable.ValueBool() {
tflog.Info(ctx, "EnableDisableVFpool: before calling CloudBroker().VFPool().Enable", map[string]any{"vfpool_id": ID})
res, err := c.CloudBroker().VFPool().Enable(ctx, vfpool.EnableRequest{VFPoolID: uint64(ID)})
if err != nil {
diags.AddError(
"EnableDisableVFpool: cannot enable VFpool",
err.Error(),
)
return diags
}
tflog.Info(ctx, "EnableDisableVFpool: response from CloudBroker().VFPool().Enable", map[string]any{"vfpool_id": ID, "response": res})
return nil
} else {
tflog.Info(ctx, "EnableDisableVFpool: before calling CloudBroker().VFPool().Disable", map[string]any{"vfpool_id": ID})
res, err := c.CloudBroker().VFPool().Disable(ctx, vfpool.DisableRequest{VFPoolID: uint64(ID)})
if err != nil {
diags.AddError(
"EnableDisableVFpool: cannot disable VFPool",
err.Error(),
)
return diags
}
tflog.Info(ctx, "EnableDisableVFpool: response from CloudBroker().VFPool().Disable", map[string]any{"vfpool_id": ID, "response": res})
}
return nil
}
func UpdateVFpool(ctx context.Context, state *models.ResourceItemVFPoolModel, plan *models.ResourceItemVFPoolModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start UpdateVFpool", map[string]any{"vfpool_id": plan.ID.ValueString()})
diags := diag.Diagnostics{}
ID, err := strconv.Atoi(plan.ID.ValueString())
if err != nil {
diags.AddError("UpdateVFpool: Cannot parse ID from state", err.Error())
return diags
}
req := vfpool.UpdateRequest{
VFPoolID: uint64(ID),
}
if !plan.Name.Equal(state.Name) {
req.Name = plan.Name.ValueString()
}
if !plan.Description.Equal(state.Description) {
req.Description = plan.Description.ValueString()
}
if !plan.Config.Equal(state.Config) && !plan.Config.IsNull() {
configList := make([]models.ResourceItemVFPoolConfigModel, 0, len(plan.Config.Elements()))
diags.Append(plan.Config.ElementsAs(ctx, &configList, true)...)
if diags.HasError() {
tflog.Error(ctx, "UpdateVFpool: cannot populate UpdateVFpool with plan.Config object element")
return diags
}
config := make([]vfpool.Config, 0, len(configList))
for _, v := range configList {
vfIDs := make([]uint64, 0, len(v.VFIDs.Elements()))
diags.Append(v.VFIDs.ElementsAs(ctx, &vfIDs, true)...)
if diags.HasError() {
tflog.Error(ctx, "UpdateVFpool: cannot populate UpdateVFpool with vfIDs object element")
return diags
}
item := vfpool.Config{
NodeID: uint64(v.NodeID.ValueInt64()),
NicName: v.NicName.ValueString(),
VFIDs: vfIDs}
config = append(config, item)
}
req.Config = config
}
if !plan.AccountAccess.Equal(state.AccountAccess) && !plan.AccountAccess.IsNull() {
aaList := make([]uint64, 0, len(plan.AccountAccess.Elements()))
diags.Append(plan.AccountAccess.ElementsAs(ctx, &aaList, true)...)
if diags.HasError() {
tflog.Error(ctx, "UpdateVFpool: cannot populate UpdateVFpool with plan.AccountAccess object element")
return diags
}
req.AccountAccess = aaList
}
if !plan.RGAccess.Equal(state.RGAccess) && !plan.RGAccess.IsNull() {
rgAccessList := make([]uint64, 0, len(plan.RGAccess.Elements()))
diags.Append(plan.RGAccess.ElementsAs(ctx, &rgAccessList, true)...)
if diags.HasError() {
tflog.Error(ctx, "UpdateVFpool: cannot populate UpdateVFpool with plan.RGAccess object element")
return diags
}
req.RGAccess = rgAccessList
}
if state.Status.ValueString() == "ENABLED" || state.Status.ValueString() == "CREATED" {
reqDisable := vfpool.DisableRequest{
VFPoolID: uint64(ID),
}
tflog.Info(ctx, fmt.Sprintf("UpdateVFpool: need to disable vfPool with ID: %d, after update", ID))
_, err = c.CloudBroker().VFPool().Disable(ctx, reqDisable)
if err != nil {
diags.AddWarning(
"UpdateVFpool: cannot disable VFPool",
err.Error(),
)
return diags
}
tflog.Info(ctx, "utilityVFPoolUpdate: disable VFPool with complete")
}
_, err = c.CloudBroker().VFPool().Update(ctx, req)
if err != nil {
diags.AddError("EnableDisableVFpool: Cannot update", err.Error())
return diags
}
tflog.Info(ctx, fmt.Sprintf("utilityVFPoolUpdate: update vfPool with ID: %d, complete with params=%v", ID, req))
if plan.Enable.ValueBool() {
reqEnable := vfpool.EnableRequest{
VFPoolID: uint64(ID),
}
tflog.Info(ctx, fmt.Sprintf("utilityVFPoolUpdate: start to enable vfPool with ID: %d, after update", ID))
_, err = c.CloudBroker().VFPool().Enable(ctx, reqEnable)
if err != nil {
diags.AddWarning(
"UpdateVFpool: cannot enable VFPool",
err.Error(),
)
return diags
}
tflog.Info(ctx, fmt.Sprintf("utilityVFPoolUpdate: enable vfPool with ID: %d, complete", ID))
} else {
diags.AddWarning(
"UpdateVFpool: vfPool is not enabled",
"the vfPool is not enabled after update, you must provide configuration for this resource, after enabling it",
)
return diags
}
return nil
}
func checkParamsExistence(ctx context.Context, accountIDs, rgIDs []uint64, c *decort.DecortClient) diag.Diagnostics {
diags := diag.Diagnostics{}
if err := ic.ExistAccounts(ctx, accountIDs, c); err != nil {
diags.AddError("Error check input values", err.Error())
}
if err := ic.ExistRGs(ctx, rgIDs, c); err != nil {
diags.AddError("Error check input values", err.Error())
}
return diags
}