This commit is contained in:
asteam
2024-12-04 13:18:58 +03:00
parent 003e4d656e
commit 76ea459b3d
417 changed files with 30051 additions and 975 deletions

View File

@@ -0,0 +1,91 @@
package k8ci
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/k8ci/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/schemas"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &dataSourceK8CI{}
)
func NewDataSourceK8CI() datasource.DataSource {
return &dataSourceK8CI{}
}
// dataSourceK8CI is the data source implementation.
type dataSourceK8CI struct {
client *decort.DecortClient
}
func (d *dataSourceK8CI) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Read Terraform configuration data into the model
var state models.DataSourceK8CIModel
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CI: Error get state")
return
}
k8ciID := uint64(state.K8ciID.ValueInt64())
tflog.Info(ctx, "Read dataSourceK8CI: got state successfully", map[string]any{"k8ci_id": k8ciID})
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout180s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CI: Error set timeout")
return
}
tflog.Info(ctx, "Read dataSourceK8CI: set timeouts successfully", map[string]any{
"k8ci_id": k8ciID,
"readTimeout": readTimeout})
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
// Map response body to schema
resp.Diagnostics.Append(flattens.K8CIDataSource(ctx, &state, d.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CI: Error flatten")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CI: Error set state")
return
}
tflog.Info(ctx, "End read dataSourceK8CI", map[string]any{"k8ci_id": k8ciID})
}
func (d *dataSourceK8CI) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaDataSourceK8CI(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx),
},
}
}
func (d *dataSourceK8CI) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_k8ci"
}
// Configure adds the provider configured client to the data source.
func (d *dataSourceK8CI) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure dataSourceK8CI")
d.client = client.DataSource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure dataSourceK8ci successfully")
}

View File

@@ -0,0 +1,89 @@
package k8ci
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/k8ci/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/schemas"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &dataSourceK8CIList{}
)
func NewDataSourceK8CIList() datasource.DataSource {
return &dataSourceK8CIList{}
}
// dataSourceK8CIList is the data source implementation.
type dataSourceK8CIList struct {
client *decort.DecortClient
}
func (d *dataSourceK8CIList) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Read Terraform configuration data into the model
var state models.DataSourceK8CIListModel
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIList: Error get state")
return
}
tflog.Info(ctx, "Read dataSourceK8CIList: got state successfully")
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout180s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIList: Error set timeout")
return
}
tflog.Info(ctx, "Read dataSourceK8CIList: 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.K8CIListDataSource(ctx, &state, d.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIList: Error flatten")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIList: Error set state")
return
}
tflog.Info(ctx, "End read dataSourceK8CIList")
}
func (d *dataSourceK8CIList) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaDataSourceK8CIList(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx),
},
}
}
func (d *dataSourceK8CIList) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_k8ci_list"
}
// Configure adds the provider configured client to the data source.
func (d *dataSourceK8CIList) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure dataSourceK8CIList")
d.client = client.DataSource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure dataSourceK8CIList successfully")
}

View File

@@ -0,0 +1,89 @@
package k8ci
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/k8ci/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/schemas"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &dataSourceK8CIListDeleted{}
)
func NewDataSourceK8CIListDeleted() datasource.DataSource {
return &dataSourceK8CIListDeleted{}
}
// dataSourceK8CIListDeleted is the data source implementation.
type dataSourceK8CIListDeleted struct {
client *decort.DecortClient
}
func (d *dataSourceK8CIListDeleted) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Read Terraform configuration data into the model
var state models.DataSourceK8CIListDeletedModel
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIListDeleted: Error get state")
return
}
tflog.Info(ctx, "Read dataSourceK8CIListDeleted: got state successfully")
// Set timeouts
readTimeout, diags := state.Timeouts.Read(ctx, constants.Timeout180s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIListDeleted: Error set timeout")
return
}
tflog.Info(ctx, "Read dataSourceK8CIListDeleted: 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.K8CIListDeletedDataSource(ctx, &state, d.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIListDeletedDeleted: Error flatten")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read dataSourceK8CIListDeleted: Error set state")
return
}
tflog.Info(ctx, "End read dataSourceK8CIListDeleted")
}
func (d *dataSourceK8CIListDeleted) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaDataSourceK8CIListDeleted(),
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx),
},
}
}
func (d *dataSourceK8CIListDeleted) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_k8ci_list_deleted"
}
// Configure adds the provider configured client to the data source.
func (d *dataSourceK8CIListDeleted) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure dataSourceK8CIListDeleted")
d.client = client.DataSource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure dataSourceK8CIListDeleted successfully")
}

View File

@@ -0,0 +1,59 @@
package flattens
import (
"context"
"github.com/google/uuid"
"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/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/utilities"
)
// K8CIDataSource flattens data source for K8CI.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func K8CIDataSource(ctx context.Context, state *models.DataSourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.K8CIDataSource")
diags := diag.Diagnostics{}
k8ciID := uint64(state.K8ciID.ValueInt64())
recordK8ci, diags := utilities.K8ciDataSourceCheckPresence(ctx, k8ciID, c)
if diags.HasError() {
return diags
}
tflog.Info(ctx, "flattens.K8CIDataSource: before flatten")
id := uuid.New()
*state = models.DataSourceK8CIModel{
K8ciID: state.K8ciID,
Timeouts: state.Timeouts,
Description: types.StringValue(recordK8ci.Description),
GID: types.Int64Value(int64(recordK8ci.GID)),
GUID: types.Int64Value(int64(recordK8ci.GUID)),
Id: types.StringValue(id.String()),
LBImageID: types.Int64Value(int64(recordK8ci.LBImageID)),
MasterDriver: types.StringValue(recordK8ci.MasterDriver),
MasterImageId: types.Int64Value(int64(recordK8ci.MasterImageID)),
MaxMasterCount: types.Int64Value(int64(recordK8ci.MaxMasterCount)),
MaxWorkerCount: types.Int64Value(int64(recordK8ci.MaxWorkerCount)),
Milestones: types.Int64Value(int64(recordK8ci.Milestones)),
Name: types.StringValue(recordK8ci.Name),
NetworkPlugins: flattens.FlattenSimpleTypeToList(ctx, types.StringType, &recordK8ci.NetworkPlugins),
SharedWith: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &recordK8ci.SharedWith),
Status: types.StringValue(recordK8ci.Status),
Version: types.StringValue(recordK8ci.Version),
WorkerDriver: types.StringValue(recordK8ci.WorkerDriver),
WorkerImageId: types.Int64Value(int64(recordK8ci.WorkerImageID)),
}
tflog.Info(ctx, "End flattens.K8CIDataSource")
return nil
}

View File

@@ -0,0 +1,75 @@
package flattens
import (
"context"
"github.com/google/uuid"
"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/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/utilities"
)
// K8CIListDataSource flattens data source for k8ci list.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func K8CIListDataSource(ctx context.Context, state *models.DataSourceK8CIListModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.K8CIListDataSource")
diags := diag.Diagnostics{}
k8ciList, diags := utilities.K8CIListDataSourceCheckPresence(ctx, state, c)
if diags.HasError() {
return diags
}
tflog.Info(ctx, "flattens.K8CIListDataSource: before flatten")
id := uuid.New()
*state = models.DataSourceK8CIListModel{
ByID: state.ByID,
Name: state.Name,
Status: state.Status,
WorkerDriver: state.WorkerDriver,
MasterDriver: state.MasterDriver,
NetworkPlugin: state.NetworkPlugin,
IncludeDisabled: state.IncludeDisabled,
SortBy: state.SortBy,
Page: state.Page,
Size: state.Size,
Timeouts: state.Timeouts,
Id: types.StringValue(id.String()),
EntryCount: types.Int64Value(int64(k8ciList.EntryCount)),
}
items := make([]models.ItemK8ciModel, 0, len(k8ciList.Data))
for _, item := range k8ciList.Data {
v := models.ItemK8ciModel{
CreatedTime: types.Int64Value(int64(item.CreatedTime)),
Description: types.StringValue(item.Description),
GID: types.Int64Value(int64(item.GID)),
GUID: types.Int64Value(int64(item.GUID)),
K8ciID: types.Int64Value(int64(item.ID)),
LBImageID: types.Int64Value(int64(item.LBImageID)),
MasterDriver: types.StringValue(item.MasterDriver),
MasterImageId: types.Int64Value(int64(item.MasterImageID)),
MaxMasterCount: types.Int64Value(int64(item.MaxMasterCount)),
MaxWorkerCount: types.Int64Value(int64(item.MaxWorkerCount)),
Name: types.StringValue(item.Name),
SharedWith: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.SharedWith),
Status: types.StringValue(item.Status),
Version: types.StringValue(item.Version),
WorkerDriver: types.StringValue(item.WorkerDriver),
WorkerImageId: types.Int64Value(int64(item.WorkerImageID)),
}
items = append(items, v)
}
state.Items = items
tflog.Info(ctx, "End flattens.K8CIListDataSource")
return nil
}

View File

@@ -0,0 +1,73 @@
package flattens
import (
"context"
"github.com/google/uuid"
"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/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/utilities"
)
// K8CIListDeletedDataSource flattens data source for k8ci deleted list.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func K8CIListDeletedDataSource(ctx context.Context, state *models.DataSourceK8CIListDeletedModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.K8CIListDataSource")
diags := diag.Diagnostics{}
k8ciList, diags := utilities.K8CIListDeletedDataSourceCheckPresence(ctx, state, c)
if diags.HasError() {
return diags
}
tflog.Info(ctx, "flattens.K8CIListDataSource: before flatten")
id := uuid.New()
*state = models.DataSourceK8CIListDeletedModel{
ByID: state.ByID,
Name: state.Name,
WorkerDriver: state.WorkerDriver,
MasterDriver: state.MasterDriver,
NetworkPlugin: state.NetworkPlugin,
SortBy: state.SortBy,
Page: state.Page,
Size: state.Size,
Timeouts: state.Timeouts,
Id: types.StringValue(id.String()),
EntryCount: types.Int64Value(int64(k8ciList.EntryCount)),
}
items := make([]models.ItemK8ciDeletedModel, 0, len(k8ciList.Data))
for _, item := range k8ciList.Data {
v := models.ItemK8ciDeletedModel{
CreatedTime: types.Int64Value(int64(item.CreatedTime)),
Description: types.StringValue(item.Description),
GID: types.Int64Value(int64(item.GID)),
GUID: types.Int64Value(int64(item.GUID)),
K8ciID: types.Int64Value(int64(item.ID)),
LBImageID: types.Int64Value(int64(item.LBImageID)),
MasterDriver: types.StringValue(item.MasterDriver),
MasterImageId: types.Int64Value(int64(item.MasterImageID)),
MaxMasterCount: types.Int64Value(int64(item.MaxMasterCount)),
MaxWorkerCount: types.Int64Value(int64(item.MaxWorkerCount)),
Name: types.StringValue(item.Name),
SharedWith: flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.SharedWith),
Status: types.StringValue(item.Status),
Version: types.StringValue(item.Version),
WorkerDriver: types.StringValue(item.WorkerDriver),
WorkerImageId: types.Int64Value(int64(item.WorkerImageID)),
}
items = append(items, v)
}
state.Items = items
tflog.Info(ctx, "End flattens.K8CIListDataSource")
return nil
}

View File

@@ -0,0 +1,59 @@
package flattens
import (
"context"
"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/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/utilities"
)
// K8CIResource flattens resource for K8CI.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func K8CIResource(ctx context.Context, state *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start flattens.K8CIResource")
diags := diag.Diagnostics{}
recordK8ci, diags := utilities.K8CIResourceCheckPresence(ctx, state, c)
if diags.HasError() {
return diags
}
tflog.Info(ctx, "flattens.K8CIResource: before flatten")
*state = models.ResourceK8CIModel{
Name: state.Name,
Version: state.Version,
MasterDriver: state.MasterDriver,
MasterImageId: state.MasterImageId,
MaxMasterCount: state.MaxMasterCount,
MaxWorkerCount: state.MaxWorkerCount,
NetworkPlugins: state.NetworkPlugins,
WorkerDriver: state.WorkerDriver,
WorkerImageId: state.WorkerImageId,
Timeouts: state.Timeouts,
Description: state.Description,
Enabled: state.Enabled,
Permanently: state.Permanently,
Restore: state.Restore,
SharedWith: state.SharedWith,
GID: types.Int64Value(int64(recordK8ci.GID)),
GUID: types.Int64Value(int64(recordK8ci.GUID)),
Id: types.StringValue(strconv.Itoa(int(recordK8ci.ID))),
K8ciID: types.Int64Value(int64(recordK8ci.ID)),
LBImageID: types.Int64Value(int64(recordK8ci.LBImageID)),
Milestones: types.Int64Value(int64(recordK8ci.Milestones)),
Status: types.StringValue(recordK8ci.Status),
}
tflog.Info(ctx, "End flattens.K8CIResource")
return nil
}

View File

@@ -0,0 +1,31 @@
package k8ci
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/ic"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
)
func resourceK8CIInputChecks(ctx context.Context, plan *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
diags := diag.Diagnostics{}
masterImageId := uint64(plan.MasterImageId.ValueInt64())
workerImageId := uint64(plan.WorkerImageId.ValueInt64())
images := make([]uint64, 0)
images = append(images, masterImageId)
if workerImageId != masterImageId {
images = append(images, workerImageId)
}
tflog.Info(ctx, "resourceK8CIInputChecks: exist images check", map[string]any{"master_image_id": masterImageId, "worker_image_id": workerImageId})
err := ic.ExistImages(ctx, images, c)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about images"), err.Error())
}
return diags
}

View File

@@ -0,0 +1,31 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type DataSourceK8CIModel struct {
// request fields
K8ciID types.Int64 `tfsdk:"k8ci_id"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// response fields
Description types.String `tfsdk:"desc"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
Id types.String `tfsdk:"id"`
LBImageID types.Int64 `tfsdk:"lb_image_id"`
MasterDriver types.String `tfsdk:"master_driver"`
MasterImageId types.Int64 `tfsdk:"master_image_id"`
MaxMasterCount types.Int64 `tfsdk:"max_master_count"`
MaxWorkerCount types.Int64 `tfsdk:"max_worker_count"`
Milestones types.Int64 `tfsdk:"milestones"`
Name types.String `tfsdk:"name"`
NetworkPlugins types.List `tfsdk:"network_plugins"`
SharedWith types.List `tfsdk:"shared_with"`
Status types.String `tfsdk:"status"`
Version types.String `tfsdk:"version"`
WorkerDriver types.String `tfsdk:"worker_driver"`
WorkerImageId types.Int64 `tfsdk:"worker_image_id"`
}

View File

@@ -0,0 +1,45 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type DataSourceK8CIListModel struct {
// request fields
ByID types.Int64 `tfsdk:"by_id"`
Name types.String `tfsdk:"name"`
Status types.String `tfsdk:"status"`
WorkerDriver types.String `tfsdk:"worker_driver"`
MasterDriver types.String `tfsdk:"master_driver"`
NetworkPlugin types.String `tfsdk:"network_plugin"`
IncludeDisabled types.Bool `tfsdk:"include_disabled"`
Page types.Int64 `tfsdk:"page"`
SortBy types.String `tfsdk:"sort_by"`
Size types.Int64 `tfsdk:"size"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// response fields
Id types.String `tfsdk:"id"`
Items []ItemK8ciModel `tfsdk:"items"`
EntryCount types.Int64 `tfsdk:"entry_count"`
}
type ItemK8ciModel struct {
CreatedTime types.Int64 `tfsdk:"created_time"`
Description types.String `tfsdk:"desc"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
K8ciID types.Int64 `tfsdk:"k8ci_id"`
LBImageID types.Int64 `tfsdk:"lb_image_id"`
MasterDriver types.String `tfsdk:"master_driver"`
MasterImageId types.Int64 `tfsdk:"master_image_id"`
MaxMasterCount types.Int64 `tfsdk:"max_master_count"`
MaxWorkerCount types.Int64 `tfsdk:"max_worker_count"`
Name types.String `tfsdk:"name"`
SharedWith types.List `tfsdk:"shared_with"`
Status types.String `tfsdk:"status"`
Version types.String `tfsdk:"version"`
WorkerDriver types.String `tfsdk:"worker_driver"`
WorkerImageId types.Int64 `tfsdk:"worker_image_id"`
}

View File

@@ -0,0 +1,43 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type DataSourceK8CIListDeletedModel struct {
// request fields
ByID types.Int64 `tfsdk:"by_id"`
Name types.String `tfsdk:"name"`
WorkerDriver types.String `tfsdk:"worker_driver"`
MasterDriver types.String `tfsdk:"master_driver"`
NetworkPlugin types.String `tfsdk:"network_plugin"`
Page types.Int64 `tfsdk:"page"`
SortBy types.String `tfsdk:"sort_by"`
Size types.Int64 `tfsdk:"size"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// response fields
Id types.String `tfsdk:"id"`
Items []ItemK8ciDeletedModel `tfsdk:"items"`
EntryCount types.Int64 `tfsdk:"entry_count"`
}
type ItemK8ciDeletedModel struct {
CreatedTime types.Int64 `tfsdk:"created_time"`
Description types.String `tfsdk:"desc"`
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
K8ciID types.Int64 `tfsdk:"k8ci_id"`
LBImageID types.Int64 `tfsdk:"lb_image_id"`
MasterDriver types.String `tfsdk:"master_driver"`
MasterImageId types.Int64 `tfsdk:"master_image_id"`
MaxMasterCount types.Int64 `tfsdk:"max_master_count"`
MaxWorkerCount types.Int64 `tfsdk:"max_worker_count"`
Name types.String `tfsdk:"name"`
SharedWith types.List `tfsdk:"shared_with"`
Status types.String `tfsdk:"status"`
Version types.String `tfsdk:"version"`
WorkerDriver types.String `tfsdk:"worker_driver"`
WorkerImageId types.Int64 `tfsdk:"worker_image_id"`
}

View File

@@ -0,0 +1,37 @@
package models
import (
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type ResourceK8CIModel struct {
// required fields
Name types.String `tfsdk:"name"`
Version types.String `tfsdk:"version"`
MasterDriver types.String `tfsdk:"master_driver"`
MasterImageId types.Int64 `tfsdk:"master_image_id"`
MaxMasterCount types.Int64 `tfsdk:"max_master_count"`
MaxWorkerCount types.Int64 `tfsdk:"max_worker_count"`
NetworkPlugins types.List `tfsdk:"network_plugins"`
WorkerDriver types.String `tfsdk:"worker_driver"`
WorkerImageId types.Int64 `tfsdk:"worker_image_id"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
// optional fields
Description types.String `tfsdk:"desc"`
Enabled types.Bool `tfsdk:"enabled"`
Permanently types.Bool `tfsdk:"permanently"`
Restore types.Bool `tfsdk:"restore"`
SharedWith types.List `tfsdk:"shared_with"`
// response fields
GID types.Int64 `tfsdk:"gid"`
GUID types.Int64 `tfsdk:"guid"`
K8ciID types.Int64 `tfsdk:"k8ci_id"`
Id types.String `tfsdk:"id"`
LBImageID types.Int64 `tfsdk:"lb_image_id"`
Milestones types.Int64 `tfsdk:"milestones"`
Status types.String `tfsdk:"status"`
}

View File

@@ -0,0 +1,330 @@
package k8ci
import (
"context"
"reflect"
"strconv"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/diag"
"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/k8ci"
"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/k8ci/flattens"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/schemas"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/utilities"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &resourceK8CI{}
_ resource.ResourceWithImportState = &resourceK8CI{}
)
// NewResourceK8Ci is a helper function to simplify the provider implementation.
func NewResourceK8Ci() resource.Resource {
return &resourceK8CI{}
}
// resourceK8CI is the resource implementation.
type resourceK8CI struct {
client *decort.DecortClient
}
// Create creates the resource and sets the initial Terraform state.
func (r *resourceK8CI) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
// Get plan to create resource group
var plan models.ResourceK8CIModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Create resourceK8CI: Error receiving the plan")
return
}
tflog.Info(ctx, "Create resourceK8CI: got plan successfully", map[string]any{"name": plan.Name.ValueString()})
tflog.Info(ctx, "Create resourceK8CI: start creating", map[string]any{"name": plan.Name.ValueString()})
// Set timeouts
createTimeout, diags := plan.Timeouts.Create(ctx, constants.Timeout600s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Create resourceK8CI: Error set timeout")
return
}
tflog.Info(ctx, "Create resourceK8CI: set timeouts successfully", map[string]any{
"name": plan.Name.ValueString(),
"createTimeout": createTimeout})
ctx, cancel := context.WithTimeout(ctx, createTimeout)
defer cancel()
// Check if input values are valid in the platform
tflog.Info(ctx, "Create resourceK8CI: starting input checks", map[string]any{"name": plan.Name.ValueString()})
resp.Diagnostics.Append(resourceK8CIInputChecks(ctx, &plan, r.client)...)
if diags.HasError() {
tflog.Error(ctx, "Create resourceK8CI: Error input checks")
return
}
tflog.Info(ctx, "Create resourceK8CI: input checks successful", map[string]any{"name": plan.Name.ValueString()})
// Make create request and get response
createReq, diags := utilities.CreateRequestResourceK8CI(ctx, &plan)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
tflog.Error(ctx, "Create resourceK8CI: Error response for create request of resource k8ci")
return
}
tflog.Info(ctx, "Create resourceK8CI: before call CloudBroker().K8CI().Create", map[string]any{"req": createReq})
k8ciid, err := r.client.CloudBroker().K8CI().Create(ctx, createReq)
if err != nil {
resp.Diagnostics.AddError(
"Create resourceK8CI: unable to Create k8ci",
err.Error(),
)
return
}
plan.Id = types.StringValue(strconv.Itoa(int(k8ciid)))
tflog.Info(ctx, "Create resourceK8CI: k8ci created", map[string]any{"k8ci_id": k8ciid, "name": plan.Name.ValueString()})
// additional settings after k8ci creation: in case of failures, warnings are added to resp.Diagnostics,
// because additional settings failure is not critical. If errors were added instead of warnings, terraform
// framework would mark resource as tainted and delete it, which would be unwanted behaviour.
// enable/disable of k8ci after creation, warnings added to resp.Diagnostics in case of failure.
temp := utilities.K8CIResourceEnableDisable(ctx, &plan, r.client)
for _, d := range temp {
if d.Severity() == diag.SeverityError {
resp.Diagnostics.AddWarning(d.Summary(), d.Detail())
}
}
tflog.Info(ctx, "Create resourceK8CI: resource creation is completed", map[string]any{"k8ci_id": k8ciid})
// Map response body to schema and populate Computed attribute values
resp.Diagnostics.Append(flattens.K8CIResource(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 *resourceK8CI) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
// Get current state
var state models.ResourceK8CIModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceK8CI: Error get state")
return
}
tflog.Info(ctx, "Read resourceK8CI: got state successfully", map[string]any{"k8ci_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 resourceK8CI: Error set timeout")
return
}
tflog.Info(ctx, "Read resourceK8CI: set timeouts successfully", map[string]any{
"k8ci_id": state.Id.ValueString(),
"readTimeout": readTimeout})
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
// read status
resp.Diagnostics.Append(utilities.K8CIReadStatus(ctx, &state, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceK8CI: Error reading resource group status")
return
}
// Overwrite items with refreshed state
resp.Diagnostics.Append(flattens.K8CIResource(ctx, &state, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceK8CI: Error flatten resource group")
return
}
// Set refreshed state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Read resourceK8CI: Error set state")
return
}
tflog.Info(ctx, "End read resource group")
}
// Update updates the resource and sets the updated Terraform state on success.
func (r *resourceK8CI) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
// Retrieve values from plan
var plan models.ResourceK8CIModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error receiving the plan")
return
}
tflog.Info(ctx, "Update resourceK8CI: got plan successfully", map[string]any{"k8ci_id": plan.Id.ValueString()})
// Retrieve values from state
var state models.ResourceK8CIModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error receiving the state")
return
}
tflog.Info(ctx, "Update resourceK8CI: got state successfully", map[string]any{"k8ci_id": state.Id.ValueString()})
// Set timeouts
updateTimeout, diags := plan.Timeouts.Update(ctx, constants.Timeout600s)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Error set timeout")
return
}
tflog.Info(ctx, "Update resourceK8CI: set timeouts successfully", map[string]any{
"k8ci_id": state.Id.ValueString(),
"updateTimeout": updateTimeout})
ctx, cancel := context.WithTimeout(ctx, updateTimeout)
defer cancel()
// Checking for values in the platform
tflog.Info(ctx, "Update resourceK8CI: starting input checks", map[string]any{"k8ci_id": plan.Id.ValueString()})
resp.Diagnostics.Append(resourceK8CIInputChecks(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error input checks")
return
}
tflog.Info(ctx, "Update resourceK8CI: input checks successful", map[string]any{"k8ci_id": state.Id.ValueString()})
// Checking that immutable variables have not changed
tflog.Info(ctx, "Update resourceK8CI: starting immutable variables checks", map[string]any{"k8ci_id": plan.Id.ValueString()})
resp.Diagnostics.Append(utilities.K8CIIUpdateVarChecks(&plan, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error input checks")
return
}
tflog.Info(ctx, "Update resourceK8CI: input checks successful", map[string]any{"k8ci_id": state.Id.ValueString()})
plan.Id = state.Id
// grant/revoke access for K8CI
if !reflect.DeepEqual(plan.SharedWith, state.SharedWith) {
resp.Diagnostics.Append(utilities.K8CISharedWithUpdate(ctx, &plan, &state, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error grant/revoke access for k8ci")
return
}
}
// enable or disable k8ci
if !plan.Enabled.Equal(state.Enabled) {
resp.Diagnostics.Append(utilities.K8CIResourceEnableDisable(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Update resourceK8CI: Error enable/disable k8ci")
return
}
}
tflog.Info(ctx, "Update resourceK8CI: resource update is completed", map[string]any{"k8ci_id": plan.Id.ValueString()})
// Map response body to schema and populate Computed attribute values
resp.Diagnostics.Append(flattens.K8CIResource(ctx, &plan, r.client)...)
if resp.Diagnostics.HasError() {
return
}
// Set state to fully populated data
diags = resp.State.Set(ctx, plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
// Delete deletes the resource and removes the Terraform state on success.
func (r *resourceK8CI) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
// Get current state
var state models.ResourceK8CIModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Delete resourceK8CI: Error get state")
return
}
tflog.Info(ctx, "Delete resourceK8CI: got state successfully", map[string]any{"k8ci_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 resourceK8CI: Error set timeout")
return
}
tflog.Info(ctx, "Delete resourceK8CI: set timeouts successfully", map[string]any{
"k8ci_id": state.Id.ValueString(),
"deleteTimeout": deleteTimeout})
ctx, cancel := context.WithTimeout(ctx, deleteTimeout)
defer cancel()
k8ciid, err := strconv.ParseUint(state.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID K8CI from state", err.Error())
return
}
// Delete existing resource group
delReq := k8ci.DeleteRequest{
K8CIID: k8ciid,
Permanently: state.Permanently.ValueBool(),
}
_, err = r.client.CloudBroker().K8CI().Delete(ctx, delReq)
if err != nil {
resp.Diagnostics.AddError("Delete resourceK8CI: Error deleting k8ci with error: ", err.Error())
return
}
tflog.Info(ctx, "End delete K8CI", map[string]any{"k8ci_id": state.Id.ValueString()})
}
// Schema defines the schema for the resource.
func (r *resourceK8CI) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: schemas.MakeSchemaResourceK8CI(),
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 *resourceK8CI) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_cb_k8ci"
}
// Configure adds the provider configured client to the resource.
func (r *resourceK8CI) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
tflog.Info(ctx, "Get Configure resourceK8CI")
r.client = client.Resource(ctx, &req, resp)
tflog.Info(ctx, "Getting Configure resourceK8CI successfully")
}
func (r *resourceK8CI) 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,73 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaDataSourceK8CI() map[string]schema.Attribute {
return map[string]schema.Attribute{
"k8ci_id": schema.Int64Attribute{
Required: true,
Description: "K8CI ID",
},
"desc": schema.StringAttribute{
Computed: true,
Description: "description",
},
"gid": schema.Int64Attribute{
Computed: true,
Description: "gid",
},
"guid": schema.Int64Attribute{
Computed: true,
Description: "guid",
},
"id": schema.StringAttribute{
Computed: true,
},
"lb_image_id": schema.Int64Attribute{
Computed: true,
Description: "LB Image ID",
},
"master_driver": schema.StringAttribute{
Computed: true,
},
"master_image_id": schema.Int64Attribute{
Computed: true,
},
"max_master_count": schema.Int64Attribute{
Computed: true,
},
"max_worker_count": schema.Int64Attribute{
Computed: true,
},
"milestones": schema.Int64Attribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
Description: "K8CI name",
},
"network_plugins": schema.ListAttribute{
Computed: true,
ElementType: types.StringType,
},
"shared_with": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
"version": schema.StringAttribute{
Computed: true,
},
"worker_driver": schema.StringAttribute{
Computed: true,
},
"worker_image_id": schema.Int64Attribute{
Computed: true,
},
}
}

View File

@@ -0,0 +1,113 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaDataSourceK8CIList() map[string]schema.Attribute {
return map[string]schema.Attribute{
"by_id": schema.Int64Attribute{
Optional: true,
Description: "Filter by ID",
},
"name": schema.StringAttribute{
Optional: true,
Description: "Filter by name",
},
"status": schema.StringAttribute{
Optional: true,
Description: "Filter by status",
},
"worker_driver": schema.StringAttribute{
Optional: true,
Description: "Filter by worker driver",
},
"master_driver": schema.StringAttribute{
Optional: true,
Description: "Filter by master driver",
},
"network_plugin": schema.StringAttribute{
Optional: true,
Description: "Filter by network plugin",
},
"include_disabled": schema.BoolAttribute{
Optional: true,
Description: "Include disabled k8cis in result",
},
"sort_by": schema.StringAttribute{
Optional: true,
Description: "sort by one of supported fields, format +|-(field)",
},
"page": schema.Int64Attribute{
Optional: true,
Description: "Page number",
},
"size": schema.Int64Attribute{
Optional: true,
Description: "Page size",
},
"id": schema.StringAttribute{
Computed: true,
},
"items": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"created_time": schema.Int64Attribute{
Computed: true,
},
"desc": schema.StringAttribute{
Computed: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"k8ci_id": schema.Int64Attribute{
Computed: true,
},
"lb_image_id": schema.Int64Attribute{
Computed: true,
},
"master_driver": schema.StringAttribute{
Computed: true,
},
"master_image_id": schema.Int64Attribute{
Computed: true,
},
"max_master_count": schema.Int64Attribute{
Computed: true,
},
"max_worker_count": schema.Int64Attribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
},
"shared_with": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
"version": schema.StringAttribute{
Computed: true,
},
"worker_driver": schema.StringAttribute{
Computed: true,
},
"worker_image_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
"entry_count": schema.Int64Attribute{
Computed: true,
},
}
}

View File

@@ -0,0 +1,105 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaDataSourceK8CIListDeleted() map[string]schema.Attribute {
return map[string]schema.Attribute{
"by_id": schema.Int64Attribute{
Optional: true,
Description: "Filter by ID",
},
"name": schema.StringAttribute{
Optional: true,
Description: "Filter by name",
},
"worker_driver": schema.StringAttribute{
Optional: true,
Description: "Filter by worker driver",
},
"master_driver": schema.StringAttribute{
Optional: true,
Description: "Filter by master driver",
},
"network_plugin": schema.StringAttribute{
Optional: true,
Description: "Filter by network plugin",
},
"sort_by": schema.StringAttribute{
Optional: true,
Description: "sort by one of supported fields, format +|-(field)",
},
"page": schema.Int64Attribute{
Optional: true,
Description: "Page number",
},
"size": schema.Int64Attribute{
Optional: true,
Description: "Page size",
},
"id": schema.StringAttribute{
Computed: true,
},
"items": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"created_time": schema.Int64Attribute{
Computed: true,
},
"desc": schema.StringAttribute{
Computed: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"k8ci_id": schema.Int64Attribute{
Computed: true,
},
"lb_image_id": schema.Int64Attribute{
Computed: true,
},
"master_driver": schema.StringAttribute{
Computed: true,
},
"master_image_id": schema.Int64Attribute{
Computed: true,
},
"max_master_count": schema.Int64Attribute{
Computed: true,
},
"max_worker_count": schema.Int64Attribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
},
"shared_with": schema.ListAttribute{
Computed: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
"version": schema.StringAttribute{
Computed: true,
},
"worker_driver": schema.StringAttribute{
Computed: true,
},
"worker_image_id": schema.Int64Attribute{
Computed: true,
},
},
},
},
"entry_count": schema.Int64Attribute{
Computed: true,
},
}
}

View File

@@ -0,0 +1,84 @@
package schemas
import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func MakeSchemaResourceK8CI() map[string]schema.Attribute {
return map[string]schema.Attribute{
"name": schema.StringAttribute{
Required: true,
Description: "K8CI name",
},
"version": schema.StringAttribute{
Required: true,
},
"master_driver": schema.StringAttribute{
Required: true,
},
"master_image_id": schema.Int64Attribute{
Required: true,
},
"max_master_count": schema.Int64Attribute{
Required: true,
},
"max_worker_count": schema.Int64Attribute{
Required: true,
},
"worker_image_id": schema.Int64Attribute{
Required: true,
},
"worker_driver": schema.StringAttribute{
Required: true,
},
"network_plugins": schema.ListAttribute{
Required: true,
ElementType: types.StringType,
},
"enabled": schema.BoolAttribute{
Optional: true,
},
"permanently": schema.BoolAttribute{
Optional: true,
Computed: true,
Default: booldefault.StaticBool(true),
// default value is true
},
"restore": schema.BoolAttribute{
Optional: true,
Computed: true,
Default: booldefault.StaticBool(true),
// default value is true
},
"desc": schema.StringAttribute{
Optional: true,
},
"gid": schema.Int64Attribute{
Computed: true,
},
"guid": schema.Int64Attribute{
Computed: true,
},
"k8ci_id": schema.Int64Attribute{
Computed: true,
},
"id": schema.StringAttribute{
Computed: true,
},
"lb_image_id": schema.Int64Attribute{
Computed: true,
},
"milestones": schema.Int64Attribute{
Computed: true,
},
"shared_with": schema.ListAttribute{
Optional: true,
ElementType: types.Int64Type,
},
"status": schema.StringAttribute{
Computed: true,
},
}
}

View File

@@ -0,0 +1,27 @@
package utilities
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8ci"
)
func K8ciDataSourceCheckPresence(ctx context.Context, k8ciID uint64, c *decort.DecortClient) (*k8ci.RecordK8CI, diag.Diagnostics) {
tflog.Info(ctx, fmt.Sprintf("K8ciDataSourceCheckPresence: Get info about k8ci with ID - %v", k8ciID))
diags := diag.Diagnostics{}
recordK8ci, err := c.CloudBroker().K8CI().Get(ctx, k8ci.GetRequest{K8CIID: k8ciID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about k8ci with ID %v", k8ciID), err.Error())
return nil, diags
}
tflog.Info(ctx, "K8ciDataSourceCheckPresence: response from CloudBroker().K8CI().Get", map[string]any{"k8ci_id": k8ciID, "response": recordK8ci})
return recordK8ci, nil
}

View File

@@ -0,0 +1,59 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8ci"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
)
func K8CIListDataSourceCheckPresence(ctx context.Context, plan *models.DataSourceK8CIListModel, c *decort.DecortClient) (*k8ci.ListK8CI, diag.Diagnostics) {
tflog.Info(ctx, "K8CIListDataSourceCheckPresence: Get info about k8ci list")
diags := diag.Diagnostics{}
listReq := k8ci.ListRequest{}
if !plan.ByID.IsNull() {
listReq.ByID = uint64(plan.ByID.ValueInt64())
}
if !plan.Name.IsNull() {
listReq.Name = plan.Name.ValueString()
}
if !plan.Status.IsNull() {
listReq.Status = plan.Status.ValueString()
}
if !plan.WorkerDriver.IsNull() {
listReq.WorkerDriver = plan.WorkerDriver.ValueString()
}
if !plan.MasterDriver.IsNull() {
listReq.MasterDriver = plan.MasterDriver.ValueString()
}
if !plan.NetworkPlugin.IsNull() {
listReq.NetworkPlugins = plan.NetworkPlugin.ValueString()
}
if !plan.IncludeDisabled.IsNull() {
listReq.IncludeDisabled = plan.IncludeDisabled.ValueBool()
}
if !plan.SortBy.IsNull() {
listReq.SortBy = plan.SortBy.ValueString()
}
if !plan.Page.IsNull() {
listReq.Page = uint64(plan.Page.ValueInt64())
}
if !plan.Size.IsNull() {
listReq.Size = uint64(plan.Size.ValueInt64())
}
tflog.Info(ctx, "K8CIListDataSourceCheckPresence: before call CloudBroker().K8CI().List", map[string]any{"req": listReq})
list, err := c.CloudBroker().K8CI().List(ctx, listReq)
if err != nil {
diags.AddError("Cannot get info about k8ci list", err.Error())
return nil, diags
}
tflog.Info(ctx, "K8CIListDataSourceCheckPresence: successfull response from CloudBroker().K8CI().List")
return list, nil
}

View File

@@ -0,0 +1,53 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8ci"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
)
func K8CIListDeletedDataSourceCheckPresence(ctx context.Context, plan *models.DataSourceK8CIListDeletedModel, c *decort.DecortClient) (*k8ci.ListK8CI, diag.Diagnostics) {
tflog.Info(ctx, "K8CIListDeletedDataSourceCheckPresence: Get info about k8ci list")
diags := diag.Diagnostics{}
listReq := k8ci.ListDeletedRequest{}
if !plan.ByID.IsNull() {
listReq.ByID = uint64(plan.ByID.ValueInt64())
}
if !plan.Name.IsNull() {
listReq.Name = plan.Name.ValueString()
}
if !plan.WorkerDriver.IsNull() {
listReq.WorkerDriver = plan.WorkerDriver.ValueString()
}
if !plan.MasterDriver.IsNull() {
listReq.MasterDriver = plan.MasterDriver.ValueString()
}
if !plan.NetworkPlugin.IsNull() {
listReq.NetworkPlugins = plan.NetworkPlugin.ValueString()
}
if !plan.SortBy.IsNull() {
listReq.SortBy = plan.SortBy.ValueString()
}
if !plan.Page.IsNull() {
listReq.Page = uint64(plan.Page.ValueInt64())
}
if !plan.Size.IsNull() {
listReq.Size = uint64(plan.Size.ValueInt64())
}
tflog.Info(ctx, "K8CIListDeletedDataSourceCheckPresence: before call CloudBroker().K8CI().ListDeleted", map[string]any{"req": listReq})
list, err := c.CloudBroker().K8CI().ListDeleted(ctx, listReq)
if err != nil {
diags.AddError("Cannot get info about k8ci deleted list", err.Error())
return nil, diags
}
tflog.Info(ctx, "K8CIListDeletedDataSourceCheckPresence: successfull response from CloudBroker().K8CI().ListDeleted")
return list, nil
}

View File

@@ -0,0 +1,331 @@
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/k8ci"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/k8ci/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status"
)
func CreateRequestResourceK8CI(ctx context.Context, plan *models.ResourceK8CIModel) (k8ci.CreateRequest, diag.Diagnostics) {
tflog.Info(ctx, "Start CreateRequestResourceK8CI", map[string]any{
"name": plan.Name.ValueString(),
})
// set up required parameters in resource group create request
createReq := k8ci.CreateRequest{
Name: plan.Name.ValueString(),
Version: plan.Version.ValueString(),
MasterDriver: plan.MasterDriver.ValueString(),
WorkerDriver: plan.WorkerDriver.ValueString(),
MaxMasterCount: uint64(plan.MaxMasterCount.ValueInt64()),
MaxWorkerCount: uint64(plan.MaxWorkerCount.ValueInt64()),
MasterImageID: uint64(plan.MasterImageId.ValueInt64()),
WorkerImageID: uint64(plan.WorkerImageId.ValueInt64()),
}
networkPlugins := make([]string, 0, len(plan.NetworkPlugins.Elements()))
for _, plugin := range plan.NetworkPlugins.Elements() {
networkPlugins = append(networkPlugins, plugin.(types.String).ValueString())
}
createReq.NetworkPlugins = networkPlugins
if !plan.Description.IsNull() {
createReq.Description = plan.Description.ValueString()
}
if !plan.SharedWith.IsNull() {
sharedWith := make([]uint64, 0, len(plan.SharedWith.Elements()))
for _, shared := range plan.SharedWith.Elements() {
sharedWith = append(sharedWith, uint64(shared.(types.Int64).ValueInt64()))
}
createReq.SharedWith = sharedWith
}
return createReq, nil
}
func K8CIResourceEnableDisable(ctx context.Context, plan *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "EnableDisable k8ci with ID", map[string]any{"k8ci_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8ciid, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID k8ci from state", err.Error())
return diags
}
if plan.Enabled.IsNull() || plan.Enabled.ValueBool() {
tflog.Info(ctx, "Enable k8ci with ID", map[string]any{"k8ci_id": plan.Id.ValueString()})
_, err := c.CloudBroker().K8CI().Enable(ctx, k8ci.EnableRequest{K8CIID: k8ciid})
if err != nil {
diags.AddError("K8CIResourceEnableDisable: error to enable k8ci", err.Error())
return diags
}
} else {
tflog.Info(ctx, "Disable k8ci with ID", map[string]any{"k8ci_id": plan.Id.ValueString()})
_, err := c.CloudBroker().K8CI().Disable(ctx, k8ci.DisableRequest{K8CIID: k8ciid})
if err != nil {
diags.AddError("K8CIResourceEnableDisable: error to disable k8ci", err.Error())
return diags
}
}
return diags
}
func K8CIResourceCheckPresence(ctx context.Context, plan *models.ResourceK8CIModel, c *decort.DecortClient) (*k8ci.RecordK8CI, diag.Diagnostics) {
tflog.Info(ctx, fmt.Sprintf("K8CIResourceCheckPresence: Get info about k8ci with ID - %v", plan.Id.ValueString()))
diags := diag.Diagnostics{}
k8ciid, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID k8ci from state", err.Error())
return nil, diags
}
recordK8ci, err := c.CloudBroker().K8CI().Get(ctx, k8ci.GetRequest{K8CIID: k8ciid})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about k8ci with ID %v", k8ciid), err.Error())
return nil, diags
}
tflog.Info(ctx, "K8CIResourceCheckPresence: response from CloudBroker().K8CI().Get", map[string]any{"k8ci_id": k8ciid, "response": recordK8ci})
return recordK8ci, nil
}
func K8CIReadStatus(ctx context.Context, plan *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Read status k8ci with ID", map[string]any{"k8ci_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8ciid, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID k8ci from state", err.Error())
return diags
}
k8ciItem, err := c.CloudBroker().K8CI().Get(ctx, k8ci.GetRequest{K8CIID: k8ciid})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot get info about k8ci with ID %v", k8ciItem), err.Error())
return diags
}
switch k8ciItem.Status {
case status.Modeled:
diags.AddError("Error:", fmt.Sprintf("The k8ci is in status: %s, please, contact support for more information", k8ciItem.Status))
return diags
case status.Deleted:
if plan.Restore.ValueBool() || plan.Restore.IsNull() {
diags = K8CIRestore(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "Error restore K8CI", map[string]any{"k8ci_id": plan.Id.ValueString()})
return diags
}
} else {
diags.AddError("k8ci in status Deleted:", "please clean state, or restore k8ci")
return diags
}
diags = K8CIResourceEnableDisable(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "Error enable/disable k8ci", map[string]any{"k8ci_id": plan.Id.ValueString()})
return diags
}
case status.Destroying:
diags.AddError("Error:", fmt.Sprintf("The k8ci is in progress with status: %s", k8ciItem.Status))
return diags
case status.Destroyed:
diags.AddError("Error:", "The resource cannot be updated because it has been destroyed")
return diags
}
tflog.Info(ctx, "Read status k8ci successfully", map[string]any{"k8ci_id": plan.Id.ValueString()})
return diags
}
func K8CIRestore(ctx context.Context, plan *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Restore k8ci with ID", map[string]any{"k8ci_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8ciid, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID k8ci from state", err.Error())
return diags
}
_, err = c.CloudBroker().K8CI().Restore(ctx, k8ci.RestoreRequest{K8CIID: k8ciid})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot restore k8ci with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
tflog.Info(ctx, "Restore k8ci successfully", map[string]any{"k8ci_id": plan.Id.ValueString()})
return diags
}
func K8CIIUpdateVarChecks(plan *models.ResourceK8CIModel, state *models.ResourceK8CIModel) diag.Diagnostics {
diags := diag.Diagnostics{}
if !plan.Name.Equal(state.Name) {
diags.AddError(
"Update resourceK8CI: Invalid input Name",
fmt.Sprintf("block Name must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.Version.Equal(state.Version) {
diags.AddError(
"Update resourceK8CI: Invalid input Version",
fmt.Sprintf("block Version must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.MasterDriver.Equal(state.MasterDriver) {
diags.AddError(
"Update resourceK8CI: Invalid MasterDriver",
fmt.Sprintf("block MasterDriver must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.MasterImageId.Equal(state.MasterImageId) {
diags.AddError(
"Update resourceK8CI: Invalid MasterImageId",
fmt.Sprintf("block MasterImageId must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.MaxMasterCount.Equal(state.MaxMasterCount) {
diags.AddError(
"Update resourceK8CI: Invalid MaxMasterCount",
fmt.Sprintf("block MaxMasterCount must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.MaxWorkerCount.Equal(state.MaxWorkerCount) {
diags.AddError(
"Update resourceK8CI: Invalid MaxWorkerCount",
fmt.Sprintf("block MaxWorkerCount must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.NetworkPlugins.Equal(state.NetworkPlugins) {
diags.AddError(
"Update resourceK8CI: Invalid NetworkPlugins",
fmt.Sprintf("block NetworkPlugins must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.WorkerDriver.Equal(state.WorkerDriver) {
diags.AddError(
"Update resourceK8CI: Invalid WorkerDriver",
fmt.Sprintf("block WorkerDriver must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
if !plan.WorkerImageId.Equal(state.WorkerImageId) {
diags.AddError(
"Update resourceK8CI: Invalid WorkerImageId",
fmt.Sprintf("block WorkerImageId must not be changed for resource with k8ci_id %s", plan.Id.ValueString()),
)
return diags
}
return nil
}
func K8CISharedWithUpdate(ctx context.Context, plan *models.ResourceK8CIModel, state *models.ResourceK8CIModel, c *decort.DecortClient) diag.Diagnostics {
diags := diag.Diagnostics{}
k8ciid, err := strconv.ParseUint(state.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("K8CISharedWithUpdate: cannot parsed ID k8ci from state", err.Error())
return diags
}
addSet, removeSet := difference(state.SharedWith, plan.SharedWith)
for _, account := range addSet {
accountId := uint64(account.(types.Int64).ValueInt64())
tflog.Info(ctx, fmt.Sprintf("K8CISharedWithUpdate: Start add account with ID - %d to sharedWith access list to k8ci with ID - %d", accountId, k8ciid))
req := k8ci.AccessAddRequest{
K8CIID: k8ciid,
AccountId: accountId,
}
res, err := c.CloudBroker().K8CI().AccessAdd(ctx, req)
tflog.Info(ctx, "K8CISharedWithUpdate: response from CloudBroker().K8CI().AccessAdd", map[string]any{"k8ci_id": plan.Id.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("K8CISharedWithUpdate: Cannot add account with ID - %d", accountId), err.Error())
}
}
if diags.HasError() {
tflog.Error(ctx, "K8CISharedWithUpdate: Errors occurred while managing add accounts")
return diags
}
for _, account := range removeSet {
accountId := uint64(account.(types.Int64).ValueInt64())
tflog.Info(ctx, fmt.Sprintf("K8CISharedWithUpdate: Start remove account with ID - %d from sharedWith access list to k8ci with ID - %d", accountId, k8ciid))
req := k8ci.AccessRemoveRequest{
K8CIID: k8ciid,
AccountId: accountId,
}
res, err := c.CloudBroker().K8CI().AccessRemove(ctx, req)
tflog.Info(ctx, "K8CISharedWithUpdate: response from CloudBroker().K8CI().AccessRemove", map[string]any{"k8ci_id": plan.Id.ValueString(), "response": res})
if err != nil {
diags.AddError(fmt.Sprintf("K8CISharedWithUpdate: Cannot remove account with ID - %d", accountId), err.Error())
}
}
if diags.HasError() {
tflog.Error(ctx, "K8CISharedWithUpdate: Errors occurred while managing remove accounts")
return diags
}
tflog.Info(ctx, "K8CISharedWithUpdate: sharedWith access list is successfully update", map[string]any{"k8ci_id": k8ciid})
return nil
}
// difference returns lists added and removed values
func difference(oldSet, newSet types.List) (added, removed []any) {
oldMap := make(map[interface{}]struct{})
newMap := make(map[interface{}]struct{})
for _, elem := range oldSet.Elements() {
oldMap[elem] = struct{}{}
}
for _, elem := range newSet.Elements() {
newMap[elem] = struct{}{}
}
for elem := range newMap {
if _, found := oldMap[elem]; !found {
added = append(added, elem)
}
}
for elem := range oldMap {
if _, found := newMap[elem]; !found {
removed = append(removed, elem)
}
}
return
}