This commit is contained in:
asteam
2024-07-25 14:33:38 +03:00
commit 6f40af6a5f
946 changed files with 98335 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/diag"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/ic"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
)
func CheckParamsExistenceCP(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
diags := diag.Diagnostics{}
if err := ic.ExistRG(ctx, uint64(plan.RGID.ValueInt64()), c); err != nil {
diags.AddError("Error check input values", err.Error())
}
if err := ic.ExistK8CI(ctx, uint64(plan.K8SCIID.ValueInt64()), c); err != nil {
diags.AddError("Error check input values", err.Error())
}
if err := ic.ExistExtNetInK8s(ctx, uint64(plan.ExtNetID.ValueInt64()), c); err != nil {
diags.AddError("Error check input values", err.Error())
}
if err := ic.ExistVinsInK8s(ctx, uint64(plan.VinsId.ValueInt64()), c); err != nil {
diags.AddError("Error check input values", err.Error())
}
return diags
}
func CheckParamsExistenceWG(ctx context.Context, plan *models.ResourceK8SWGModel, c *decort.DecortClient) diag.Diagnostics {
diags := diag.Diagnostics{}
if err := ic.ExistK8s(ctx, uint64(plan.K8SID.ValueInt64()), c); err != nil {
diags.AddError("Error check input values", err.Error())
}
return diags
}

View File

@@ -0,0 +1,55 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8ci"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
)
func K8ciListCheckPresence(ctx context.Context, state *models.K8ciListModel, c *decort.DecortClient) (*k8ci.ListK8CI, error) {
tflog.Info(ctx, "Get k8ci list info")
req := k8ci.ListRequest{}
if !state.ByID.IsNull() {
req.ByID = uint64(state.ByID.ValueInt64())
}
if !state.Name.IsNull() {
req.Name = state.Name.ValueString()
}
if !state.Status.IsNull() {
req.Status = state.Status.ValueString()
}
if !state.WorkerDriver.IsNull() {
req.WorkerDriver = state.WorkerDriver.ValueString()
}
if !state.MasterDriver.IsNull() {
req.MasterDriver = state.MasterDriver.ValueString()
}
if !state.NetworkPlugins.IsNull() {
req.NetworkPlugins = state.NetworkPlugins.ValueString()
}
if !state.IncludeDisabled.IsNull() {
req.IncludeDisabled = state.IncludeDisabled.ValueBool()
}
if !state.SortBy.IsNull() {
req.SortBy = state.SortBy.ValueString()
}
if !state.Size.IsNull() {
req.Size = uint64(state.Size.ValueInt64())
}
if !state.Page.IsNull() {
req.Page = uint64(state.Page.ValueInt64())
}
k8sList, err := c.CloudAPI().K8CI().List(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting k8ci list info, successfully")
return k8sList, nil
}

View File

@@ -0,0 +1,61 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
)
func K8sListCheckPresence(ctx context.Context, state *models.K8SListModel, c *decort.DecortClient) (*k8s.ListK8SClusters, error) {
tflog.Info(ctx, "Get k8s list info")
req := k8s.ListRequest{}
if !state.ByID.IsNull() {
req.ByID = uint64(state.ByID.ValueInt64())
}
if !state.Name.IsNull() {
req.Name = state.Name.ValueString()
}
if !state.IPAddress.IsNull() {
req.IPAddress = state.IPAddress.ValueString()
}
if !state.RGID.IsNull() {
req.RGID = uint64(state.RGID.ValueInt64())
}
if !state.LBID.IsNull() {
req.LBID = uint64(state.LBID.ValueInt64())
}
if !state.BasicServiceID.IsNull() {
req.BasicServiceID = uint64(state.BasicServiceID.ValueInt64())
}
if !state.Status.IsNull() {
req.Status = state.Status.ValueString()
}
if !state.TechStatus.IsNull() {
req.TechStatus = state.TechStatus.ValueString()
}
if !state.IncludeDeleted.IsNull() {
req.IncludeDeleted = state.IncludeDeleted.ValueBool()
}
if !state.SortBy.IsNull() {
req.SortBy = state.SortBy.ValueString()
}
if !state.Size.IsNull() {
req.Size = uint64(state.Size.ValueInt64())
}
if !state.Page.IsNull() {
req.Page = uint64(state.Page.ValueInt64())
}
k8sList, err := c.CloudAPI().K8S().List(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting k8s list info, successfully")
return k8sList, nil
}

View File

@@ -0,0 +1,55 @@
package utilities
import (
"context"
"github.com/hashicorp/terraform-plugin-log/tflog"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
)
func K8sListDeletedCheckPresence(ctx context.Context, state *models.K8SListDeletedModel, c *decort.DecortClient) (*k8s.ListK8SClusters, error) {
tflog.Info(ctx, "Get k8s list deleted info")
req := k8s.ListDeletedRequest{}
if !state.ByID.IsNull() {
req.ByID = uint64(state.ByID.ValueInt64())
}
if !state.Name.IsNull() {
req.Name = state.Name.ValueString()
}
if !state.IPAddress.IsNull() {
req.IPAddress = state.IPAddress.ValueString()
}
if !state.RGID.IsNull() {
req.RGID = uint64(state.RGID.ValueInt64())
}
if !state.LBID.IsNull() {
req.LBID = uint64(state.LBID.ValueInt64())
}
if !state.BasicServiceID.IsNull() {
req.BasicServiceID = uint64(state.BasicServiceID.ValueInt64())
}
if !state.TechStatus.IsNull() {
req.TechStatus = state.TechStatus.ValueString()
}
if !state.SortBy.IsNull() {
req.SortBy = state.SortBy.ValueString()
}
if !state.Size.IsNull() {
req.Size = uint64(state.Size.ValueInt64())
}
if !state.Page.IsNull() {
req.Page = uint64(state.Page.ValueInt64())
}
k8sList, err := c.CloudAPI().K8S().ListDeleted(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting k8s list deleted info, successfully")
return k8sList, nil
}

View File

@@ -0,0 +1,488 @@
package utilities
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"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/cloudapi/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/lb"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/tasks"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/status"
)
func CreateRequestResourceK8CP(ctx context.Context, plan *models.ResourceK8SCPModel) k8s.CreateRequest {
tflog.Info(ctx, "Start CreateRequestResourceK8CP", map[string]any{"name": plan.Name.ValueString()})
req := k8s.CreateRequest{
Name: plan.Name.ValueString(),
RGID: uint64(plan.RGID.ValueInt64()),
K8SCIID: uint64(plan.K8SCIID.ValueInt64()),
WorkerGroupName: "temp",
NetworkPlugin: plan.NetworkPlugin.ValueString(),
}
if !plan.Num.IsUnknown() {
req.MasterNum = uint(plan.Num.ValueInt64())
}
if !plan.CPU.IsUnknown() {
req.MasterCPU = uint(plan.CPU.ValueInt64())
}
if !plan.RAM.IsUnknown() {
req.MasterRAM = uint64(plan.RAM.ValueInt64())
}
if !plan.Disk.IsUnknown() {
req.MasterDisk = uint(plan.Disk.ValueInt64())
}
if !plan.SEPID.IsNull() {
req.MasterSEPID = uint64(plan.SEPID.ValueInt64())
}
if !plan.SEPPool.IsNull() {
req.MasterSEPPool = plan.SEPPool.ValueString()
}
if !plan.WithLB.IsNull() {
req.WithLB = plan.WithLB.ValueBool()
} else {
req.WithLB = true
}
if !plan.ExtNetID.IsUnknown() {
req.ExtNetID = uint64(plan.ExtNetID.ValueInt64())
}
if !plan.VinsId.IsUnknown() {
req.VinsId = uint64(plan.VinsId.ValueInt64())
}
if !plan.HighlyAvailable.IsNull() {
req.HighlyAvailable = plan.HighlyAvailable.ValueBool()
}
if !plan.AdditionalSANs.IsNull() {
result := make([]string, 0, len(plan.AdditionalSANs.Elements()))
for _, val := range plan.AdditionalSANs.Elements() {
result = append(result, strings.Trim(val.String(), "\""))
}
req.AdditionalSANs = result
}
if !plan.ClusterConfiguration.IsNull() {
req.ClusterConfiguration = plan.ClusterConfiguration.ValueString()
}
if !plan.KubeletConfiguration.IsNull() {
req.KubeletConfiguration = plan.KubeletConfiguration.ValueString()
}
if !plan.KubeProxyConfiguration.IsNull() {
req.KubeProxyConfiguration = plan.KubeProxyConfiguration.ValueString()
}
if !plan.InitConfiguration.IsNull() {
req.InitConfiguration = plan.InitConfiguration.ValueString()
}
if !plan.OidcCertificate.IsNull() {
req.OidcCertificate = plan.OidcCertificate.ValueString()
}
if !plan.Description.IsNull() {
req.Description = plan.Description.ValueString()
}
if !plan.ExtNetOnly.IsNull() {
req.ExtNetOnly = plan.ExtNetOnly.ValueBool()
}
if !plan.LBSysctlParams.IsNull() {
result := make([]map[string]interface{}, 0, len(plan.LBSysctlParams.Elements()))
for _, val := range plan.LBSysctlParams.Elements() {
objVal := val.(types.Object)
valMap := objVal.Attributes()
mapKey := valMap["key"].(types.String).ValueString()
mapVal := valMap["value"].(types.String).ValueString()
tempMap := make(map[string]interface{})
tempMap[mapKey] = mapVal
result = append(result, tempMap)
}
req.LbSysctlParams = result
}
tflog.Info(ctx, "End CreateRequestResourceK8CP", map[string]any{"name": plan.Name.String()})
return req
}
func CheckResourceK8SCPCreateAndDeleteWG(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient, resp string) diag.Diagnostics {
tflog.Info(ctx, "Start CheckResourceK8CPCreateAndDeleteWG", map[string]any{"name": plan.Name.ValueString()})
diags := diag.Diagnostics{}
taskReq := tasks.GetRequest{
AuditID: strings.Trim(resp, `"`),
}
for {
task, err := c.CloudAPI().Tasks().Get(ctx, taskReq)
if err != nil {
diags.AddError("The audit cannot be found", err.Error())
return diags
}
tflog.Info(ctx, fmt.Sprintf("ResourceK8sControlPlaneCreate instance creating - %s", task.Stage))
if task.Completed {
if task.Error != "" {
diags.AddError("Cannot create cluster instance:", task.Error)
return diags
}
result, err := task.Result.ID()
if err != nil {
diags.AddError("Cannot get cluster ID:", err.Error())
return diags
}
plan.Id = types.StringValue(strconv.Itoa(result))
plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850))
break
}
time.Sleep(time.Second * 20)
}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
cluster, err := K8SCPResourceCheckPresence(ctx, k8sID, c)
if err != nil {
diags.AddError("Cannot get info about cluster ", err.Error())
return diags
}
tflog.Info(ctx, "Start delete Work Group from cluster with ID", map[string]any{"k8s_id": k8sID})
delWGReq := k8s.WorkersGroupDeleteRequest{
K8SID: cluster.ID,
WorkersGroupID: cluster.K8SGroups.Workers[0].ID,
}
_, err = c.CloudAPI().K8S().WorkersGroupDelete(ctx, delWGReq)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot create cluster with ID - %d: platform error, creation cancelled, cluster will be delete permanently", cluster.ID), err.Error())
tflog.Error(ctx, "Start delete cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
_, err = c.CloudAPI().K8S().Delete(ctx, k8s.DeleteRequest{K8SID: cluster.ID, Permanently: true})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot delete cluster with ID - %d, after error creation. Please report this issue to the provider developers.", cluster.ID), err.Error())
return diags
}
tflog.Error(ctx, "Delete cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
tflog.Info(ctx, "End CheckResourceK8CPCreateAndDeleteWG", map[string]any{"k8s_id": cluster.ID})
return diags
}
func K8SCPResourceCheckPresence(ctx context.Context, k8SID uint64, c *decort.DecortClient) (*k8s.RecordK8S, error) {
tflog.Info(ctx, "Get info about cluster with ID", map[string]any{"k8s_id": k8SID})
cluster, err := c.CloudAPI().K8S().Get(ctx, k8s.GetRequest{K8SID: k8SID})
if err != nil {
return nil, fmt.Errorf("cannot get info about cluster with error: %w", err)
}
tflog.Info(ctx, "Getting info about cluster successfully", map[string]any{"k8s_id": k8SID})
return cluster, nil
}
func K8sListForResourceCheckPresence(ctx context.Context, k8SID uint64, c *decort.DecortClient) (*k8s.ListK8SClusters, error) {
tflog.Info(ctx, "Get info in List about cluster with ID", map[string]any{"k8s_id": k8SID})
req := k8s.ListRequest{
IncludeDeleted: false,
ByID: k8SID,
}
k8sList, err := c.CloudAPI().K8S().List(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "Getting info in List about cluster successfully", map[string]any{"k8s_id": k8SID})
return k8sList, nil
}
func ComputeCheckPresence(ctx context.Context, computeID uint64, c *decort.DecortClient) (*compute.RecordCompute, error) {
tflog.Info(ctx, "Start utilityComputeCheckPresence", map[string]any{"compute_id": computeID})
req := compute.GetRequest{
ComputeID: computeID,
}
compute, err := c.CloudAPI().Compute().Get(ctx, req)
if err != nil {
return nil, err
}
tflog.Info(ctx, "End utilityComputeCheckPresence", map[string]any{"compute_id": computeID})
return compute, nil
}
func K8SCPUpdateNameOrDescription(ctx context.Context, plan, state *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Update info about cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
req := k8s.UpdateRequest{
K8SID: k8sID,
}
if !plan.Name.Equal(state.Name) {
req.Name = plan.Name.ValueString()
}
if !plan.Description.Equal(state.Description) {
req.Description = plan.Description.ValueString()
}
_, err = c.CloudAPI().K8S().Update(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot update cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
tflog.Info(ctx, "Update info about cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8SCPReadStatus(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Read status cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
cluster, err := K8SCPResourceCheckPresence(ctx, k8sID, c)
if err != nil {
diags.AddError("Cannot get info about cluster ", err.Error())
return diags
}
switch cluster.Status {
case status.Modeled:
diags.AddError("Error:", fmt.Sprintf("The k8s cluster is in status: %s, please, contact support for more information", cluster.Status))
return diags
case status.Deleted:
if plan.Restore.ValueBool() || plan.Restore.IsNull() {
diags = K8SCPRestore(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "Error restore cluster", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
} else {
diags.AddError("Cluster in status Deleted:", "please clean state, or restore cluster")
return diags
}
if plan.Enabled.ValueBool() || plan.Enabled.IsNull() {
diags = K8SCPEnableDisable(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "Error enable/disable cluster", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
if plan.Start.ValueBool() || plan.Start.IsNull() {
diags = K8SCPStartStop(ctx, plan, c)
if diags.HasError() {
tflog.Error(ctx, "Error start/stop cluster", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
}
}
case status.Destroying:
diags.AddError("Error:", fmt.Sprintf("The k8s cluster is in progress with status: %s", cluster.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 cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8SCPRestore(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Restore cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
_, err = c.CloudAPI().K8S().Restore(ctx, k8s.RestoreRequest{K8SID: k8sID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot restore cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
tflog.Info(ctx, "Restore cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8SCPEnableDisable(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Enable/Disable cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
if plan.Enabled.ValueBool() || plan.Enabled.IsNull() {
_, err := c.CloudAPI().K8S().Enable(ctx, k8s.DisableEnableRequest{K8SID: k8sID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot enable cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
}
if !plan.Enabled.ValueBool() && !plan.Enabled.IsNull() {
_, err := c.CloudAPI().K8S().Disable(ctx, k8s.DisableEnableRequest{K8SID: k8sID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot disable cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
}
tflog.Info(ctx, "Enable/Disable cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8SCPStartStop(ctx context.Context, plan *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start/Stop cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
k8sID, err := strconv.ParseUint(plan.Id.ValueString(), 10, 64)
if err != nil {
diags.AddError("Cannot parsed ID cluster from state", err.Error())
return diags
}
if plan.Enabled.ValueBool() || plan.Enabled.IsNull() {
if plan.Start.ValueBool() || plan.Start.IsNull() {
_, err := c.CloudAPI().K8S().Start(ctx, k8s.StartRequest{K8SID: k8sID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot start cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
}
}
if plan.Enabled.ValueBool() || plan.Enabled.IsNull() {
if !plan.Start.ValueBool() && !plan.Start.IsNull() {
_, err := c.CloudAPI().K8S().Stop(ctx, k8s.StopRequest{K8SID: k8sID})
if err != nil {
diags.AddError(fmt.Sprintf("Cannot stop cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
}
}
tflog.Info(ctx, "Start/Stop cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8SCPDeleteMaster(ctx context.Context, plan *models.ResourceK8SCPModel, state *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Delete Master node from cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
deleteMasterComp := make([]string, 0)
for i, val := range state.DetailedInfo.Elements() {
if i == 2 {
break
}
obj, err := types.ObjectValueFrom(ctx, models.ItemDetailedInfo, val)
if err != nil {
tflog.Error(ctx, fmt.Sprint("Error flattenDetailedInfo struct to obj", err), map[string]any{"k8s_id": plan.Id.ValueString()})
}
id := obj.Attributes()["compute_id"]
deleteMasterComp = append(deleteMasterComp, id.String())
}
req := k8s.DeleteMasterFromGroupRequest{
K8SID: uint64(state.K8SID.ValueInt64()),
MasterGroupID: uint64(state.MasterGroupId.ValueInt64()),
MasterIDs: deleteMasterComp,
}
_, err := c.CloudAPI().K8S().DeleteMasterFromGroup(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot delete master node from cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
tflog.Info(ctx, "Delete Master node from cluster successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}
func K8CPUpdateSysctlParams(ctx context.Context, plan *models.ResourceK8SCPModel, state *models.ResourceK8SCPModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Update LB parameters from cluster with ID", map[string]any{"k8s_id": plan.Id.ValueString()})
diags := diag.Diagnostics{}
result := make([]map[string]interface{}, 0, len(plan.LBSysctlParams.Elements()))
for _, val := range plan.LBSysctlParams.Elements() {
objVal := val.(types.Object)
valMap := objVal.Attributes()
mapKey := valMap["key"].(types.String).ValueString()
mapVal := valMap["value"].(types.String).ValueString()
tempMap := make(map[string]interface{})
tempMap[mapKey] = mapVal
result = append(result, tempMap)
}
req := lb.UpdateSysctParamsRequest{
LBID: uint64(state.LBID.ValueInt64()),
SysctlParams: result,
}
_, err := c.CloudAPI().LB().UpdateSysctlParams(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot update LB parameters from cluster with ID - %s", plan.Id.ValueString()), err.Error())
return diags
}
tflog.Info(ctx, "Update LB parameters from cluster with ID successfully", map[string]any{"k8s_id": plan.Id.ValueString()})
return diags
}

View File

@@ -0,0 +1,220 @@
package utilities
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"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/cloudapi/k8s"
"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
)
func CreateRequestResourceK8WG(ctx context.Context, plan *models.ResourceK8SWGModel) k8s.WorkersGroupAddRequest {
tflog.Info(ctx, "Start CreateRequestResourceK8WG", map[string]any{"name": plan.Name.ValueString()})
req := k8s.WorkersGroupAddRequest{
K8SID: uint64(plan.K8SID.ValueInt64()),
Name: plan.Name.ValueString(),
}
if !plan.WorkerSEPID.IsNull() {
req.WorkerSEPID = uint64(plan.WorkerSEPID.ValueInt64())
} else {
req.WorkerSEPID = 0
}
if !plan.WorkerSEPPool.IsNull() {
req.WorkerSEPPool = plan.WorkerSEPPool.ValueString()
}
if !plan.Num.IsUnknown() {
req.WorkerNum = uint64(plan.Num.ValueInt64())
} else {
req.WorkerNum = 1
}
if !plan.CPU.IsUnknown() {
req.WorkerCPU = uint64(plan.CPU.ValueInt64())
} else {
req.WorkerCPU = 1
}
if !plan.RAM.IsUnknown() {
req.WorkerRAM = uint64(plan.RAM.ValueInt64())
} else {
req.WorkerRAM = 1024
}
if !plan.Disk.IsUnknown() {
req.WorkerDisk = uint64(plan.Disk.ValueInt64())
} else {
req.WorkerDisk = 0
}
if !plan.Annotations.IsUnknown() {
result := make([]string, 0, len(plan.Annotations.Elements()))
for _, val := range plan.Annotations.Elements() {
result = append(result, strings.Trim(val.String(), "\""))
}
req.Annotations = result
}
if !plan.Labels.IsUnknown() {
result := make([]string, 0, len(plan.Labels.Elements()))
for _, val := range plan.Labels.Elements() {
result = append(result, strings.Trim(val.String(), "\""))
}
req.Labels = result
}
if !plan.Taints.IsUnknown() {
result := make([]string, 0, len(plan.Taints.Elements()))
for _, val := range plan.Taints.Elements() {
result = append(result, strings.Trim(val.String(), "\""))
}
req.Taints = result
}
if !plan.CloudInit.IsNull() {
req.UserData = plan.CloudInit.ValueString()
}
tflog.Info(ctx, "End CreateRequestResourceK8WG", map[string]any{"name": plan.Name.ValueString()})
return req
}
func ResourceK8SWGCreate(ctx context.Context, plan *models.ResourceK8SWGModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Start ResourceK8SWGCreate", map[string]any{"name": plan.Name.ValueString(), "k8s_id": plan.K8SID.ValueInt64()})
diags := diag.Diagnostics{}
// Make request and get response
wgId, err := c.CloudAPI().K8S().WorkersGroupAdd(ctx, CreateRequestResourceK8WG(ctx, plan))
if err != nil {
tflog.Error(ctx, "Error response for create k8s_wg")
diags.AddError("Unable to Create K8SWG", err.Error())
return diags
}
plan.Id = types.StringValue(strconv.Itoa(int(wgId)))
plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850))
wg, k8sId, err := K8SWGResourceCheckPresence(ctx, plan, c)
if err != nil {
diags.AddError("Cannot get info about wg ", err.Error())
return diags
}
tflog.Info(ctx, "End ResourceK8SWGCreate", map[string]any{"k8s_id": k8sId, "k8s_wg": wg.ID})
return diags
}
func K8SWGResourceCheckPresence(ctx context.Context, plan *models.ResourceK8SWGModel, c *decort.DecortClient) (*k8s.ItemK8SGroup, uint64, error) {
tflog.Info(ctx, "Get info about wg with ID", map[string]any{"wg_id": plan.Id.ValueString()})
var wgId int
var k8sId int
var err error
ids := strings.Split(plan.Id.ValueString(), "#")
if len(ids) == 2 {
k8sId, err = strconv.Atoi(ids[0])
if err != nil {
return nil, 0, err
}
wgId, err = strconv.Atoi(ids[1])
if err != nil {
return nil, 0, err
}
} else {
wgId, err = strconv.Atoi(plan.Id.ValueString())
if err != nil {
return nil, 0, err
}
k8sId = int(plan.K8SID.ValueInt64())
}
cluster, err := c.CloudAPI().K8S().Get(ctx, k8s.GetRequest{K8SID: uint64(k8sId)})
if err != nil {
return nil, 0, fmt.Errorf("cannot get info about cluster with error: %w", err)
}
for _, wg := range cluster.K8SGroups.Workers {
if wg.ID == uint64(wgId) {
tflog.Info(ctx, "Getting info about wg successfully", map[string]any{"wg_id": plan.Id.ValueString()})
return &wg, cluster.ID, nil
}
}
tflog.Error(ctx, fmt.Sprintf("Getting info about wg end with error - %s", err.Error()))
return nil, 0, fmt.Errorf("not found wg with id: %d in k8s cluster: %d", wgId, cluster.ID)
}
func K8SWGUpdateCloudInit(ctx context.Context, plan, state *models.ResourceK8SWGModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Update cloud init in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
diags := diag.Diagnostics{}
req := k8s.UpdateWorkerNodesMetaDataRequest{
K8SID: uint64(state.K8SID.ValueInt64()),
WorkersGroupID: uint64(state.WorkerGroupId.ValueInt64()),
UserData: plan.CloudInit.ValueString(),
}
_, err := c.CloudAPI().K8S().UpdateWorkerNodesMetaData(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot update cloud init in wg with id: %d", state.WorkerGroupId.ValueInt64()), err.Error())
return diags
}
tflog.Info(ctx, "Update cloud init successfully in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
return diags
}
func K8SWGUpdateNumWorkers(ctx context.Context, plan, state *models.ResourceK8SWGModel, c *decort.DecortClient) diag.Diagnostics {
tflog.Info(ctx, "Update num workers in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
diags := diag.Diagnostics{}
wg, k8sId, err := K8SWGResourceCheckPresence(ctx, plan, c)
if err != nil {
diags.AddError("Cannot get info about wg ", err.Error())
return diags
}
if newNum := plan.Num.ValueInt64(); uint64(newNum) > wg.Num {
req := k8s.WorkerAddRequest{
K8SID: k8sId,
WorkersGroupID: wg.ID,
Num: uint64(newNum) - wg.Num,
}
tflog.Info(ctx, "Add workers in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
_, err := c.CloudAPI().K8S().WorkerAdd(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot add workers in wg with id: %d", state.WorkerGroupId.ValueInt64()), err.Error())
return diags
}
tflog.Info(ctx, "Add workers successfully in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
} else {
for i := int64(wg.Num) - 1; i >= newNum; i-- {
req := k8s.DeleteWorkerFromGroupRequest{
K8SID: k8sId,
WorkersGroupID: wg.ID,
WorkerID: wg.DetailedInfo[i].ID,
}
tflog.Info(ctx, "Start delete worker in wg with id", map[string]any{"worker_id": wg.DetailedInfo[i].ID, "wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
_, err := c.CloudAPI().K8S().DeleteWorkerFromGroup(ctx, req)
if err != nil {
diags.AddError(fmt.Sprintf("Cannot delete worker from wg with id: %d", state.WorkerGroupId.ValueInt64()), err.Error())
return diags
}
tflog.Info(ctx, "End delete worker successfully in wg with id", map[string]any{"worker_id": wg.DetailedInfo[i].ID, "wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
}
}
tflog.Info(ctx, "Update num workers successfully in wg with id", map[string]any{"wg_id": state.WorkerGroupId.ValueInt64(), "k8s_id": state.K8SID.ValueInt64()})
return diags
}