This commit is contained in:
KasimBaybikov
2023-05-04 10:08:25 +03:00
parent 9bad8a6947
commit 8ca233dd32
288 changed files with 6645 additions and 11464 deletions

View File

@@ -119,13 +119,13 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeString,
Computed: true,
},
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
// "meta": {
// Type: schema.TypeList,
// Computed: true,
// Elem: &schema.Schema{
// Type: schema.TypeString,
// },
// },
"acl": {
Type: schema.TypeList,
Computed: true,
@@ -234,10 +234,10 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeBool,
Computed: true,
},
"service_account": {
Type: schema.TypeBool,
Computed: true,
},
// "service_account": {
// Type: schema.TypeBool,
// Computed: true,
// },
"status": {
Type: schema.TypeString,
Computed: true,

View File

@@ -218,13 +218,13 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeString,
Computed: true,
},
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
// "meta": {
// Type: schema.TypeList,
// Computed: true,
// Elem: &schema.Schema{
// Type: schema.TypeString,
// },
// },
"acl": {
Type: schema.TypeList,
Computed: true,
@@ -293,10 +293,10 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"service_account": {
Type: schema.TypeBool,
Computed: true,
},
// "service_account": {
// Type: schema.TypeBool,
// Computed: true,
// },
"status": {
Type: schema.TypeString,
Computed: true,

View File

@@ -33,12 +33,11 @@ package account
import (
"context"
"strconv"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func dataSourceAccountRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -47,51 +46,12 @@ func dataSourceAccountRead(ctx context.Context, d *schema.ResourceData, m interf
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("dc_location", acc.DCLocation)
d.Set("resources", flattenAccResources(acc.Resources))
d.Set("ckey", acc.CKey)
d.Set("meta", flattens.FlattenMeta(acc.Meta))
d.Set("acl", flattenAccAcl(acc.Acl))
d.Set("company", acc.Company)
d.Set("companyurl", acc.CompanyUrl)
d.Set("created_by", acc.CreatedBy)
d.Set("created_time", acc.CreatedTime)
d.Set("deactivation_time", acc.DeactiovationTime)
d.Set("deleted_by", acc.DeletedBy)
d.Set("deleted_time", acc.DeletedTime)
d.Set("displayname", acc.DisplayName)
d.Set("guid", acc.GUID)
d.Set("account_id", acc.ID)
d.Set("account_name", acc.Name)
d.Set("resource_limits", flattenRgResourceLimits(acc.ResourceLimits))
d.Set("send_access_emails", acc.SendAccessEmails)
d.Set("service_account", acc.ServiceAccount)
d.Set("status", acc.Status)
d.Set("updated_time", acc.UpdatedTime)
d.Set("version", acc.Version)
d.Set("vins", acc.Vins)
d.SetId(strconv.FormatUint(acc.ID, 10))
flattenDataAccount(d, acc)
return nil
}
func flattenAccAcl(acls []AccountAclRecord) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acls := range acls {
temp := map[string]interface{}{
"explicit": acls.IsExplicit,
"guid": acls.Guid,
"right": acls.Rights,
"status": acls.Status,
"type": acls.Type,
"user_group_id": acls.UgroupID,
}
res = append(res, temp)
}
return res
}
func DataSourceAccount() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,

View File

@@ -40,22 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountAuditsList(aal AccountAuditsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, aa := range aal {
temp := map[string]interface{}{
"call": aa.Call,
"responsetime": aa.ResponseTime,
"statuscode": aa.StatusCode,
"timestamp": aa.Timestamp,
"user": aa.User,
}
res = append(res, temp)
}
return res
}
func dataSourceAccountAuditsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountAuditsList, err := utilityAccountAuditsListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -40,37 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountComputesList(acl AccountComputesList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acc := range acl {
temp := map[string]interface{}{
"account_id": acc.AccountId,
"account_name": acc.AccountName,
"cpus": acc.CPUs,
"created_by": acc.CreatedBy,
"created_time": acc.CreatedTime,
"deleted_by": acc.DeletedBy,
"deleted_time": acc.DeletedTime,
"compute_id": acc.ComputeId,
"compute_name": acc.ComputeName,
"ram": acc.RAM,
"registered": acc.Registered,
"rg_id": acc.RgId,
"rg_name": acc.RgName,
"status": acc.Status,
"tech_status": acc.TechStatus,
"total_disks_size": acc.TotalDisksSize,
"updated_by": acc.UpdatedBy,
"updated_time": acc.UpdatedTime,
"user_managed": acc.UserManaged,
"vins_connected": acc.VinsConnected,
}
res = append(res, temp)
}
return res
}
func dataSourceAccountComputesListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountComputesList, err := utilityAccountComputesListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -39,23 +39,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountDisksList(adl AccountDisksList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, ad := range adl {
temp := map[string]interface{}{
"disk_id": ad.ID,
"disk_name": ad.Name,
"pool_name": ad.Pool,
"sep_id": ad.SepId,
"size_max": ad.SizeMax,
"type": ad.Type,
}
res = append(res, temp)
}
return res
}
func dataSourceAccountDisksListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountDisksList, err := utilityAccountDisksListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -40,38 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountFlipGroupsList(afgl AccountFlipGroupsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, afg := range afgl {
temp := map[string]interface{}{
"account_id": afg.AccountId,
"client_type": afg.ClientType,
"conn_type": afg.ConnType,
"created_by": afg.CreatedBy,
"created_time": afg.CreatedTime,
"default_gw": afg.DefaultGW,
"deleted_by": afg.DeletedBy,
"deleted_time": afg.DeletedTime,
"desc": afg.Desc,
"gid": afg.GID,
"guid": afg.GUID,
"fg_id": afg.ID,
"ip": afg.IP,
"milestones": afg.Milestones,
"fg_name": afg.Name,
"net_id": afg.NetID,
"net_type": afg.NetType,
"netmask": afg.NetMask,
"status": afg.Status,
"updated_by": afg.UpdatedBy,
"updated_time": afg.UpdatedTime,
}
res = append(res, temp)
}
return res
}
func dataSourceAccountFlipGroupsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountFlipGroupsList, err := utilityAccountFlipGroupsListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -38,83 +38,8 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenRgAcl(rgAcls []AccountAclRecord) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rgAcl := range rgAcls {
temp := map[string]interface{}{
"explicit": rgAcl.IsExplicit,
"guid": rgAcl.Guid,
"right": rgAcl.Rights,
"status": rgAcl.Status,
"type": rgAcl.Type,
"user_group_id": rgAcl.UgroupID,
}
res = append(res, temp)
}
return res
}
func flattenAccountList(al AccountList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acc := range al {
temp := map[string]interface{}{
"dc_location": acc.DCLocation,
"ckey": acc.CKey,
"meta": flattens.FlattenMeta(acc.Meta),
"acl": flattenRgAcl(acc.Acl),
"company": acc.Company,
"companyurl": acc.CompanyUrl,
"created_by": acc.CreatedBy,
"created_time": acc.CreatedTime,
"deactivation_time": acc.DeactiovationTime,
"deleted_by": acc.DeletedBy,
"deleted_time": acc.DeletedTime,
"displayname": acc.DisplayName,
"guid": acc.GUID,
"account_id": acc.ID,
"account_name": acc.Name,
"resource_limits": flattenRgResourceLimits(acc.ResourceLimits),
"send_access_emails": acc.SendAccessEmails,
"service_account": acc.ServiceAccount,
"status": acc.Status,
"updated_time": acc.UpdatedTime,
"version": acc.Version,
"vins": acc.Vins,
}
res = append(res, temp)
}
return res
}
func flattenRgResourceLimits(rl ResourceLimits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cu_c": rl.CUC,
"cu_d": rl.CUD,
"cu_i": rl.CUI,
"cu_m": rl.CUM,
"cu_np": rl.CUNP,
"gpu_units": rl.GpuUnits,
}
res = append(res, temp)
return res
}
func dataSourceAccountListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountList, err := utilityAccountListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -40,75 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountRGList(argl AccountRGList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, arg := range argl {
temp := map[string]interface{}{
"computes": flattenAccRGComputes(arg.Computes),
"resources": flattenAccRGResources(arg.Resources),
"created_by": arg.CreatedBy,
"created_time": arg.CreatedTime,
"deleted_by": arg.DeletedBy,
"deleted_time": arg.DeletedTime,
"rg_id": arg.RGID,
"milestones": arg.Milestones,
"rg_name": arg.RGName,
"status": arg.Status,
"updated_by": arg.UpdatedBy,
"updated_time": arg.UpdatedTime,
"vinses": arg.Vinses,
}
res = append(res, temp)
}
return res
}
func flattenAccRGComputes(argc AccountRGComputes) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"started": argc.Started,
"stopped": argc.Stopped,
}
res = append(res, temp)
return res
}
func flattenAccRGResources(argr AccountRGResources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"consumed": flattenAccResource(argr.Consumed),
"limits": flattenAccResource(argr.Limits),
"reserved": flattenAccResource(argr.Reserved),
}
res = append(res, temp)
return res
}
func flattenAccResources(r Resources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"current": flattenAccResource(r.Current),
"reserved": flattenAccResource(r.Reserved),
}
res = append(res, temp)
return res
}
func flattenAccResource(r Resource) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": r.CPU,
"disksize": r.Disksize,
"extips": r.Extips,
"exttraffic": r.Exttraffic,
"gpu": r.GPU,
"ram": r.RAM,
}
res = append(res, temp)
return res
}
func dataSourceAccountRGListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountRGList, err := utilityAccountRGListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -40,34 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenAccountVinsList(avl AccountVinsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, av := range avl {
temp := map[string]interface{}{
"account_id": av.AccountId,
"account_name": av.AccountName,
"computes": av.Computes,
"created_by": av.CreatedBy,
"created_time": av.CreatedTime,
"deleted_by": av.DeletedBy,
"deleted_time": av.DeletedTime,
"external_ip": av.ExternalIP,
"vin_id": av.ID,
"vin_name": av.Name,
"network": av.Network,
"pri_vnf_dev_id": av.PriVnfDevId,
"rg_id": av.RgId,
"rg_name": av.RgName,
"status": av.Status,
"updated_by": av.UpdatedBy,
"updated_time": av.UpdatedTime,
}
res = append(res, temp)
}
return res
}
func dataSourceAccountVinsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
accountVinsList, err := utilityAccountVinsListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -0,0 +1,363 @@
package account
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenResourceAccount(d *schema.ResourceData, acc *account.RecordAccount) {
d.Set("dc_location", acc.DCLocation)
d.Set("resources", flattenAccResources(acc.Resources))
d.Set("ckey", acc.CKey)
d.Set("acl", flattenAccAcl(acc.ACL))
d.Set("company", acc.Company)
d.Set("companyurl", acc.CompanyURL)
d.Set("created_by", acc.CreatedBy)
d.Set("created_time", acc.CreatedTime)
d.Set("deactivation_time", acc.DeactivationTime)
d.Set("deleted_by", acc.DeletedBy)
d.Set("deleted_time", acc.DeletedTime)
d.Set("displayname", acc.DisplayName)
d.Set("guid", acc.GUID)
d.Set("account_id", acc.ID)
d.Set("account_name", acc.Name)
d.Set("resource_limits", flattenRgResourceLimits(acc.ResourceLimits))
d.Set("send_access_emails", acc.SendAccessEmails)
d.Set("status", acc.Status)
d.Set("updated_time", acc.UpdatedTime)
d.Set("version", acc.Version)
d.Set("vins", acc.VINS)
}
func flattenDataAccount(d *schema.ResourceData, acc *account.RecordAccount) {
d.Set("dc_location", acc.DCLocation)
d.Set("resources", flattenAccResources(acc.Resources))
d.Set("ckey", acc.CKey)
// d.Set("meta", flattens.FlattenMeta(acc.))
d.Set("acl", flattenAccAcl(acc.ACL))
d.Set("company", acc.Company)
d.Set("companyurl", acc.CompanyURL)
d.Set("created_by", acc.CreatedBy)
d.Set("created_time", acc.CreatedTime)
d.Set("deactivation_time", acc.DeactivationTime)
d.Set("deleted_by", acc.DeletedBy)
d.Set("deleted_time", acc.DeletedTime)
d.Set("displayname", acc.DisplayName)
d.Set("guid", acc.GUID)
d.Set("account_id", acc.ID)
d.Set("account_name", acc.Name)
d.Set("resource_limits", flattenRgResourceLimits(acc.ResourceLimits))
d.Set("send_access_emails", acc.SendAccessEmails)
// d.Set("service_account", acc.ServiceAccount)
d.Set("status", acc.Status)
d.Set("updated_time", acc.UpdatedTime)
d.Set("version", acc.Version)
d.Set("vins", acc.VINS)
}
func flattenAccountRGList(argl account.ListRG) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, arg := range argl {
temp := map[string]interface{}{
"computes": flattenAccRGComputes(arg.Computes),
"resources": flattenAccRGResources(arg.Resources),
"created_by": arg.CreatedBy,
"created_time": arg.CreatedTime,
"deleted_by": arg.DeletedBy,
"deleted_time": arg.DeletedTime,
"rg_id": arg.ID,
"milestones": arg.Milestones,
"rg_name": arg.Name,
"status": arg.Status,
"updated_by": arg.UpdatedBy,
"updated_time": arg.UpdatedTime,
"vinses": arg.VINSes,
}
res = append(res, temp)
}
return res
}
func flattenAccRGComputes(argc account.Computes) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"started": argc.Started,
"stopped": argc.Stopped,
}
res = append(res, temp)
return res
}
func flattenAccRGResources(argr account.RGResuorces) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"consumed": flattenAccConsumed(argr.Consumed),
"limits": flattenAccLimits(argr.Limits),
"reserved": flattenAccResource(argr.Reserved),
}
res = append(res, temp)
return res
}
func flattenAccResources(r account.RecordResources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"current": flattenAccResource(r.Current),
"reserved": flattenAccResource(r.Reserved),
}
res = append(res, temp)
return res
}
func flattenAccConsumed(c account.Consumed) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": c.CPU,
"disksize": c.DiskSize,
"extips": c.ExtIPs,
"exttraffic": c.ExtTraffic,
"gpu": c.GPU,
"ram": c.RAM,
}
res = append(res, temp)
return res
}
func flattenAccLimits(l account.Limits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": l.CPU,
"disksize": l.DiskSize,
"extips": l.ExtIPs,
"exttraffic": l.ExtTraffic,
"gpu": l.GPU,
"ram": l.RAM,
}
res = append(res, temp)
return res
}
func flattenAccResource(r account.Resource) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": r.CPU,
"disksize": r.DiskSize,
"extips": r.ExtIPs,
"exttraffic": r.ExtTraffic,
"gpu": r.GPU,
"ram": r.RAM,
}
res = append(res, temp)
return res
}
func flattenAccAcl(acls []account.ACL) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acls := range acls {
temp := map[string]interface{}{
"explicit": acls.Explicit,
"guid": acls.GUID,
"right": acls.Right,
"status": acls.Status,
"type": acls.Type,
"user_group_id": acls.UserGroupID,
}
res = append(res, temp)
}
return res
}
func flattenRgResourceLimits(rl account.ResourceLimits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cu_c": rl.CuC,
"cu_d": rl.CuD,
"cu_i": rl.CuI,
"cu_m": rl.CuM,
"cu_np": rl.CuNP,
"gpu_units": rl.GPUUnits,
}
res = append(res, temp)
return res
}
func flattenRgAcl(rgAcls []account.ACL) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rgAcl := range rgAcls {
temp := map[string]interface{}{
"explicit": rgAcl.Explicit,
"guid": rgAcl.GUID,
"right": rgAcl.Right,
"status": rgAcl.Status,
"type": rgAcl.Type,
"user_group_id": rgAcl.UserGroupID,
}
res = append(res, temp)
}
return res
}
func flattenAccountList(al account.ListAccounts) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acc := range al {
temp := map[string]interface{}{
"dc_location": acc.DCLocation,
"ckey": acc.CKey,
"meta": flattens.FlattenMeta(acc.Meta),
"acl": flattenRgAcl(acc.ACL),
"company": acc.Company,
"companyurl": acc.CompanyURL,
"created_by": acc.CreatedBy,
"created_time": acc.CreatedTime,
"deactivation_time": acc.DeactivationTime,
"deleted_by": acc.DeletedBy,
"deleted_time": acc.DeletedTime,
"displayname": acc.DisplayName,
"guid": acc.GUID,
"account_id": acc.ID,
"account_name": acc.Name,
"resource_limits": flattenRgResourceLimits(acc.ResourceLimits),
"send_access_emails": acc.SendAccessEmails,
// "service_account": acc.ServiceAccount,
"status": acc.Status,
"updated_time": acc.UpdatedTime,
"version": acc.Version,
"vins": acc.VINS,
}
res = append(res, temp)
}
return res
}
func flattenAccountAuditsList(aal account.ListAudits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, aa := range aal {
temp := map[string]interface{}{
"call": aa.Call,
"responsetime": aa.ResponseTime,
"statuscode": aa.StatusCode,
"timestamp": aa.Timestamp,
"user": aa.User,
}
res = append(res, temp)
}
return res
}
func flattenAccountComputesList(acl account.ListComputes) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acc := range acl {
temp := map[string]interface{}{
"account_id": acc.AccountID,
"account_name": acc.AccountName,
"cpus": acc.CPUs,
"created_by": acc.CreatedBy,
"created_time": acc.CreatedTime,
"deleted_by": acc.DeletedBy,
"deleted_time": acc.DeletedTime,
"compute_id": acc.ID,
"compute_name": acc.Name,
"ram": acc.RAM,
"registered": acc.Registered,
"rg_id": acc.RGID,
"rg_name": acc.RgName,
"status": acc.Status,
"tech_status": acc.TechStatus,
"total_disks_size": acc.TotalDisksSize,
"updated_by": acc.UpdatedBy,
"updated_time": acc.UpdatedTime,
"user_managed": acc.UserManaged,
"vins_connected": acc.VINSConnected,
}
res = append(res, temp)
}
return res
}
func flattenAccountDisksList(adl account.ListDisks) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, ad := range adl {
temp := map[string]interface{}{
"disk_id": ad.ID,
"disk_name": ad.Name,
"pool_name": ad.Pool,
"sep_id": ad.SepID,
"size_max": ad.SizeMax,
"type": ad.Type,
}
res = append(res, temp)
}
return res
}
func flattenAccountFlipGroupsList(afgl account.ListFLIPGroups) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, afg := range afgl {
temp := map[string]interface{}{
"account_id": afg.AccountID,
"client_type": afg.ClientType,
"conn_type": afg.ConnType,
"created_by": afg.CreatedBy,
"created_time": afg.CreatedTime,
"default_gw": afg.DefaultGW,
"deleted_by": afg.DeletedBy,
"deleted_time": afg.DeletedTime,
"desc": afg.Description,
"gid": afg.GID,
"guid": afg.GUID,
"fg_id": afg.ID,
"ip": afg.IP,
"milestones": afg.Milestones,
"fg_name": afg.Name,
"net_id": afg.NetID,
"net_type": afg.NetType,
"netmask": afg.Netmask,
"status": afg.Status,
"updated_by": afg.UpdatedBy,
"updated_time": afg.UpdatedTime,
}
res = append(res, temp)
}
return res
}
func flattenAccountVinsList(avl account.ListVINS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, av := range avl {
temp := map[string]interface{}{
"account_id": av.AccountID,
"account_name": av.AccountName,
"computes": av.Computes,
"created_by": av.CreatedBy,
"created_time": av.CreatedTime,
"deleted_by": av.DeletedBy,
"deleted_time": av.DeletedTime,
"external_ip": av.ExternalIP,
"vin_id": av.ID,
"vin_name": av.Name,
"network": av.Network,
"pri_vnf_dev_id": av.PriVNFDevID,
"rg_id": av.RGID,
"rg_name": av.RGName,
"status": av.Status,
"updated_by": av.UpdatedBy,
"updated_time": av.UpdatedTime,
}
res = append(res, temp)
}
return res
}

View File

@@ -33,95 +33,94 @@ package account
import (
"context"
"net/url"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
log "github.com/sirupsen/logrus"
)
func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceAccountCreate")
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := account.CreateRequest{}
urlValues.Add("name", d.Get("account_name").(string))
urlValues.Add("username", d.Get("username").(string))
req.Name = d.Get("account_name").(string)
req.Username = d.Get("username").(string)
if emailaddress, ok := d.GetOk("emailaddress"); ok {
urlValues.Add("emailaddress", emailaddress.(string))
req.EmailAddress = emailaddress.(string)
}
if sendAccessEmails, ok := d.GetOk("send_access_emails"); ok {
urlValues.Add("sendAccessEmails", strconv.FormatBool(sendAccessEmails.(bool)))
req.SendAccessEmails = sendAccessEmails.(bool)
}
if resLimits, ok := d.GetOk("resource_limits"); ok {
resLimit := resLimits.([]interface{})[0]
resLimitConv := resLimit.(map[string]interface{})
if resLimitConv["cu_m"] != nil {
maxMemCap := int(resLimitConv["cu_m"].(float64))
maxMemCap := int64(resLimitConv["cu_m"].(float64))
if maxMemCap == 0 {
urlValues.Add("maxMemoryCapacity", strconv.Itoa(-1))
req.MaxMemoryCapacity = -1
} else {
urlValues.Add("maxMemoryCapacity", strconv.Itoa(maxMemCap))
req.MaxMemoryCapacity = maxMemCap
}
}
if resLimitConv["cu_d"] != nil {
maxDiskCap := int(resLimitConv["cu_d"].(float64))
maxDiskCap := int64(resLimitConv["cu_d"].(float64))
if maxDiskCap == 0 {
urlValues.Add("maxVDiskCapacity", strconv.Itoa(-1))
req.MaxVDiskCapacity = -1
} else {
urlValues.Add("maxVDiskCapacity", strconv.Itoa(maxDiskCap))
req.MaxVDiskCapacity = maxDiskCap
}
}
if resLimitConv["cu_c"] != nil {
maxCPUCap := int(resLimitConv["cu_c"].(float64))
maxCPUCap := int64(resLimitConv["cu_c"].(float64))
if maxCPUCap == 0 {
urlValues.Add("maxCPUCapacity", strconv.Itoa(-1))
req.MaxCPUCapacity = -1
} else {
urlValues.Add("maxCPUCapacity", strconv.Itoa(maxCPUCap))
req.MaxCPUCapacity = maxCPUCap
}
}
if resLimitConv["cu_i"] != nil {
maxNumPublicIP := int(resLimitConv["cu_i"].(float64))
maxNumPublicIP := int64(resLimitConv["cu_i"].(float64))
if maxNumPublicIP == 0 {
urlValues.Add("maxNumPublicIP", strconv.Itoa(-1))
req.MaxNumPublicIP = -1
} else {
urlValues.Add("maxNumPublicIP", strconv.Itoa(maxNumPublicIP))
req.MaxNumPublicIP = maxNumPublicIP
}
}
if resLimitConv["cu_np"] != nil {
maxNP := int(resLimitConv["cu_np"].(float64))
maxNP := int64(resLimitConv["cu_np"].(float64))
if maxNP == 0 {
urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(-1))
req.MaxNetworkPeerTransfer = -1
} else {
urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(maxNP))
req.MaxNetworkPeerTransfer = maxNP
}
}
if resLimitConv["gpu_units"] != nil {
gpuUnits := int(resLimitConv["gpu_units"].(float64))
gpuUnits := int64(resLimitConv["gpu_units"].(float64))
if gpuUnits == 0 {
urlValues.Add("gpu_units", strconv.Itoa(-1))
req.GPUUnits = -1
} else {
urlValues.Add("gpu_units", strconv.Itoa(gpuUnits))
req.GPUUnits = gpuUnits
}
}
}
accountId, err := c.DecortAPICall(ctx, "POST", accountCreateAPI, urlValues)
accountId, err := c.CloudBroker().Account().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(accountId)
d.SetId(strconv.FormatUint(accountId, 10))
d.Set("account_id", accountId)
diagnostics := resourceAccountRead(ctx, d, m)
@@ -130,19 +129,24 @@ func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interf
}
if enable, ok := d.GetOk("enable"); ok {
api := accountDisableAPI
enable := enable.(bool)
if enable {
api = accountEnableAPI
req := account.EnableRequest{
AccountID: accountId,
}
_, err := c.CloudBroker().Account().Enable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
} else {
req := account.DisableRequest{
AccountID: accountId,
}
_, err := c.CloudBroker().Account().Disable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if users, ok := d.GetOk("users"); ok {
@@ -151,15 +155,16 @@ func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interf
if len(addedUsers) > 0 {
for _, user := range addedUsers {
userConv := user.(map[string]interface{})
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("userId", userConv["user_id"].(string))
urlValues.Add("accesstype", strings.ToUpper(userConv["access_type"].(string)))
_, err := c.DecortAPICall(ctx, "POST", accountAddUserAPI, urlValues)
req := account.AddUserRequest{
AccountID: accountId,
Username: userConv["user_id"].(string),
AccessType: userConv["access_type"].(string),
}
_, err := c.CloudBroker().Account().AddUser(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
}
@@ -171,34 +176,12 @@ func resourceAccountRead(ctx context.Context, d *schema.ResourceData, m interfac
log.Debugf("resourceAccountRead")
acc, err := utilityAccountCheckPresence(ctx, d, m)
if acc == nil {
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
d.Set("dc_location", acc.DCLocation)
d.Set("resources", flattenAccResources(acc.Resources))
d.Set("ckey", acc.CKey)
d.Set("meta", flattens.FlattenMeta(acc.Meta))
d.Set("acl", flattenAccAcl(acc.Acl))
d.Set("company", acc.Company)
d.Set("companyurl", acc.CompanyUrl)
d.Set("created_by", acc.CreatedBy)
d.Set("created_time", acc.CreatedTime)
d.Set("deactivation_time", acc.DeactiovationTime)
d.Set("deleted_by", acc.DeletedBy)
d.Set("deleted_time", acc.DeletedTime)
d.Set("displayname", acc.DisplayName)
d.Set("guid", acc.GUID)
d.Set("account_id", acc.ID)
d.Set("account_name", acc.Name)
d.Set("resource_limits", flattenRgResourceLimits(acc.ResourceLimits))
d.Set("send_access_emails", acc.SendAccessEmails)
d.Set("service_account", acc.ServiceAccount)
d.Set("status", acc.Status)
d.Set("updated_time", acc.UpdatedTime)
d.Set("version", acc.Version)
d.Set("vins", acc.Vins)
flattenResourceAccount(d, acc)
return nil
}
@@ -206,58 +189,65 @@ func resourceAccountRead(ctx context.Context, d *schema.ResourceData, m interfac
func resourceAccountDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceAccountDelete")
account, err := utilityAccountCheckPresence(ctx, d, m)
if account == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
_, err = c.DecortAPICall(ctx, "POST", accountDeleteAPI, urlValues)
accountData, err := utilityAccountCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := account.DeleteRequest{
AccountID: accountData.ID,
Permanently: d.Get("permanently").(bool),
}
_, err = c.CloudBroker().Account().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceAccountEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceAccountEdit")
func resourceAccountUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceAccountUpdate")
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if d.HasChange("enable") {
api := accountDisableAPI
enable := d.Get("enable").(bool)
if enable {
api = accountEnableAPI
}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
acc, err := utilityAccountCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
if d.HasChange("account_name") {
urlValues.Add("name", d.Get("account_name").(string))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", accountUpdateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
if d.HasChange("enable") {
enable := d.Get("enable").(bool)
if enable {
req := account.EnableRequest{
AccountID: acc.ID,
}
_, err := c.CloudBroker().Account().Enable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
} else {
req := account.DisableRequest{
AccountID: acc.ID,
}
_, err := c.CloudBroker().Account().Disable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
urlValues = &url.Values{}
updateReq := account.UpdateRequest{AccountID: acc.ID}
hasChange := false
if d.HasChange("account_name") {
updateReq.Name = d.Get("account_name").(string)
hasChange = true
}
if d.HasChange("resource_limits") {
resLimit := d.Get("resource_limits").([]interface{})[0]
@@ -266,85 +256,81 @@ func resourceAccountEdit(ctx context.Context, d *schema.ResourceData, m interfac
if resLimitConv["cu_m"] != nil {
maxMemCap := int(resLimitConv["cu_m"].(float64))
if maxMemCap == 0 {
urlValues.Add("maxMemoryCapacity", strconv.Itoa(-1))
updateReq.MaxMemoryCapacity = -1
} else {
urlValues.Add("maxMemoryCapacity", strconv.Itoa(maxMemCap))
updateReq.MaxMemoryCapacity = int64(maxMemCap)
}
}
if resLimitConv["cu_d"] != nil {
maxDiskCap := int(resLimitConv["cu_d"].(float64))
if maxDiskCap == 0 {
urlValues.Add("maxVDiskCapacity", strconv.Itoa(-1))
updateReq.MaxVDiskCapacity = -1
} else {
urlValues.Add("maxVDiskCapacity", strconv.Itoa(maxDiskCap))
updateReq.MaxVDiskCapacity = int64(maxDiskCap)
}
}
if resLimitConv["cu_c"] != nil {
maxCPUCap := int(resLimitConv["cu_c"].(float64))
if maxCPUCap == 0 {
urlValues.Add("maxCPUCapacity", strconv.Itoa(-1))
updateReq.MaxCPUCapacity = -1
} else {
urlValues.Add("maxCPUCapacity", strconv.Itoa(maxCPUCap))
updateReq.MaxCPUCapacity = int64(maxCPUCap)
}
}
if resLimitConv["cu_i"] != nil {
maxNumPublicIP := int(resLimitConv["cu_i"].(float64))
if maxNumPublicIP == 0 {
urlValues.Add("maxNumPublicIP", strconv.Itoa(-1))
updateReq.MaxNumPublicIP = -1
} else {
urlValues.Add("maxNumPublicIP", strconv.Itoa(maxNumPublicIP))
updateReq.MaxNumPublicIP = int64(maxNumPublicIP)
}
}
if resLimitConv["cu_np"] != nil {
maxNP := int(resLimitConv["cu_np"].(float64))
if maxNP == 0 {
urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(-1))
updateReq.MaxNetworkPeerTransfer = -1
} else {
urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(maxNP))
updateReq.MaxNetworkPeerTransfer = int64(maxNP)
}
}
if resLimitConv["gpu_units"] != nil {
gpuUnits := int(resLimitConv["gpu_units"].(float64))
if gpuUnits == 0 {
urlValues.Add("gpu_units", strconv.Itoa(-1))
updateReq.GPUUnits = -1
} else {
urlValues.Add("gpu_units", strconv.Itoa(gpuUnits))
updateReq.GPUUnits = int64(gpuUnits)
}
}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", accountUpdateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
hasChange = true
}
if d.HasChange("send_access_emails") {
urlValues.Add("sendAccessEmails", strconv.FormatBool(d.Get("send_access_emails").(bool)))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", accountUpdateAPI, urlValues)
updateReq.SendAccessEmails = d.Get("send_access_emails").(bool)
hasChange = true
}
if hasChange {
_, err := c.CloudBroker().Account().Update(ctx, updateReq)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("restore") {
restore := d.Get("restore").(bool)
if restore {
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", accountRestoreAPI, urlValues)
req := account.RestoreRequest{
AccountID: acc.ID,
}
_, err := c.CloudBroker().Account().Restore(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
@@ -374,45 +360,48 @@ func resourceAccountEdit(ctx context.Context, d *schema.ResourceData, m interfac
if len(deletedUsers) > 0 {
for _, user := range deletedUsers {
userConv := user.(map[string]interface{})
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("userId", userConv["user_id"].(string))
urlValues.Add("recursivedelete", strconv.FormatBool(userConv["recursive_delete"].(bool)))
_, err := c.DecortAPICall(ctx, "POST", accountDeleteUserAPI, urlValues)
req := account.DeleteUserRequest{
AccountID: acc.ID,
UserName: userConv["user_id"].(string),
RecursiveDelete: userConv["recursive_delete"].(bool),
}
_, err := c.CloudBroker().Account().DeleteUser(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
if len(addedUsers) > 0 {
for _, user := range addedUsers {
userConv := user.(map[string]interface{})
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("userId", userConv["user_id"].(string))
urlValues.Add("accesstype", strings.ToUpper(userConv["access_type"].(string)))
_, err := c.DecortAPICall(ctx, "POST", accountAddUserAPI, urlValues)
req := account.AddUserRequest{
AccountID: acc.ID,
Username: userConv["user_id"].(string),
AccessType: strings.ToUpper(userConv["access_type"].(string)),
}
_, err := c.CloudBroker().Account().AddUser(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
if len(updatedUsers) > 0 {
for _, user := range updatedUsers {
userConv := user.(map[string]interface{})
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("userId", userConv["user_id"].(string))
urlValues.Add("accesstype", strings.ToUpper(userConv["access_type"].(string)))
_, err := c.DecortAPICall(ctx, "POST", accountUpdateUserAPI, urlValues)
req := account.UpdateUserRequest{
AccountID: acc.ID,
UserID: userConv["user_id"].(string),
AccessType: strings.ToUpper(userConv["access_type"].(string)),
}
_, err := c.CloudBroker().Account().UpdateUser(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
@@ -451,7 +440,7 @@ func ResourceAccount() *schema.Resource {
CreateContext: resourceAccountCreate,
ReadContext: resourceAccountRead,
UpdateContext: resourceAccountEdit,
UpdateContext: resourceAccountUpdate,
DeleteContext: resourceAccountDelete,
Importer: &schema.ResourceImporter{

View File

@@ -33,34 +33,28 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*AccountWithResources, error) {
account := &AccountWithResources{}
func utilityAccountCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*account.RecordAccount, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := account.GetRequest{}
if (strconv.Itoa(d.Get("account_id").(int))) != "0" {
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
req.AccountID = uint64(d.Get("account_id").(int))
} else {
urlValues.Add("accountId", d.Id())
id, _ := strconv.ParseUint(d.Id(), 10, 64)
req.AccountID = id
}
log.Debugf("utilityAccountCheckPresence: load account")
accountRaw, err := c.DecortAPICall(ctx, "POST", accountGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(accountRaw), &account)
account, err := c.CloudBroker().Account().Get(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountAuditsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountAuditsList, error) {
accountAuditsList := AccountAuditsList{}
func utilityAccountAuditsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListAudits, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountAuditsListCheckPresence: load account list")
accountAuditsListRaw, err := c.DecortAPICall(ctx, "POST", accountAuditsAPI, urlValues)
if err != nil {
return nil, err
req := account.AuditsRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountAuditsListRaw), &accountAuditsList)
log.Debugf("utilityAccountAuditsListCheckPresence: load account list")
accountAuditsList, err := c.CloudBroker().Account().Audits(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountComputesListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountComputesList, error) {
accountComputesList := AccountComputesList{}
func utilityAccountComputesListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListComputes, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountComputesListCheckPresence: load account list")
accountComputesListRaw, err := c.DecortAPICall(ctx, "POST", accountListComputesAPI, urlValues)
if err != nil {
return nil, err
req := account.ListComputesRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountComputesListRaw), &accountComputesList)
log.Debugf("utilityAccountComputesListCheckPresence: load account list")
accountComputesList, err := c.CloudBroker().Account().ListComputes(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,35 +33,27 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountDeletedListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountList, error) {
accountDeletedList := AccountList{}
func utilityAccountDeletedListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListAccounts, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := account.ListDeletedRequest{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilityAccountDeletedListCheckPresence: load")
accountDeletedListRaw, err := c.DecortAPICall(ctx, "POST", accountListDeletedAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(accountDeletedListRaw), &accountDeletedList)
accountDeletedList, err := c.CloudBroker().Account().ListDeleted(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountDisksListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountDisksList, error) {
accountDisksList := AccountDisksList{}
func utilityAccountDisksListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListDisks, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountDisksListCheckPresence: load account list")
accountDisksListRaw, err := c.DecortAPICall(ctx, "POST", accountListDisksAPI, urlValues)
if err != nil {
return nil, err
req := account.ListDisksRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountDisksListRaw), &accountDisksList)
log.Debugf("utilityAccountDisksListCheckPresence: load account list")
accountDisksList, err := c.CloudBroker().Account().ListDisks(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountFlipGroupsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountFlipGroupsList, error) {
accountFlipGroupsList := AccountFlipGroupsList{}
func utilityAccountFlipGroupsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListFLIPGroups, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountFlipGroupsListCheckPresence")
accountFlipGroupsListRaw, err := c.DecortAPICall(ctx, "POST", accountListFlipGroupsAPI, urlValues)
if err != nil {
return nil, err
req := account.ListFLIPGroupsRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountFlipGroupsListRaw), &accountFlipGroupsList)
log.Debugf("utilityAccountFlipGroupsListCheckPresence")
accountFlipGroupsList, err := c.CloudBroker().Account().ListFLIPGroups(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,35 +33,27 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountList, error) {
accountList := AccountList{}
func utilityAccountListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListAccounts, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := account.ListRequest{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilityAccountListCheckPresence: load account list")
accountListRaw, err := c.DecortAPICall(ctx, "POST", accountListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(accountListRaw), &accountList)
accountList, err := c.CloudBroker().Account().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountRGListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountRGList, error) {
accountRGList := AccountRGList{}
func utilityAccountRGListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListRG, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountRGListCheckPresence: load account list")
accountRGListRaw, err := c.DecortAPICall(ctx, "POST", accountListRGAPI, urlValues)
if err != nil {
return nil, err
req := account.ListRGRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountRGListRaw), &accountRGList)
log.Debugf("utilityAccountRGListCheckPresence: load account list")
accountRGList, err := c.CloudBroker().Account().ListRG(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package account
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityAccountVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (AccountVinsList, error) {
accountVinsList := AccountVinsList{}
func utilityAccountVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (account.ListVINS, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
log.Debugf("utilityAccountVinsListCheckPresence: load account list")
accountVinsListRaw, err := c.DecortAPICall(ctx, "POST", accountListVinsAPI, urlValues)
if err != nil {
return nil, err
req := account.ListVINSRequest{
AccountID: uint64(d.Get("account_id").(int)),
}
err = json.Unmarshal([]byte(accountVinsListRaw), &accountVinsList)
log.Debugf("utilityAccountVinsListCheckPresence: load account list")
accountVinsList, err := c.CloudBroker().Account().ListVINS(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -1,41 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package disks
const disksCreateAPI = "/restmachine/cloudbroker/disks/create"
const disksGetAPI = "/restmachine/cloudbroker/disks/get"
const disksListAPI = "/restmachine/cloudbroker/disks/list"
const disksResizeAPI = "/restmachine/cloudbroker/disks/resize2"
const disksRenameAPI = "/restmachine/cloudbroker/disks/rename"
const disksDeleteAPI = "/restmachine/cloudbroker/disks/delete"
const disksIOLimitAPI = "/restmachine/cloudbroker/disks/limitIO"
const disksRestoreAPI = "/restmachine/cloudbroker/disks/restore"

View File

@@ -33,7 +33,6 @@ package disks
import (
"context"
"encoding/json"
// "net/url"
@@ -53,52 +52,7 @@ func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface
id := uuid.New()
d.SetId(id.String())
diskAcl, _ := json.Marshal(disk.Acl)
d.Set("account_id", disk.AccountID)
d.Set("account_name", disk.AccountName)
d.Set("acl", string(diskAcl))
d.Set("boot_partition", disk.BootPartition)
d.Set("compute_id", disk.ComputeID)
d.Set("compute_name", disk.ComputeName)
d.Set("created_time", disk.CreatedTime)
d.Set("deleted_time", disk.DeletedTime)
d.Set("desc", disk.Desc)
d.Set("destruction_time", disk.DestructionTime)
d.Set("devicename", disk.DeviceName)
d.Set("disk_path", disk.DiskPath)
d.Set("gid", disk.GridID)
d.Set("guid", disk.GUID)
d.Set("disk_id", disk.ID)
d.Set("image_id", disk.ImageID)
d.Set("images", disk.Images)
d.Set("iotune", flattenIOTune(disk.IOTune))
d.Set("iqn", disk.IQN)
d.Set("login", disk.Login)
d.Set("milestones", disk.Milestones)
d.Set("disk_name", disk.Name)
d.Set("order", disk.Order)
d.Set("params", disk.Params)
d.Set("parent_id", disk.ParentId)
d.Set("passwd", disk.Passwd)
d.Set("pci_slot", disk.PciSlot)
d.Set("pool", disk.Pool)
d.Set("purge_attempts", disk.PurgeAttempts)
d.Set("purge_time", disk.PurgeTime)
d.Set("reality_device_number", disk.RealityDeviceNumber)
d.Set("reference_id", disk.ReferenceId)
d.Set("res_id", disk.ResID)
d.Set("res_name", disk.ResName)
d.Set("role", disk.Role)
d.Set("sep_id", disk.SepID)
d.Set("sep_type", disk.SepType)
d.Set("size_max", disk.SizeMax)
d.Set("size_used", disk.SizeUsed)
d.Set("snapshots", flattendDiskSnapshotList(disk.Snapshots))
d.Set("status", disk.Status)
d.Set("tech_status", disk.TechStatus)
d.Set("type", disk.Type)
d.Set("vmid", disk.VMID)
flattenDisk(d, disk)
return nil
}
@@ -125,14 +79,6 @@ func dataSourceDiskSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -33,7 +33,6 @@ package disks
import (
"context"
"encoding/json"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -41,104 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenIOTune(iot IOTune) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"read_bytes_sec": iot.ReadBytesSec,
"read_bytes_sec_max": iot.ReadBytesSecMax,
"read_iops_sec": iot.ReadIopsSec,
"read_iops_sec_max": iot.ReadIopsSecMax,
"size_iops_sec": iot.SizeIopsSec,
"total_bytes_sec": iot.TotalBytesSec,
"total_bytes_sec_max": iot.TotalBytesSecMax,
"total_iops_sec": iot.TotalIopsSec,
"total_iops_sec_max": iot.TotalIopsSecMax,
"write_bytes_sec": iot.WriteBytesSec,
"write_bytes_sec_max": iot.WriteBytesSecMax,
"write_iops_sec": iot.WriteIopsSec,
"write_iops_sec_max": iot.WriteIopsSecMax,
}
res = append(res, temp)
return res
}
func flattenDiskList(dl DisksList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range dl {
diskAcl, _ := json.Marshal(disk.Acl)
temp := map[string]interface{}{
"account_id": disk.AccountID,
"account_name": disk.AccountName,
"acl": string(diskAcl),
"boot_partition": disk.BootPartition,
"compute_id": disk.ComputeID,
"compute_name": disk.ComputeName,
"created_time": disk.CreatedTime,
"deleted_time": disk.DeletedTime,
"desc": disk.Desc,
"destruction_time": disk.DestructionTime,
"devicename": disk.DeviceName,
"disk_path": disk.DiskPath,
"gid": disk.GridID,
"guid": disk.GUID,
"disk_id": disk.ID,
"image_id": disk.ImageID,
"images": disk.Images,
"iotune": flattenIOTune(disk.IOTune),
"iqn": disk.IQN,
"login": disk.Login,
"machine_id": disk.MachineId,
"machine_name": disk.MachineName,
"milestones": disk.Milestones,
"disk_name": disk.Name,
"order": disk.Order,
"params": disk.Params,
"parent_id": disk.ParentId,
"passwd": disk.Passwd,
"pci_slot": disk.PciSlot,
"pool": disk.Pool,
"purge_attempts": disk.PurgeAttempts,
"purge_time": disk.PurgeTime,
"reality_device_number": disk.RealityDeviceNumber,
"reference_id": disk.ReferenceId,
"res_id": disk.ResID,
"res_name": disk.ResName,
"role": disk.Role,
"sep_id": disk.SepID,
"sep_type": disk.SepType,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"snapshots": flattendDiskSnapshotList(disk.Snapshots),
"status": disk.Status,
"tech_status": disk.TechStatus,
"type": disk.Type,
"vmid": disk.VMID,
}
res = append(res, temp)
}
return res
}
func flattendDiskSnapshotList(sl SnapshotList) []interface{} {
res := make([]interface{}, 0)
for _, snapshot := range sl {
temp := map[string]interface{}{
"guid": snapshot.Guid,
"label": snapshot.Label,
"res_id": snapshot.ResId,
"snap_set_guid": snapshot.SnapSetGuid,
"snap_set_time": snapshot.SnapSetTime,
"timestamp": snapshot.TimeStamp,
}
res = append(res, temp)
}
return res
}
func dataSourceDiskListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
diskList, err := utilityDiskListCheckPresence(ctx, d, m)
if err != nil {
@@ -195,14 +96,6 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -0,0 +1,153 @@
package disks
import (
"encoding/json"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
)
func flattenDisk(d *schema.ResourceData, disk *disks.RecordDisk) {
diskAcl, _ := json.Marshal(disk.ACL)
d.Set("account_id", disk.AccountID)
d.Set("account_name", disk.AccountName)
d.Set("acl", string(diskAcl))
d.Set("boot_partition", disk.BootPartition)
d.Set("created_time", disk.CreatedTime)
d.Set("deleted_time", disk.DeletedTime)
d.Set("desc", disk.Description)
d.Set("destruction_time", disk.DestructionTime)
d.Set("devicename", disk.DeviceName)
d.Set("disk_path", disk.DiskPath)
d.Set("gid", disk.GID)
d.Set("guid", disk.GUID)
d.Set("disk_id", disk.ID)
d.Set("image_id", disk.ImageID)
d.Set("images", disk.Images)
d.Set("iotune", flattenIOTune(disk.IOTune))
d.Set("iqn", disk.IQN)
d.Set("login", disk.Login)
d.Set("milestones", disk.Milestones)
d.Set("disk_name", disk.Name)
d.Set("order", disk.Order)
d.Set("params", disk.Params)
d.Set("parent_id", disk.ParentID)
d.Set("passwd", disk.Password)
d.Set("pci_slot", disk.PCISlot)
d.Set("pool", disk.Pool)
d.Set("purge_attempts", disk.PurgeAttempts)
d.Set("purge_time", disk.PurgeTime)
d.Set("reality_device_number", disk.RealityDeviceNumber)
d.Set("reference_id", disk.ReferenceID)
d.Set("res_id", disk.ResID)
d.Set("res_name", disk.ResName)
d.Set("role", disk.Role)
d.Set("sep_id", disk.SEPID)
d.Set("sep_type", disk.SEPType)
d.Set("size_max", disk.SizeMax)
d.Set("size_used", disk.SizeUsed)
d.Set("snapshots", flattendDiskSnapshotList(disk.Snapshots))
d.Set("status", disk.Status)
d.Set("tech_status", disk.TechStatus)
d.Set("type", disk.Type)
d.Set("vmid", disk.VMID)
}
func flattenIOTune(iot disks.IOTune) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"read_bytes_sec": iot.ReadBytesSec,
"read_bytes_sec_max": iot.ReadBytesSecMax,
"read_iops_sec": iot.ReadIOPSSec,
"read_iops_sec_max": iot.ReadIOPSSecMax,
"size_iops_sec": iot.SizeIOPSSec,
"total_bytes_sec": iot.TotalBytesSec,
"total_bytes_sec_max": iot.TotalBytesSecMax,
"total_iops_sec": iot.TotalIOPSSec,
"total_iops_sec_max": iot.TotalIOPSSecMax,
"write_bytes_sec": iot.WriteBytesSec,
"write_bytes_sec_max": iot.WriteBytesSecMax,
"write_iops_sec": iot.WriteIOPSSec,
"write_iops_sec_max": iot.WriteIOPSSecMax,
}
res = append(res, temp)
return res
}
func flattenDiskList(dl disks.ListDisks) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range dl {
diskAcl, _ := json.Marshal(disk.ACL)
temp := map[string]interface{}{
"account_id": disk.AccountID,
"account_name": disk.AccountName,
"acl": string(diskAcl),
"boot_partition": disk.BootPartition,
// "compute_id": disk.MachineID,
// "compute_name": disk.MachineName,
"created_time": disk.CreatedTime,
"deleted_time": disk.DeletedTime,
"desc": disk.Description,
"destruction_time": disk.DestructionTime,
"devicename": disk.DeviceName,
"disk_path": disk.DiskPath,
"gid": disk.GID,
"guid": disk.GUID,
"disk_id": disk.ID,
"image_id": disk.ImageID,
"images": disk.Images,
"iotune": flattenIOTune(disk.IOTune),
"iqn": disk.IQN,
"login": disk.Login,
"machine_id": disk.MachineID,
"machine_name": disk.MachineName,
"milestones": disk.Milestones,
"disk_name": disk.Name,
"order": disk.Order,
"params": disk.Params,
"parent_id": disk.ParentID,
"passwd": disk.Password,
"pci_slot": disk.PCISlot,
"pool": disk.Pool,
"purge_attempts": disk.PurgeAttempts,
"purge_time": disk.PurgeTime,
"reality_device_number": disk.RealityDeviceNumber,
"reference_id": disk.ReferenceID,
"res_id": disk.ResID,
"res_name": disk.ResName,
"role": disk.Role,
"sep_id": disk.SEPID,
"sep_type": disk.SEPType,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"snapshots": flattendDiskSnapshotList(disk.Snapshots),
"status": disk.Status,
"tech_status": disk.TechStatus,
"type": disk.Type,
"vmid": disk.VMID,
}
res = append(res, temp)
}
return res
}
func flattendDiskSnapshotList(sl disks.ListSnapshots) []interface{} {
res := make([]interface{}, 0)
for _, snapshot := range sl {
temp := map[string]interface{}{
"guid": snapshot.GUID,
"label": snapshot.Label,
"res_id": snapshot.ResID,
"snap_set_guid": snapshot.SnapSetGUID,
"snap_set_time": snapshot.SnapSetTime,
"timestamp": snapshot.Timestamp,
}
res = append(res, temp)
}
return res
}

View File

@@ -1,111 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package disks
type Disk struct {
Acl map[string]interface{} `json:"acl"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
BootPartition int `json:"bootPartition"`
CreatedTime uint64 `json:"creationTime"`
ComputeID int `json:"computeId"`
ComputeName string `json:"computeName"`
DeletedTime uint64 `json:"deletionTime"`
DeviceName string `json:"devicename"`
Desc string `json:"desc"`
DestructionTime uint64 `json:"destructionTime"`
DiskPath string `json:"diskPath"`
GridID int `json:"gid"`
GUID int `json:"guid"`
ID uint `json:"id"`
ImageID int `json:"imageId"`
Images []int `json:"images"`
IOTune IOTune `json:"iotune"`
IQN string `json:"iqn"`
Login string `json:"login"`
Name string `json:"name"`
MachineId int `json:"machineId"`
MachineName string `json:"machineName"`
Milestones uint64 `json:"milestones"`
Order int `json:"order"`
Params string `json:"params"`
Passwd string `json:"passwd"`
ParentId int `json:"parentId"`
PciSlot int `json:"pciSlot"`
Pool string `json:"pool"`
PurgeTime uint64 `json:"purgeTime"`
PurgeAttempts uint64 `json:"purgeAttempts"`
RealityDeviceNumber int `json:"realityDeviceNumber"`
ReferenceId string `json:"referenceId"`
ResID string `json:"resId"`
ResName string `json:"resName"`
Role string `json:"role"`
SepType string `json:"sepType"`
SepID int `json:"sepId"` // NOTE: absent from compute/get output
SizeMax int `json:"sizeMax"`
SizeUsed float64 `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
Snapshots []Snapshot `json:"snapshots"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Type string `json:"type"`
UpdateBy uint64 `json:"updateBy"`
VMID int `json:"vmid"`
}
type Snapshot struct {
Guid string `json:"guid"`
Label string `json:"label"`
ResId string `json:"resId"`
SnapSetGuid string `json:"snapSetGuid"`
SnapSetTime uint64 `json:"snapSetTime"`
TimeStamp uint64 `json:"timestamp"`
}
type SnapshotList []Snapshot
type DisksList []Disk
type IOTune struct {
ReadBytesSec int `json:"read_bytes_sec"`
ReadBytesSecMax int `json:"read_bytes_sec_max"`
ReadIopsSec int `json:"read_iops_sec"`
ReadIopsSecMax int `json:"read_iops_sec_max"`
SizeIopsSec int `json:"size_iops_sec"`
TotalBytesSec int `json:"total_bytes_sec"`
TotalBytesSecMax int `json:"total_bytes_sec_max"`
TotalIopsSec int `json:"total_iops_sec"`
TotalIopsSecMax int `json:"total_iops_sec_max"`
WriteBytesSec int `json:"write_bytes_sec"`
WriteBytesSecMax int `json:"write_bytes_sec_max"`
WriteIopsSec int `json:"write_iops_sec"`
WriteIopsSecMax int `json:"write_iops_sec_max"`
}

View File

@@ -33,15 +33,14 @@ package disks
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -50,230 +49,178 @@ import (
func resourceDiskCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := disks.CreateRequest{}
req.AccountID = uint64(d.Get("account_id").(int))
req.GID = uint64(d.Get("gid").(int))
req.Name = d.Get("disk_name").(string)
req.Size = uint64(d.Get("size_max").(int))
urlValues.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
urlValues.Add("gid", fmt.Sprintf("%d", d.Get("gid").(int)))
urlValues.Add("name", d.Get("disk_name").(string))
urlValues.Add("size", fmt.Sprintf("%d", d.Get("size_max").(int)))
if typeRaw, ok := d.GetOk("type"); ok {
urlValues.Add("type", strings.ToUpper(typeRaw.(string)))
req.Type = strings.ToUpper(typeRaw.(string))
} else {
urlValues.Add("type", "D")
req.Type = "D"
}
if sepId, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sep_id", strconv.Itoa(sepId.(int)))
req.SEPID = uint64(sepId.(int))
}
if poolName, ok := d.GetOk("pool"); ok {
urlValues.Add("pool", poolName.(string))
req.Pool = poolName.(string)
}
argVal, argSet := d.GetOk("desc")
if argSet {
urlValues.Add("description", argVal.(string))
req.Description = argVal.(string)
}
diskId, err := c.DecortAPICall(ctx, "POST", disksCreateAPI, urlValues)
diskId, err := c.CloudBroker().Disks().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
d.SetId(diskId) // update ID of the resource to tell Terraform that the disk resource exists
d.SetId(strconv.FormatUint(diskId, 10))
if iotuneRaw, ok := d.GetOk("iotune"); ok {
iot := iotuneRaw.([]interface{})[0]
iotune := iot.(map[string]interface{})
urlValues.Add("diskId", diskId)
urlValues.Add("iops", strconv.Itoa(iotune["total_iops_sec"].(int)))
urlValues.Add("read_bytes_sec", strconv.Itoa(iotune["read_bytes_sec"].(int)))
urlValues.Add("read_bytes_sec_max", strconv.Itoa(iotune["read_bytes_sec_max"].(int)))
urlValues.Add("read_iops_sec", strconv.Itoa(iotune["read_iops_sec"].(int)))
urlValues.Add("read_iops_sec_max", strconv.Itoa(iotune["read_iops_sec_max"].(int)))
urlValues.Add("size_iops_sec", strconv.Itoa(iotune["size_iops_sec"].(int)))
urlValues.Add("total_bytes_sec", strconv.Itoa(iotune["total_bytes_sec"].(int)))
urlValues.Add("total_bytes_sec_max", strconv.Itoa(iotune["total_bytes_sec_max"].(int)))
urlValues.Add("total_iops_sec_max", strconv.Itoa(iotune["total_iops_sec_max"].(int)))
urlValues.Add("write_bytes_sec", strconv.Itoa(iotune["write_bytes_sec"].(int)))
urlValues.Add("write_bytes_sec_max", strconv.Itoa(iotune["write_bytes_sec_max"].(int)))
urlValues.Add("write_iops_sec", strconv.Itoa(iotune["write_iops_sec"].(int)))
urlValues.Add("write_iops_sec_max", strconv.Itoa(iotune["write_iops_sec_max"].(int)))
req := disks.LimitIORequest{
DiskID: diskId,
IOPS: uint64(iotune["total_iops_sec"].(int)),
TotalBytesSec: uint64(iotune["total_bytes_sec"].(int)),
ReadBytesSec: uint64(iotune["read_bytes_sec"].(int)),
WriteBytesSec: uint64(iotune["write_bytes_sec"].(int)),
TotalIOPSSec: uint64(iotune["total_iops_sec"].(int)),
ReadIOPSSec: uint64(iotune["read_iops_sec"].(int)),
WriteIOPSSec: uint64(iotune["write_iops_sec"].(int)),
TotalBytesSecMax: uint64(iotune["total_bytes_sec_max"].(int)),
ReadBytesSecMax: uint64(iotune["read_bytes_sec_max"].(int)),
WriteBytesSecMax: uint64(iotune["write_bytes_sec_max"].(int)),
TotalIOPSSecMax: uint64(iotune["total_iops_sec_max"].(int)),
ReadIOPSSecMax: uint64(iotune["read_iops_sec_max"].(int)),
WriteIOPSSecMax: uint64(iotune["write_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotune["size_iops_sec"].(int)),
}
_, err := c.DecortAPICall(ctx, "POST", disksIOLimitAPI, urlValues)
_, err := c.CloudBroker().Disks().LimitIO(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
dgn := resourceDiskRead(ctx, d, m)
if dgn != nil {
return dgn
}
return nil
return resourceDiskRead(ctx, d, m)
}
func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
disk, err := utilityDiskCheckPresence(ctx, d, m)
if disk == nil {
if err != nil {
d.SetId("")
if err != nil {
return diag.FromErr(err)
}
return nil
return diag.FromErr(err)
}
diskAcl, _ := json.Marshal(disk.Acl)
d.Set("account_id", disk.AccountID)
d.Set("account_name", disk.AccountName)
d.Set("acl", string(diskAcl))
d.Set("boot_partition", disk.BootPartition)
d.Set("compute_id", disk.ComputeID)
d.Set("compute_name", disk.ComputeName)
d.Set("created_time", disk.CreatedTime)
d.Set("deleted_time", disk.DeletedTime)
d.Set("desc", disk.Desc)
d.Set("destruction_time", disk.DestructionTime)
d.Set("devicename", disk.DeviceName)
d.Set("disk_path", disk.DiskPath)
d.Set("gid", disk.GridID)
d.Set("guid", disk.GUID)
d.Set("disk_id", disk.ID)
d.Set("image_id", disk.ImageID)
d.Set("images", disk.Images)
d.Set("iotune", flattenIOTune(disk.IOTune))
d.Set("iqn", disk.IQN)
d.Set("login", disk.Login)
d.Set("milestones", disk.Milestones)
d.Set("disk_name", disk.Name)
d.Set("order", disk.Order)
d.Set("params", disk.Params)
d.Set("parent_id", disk.ParentId)
d.Set("passwd", disk.Passwd)
d.Set("pci_slot", disk.PciSlot)
d.Set("pool", disk.Pool)
d.Set("purge_attempts", disk.PurgeAttempts)
d.Set("purge_time", disk.PurgeTime)
d.Set("reality_device_number", disk.RealityDeviceNumber)
d.Set("reference_id", disk.ReferenceId)
d.Set("res_id", disk.ResID)
d.Set("res_name", disk.ResName)
d.Set("role", disk.Role)
d.Set("sep_id", disk.SepID)
d.Set("sep_type", disk.SepType)
d.Set("size_max", disk.SizeMax)
d.Set("size_used", disk.SizeUsed)
d.Set("snapshots", flattendDiskSnapshotList(disk.Snapshots))
d.Set("status", disk.Status)
d.Set("tech_status", disk.TechStatus)
d.Set("type", disk.Type)
d.Set("vmid", disk.VMID)
flattenDisk(d, disk)
return nil
}
func resourceDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
diskID, _ := strconv.ParseUint(d.Id(), 10, 64)
if d.HasChange("size_max") {
oldSize, newSize := d.GetChange("size_max")
if oldSize.(int) < newSize.(int) {
log.Debugf("resourceDiskUpdate: resizing disk ID %s - %d GB -> %d GB",
d.Id(), oldSize.(int), newSize.(int))
urlValues.Add("diskId", d.Id())
urlValues.Add("size", fmt.Sprintf("%d", newSize.(int)))
_, err := c.DecortAPICall(ctx, "POST", disksResizeAPI, urlValues)
req := disks.ResizeRequest{
DiskID: diskID,
Size: uint64(newSize.(int)),
}
_, err := c.CloudBroker().Disks().Resize(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.Set("size_max", newSize)
} else if oldSize.(int) > newSize.(int) {
return diag.FromErr(fmt.Errorf("resourceDiskUpdate: Disk ID %s - reducing disk size is not allowed", d.Id()))
}
urlValues = &url.Values{}
}
if d.HasChange("disk_name") {
urlValues.Add("diskId", d.Id())
urlValues.Add("name", d.Get("disk_name").(string))
_, err := c.DecortAPICall(ctx, "POST", disksRenameAPI, urlValues)
req := disks.RenameRequest{
DiskID: diskID,
Name: d.Get("disk_name").(string),
}
_, err := c.CloudBroker().Disks().Rename(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("iotune") {
iot := d.Get("iotune").([]interface{})[0]
iotune := iot.(map[string]interface{})
urlValues.Add("diskId", d.Id())
urlValues.Add("iops", strconv.Itoa(iotune["total_iops_sec"].(int)))
urlValues.Add("read_bytes_sec", strconv.Itoa(iotune["read_bytes_sec"].(int)))
urlValues.Add("read_bytes_sec_max", strconv.Itoa(iotune["read_bytes_sec_max"].(int)))
urlValues.Add("read_iops_sec", strconv.Itoa(iotune["read_iops_sec"].(int)))
urlValues.Add("read_iops_sec_max", strconv.Itoa(iotune["read_iops_sec_max"].(int)))
urlValues.Add("size_iops_sec", strconv.Itoa(iotune["size_iops_sec"].(int)))
urlValues.Add("total_bytes_sec", strconv.Itoa(iotune["total_bytes_sec"].(int)))
urlValues.Add("total_bytes_sec_max", strconv.Itoa(iotune["total_bytes_sec_max"].(int)))
urlValues.Add("total_iops_sec_max", strconv.Itoa(iotune["total_iops_sec_max"].(int)))
urlValues.Add("write_bytes_sec", strconv.Itoa(iotune["write_bytes_sec"].(int)))
urlValues.Add("write_bytes_sec_max", strconv.Itoa(iotune["write_bytes_sec_max"].(int)))
urlValues.Add("write_iops_sec", strconv.Itoa(iotune["write_iops_sec"].(int)))
urlValues.Add("write_iops_sec_max", strconv.Itoa(iotune["write_iops_sec_max"].(int)))
req := disks.LimitIORequest{
DiskID: diskID,
IOPS: uint64(iotune["total_iops_sec"].(int)),
TotalBytesSec: uint64(iotune["total_bytes_sec"].(int)),
ReadBytesSec: uint64(iotune["read_bytes_sec"].(int)),
WriteBytesSec: uint64(iotune["write_bytes_sec"].(int)),
TotalIOPSSec: uint64(iotune["total_iops_sec"].(int)),
ReadIOPSSec: uint64(iotune["read_iops_sec"].(int)),
WriteIOPSSec: uint64(iotune["write_iops_sec"].(int)),
TotalBytesSecMax: uint64(iotune["total_bytes_sec_max"].(int)),
ReadBytesSecMax: uint64(iotune["read_bytes_sec_max"].(int)),
WriteBytesSecMax: uint64(iotune["write_bytes_sec_max"].(int)),
TotalIOPSSecMax: uint64(iotune["total_iops_sec_max"].(int)),
ReadIOPSSecMax: uint64(iotune["read_iops_sec_max"].(int)),
WriteIOPSSecMax: uint64(iotune["write_iops_sec_max"].(int)),
SizeIOPSSec: uint64(iotune["size_iops_sec"].(int)),
}
_, err := c.DecortAPICall(ctx, "POST", disksIOLimitAPI, urlValues)
_, err := c.CloudBroker().Disks().LimitIO(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("restore") {
if d.Get("restore").(bool) {
urlValues.Add("diskId", d.Id())
urlValues.Add("reason", d.Get("reason").(string))
req := disks.RestoreRequest{
DiskID: diskID,
Reason: d.Get("reason").(string),
}
_, err := c.DecortAPICall(ctx, "POST", disksRestoreAPI, urlValues)
_, err := c.CloudBroker().Disks().Restore(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
}
return resourceDiskRead(ctx, d, m)
}
func resourceDiskDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := m.(*controller.ControllerCfg)
disk, err := utilityDiskCheckPresence(ctx, d, m)
if disk == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
if err != nil {
return diag.FromErr(err)
}
params := &url.Values{}
params.Add("diskId", d.Id())
params.Add("detach", strconv.FormatBool(d.Get("detach").(bool)))
params.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
params.Add("reason", d.Get("reason").(string))
req := disks.DeleteRequest{
DiskID: disk.ID,
Detach: d.Get("detach").(bool),
Permanently: d.Get("permanently").(bool),
Reason: d.Get("reason").(string),
}
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", disksDeleteAPI, params)
_, err = c.CloudBroker().Disks().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -362,14 +309,6 @@ func resourceDiskSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"compute_name": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -33,35 +33,28 @@ package disks
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityDiskCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Disk, error) {
func utilityDiskCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*disks.RecordDisk, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
disk := &Disk{}
req := disks.GetRequest{}
if d.Get("disk_id").(int) == 0 {
urlValues.Add("diskId", d.Id())
id, _ := strconv.ParseUint(d.Id(), 10, 64)
req.DiskID = id
} else {
urlValues.Add("diskId", strconv.Itoa(d.Get("disk_id").(int)))
req.DiskID = uint64(d.Get("disk_id").(int))
}
log.Debugf("utilityDiskCheckPresence: load disk")
diskRaw, err := c.DecortAPICall(ctx, "POST", disksGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(diskRaw), disk)
disk, err := c.CloudBroker().Disks().Get(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,42 +33,34 @@ package disks
import (
"context"
"encoding/json"
"net/url"
"strconv"
"strings"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (DisksList, error) {
diskList := DisksList{}
func utilityDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (disks.ListDisks, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := disks.ListRequest{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
if diskType, ok := d.GetOk("type"); ok {
urlValues.Add("type", strings.ToUpper(diskType.(string)))
req.Type = strings.ToUpper(diskType.(string))
}
if accountId, ok := d.GetOk("accountId"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
req.AccountID = uint64(accountId.(int))
}
log.Debugf("utilityDiskListCheckPresence: load disk list")
diskListRaw, err := c.DecortAPICall(ctx, "POST", disksListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(diskListRaw), &diskList)
diskList, err := c.CloudBroker().Disks().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -40,21 +40,12 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenGrid(d *schema.ResourceData, grid *Grid) {
d.Set("name", grid.Name)
d.Set("flag", grid.Flag)
d.Set("gid", grid.Gid)
d.Set("guid", grid.Guid)
d.Set("location_code", grid.LocationCode)
d.Set("id", grid.Id)
}
func dataSourceGridRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
grid, err := utilityGridCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(grid.Id))
d.SetId(strconv.FormatUint(grid.ID, 10))
flattenGrid(d, grid)
return nil

View File

@@ -40,23 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenGridList(gl GridList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range gl {
temp := map[string]interface{}{
"name": item.Name,
"flag": item.Flag,
"gid": item.Gid,
"guid": item.Guid,
"location_code": item.LocationCode,
"id": item.Id,
}
res = append(res, temp)
}
return res
}
func dataSourceGridListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
gridList, err := utilityGridListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -0,0 +1,32 @@
package grid
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/grid"
)
func flattenGrid(d *schema.ResourceData, grid *grid.RecordGrid) {
d.Set("name", grid.Name)
d.Set("flag", grid.Flag)
d.Set("gid", grid.GID)
d.Set("guid", grid.GUID)
d.Set("location_code", grid.LocationCode)
d.Set("id", grid.ID)
}
func flattenGridList(gl grid.ListGrids) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range gl {
temp := map[string]interface{}{
"name": item.Name,
"flag": item.Flag,
"gid": item.GID,
"guid": item.GUID,
"location_code": item.LocationCode,
"id": item.ID,
}
res = append(res, temp)
}
return res
}

View File

@@ -1,43 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package grid
type Grid struct {
Flag string `json:"flag"`
Gid int `json:"gid"`
Guid int `json:"guid"`
Id int `json:"id"`
LocationCode string `json:"locationCode"`
Name string `json:"name"`
}
type GridList []Grid

View File

@@ -33,35 +33,27 @@ package grid
import (
"context"
"encoding/json"
"errors"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/grid"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityGridCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Grid, error) {
grid := &Grid{}
func utilityGridCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*grid.RecordGrid, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := grid.GetRequest{}
if gridId, ok := d.GetOk("grid_id"); ok {
urlValues.Add("gridId", strconv.Itoa(gridId.(int)))
req.GID = uint64(gridId.(int))
} else {
return nil, errors.New("grid_id is required")
}
log.Debugf("utilityGridCheckPresence: load grid")
gridRaw, err := c.DecortAPICall(ctx, "POST", GridGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(gridRaw), grid)
grid, err := c.CloudBroker().Grid().Get(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,35 +33,27 @@ package grid
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/grid"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityGridListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (GridList, error) {
gridList := GridList{}
func utilityGridListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (grid.ListGrids, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := grid.ListRequest{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilityGridListCheckPresence: load grid list")
gridListRaw, err := c.DecortAPICall(ctx, "POST", GridListGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(gridListRaw), &gridList)
gridList, err := c.CloudBroker().Grid().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -38,57 +38,15 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenImage(d *schema.ResourceData, image *Image) {
d.Set("name", image.Name)
d.Set("drivers", image.Drivers)
d.Set("url", image.Url)
d.Set("gid", image.Gid)
d.Set("image_id", image.ImageId)
d.Set("boot_type", image.Boottype)
d.Set("image_type", image.Imagetype)
d.Set("bootable", image.Bootable)
d.Set("sep_id", image.SepId)
d.Set("unc_path", image.UNCPath)
d.Set("link_to", image.LinkTo)
d.Set("status", image.Status)
d.Set("tech_status", image.TechStatus)
d.Set("version", image.Version)
d.Set("size", image.Size)
d.Set("enabled", image.Enabled)
d.Set("computeci_id", image.ComputeciId)
d.Set("pool_name", image.PoolName)
d.Set("username", image.Username)
d.Set("username_dl", image.UsernameDL)
d.Set("password", image.Password)
d.Set("password_dl", image.PasswordDL)
d.Set("account_id", image.AccountId)
d.Set("guid", image.Guid)
d.Set("milestones", image.Milestones)
d.Set("provider_name", image.ProviderName)
d.Set("purge_attempts", image.PurgeAttempts)
d.Set("reference_id", image.ReferenceId)
d.Set("res_id", image.ResId)
d.Set("res_name", image.ResName)
d.Set("rescuecd", image.Rescuecd)
d.Set("architecture", image.Architecture)
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
d.Set("meta", flattens.FlattenMeta(image.Meta))
d.Set("desc", image.Desc)
d.Set("shared_with", image.SharedWith)
}
func dataSourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(image.Guid))
d.SetId(strconv.FormatUint(image.ID, 10))
flattenImage(d, image)
return nil

View File

@@ -40,54 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenImageList(il ImageList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range il {
temp := map[string]interface{}{
"name": item.Name,
"url": item.Url,
"gid": item.Gid,
"guid": item.Guid,
"drivers": item.Drivers,
"image_id": item.ImageId,
"boot_type": item.Boottype,
"bootable": item.Bootable,
"image_type": item.Imagetype,
"status": item.Status,
"tech_status": item.TechStatus,
"version": item.Version,
"username": item.Username,
"username_dl": item.UsernameDL,
"password": item.Password,
"password_dl": item.PasswordDL,
"purge_attempts": item.PurgeAttempts,
"architecture": item.Architecture,
"account_id": item.AccountId,
"computeci_id": item.ComputeciId,
"enabled": item.Enabled,
"reference_id": item.ReferenceId,
"res_id": item.ResId,
"res_name": item.ResName,
"rescuecd": item.Rescuecd,
"provider_name": item.ProviderName,
"milestones": item.Milestones,
"size": item.Size,
"sep_id": item.SepId,
"link_to": item.LinkTo,
"unc_path": item.UNCPath,
"pool_name": item.PoolName,
"hot_resize": item.Hotresize,
"history": flattenHistory(item.History),
"last_modified": item.LastModified,
"meta": flattenMeta(item.Meta),
"desc": item.Desc,
"shared_with": item.SharedWith,
}
res = append(res, temp)
}
return res
}
func dataSourceImageListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
imageList, err := utilityImageListCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -40,32 +40,6 @@ import (
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenImageListStacks(_ *schema.ResourceData, stack ImageListStacks) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range stack {
t := map[string]interface{}{
"api_url": item.ApiURL,
"api_key": item.ApiKey,
"app_id": item.AppId,
"desc": item.Desc,
"drivers": item.Drivers,
"error": item.Error,
"guid": item.Guid,
"id": item.Id,
"images": item.Images,
"login": item.Login,
"name": item.Name,
"passwd": item.Passwd,
"reference_id": item.ReferenceId,
"status": item.Status,
"type": item.Type,
}
temp = append(temp, t)
}
return temp
}
func dataSourceImageListStacksRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
imageListStacks, err := utilityImageListStacksCheckPresence(ctx, d, m)
if err != nil {

View File

@@ -0,0 +1,157 @@
package image
import (
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenImage(d *schema.ResourceData, img *image.RecordImage) {
d.Set("name", img.Name)
d.Set("drivers", img.Drivers)
d.Set("url", img.URL)
d.Set("gid", img.GID)
d.Set("image_id", img.ID)
d.Set("boot_type", img.BootType)
d.Set("image_type", img.Type)
d.Set("bootable", img.Bootable)
d.Set("sep_id", img.SEPID)
d.Set("unc_path", img.UNCPath)
d.Set("link_to", img.LinkTo)
d.Set("status", img.Status)
d.Set("tech_status", img.TechStatus)
d.Set("version", img.Version)
d.Set("size", img.Size)
d.Set("enabled", img.Enabled)
d.Set("computeci_id", img.ComputeCIID)
d.Set("pool_name", img.Pool)
d.Set("username", img.Username)
// d.Set("username_dl", img.UsernameDL)
d.Set("password", img.Password)
// d.Set("password_dl", img.PasswordDL)
d.Set("account_id", img.AccountID)
d.Set("guid", img.GUID)
d.Set("milestones", img.Milestones)
d.Set("provider_name", img.ProviderName)
d.Set("purge_attempts", img.PurgeAttempts)
d.Set("reference_id", img.ReferenceID)
d.Set("res_id", img.ResID)
d.Set("res_name", img.ResName)
d.Set("rescuecd", img.RescueCD)
d.Set("architecture", img.Architecture)
d.Set("hot_resize", img.HotResize)
d.Set("history", flattenHistory(img.History))
d.Set("last_modified", img.LastModified)
d.Set("meta", flattens.FlattenMeta(img.Meta))
d.Set("desc", img.Description)
d.Set("shared_with", img.SharedWith)
}
func flattenMeta(m []interface{}) []string {
output := []string{}
for _, item := range m {
switch d := item.(type) {
case string:
output = append(output, d)
case int:
output = append(output, strconv.Itoa(d))
case int64:
output = append(output, strconv.FormatInt(d, 10))
case float64:
output = append(output, strconv.FormatInt(int64(d), 10))
default:
output = append(output, "")
}
}
return output
}
func flattenHistory(history []image.History) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range history {
t := map[string]interface{}{
"id": item.ID,
"guid": item.GUID,
"timestamp": item.Timestamp,
}
temp = append(temp, t)
}
return temp
}
func flattenImageList(il image.ListImages) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range il {
temp := map[string]interface{}{
"name": item.Name,
"url": item.URL,
"gid": item.GID,
"guid": item.GUID,
"drivers": item.Drivers,
"image_id": item.ID,
"boot_type": item.BootType,
"bootable": item.Bootable,
"image_type": item.Type,
"status": item.Status,
"tech_status": item.TechStatus,
"version": item.Version,
"username": item.Username,
// "username_dl": item.UsernameDL,
"password": item.Password,
// "password_dl": item.PasswordDL,
"purge_attempts": item.PurgeAttempts,
"architecture": item.Architecture,
"account_id": item.AccountID,
"computeci_id": item.ComputeCIID,
"enabled": item.Enabled,
"reference_id": item.ReferenceID,
"res_id": item.ResID,
"res_name": item.ResName,
"rescuecd": item.RescueCD,
"provider_name": item.ProviderName,
"milestones": item.Milestones,
"size": item.Size,
"sep_id": item.SEPID,
"link_to": item.LinkTo,
"unc_path": item.UNCPath,
"pool_name": item.Pool,
"hot_resize": item.HotResize,
"history": flattenHistory(item.History),
"last_modified": item.LastModified,
"meta": flattenMeta(item.Meta),
"desc": item.Description,
"shared_with": item.SharedWith,
}
res = append(res, temp)
}
return res
}
func flattenImageListStacks(_ *schema.ResourceData, stack image.ListStacks) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range stack {
t := map[string]interface{}{
"api_url": item.APIURL,
"api_key": item.APIKey,
"app_id": item.AppID,
"desc": item.Description,
"drivers": item.Drivers,
"error": item.Error,
"guid": item.GUID,
"id": item.ID,
"images": item.Images,
"login": item.Login,
"name": item.Name,
"passwd": item.Password,
"reference_id": item.ReferenceID,
"status": item.Status,
"type": item.Type,
}
temp = append(temp, t)
}
return temp
}

View File

@@ -1,101 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
type History struct {
Guid string `json:"guid"`
Id int `json:"id"`
Timestamp int64 `json:"timestamp"`
}
type Image struct {
ImageId int `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
Gid int `json:"gid"`
Guid int `json:"guid"`
Boottype string `json:"bootType"`
Imagetype string `json:"type"`
Drivers []string `json:"drivers"`
Hotresize bool `json:"hotResize"`
Bootable bool `json:"bootable"`
Username string `json:"username"`
Password string `json:"password"`
AccountId int `json:"accountId"`
UsernameDL string `json:"usernameDL"`
PasswordDL string `json:"passwordDL"`
SepId int `json:"sepId"`
PoolName string `json:"pool"`
Architecture string `json:"architecture"`
UNCPath string `json:"UNCPath"`
LinkTo int `json:"linkTo"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Size int `json:"size"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
ComputeciId int `json:"computeciId"`
Milestones int `json:"milestones"`
ProviderName string `json:"provider_name"`
PurgeAttempts int `json:"purgeAttempts"`
ReferenceId string `json:"referenceId"`
ResId string `json:"resId"`
ResName string `json:"resName"`
Rescuecd bool `json:"rescuecd"`
Meta []interface{} `json:"_meta"`
History []History `json:"history"`
LastModified int64 `json:"lastModified"`
Desc string `json:"desc"`
SharedWith []int `json:"sharedWith"`
}
type ImageList []Image
type ImageStack struct {
ApiURL string `json:"apiUrl"`
ApiKey string `json:"apikey"`
AppId string `json:"appId"`
Desc string `json:"desc"`
Drivers []string `json:"drivers"`
Error int `json:"error"`
Guid int `json:"guid"`
Id int `json:"id"`
Images []int `json:"images"`
Login string `json:"login"`
Name string `json:"name"`
Passwd string `json:"passwd"`
ReferenceId string `json:"referenceId"`
Status string `json:"status"`
Type string `json:"type"`
}
type ImageListStacks []ImageStack

View File

@@ -33,69 +33,57 @@ package image
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceCDROMImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceCDROMImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("url", d.Get("url").(string))
urlValues.Add("gid", strconv.Itoa(d.Get("gid").(int)))
tstr := d.Get("drivers").([]interface{})
temp := ""
l := len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s
req := image.CreateCDROMImageRequest{
Name: d.Get("name").(string),
URL: d.Get("url").(string),
GID: uint64(d.Get("gid").(int)),
}
temp = "[" + temp + "]"
urlValues.Add("drivers", temp)
if username, ok := d.GetOk("username"); ok {
urlValues.Add("username", username.(string))
drivers := []string{}
for _, driver := range d.Get("drivers").([]interface{}) {
drivers = append(drivers, driver.(string))
}
if password, ok := d.GetOk("password"); ok {
urlValues.Add("password", password.(string))
req.Drivers = drivers
if username, ok := d.GetOk("username_dl"); ok {
req.UsernameDL = username.(string)
}
if password, ok := d.GetOk("password_dl"); ok {
req.PasswordDl = password.(string)
}
if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
}
if usernameDL, ok := d.GetOk("username_dl"); ok {
urlValues.Add("usernameDL", usernameDL.(string))
}
if passwordDL, ok := d.GetOk("password_dl"); ok {
urlValues.Add("passwordDL", passwordDL.(string))
req.AccountID = uint64(accountId.(int))
}
if sepId, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepId.(int)))
req.SEPID = uint64(sepId.(int))
}
if poolName, ok := d.GetOk("pool_name"); ok {
urlValues.Add("pool_name", poolName.(string))
req.PoolName = poolName.(string)
}
if architecture, ok := d.GetOk("architecture"); ok {
urlValues.Add("architecture", architecture.(string))
req.Architecture = architecture.(string)
}
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateCDROMAPI, urlValues)
imageId, err := c.CloudBroker().Image().CreateCDROMImage(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(imageId)
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
@@ -103,9 +91,7 @@ func resourceCDROMImageCreate(ctx context.Context, d *schema.ResourceData, m int
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
@@ -118,26 +104,25 @@ func resourceCDROMImageCreate(ctx context.Context, d *schema.ResourceData, m int
func resourceCDROMImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceCDROMImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
if image == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if permanently, ok := d.GetOk("permanently"); ok {
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
_, err = c.DecortAPICall(ctx, "POST", imageDeleteCDROMAPI, urlValues)
imageData, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := image.DeleteCDROMImageRequest{
ImageID: imageData.ID,
}
if permanently, ok := d.GetOk("permanently"); ok {
req.Permanently = permanently.(bool)
}
_, err = c.CloudBroker().Image().DeleteCDROMImage(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
@@ -192,18 +177,18 @@ func resourceCDROMImageSchemaMake() map[string]*schema.Schema {
Computed: true,
Description: "Does this machine supports hot resize",
},
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
},
"password": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
},
// "username": {
// Type: schema.TypeString,
// Optional: true,
// Computed: true,
// Description: "Optional username for the image",
// },
// "password": {
// Type: schema.TypeString,
// Optional: true,
// Computed: true,
// Description: "Optional password for the image",
// },
"account_id": {
Type: schema.TypeInt,
Optional: true,
@@ -377,7 +362,7 @@ func ResourceCDROMImage() *schema.Resource {
CreateContext: resourceCDROMImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
UpdateContext: resourceImageUpdate,
DeleteContext: resourceCDROMImageDelete,
Importer: &schema.ResourceImporter{

View File

@@ -33,54 +33,17 @@ package image
import (
"context"
"net/url"
"strconv"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceCreateListImages(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
id := uuid.New()
d.SetId(id.String())
return nil
}
func resourceDeleteListImages(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceDeleteListImages: start deleting...")
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
imageIds := d.Get("image_ids").([]interface{})
temp := ""
l := len(imageIds)
for i, imageId := range imageIds {
s := strconv.Itoa(imageId.(int))
if i != (l - 1) {
s += ",\n"
} else {
s += "\n"
}
temp = temp + s
}
temp = "[" + temp + "]"
urlValues.Add("reason", d.Get("reason").(string))
urlValues.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
urlValues.Add("imageIds", temp)
_, err := c.DecortAPICall(ctx, "POST", imageDeleteImagesAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}

View File

@@ -33,148 +33,84 @@ package image
import (
"context"
"errors"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
log "github.com/sirupsen/logrus"
)
func resourceImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("url", d.Get("url").(string))
urlValues.Add("gid", strconv.Itoa(d.Get("gid").(int)))
urlValues.Add("boottype", d.Get("boot_type").(string))
urlValues.Add("imagetype", d.Get("image_type").(string))
tstr := d.Get("drivers").([]interface{})
temp := ""
l := len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s
req := image.CreateRequest{
Name: d.Get("name").(string),
URL: d.Get("url").(string),
GID: uint64(d.Get("gid").(int)),
BootType: d.Get("boot_type").(string),
ImageType: d.Get("image_type").(string),
}
temp = "[" + temp + "]"
urlValues.Add("drivers", temp)
drivers := []string{}
for _, driver := range d.Get("drivers").([]interface{}) {
drivers = append(drivers, driver.(string))
}
req.Drivers = drivers
if hotresize, ok := d.GetOk("hot_resize"); ok {
urlValues.Add("hotresize", strconv.FormatBool(hotresize.(bool)))
req.HotResize = hotresize.(bool)
}
if username, ok := d.GetOk("username"); ok {
urlValues.Add("username", username.(string))
req.Username = username.(string)
}
if password, ok := d.GetOk("password"); ok {
urlValues.Add("password", password.(string))
req.Password = password.(string)
}
if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
req.AccountID = uint64(accountId.(int))
}
if usernameDL, ok := d.GetOk("username_dl"); ok {
urlValues.Add("usernameDL", usernameDL.(string))
req.UsernameDL = usernameDL.(string)
}
if passwordDL, ok := d.GetOk("password_dl"); ok {
urlValues.Add("passwordDL", passwordDL.(string))
req.PasswordDL = passwordDL.(string)
}
if sepId, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepId.(int)))
req.SEPID = uint64(sepId.(int))
}
if poolName, ok := d.GetOk("pool_name"); ok {
urlValues.Add("poolName", poolName.(string))
req.PoolName = poolName.(string)
}
if architecture, ok := d.GetOk("architecture"); ok {
urlValues.Add("architecture", architecture.(string))
req.Architecture = architecture.(string)
}
api := ""
if isSync := d.Get("sync").(bool); !isSync {
api = imageCreateAPI
} else {
api = imageSyncCreateAPI
}
imageId, err := c.DecortAPICall(ctx, "POST", api, urlValues)
imageId, err := c.CloudBroker().Image().CreateImage(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(imageId)
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourceImageRead(ctx, d, m)
}
func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageRead: called for %s id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
if image == nil {
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
d.Set("name", image.Name)
d.Set("drivers", image.Drivers)
d.Set("url", image.Url)
d.Set("gid", image.Gid)
d.Set("image_id", image.ImageId)
d.Set("boot_type", image.Boottype)
d.Set("image_type", image.Imagetype)
d.Set("bootable", image.Bootable)
d.Set("sep_id", image.SepId)
d.Set("unc_path", image.UNCPath)
d.Set("link_to", image.LinkTo)
d.Set("status", image.Status)
d.Set("tech_status", image.TechStatus)
d.Set("version", image.Version)
d.Set("size", image.Size)
d.Set("enabled", image.Enabled)
d.Set("computeci_id", image.ComputeciId)
d.Set("pool_name", image.PoolName)
d.Set("username", image.Username)
d.Set("username_dl", image.UsernameDL)
d.Set("password", image.Password)
d.Set("password_dl", image.PasswordDL)
d.Set("account_id", image.AccountId)
d.Set("guid", image.Guid)
d.Set("milestones", image.Milestones)
d.Set("provider_name", image.ProviderName)
d.Set("purge_attempts", image.PurgeAttempts)
d.Set("reference_id", image.ReferenceId)
d.Set("res_id", image.ResId)
d.Set("res_name", image.ResName)
d.Set("rescuecd", image.Rescuecd)
d.Set("architecture", image.Architecture)
d.Set("meta", flattens.FlattenMeta(image.Meta))
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
d.Set("desc", image.Desc)
d.Set("shared_with", image.SharedWith)
flattenImage(d, image)
return nil
}
@@ -182,30 +118,28 @@ func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{
func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(ctx, d, m)
if image == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
} else {
urlValues.Add("reason", "")
}
if permanently, ok := d.GetOk("permanently"); ok {
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
_, err = c.DecortAPICall(ctx, "POST", imageDeleteAPI, urlValues)
_, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := image.DeleteRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
if reason, ok := d.GetOk("reason"); ok {
req.Reason = reason.(string)
}
if permanently, ok := d.GetOk("permanently"); ok {
req.Permanently = permanently.(bool)
}
_, err = c.CloudBroker().Image().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
@@ -214,10 +148,12 @@ func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interfac
func resourceImageEditName(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageEditName: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
_, err := c.DecortAPICall(ctx, "POST", imageEditNameAPI, urlValues)
req := image.RenameRequest{
ImageID: uint64(d.Get("image_id").(int)),
Name: d.Get("name").(string),
}
_, err := c.CloudBroker().Image().Rename(ctx, req)
if err != nil {
return err
}
@@ -225,17 +161,15 @@ func resourceImageEditName(ctx context.Context, d *schema.ResourceData, m interf
return nil
}
func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceImageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if d.HasChange("enabled") {
err := resourceImageChangeEnabled(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("name") {
@@ -243,7 +177,6 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("shared_with") {
@@ -251,14 +184,13 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("computeci_id") {
err := resourceImageChangeComputeci(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("enabled_stacks") {
@@ -266,7 +198,6 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChange("link_to") {
@@ -274,21 +205,21 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if d.HasChanges("name", "username", "password", "account_id", "bootable", "hot_resize") {
req := image.EditRequest{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
req.ImageID = uint64(d.Get("image_id").(int))
req.Name = d.Get("name").(string)
urlValues.Add("username", d.Get("username").(string))
urlValues.Add("password", d.Get("password").(string))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("bootable", strconv.FormatBool(d.Get("bootable").(bool)))
urlValues.Add("hotresize", strconv.FormatBool(d.Get("hot_resize").(bool)))
req.Username = d.Get("username").(string)
req.Password = d.Get("password").(string)
req.AccountID = uint64(d.Get("account_id").(int))
req.Bootable = d.Get("bootable").(bool)
req.HotResize = d.Get("hot_resize").(bool)
_, err := c.DecortAPICall(ctx, "POST", imageEditAPI, urlValues)
_, err := c.CloudBroker().Image().Edit(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -298,37 +229,41 @@ func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{
}
func resourceImageChangeEnabled(ctx context.Context, d *schema.ResourceData, m interface{}) error {
var api string
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
imageId := uint64(d.Get("image_id").(int))
if d.Get("enabled").(bool) {
api = imageEnableAPI
req := image.EnableRequest{
ImageID: imageId,
}
_, err := c.CloudBroker().Image().Enable(ctx, req)
if err != nil {
return err
}
} else {
api = imageDisableAPI
}
resp, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return err
}
res, err := strconv.ParseBool(resp)
if err != nil {
return err
}
if !res {
return errors.New("Cannot enable/disable")
req := image.DisableRequest{
ImageID: imageId,
}
_, err := c.CloudBroker().Image().Disable(ctx, req)
if err != nil {
return err
}
}
return nil
}
func resourceImageLink(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceVirtualImageLink: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("targetId", strconv.Itoa(d.Get("link_to").(int)))
_, err := c.DecortAPICall(ctx, "POST", imageLinkAPI, urlValues)
req := image.LinkRequest{
ImageID: uint64(d.Get("image_id").(int)),
TargetID: uint64(d.Get("link_to").(int)),
}
_, err := c.CloudBroker().Image().Link(ctx, req)
if err != nil {
return err
}
@@ -339,23 +274,16 @@ func resourceImageLink(ctx context.Context, d *schema.ResourceData, m interface{
func resourceImageShare(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageShare: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
accIds := d.Get("shared_with").([]interface{})
temp := ""
l := len(accIds)
for i, accId := range accIds {
s := strconv.Itoa(accId.(int))
if i != (l - 1) {
s += ",\n"
} else {
s += "\n"
}
temp = temp + s
req := image.ShareRequest{
ImageId: uint64(d.Get("image_id").(int)),
}
temp = "[" + temp + "]"
urlValues.Add("accounts", temp)
_, err := c.DecortAPICall(ctx, "POST", imageShareAPI, urlValues)
accIds := []uint64{}
for _, accId := range d.Get("shared_with").([]interface{}) {
accIds = append(accIds, uint64(accId.(int)))
}
req.AccountIDs = accIds
_, err := c.CloudBroker().Image().Share(ctx, req)
if err != nil {
return err
}
@@ -365,23 +293,29 @@ func resourceImageShare(ctx context.Context, d *schema.ResourceData, m interface
func resourceImageChangeComputeci(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
computeci := d.Get("computeci_id").(int)
api := ""
imageId := uint64(d.Get("image_id").(int))
computeci := uint64(d.Get("computeci_id").(int))
if computeci == 0 {
api = imageComputeciUnsetAPI
} else {
urlValues.Add("computeciId", strconv.Itoa(computeci))
api = imageComputeciSetAPI
}
req := image.ComputeCIUnsetRequest{
ImageID: imageId,
}
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return err
_, err := c.CloudBroker().Image().ComputeCIUnset(ctx, req)
if err != nil {
return err
}
} else {
req := image.ComputeCISetRequest{
ImageID: imageId,
ComputeCIID: computeci,
}
_, err := c.CloudBroker().Image().ComputeCISet(ctx, req)
if err != nil {
return err
}
}
return nil
@@ -390,21 +324,17 @@ func resourceImageChangeComputeci(ctx context.Context, d *schema.ResourceData, m
func resourceImageUpdateNodes(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageUpdateNodes: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
enabledStacks := d.Get("enabled_stacks").([]interface{})
temp := ""
l := len(enabledStacks)
for i, stackId := range enabledStacks {
s := stackId.(string)
if i != (l - 1) {
s += ","
}
temp = temp + s
req := image.UpdateNodesRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
temp = "[" + temp + "]"
urlValues.Add("enabledStacks", temp)
_, err := c.DecortAPICall(ctx, "POST", imageUpdateNodesAPI, urlValues)
enabledStacks := []uint64{}
for _, stack := range d.Get("enabled_stacks").([]interface{}) {
enabledStacks = append(enabledStacks, uint64(stack.(int)))
}
req.EnabledStacks = enabledStacks
_, err := c.CloudBroker().Image().UpdateNodes(ctx, req)
if err != nil {
return err
}
@@ -661,7 +591,7 @@ func ResourceImage() *schema.Resource {
CreateContext: resourceImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
UpdateContext: resourceImageUpdate,
DeleteContext: resourceImageDelete,
Importer: &schema.ResourceImporter{
@@ -679,36 +609,3 @@ func ResourceImage() *schema.Resource {
Schema: resourceImageSchemaMake(),
}
}
func flattenMeta(m []interface{}) []string {
output := []string{}
for _, item := range m {
switch d := item.(type) {
case string:
output = append(output, d)
case int:
output = append(output, strconv.Itoa(d))
case int64:
output = append(output, strconv.FormatInt(d, 10))
case float64:
output = append(output, strconv.FormatInt(int64(d), 10))
default:
output = append(output, "")
}
}
return output
}
func flattenHistory(history []History) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range history {
t := map[string]interface{}{
"id": item.Id,
"guid": item.Guid,
"timestamp": item.Timestamp,
}
temp = append(temp, t)
}
return temp
}

View File

@@ -33,47 +33,34 @@ package image
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceVirtualImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("targetId", strconv.Itoa(d.Get("target_id").(int)))
req := image.CreateVirtualRequest{
Name: d.Get("name").(string),
TargetID: uint64(d.Get("target_id").(int)),
}
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateVirtualAPI, urlValues)
imageId, err := c.CloudBroker().Image().CreateVirtual(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(imageId)
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
diagnostics := resourceImageRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourceImageRead(ctx, d, m)
}
func resourceVirtualImageSchemaMake() map[string]*schema.Schema {
@@ -324,7 +311,7 @@ func ResourceVirtualImage() *schema.Resource {
CreateContext: resourceVirtualImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageEdit,
UpdateContext: resourceImageUpdate,
DeleteContext: resourceImageDelete,
Importer: &schema.ResourceImporter{

View File

@@ -33,39 +33,28 @@ package image
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Image, error) {
func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*image.RecordImage, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := image.GetRequest{}
if (strconv.Itoa(d.Get("image_id").(int))) != "0" {
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
req.ImageID = uint64(d.Get("image_id").(int))
} else {
urlValues.Add("imageId", d.Id())
id, _ := strconv.ParseUint(d.Id(), 10, 64)
req.ImageID = id
}
resp, err := c.DecortAPICall(ctx, "POST", imageGetAPI, urlValues)
image, err := c.CloudBroker().Image().Get(ctx, req)
if err != nil {
return nil, err
}
if resp == "" {
return nil, nil
}
image := &Image{}
if err := json.Unmarshal([]byte(resp), image); err != nil {
return nil, errors.New(fmt.Sprint("Can not unmarshall data to image: ", resp, " ", image))
}
return image, nil
}

View File

@@ -33,42 +33,34 @@ package image
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ImageList, error) {
imageList := ImageList{}
func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (image.ListImages, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := image.ListRequest{}
if sepId, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepId.(int)))
req.SepID = uint64(sepId.(int))
}
if sharedWith, ok := d.GetOk("shared_with"); ok {
urlValues.Add("sharedWith", strconv.Itoa(sharedWith.(int)))
req.SharedWith = uint64(sharedWith.(int))
}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilityImageListCheckPresence: load image list")
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(imageListRaw), &imageList)
imageList, err := c.CloudBroker().Image().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,30 +33,22 @@ package image
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityImageListStacksCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ImageListStacks, error) {
imageListStacks := ImageListStacks{}
func utilityImageListStacksCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (image.ListStacks, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
log.Debugf("utilityImageListStacksCheckPresence: load image list")
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListStacksApi, urlValues)
if err != nil {
return nil, err
req := image.ListStacksRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
err = json.Unmarshal([]byte(imageListRaw), &imageListStacks)
log.Debugf("utilityImageListStacksCheckPresence: load image list")
imageListStacks, err := c.CloudBroker().Image().ListStacks(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -31,43 +31,68 @@ Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/w
package k8s
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
)
func nodeMasterDefault() K8sNodeRecord {
return K8sNodeRecord{
func nodeMasterDefault() k8s.MasterGroup {
return k8s.MasterGroup{
Num: 1,
Cpu: 2,
Ram: 2048,
CPU: 2,
RAM: 2048,
Disk: 0,
}
}
func nodeWorkerDefault() K8sNodeRecord {
return K8sNodeRecord{
func nodeWorkerDefault() k8s.RecordK8SGroup {
return k8s.RecordK8SGroup{
Num: 1,
Cpu: 1,
Ram: 1024,
CPU: 1,
RAM: 1024,
Disk: 0,
}
}
func parseNode(nodeList []interface{}) K8sNodeRecord {
func parseWorkerNode(nodeList []interface{}) k8s.RecordK8SGroup {
node := nodeList[0].(map[string]interface{})
return K8sNodeRecord{
Num: node["num"].(int),
Cpu: node["cpu"].(int),
Ram: node["ram"].(int),
Disk: node["disk"].(int),
return k8s.RecordK8SGroup{
Num: uint64(node["num"].(int)),
CPU: uint64(node["cpu"].(int)),
RAM: uint64(node["ram"].(int)),
Disk: uint64(node["disk"].(int)),
}
}
func nodeToResource(node K8sNodeRecord) []interface{} {
func parseMasterNode(nodeList []interface{}) k8s.MasterGroup {
node := nodeList[0].(map[string]interface{})
return k8s.MasterGroup{
Num: uint64(node["num"].(int)),
CPU: uint64(node["cpu"].(int)),
RAM: uint64(node["ram"].(int)),
Disk: uint64(node["disk"].(int)),
}
}
func workerNodeToResource(node k8s.RecordK8SGroup) []interface{} {
mp := make(map[string]interface{})
mp["num"] = node.Num
mp["cpu"] = node.Cpu
mp["ram"] = node.Ram
mp["cpu"] = node.CPU
mp["ram"] = node.RAM
mp["disk"] = node.Disk
return []interface{}{mp}
}
func masterNodeToResource(node k8s.MasterGroup) []interface{} {
mp := make(map[string]interface{})
mp["num"] = node.Num
mp["cpu"] = node.CPU
mp["ram"] = node.RAM
mp["disk"] = node.Disk
return []interface{}{mp}

View File

@@ -33,85 +33,84 @@ package k8s
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/lb"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/tasks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceK8sCreate: called with name %s, rg %d", d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
urlValues.Add("k8ciId", strconv.Itoa(d.Get("k8sci_id").(int)))
urlValues.Add("workerGroupName", d.Get("wg_name").(string))
req := k8s.CreateRequest{}
var masterNode K8sNodeRecord
req.Name = d.Get("name").(string)
req.RGID = uint64(d.Get("rg_id").(int))
req.K8CIID = uint64(d.Get("k8sci_id").(int))
req.WorkerGroupName = d.Get("wg_name").(string)
var masterNode k8s.MasterGroup
if masters, ok := d.GetOk("masters"); ok {
masterNode = parseNode(masters.([]interface{}))
masterNode = parseMasterNode(masters.([]interface{}))
} else {
masterNode = nodeMasterDefault()
}
urlValues.Add("masterNum", strconv.Itoa(masterNode.Num))
urlValues.Add("masterCpu", strconv.Itoa(masterNode.Cpu))
urlValues.Add("masterRam", strconv.Itoa(masterNode.Ram))
urlValues.Add("masterDisk", strconv.Itoa(masterNode.Disk))
req.MasterNum = uint64(masterNode.Num)
req.MasterCPU = uint64(masterNode.CPU)
req.MasterRAM = uint64(masterNode.RAM)
req.MasterDisk = uint64(masterNode.Disk)
var workerNode K8sNodeRecord
var workerNode k8s.RecordK8SGroup
if workers, ok := d.GetOk("workers"); ok {
workerNode = parseNode(workers.([]interface{}))
workerNode = parseWorkerNode(workers.([]interface{}))
} else {
workerNode = nodeWorkerDefault()
}
urlValues.Add("workerNum", strconv.Itoa(workerNode.Num))
urlValues.Add("workerCpu", strconv.Itoa(workerNode.Cpu))
urlValues.Add("workerRam", strconv.Itoa(workerNode.Ram))
urlValues.Add("workerDisk", strconv.Itoa(workerNode.Disk))
req.WorkerNum = uint64(workerNode.Num)
req.WorkerCPU = uint64(workerNode.CPU)
req.WorkerRAM = uint64(workerNode.RAM)
req.WorkerDisk = uint64(workerNode.Disk)
//if withLB, ok := d.GetOk("with_lb"); ok {
//urlValues.Add("withLB", strconv.FormatBool(withLB.(bool)))
//}
urlValues.Add("withLB", strconv.FormatBool(true))
if extNet, ok := d.GetOk("extnet_id"); ok {
urlValues.Add("extnetId", strconv.Itoa(extNet.(int)))
if withLB, ok := d.GetOk("with_lb"); ok {
req.WithLB = withLB.(bool)
} else {
urlValues.Add("extnetId", "0")
req.WithLB = true
}
//if desc, ok := d.GetOk("desc"); ok {
//urlValues.Add("desc", desc.(string))
//}
if extNet, ok := d.GetOk("extnet_id"); ok {
req.ExtNetID = uint64(extNet.(int))
} else {
req.ExtNetID = 0
}
resp, err := c.DecortAPICall(ctx, "POST", K8sCreateAPI, urlValues)
if desc, ok := d.GetOk("desc"); ok {
req.Description = desc.(string)
}
resp, err := c.CloudBroker().K8S().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
urlValues.Add("auditId", strings.Trim(resp, `"`))
tasksReq := tasks.GetRequest{
AuditID: resp,
}
for {
resp, err := c.DecortAPICall(ctx, "POST", AsyncTaskGetAPI, urlValues)
task, err := c.CloudBroker().Tasks().Get(ctx, tasksReq)
if err != nil {
return diag.FromErr(err)
}
task := AsyncTask{}
if err := json.Unmarshal([]byte(resp), &task); err != nil {
return diag.FromErr(err)
}
log.Debugf("resourceK8sCreate: instance creating - %s", task.Stage)
if task.Completed {
@@ -126,78 +125,50 @@ func resourceK8sCreate(ctx context.Context, d *schema.ResourceData, m interface{
time.Sleep(time.Second * 10)
}
k8s, err := utilityK8sCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.Set("default_wg_id", k8s.Groups.Workers[0].ID)
urlValues = &url.Values{}
urlValues.Add("lbId", strconv.Itoa(k8s.LbID))
resp, err = c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
var lb LbRecord
if err := json.Unmarshal([]byte(resp), &lb); err != nil {
return diag.FromErr(err)
}
d.Set("extnet_id", lb.ExtNetID)
d.Set("lb_ip", lb.PrimaryNode.FrontendIP)
urlValues = &url.Values{}
urlValues.Add("k8sId", d.Id())
kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues)
if err != nil {
log.Warnf("could not get kubeconfig: %v", err)
}
d.Set("kubeconfig", kubeconfig)
return nil
return resourceK8sRead(ctx, d, m)
}
func resourceK8sRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceK8sRead: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityK8sCheckPresence(ctx, d, m)
if k8s == nil {
k8sData, err := utilityK8sCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
d.Set("name", k8s.Name)
d.Set("rg_id", k8s.RgID)
d.Set("k8sci_id", k8s.CI)
d.Set("wg_name", k8s.Groups.Workers[0].Name)
d.Set("masters", nodeToResource(k8s.Groups.Masters))
d.Set("workers", nodeToResource(k8s.Groups.Workers[0]))
d.Set("default_wg_id", k8s.Groups.Workers[0].ID)
d.Set("name", k8sData.Name)
d.Set("rg_id", k8sData.RGID)
d.Set("k8sci_id", k8sData.CIID)
d.Set("wg_name", k8sData.K8SGroups.Workers[0].Name)
d.Set("masters", masterNodeToResource(k8sData.K8SGroups.Masters))
d.Set("workers", workerNodeToResource(k8sData.K8SGroups.Workers[0]))
d.Set("default_wg_id", k8sData.K8SGroups.Workers[0].ID)
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("lbId", strconv.Itoa(k8s.LbID))
resp, err := c.DecortAPICall(ctx, "POST", LbGetAPI, urlValues)
lbReq := lb.GetRequest{
LBID: k8sData.LBID,
}
lbData, err := c.CloudBroker().LB().Get(ctx, lbReq)
if err != nil {
return diag.FromErr(err)
}
var lb LbRecord
if err := json.Unmarshal([]byte(resp), &lb); err != nil {
return diag.FromErr(err)
}
d.Set("extnet_id", lb.ExtNetID)
d.Set("lb_ip", lb.PrimaryNode.FrontendIP)
d.Set("extnet_id", lbData.ExtNetID)
d.Set("lb_ip", lbData.PrimaryNode.FrontendIP)
urlValues = &url.Values{}
urlValues.Add("k8sId", d.Id())
kubeconfig, err := c.DecortAPICall(ctx, "POST", K8sGetConfigAPI, urlValues)
configReq := k8s.GetConfigRequest{
K8SID: k8sData.ID,
}
kubeconfig, err := c.CloudBroker().K8S().GetConfig(ctx, configReq)
if err != nil {
log.Warnf("could not get kubeconfig: %v", err)
return nil
}
d.Set("kubeconfig", kubeconfig)
return nil
@@ -207,40 +178,47 @@ func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{
log.Debugf("resourceK8sUpdate: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
k8sId, _ := strconv.ParseUint(d.Id(), 10, 64)
if d.HasChange("name") {
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("name", d.Get("name").(string))
req := k8s.UpdateRequest{
K8SID: k8sId,
Name: d.Get("name").(string),
}
_, err := c.DecortAPICall(ctx, "POST", K8sUpdateAPI, urlValues)
_, err := c.CloudBroker().K8S().Update(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
if d.HasChange("workers") {
k8s, err := utilityK8sCheckPresence(ctx, d, m)
k8sData, err := utilityK8sCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
wg := k8s.Groups.Workers[0]
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("workersGroupId", strconv.Itoa(wg.ID))
wg := k8sData.K8SGroups.Workers[0]
deleteReq := k8s.DeleteWorkerFromGroupRequest{
K8SID: k8sId,
WorkersGroupID: wg.ID,
}
addReq := k8s.WorkerAddRequest{
K8SID: k8sId,
WorkersGroupID: wg.ID,
}
newWorkers := parseNode(d.Get("workers").([]interface{}))
newWorkers := parseWorkerNode(d.Get("workers").([]interface{}))
if newWorkers.Num > wg.Num {
urlValues.Add("num", strconv.Itoa(newWorkers.Num-wg.Num))
if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues); err != nil {
addReq.Num = uint64(newWorkers.Num - wg.Num)
if _, err := c.CloudBroker().K8S().WorkerAdd(ctx, addReq); err != nil {
return diag.FromErr(err)
}
} else {
for i := wg.Num - 1; i >= newWorkers.Num; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
if _, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues); err != nil {
deleteReq.WorkerID = wg.DetailedInfo[i].ID
if _, err := c.CloudBroker().K8S().DeleteWorkerFromGroup(ctx, deleteReq); err != nil {
return diag.FromErr(err)
}
}
@@ -253,20 +231,22 @@ func resourceK8sUpdate(ctx context.Context, d *schema.ResourceData, m interface{
func resourceK8sDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceK8sDelete: called with id %s, rg %d", d.Id(), d.Get("rg_id").(int))
k8s, err := utilityK8sCheckPresence(ctx, d, m)
if k8s == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
k8sData, err := utilityK8sCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
urlValues.Add("permanently", "true")
req := k8s.DeleteRequest{
K8SID: k8sData.ID,
}
if perm, ok := d.GetOk("permanently"); ok {
req.Permanently = perm.(bool)
} else {
req.Permanently = false
}
_, err = c.DecortAPICall(ctx, "POST", K8sDeleteAPI, urlValues)
_, err = c.CloudBroker().K8S().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}

View File

@@ -33,12 +33,11 @@ package k8s
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
@@ -47,15 +46,16 @@ func resourceK8sWgCreate(ctx context.Context, d *schema.ResourceData, m interfac
log.Debugf("resourceK8sWgCreate: called with k8s id %d", d.Get("k8s_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("workerNum", strconv.Itoa(d.Get("num").(int)))
urlValues.Add("workerCpu", strconv.Itoa(d.Get("cpu").(int)))
urlValues.Add("workerRam", strconv.Itoa(d.Get("ram").(int)))
urlValues.Add("workerDisk", strconv.Itoa(d.Get("disk").(int)))
req := k8s.WorkersGroupAddRequest{
K8SID: uint64(d.Get("k8s_id").(int)),
Name: d.Get("name").(string),
WorkerNum: uint64(d.Get("num").(int)),
WorkerCPU: uint64(d.Get("cpu").(int)),
WorkerRAM: uint64(d.Get("ram").(int)),
WorkerDisk: uint64(d.Get("disk").(int)),
}
resp, err := c.DecortAPICall(ctx, "POST", K8sWgCreateAPI, urlValues)
resp, err := c.CloudBroker().K8S().WorkersGroupAdd(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -69,15 +69,15 @@ func resourceK8sWgRead(ctx context.Context, d *schema.ResourceData, m interface{
log.Debugf("resourceK8sWgRead: called with k8s id %d", d.Get("k8s_id").(int))
wg, err := utilityK8sWgCheckPresence(ctx, d, m)
if wg == nil {
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
d.Set("name", wg.Name)
d.Set("num", wg.Num)
d.Set("cpu", wg.Cpu)
d.Set("ram", wg.Ram)
d.Set("cpu", wg.CPU)
d.Set("ram", wg.RAM)
d.Set("disk", wg.Disk)
return nil
@@ -93,20 +93,26 @@ func resourceK8sWgUpdate(ctx context.Context, d *schema.ResourceData, m interfac
return diag.FromErr(err)
}
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("workersGroupId", d.Id())
addReq := k8s.WorkerAddRequest{
K8SID: uint64(d.Get("k8s_id").(int)),
WorkersGroupID: wg.ID,
}
if newNum := d.Get("num").(int); newNum > wg.Num {
urlValues.Add("num", strconv.Itoa(newNum-wg.Num))
_, err := c.DecortAPICall(ctx, "POST", K8sWorkerAddAPI, urlValues)
delReq := k8s.DeleteWorkerFromGroupRequest{
K8SID: uint64(d.Get("k8s_id").(int)),
WorkersGroupID: wg.ID,
}
if newNum := uint64(d.Get("num").(int)); newNum > wg.Num {
addReq.Num = newNum - wg.Num
_, err := c.CloudBroker().K8S().WorkerAdd(ctx, addReq)
if err != nil {
return diag.FromErr(err)
}
} else {
for i := wg.Num - 1; i >= newNum; i-- {
urlValues.Set("workerId", strconv.Itoa(wg.DetailedInfo[i].ID))
_, err := c.DecortAPICall(ctx, "POST", K8sWorkerDeleteAPI, urlValues)
delReq.WorkerID = wg.DetailedInfo[i].ID
_, err := c.CloudBroker().K8S().DeleteWorkerFromGroup(ctx, delReq)
if err != nil {
return diag.FromErr(err)
}
@@ -120,23 +126,23 @@ func resourceK8sWgDelete(ctx context.Context, d *schema.ResourceData, m interfac
log.Debugf("resourceK8sWgDelete: called with k8s id %d", d.Get("k8s_id").(int))
wg, err := utilityK8sWgCheckPresence(ctx, d, m)
if wg == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
urlValues.Add("workersGroupId", strconv.Itoa(wg.ID))
_, err = c.DecortAPICall(ctx, "POST", K8sWgDeleteAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := k8s.WorkersGroupDeleteRequest{
K8SID: uint64(d.Get("k8s_id").(int)),
WorkersGroupID: wg.ID,
}
_, err = c.CloudBroker().K8S().WorkersGroupDelete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}

View File

@@ -33,31 +33,24 @@ package k8s
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sRecord, error) {
func utilityK8sCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*k8s.RecordK8S, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", d.Id())
req := k8s.GetRequest{}
k8sId, _ := strconv.ParseUint(d.Id(), 10, 64)
resp, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues)
req.K8SID = k8sId
k8s, err := c.CloudBroker().K8S().Get(ctx, req)
if err != nil {
return nil, err
}
if resp == "" {
return nil, nil
}
var k8s K8sRecord
if err := json.Unmarshal([]byte(resp), &k8s); err != nil {
return nil, err
}
return &k8s, nil
return k8s, nil
}

View File

@@ -33,40 +33,28 @@ package k8s
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*K8sNodeRecord, error) {
func utilityK8sWgCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*k8s.RecordK8SGroup, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("k8sId", strconv.Itoa(d.Get("k8s_id").(int)))
req := k8s.GetRequest{
K8SID: uint64(d.Get("k8s_id").(int)),
}
resp, err := c.DecortAPICall(ctx, "POST", K8sGetAPI, urlValues)
k8sData, err := c.CloudBroker().K8S().Get(ctx, req)
if err != nil {
return nil, err
}
if resp == "" {
return nil, nil
}
k8sWgID, _ := strconv.ParseUint(d.Id(), 10, 64)
var k8s K8sRecord
if err := json.Unmarshal([]byte(resp), &k8s); err != nil {
return nil, err
}
id, err := strconv.Atoi(d.Id())
if err != nil {
return nil, err
}
for _, wg := range k8s.Groups.Workers {
if wg.ID == id {
for _, wg := range k8sData.K8SGroups.Workers {
if wg.ID == k8sWgID {
return &wg, nil
}
}

View File

@@ -33,13 +33,13 @@ package kvmvm
import (
"context"
"encoding/json"
"fmt"
// "net/url"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -48,7 +48,7 @@ import (
// Parse list of all disks from API compute/get into a list of "extra disks" attached to this compute
// Extra disks are all compute disks but a boot disk.
func parseComputeDisksToExtraDisks(disks []DiskRecord) []interface{} {
func parseComputeDisksToExtraDisks(disks compute.ListDisks) []interface{} {
// this return value will be used to d.Set("extra_disks",) item of dataSourceCompute schema,
// which is a simple list of integer disk IDs excluding boot disk ID
length := len(disks)
@@ -76,7 +76,7 @@ func parseComputeDisksToExtraDisks(disks []DiskRecord) []interface{} {
return result
}
func findBootDisk(disks []DiskRecord) *DiskRecord {
func findBootDisk(disks compute.ListDisks) *compute.ItemDisk {
for _, d := range disks {
if d.Type == "B" {
return &d
@@ -84,12 +84,12 @@ func findBootDisk(disks []DiskRecord) *DiskRecord {
}
// some computes don't have a boot disk, so...
return &DiskRecord{}
return &compute.ItemDisk{}
}
// Parse the list of interfaces from compute/get response into a list of networks
// attached to this compute
func parseComputeInterfacesToNetworks(ifaces []InterfaceRecord) []interface{} {
func parseComputeInterfacesToNetworks(ifaces compute.ListInterfaces) []interface{} {
// return value will be used to d.Set("network") item of dataSourceCompute schema
length := len(ifaces)
log.Debugf("parseComputeInterfacesToNetworks: called for %d ifaces", length)
@@ -113,68 +113,58 @@ func parseComputeInterfacesToNetworks(ifaces []InterfaceRecord) []interface{} {
return result
}
func flattenCompute(d *schema.ResourceData, compFacts string) error {
func flattenCompute(d *schema.ResourceData, compFacts *compute.RecordCompute) error {
// This function expects that compFacts string contains response from API compute/get,
// i.e. detailed information about compute instance.
//
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceComputeExists(...) method
model := ComputeGetResp{}
log.Debugf("flattenCompute: ready to unmarshal string %s", compFacts)
err := json.Unmarshal([]byte(compFacts), &model)
if err != nil {
return err
}
log.Debugf("flattenCompute: ID %d, RG ID %d", model.ID, model.RgID)
log.Debugf("flattenCompute: ID %d, RG ID %d", compFacts.ID, compFacts.RGID)
d.SetId(fmt.Sprintf("%d", model.ID))
// d.Set("compute_id", model.ID) - we should NOT set compute_id in the schema here: if it was set - it is already set, if it wasn't - we shouldn't
d.Set("name", model.Name)
d.Set("rg_id", model.RgID)
d.Set("rg_name", model.RgName)
d.Set("account_id", model.AccountID)
d.Set("account_name", model.AccountName)
d.Set("driver", model.Driver)
d.Set("cpu", model.Cpu)
d.Set("ram", model.Ram)
// d.Set("boot_disk_size", model.BootDiskSize) - bootdiskSize key in API compute/get is always zero, so we set boot_disk_size in another way
d.Set("image_id", model.ImageID)
d.Set("description", model.Desc)
d.Set("cloud_init", "applied") // NOTE: for existing compute we hard-code this value as an indicator for DiffSuppress fucntion
// d.Set("status", model.Status)
// d.Set("tech_status", model.TechStatus)
d.SetId(fmt.Sprintf("%d", compFacts.ID))
d.Set("name", compFacts.Name)
d.Set("rg_id", compFacts.RGID)
d.Set("rg_name", compFacts.RGName)
d.Set("account_id", compFacts.AccountID)
d.Set("account_name", compFacts.AccountName)
d.Set("driver", compFacts.Driver)
d.Set("cpu", compFacts.CPUs)
d.Set("ram", compFacts.RAM)
d.Set("image_id", compFacts.ImageID)
d.Set("description", compFacts.Description)
d.Set("cloud_init", "applied")
if model.TechStatus == "STARTED" {
if compFacts.TechStatus == "STARTED" {
d.Set("started", true)
} else {
d.Set("started", false)
}
bootDisk := findBootDisk(model.Disks)
bootDisk := findBootDisk(compFacts.Disks)
d.Set("boot_disk_size", bootDisk.SizeMax)
d.Set("boot_disk_id", bootDisk.ID) // we may need boot disk ID in resize operations
d.Set("sep_id", bootDisk.SepID)
d.Set("sep_id", bootDisk.SEPID)
d.Set("pool", bootDisk.Pool)
if len(model.Disks) > 0 {
log.Debugf("flattenCompute: calling parseComputeDisksToExtraDisks for %d disks", len(model.Disks))
if err = d.Set("extra_disks", parseComputeDisksToExtraDisks(model.Disks)); err != nil {
if len(compFacts.Disks) > 0 {
log.Debugf("flattenCompute: calling parseComputeDisksToExtraDisks for %d disks", len(compFacts.Disks))
if err := d.Set("extra_disks", parseComputeDisksToExtraDisks(compFacts.Disks)); err != nil {
return err
}
}
if len(model.Interfaces) > 0 {
log.Debugf("flattenCompute: calling parseComputeInterfacesToNetworks for %d interfaces", len(model.Interfaces))
if err = d.Set("network", parseComputeInterfacesToNetworks(model.Interfaces)); err != nil {
if len(compFacts.Interfaces) > 0 {
log.Debugf("flattenCompute: calling parseComputeInterfacesToNetworks for %d interfaces", len(compFacts.Interfaces))
if err := d.Set("network", parseComputeInterfacesToNetworks(compFacts.Interfaces)); err != nil {
return err
}
}
if len(model.OsUsers) > 0 {
log.Debugf("flattenCompute: calling parseOsUsers for %d logins", len(model.OsUsers))
if err = d.Set("os_users", parseOsUsers(model.OsUsers)); err != nil {
if len(compFacts.OSUsers) > 0 {
log.Debugf("flattenCompute: calling parseOsUsers for %d logins", len(compFacts.OSUsers))
if err := d.Set("os_users", parseOsUsers(compFacts.OSUsers)); err != nil {
return err
}
}
@@ -184,10 +174,8 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
func dataSourceComputeRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
compFacts, err := utilityComputeCheckPresence(ctx, d, m)
if compFacts == "" {
// if empty string is returned from utilityComputeCheckPresence then there is no
// such Compute and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
if compFacts == nil {
d.SetId("")
return diag.FromErr(err)
}
@@ -277,7 +265,6 @@ func DataSourceCompute() *schema.Resource {
Computed: true,
Description: "Name of the OS image this compute instance is based on.",
},
"boot_disk_size": {
Type: schema.TypeInt,
Computed: true,

View File

@@ -33,17 +33,18 @@ package kvmvm
import (
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func parseOsUsers(logins []OsUserRecord) []interface{} {
func parseOsUsers(logins compute.ListOSUsers) []interface{} {
var result = make([]interface{}, len(logins))
for index, value := range logins {
elem := make(map[string]interface{})
elem["guid"] = value.Guid
elem["guid"] = value.GUID
elem["login"] = value.Login
elem["password"] = value.Password
elem["public_key"] = value.PubKey

View File

@@ -33,14 +33,16 @@ package kvmvm
import (
"context"
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/disks"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/kvmppc"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/kvmx86"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/statefuncs"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -49,110 +51,112 @@ import (
func cloudInitDiffSupperss(key, oldVal, newVal string, d *schema.ResourceData) bool {
if oldVal == "" && newVal != "applied" {
// if old value for "cloud_init" resource is empty string, it means that we are creating new compute
// and there is a chance that the user will want custom cloud init parameters - so we check if
// cloud_init is explicitly set in TF file by making sure that its new value is different from "applied",
// which is a reserved key word.
log.Debugf("cloudInitDiffSupperss: key=%s, oldVal=%q, newVal=%q -> suppress=FALSE", key, oldVal, newVal)
return false // there is a difference between stored and new value
return false
}
log.Debugf("cloudInitDiffSupperss: key=%s, oldVal=%q, newVal=%q -> suppress=TRUE", key, oldVal, newVal)
return true // suppress difference
return true
}
func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// we assume all mandatory parameters it takes to create a comptue instance are properly
// specified - we rely on schema "Required" attributes to let Terraform validate them for us
log.Debugf("resourceComputeCreate: called for Compute name %q, RG ID %d", d.Get("name").(string), d.Get("rg_id").(int))
// create basic Compute (i.e. without extra disks and network connections - those will be attached
// by subsequent individual API calls).
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("rgId", fmt.Sprintf("%d", d.Get("rg_id").(int)))
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("cpu", fmt.Sprintf("%d", d.Get("cpu").(int)))
urlValues.Add("ram", fmt.Sprintf("%d", d.Get("ram").(int)))
urlValues.Add("imageId", fmt.Sprintf("%d", d.Get("image_id").(int)))
urlValues.Add("bootDisk", fmt.Sprintf("%d", d.Get("boot_disk_size").(int)))
urlValues.Add("netType", "NONE") // at the 1st step create isolated compute
urlValues.Add("start", "0") // at the 1st step create compute in a stopped state
reqPPC := kvmppc.CreateRequest{}
reqX86 := kvmx86.CreateRequest{}
reqPPC.RGID = uint64(d.Get("rg_id").(int))
reqX86.RGID = uint64(d.Get("rg_id").(int))
reqPPC.Name = d.Get("name").(string)
reqX86.Name = d.Get("name").(string)
reqPPC.CPU = uint64(d.Get("cpu").(int))
reqPPC.RAM = uint64(d.Get("ram").(int))
reqPPC.ImageID = uint64(d.Get("image_id").(int))
reqPPC.BootDisk = uint64(d.Get("boot_disk_size").(int))
reqPPC.NetType = "NONE"
reqPPC.Start = false
reqX86.CPU = uint64(d.Get("cpu").(int))
reqX86.RAM = uint64(d.Get("ram").(int))
reqX86.ImageID = uint64(d.Get("image_id").(int))
reqX86.BootDisk = uint64(d.Get("boot_disk_size").(int))
reqX86.NetType = "NONE"
reqX86.Start = false
argVal, argSet := d.GetOk("description")
if argSet {
urlValues.Add("desc", argVal.(string))
reqPPC.Description = argVal.(string)
reqX86.Description = argVal.(string)
}
if sepID, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepID.(int)))
reqPPC.SEPID = uint64(sepID.(int))
reqX86.SEPID = uint64(sepID.(int))
}
if pool, ok := d.GetOk("pool"); ok {
urlValues.Add("pool", pool.(string))
}
/*
sshKeysVal, sshKeysSet := d.GetOk("ssh_keys")
if sshKeysSet {
// process SSH Key settings and set API values accordingly
log.Debugf("resourceComputeCreate: calling makeSshKeysArgString to setup SSH keys for guest login(s)")
urlValues.Add("userdata", makeSshKeysArgString(sshKeysVal.([]interface{})))
}
*/
computeCreateAPI := KvmX86CreateAPI
driver := d.Get("driver").(string)
if driver == "KVM_PPC" {
computeCreateAPI = KvmPPCCreateAPI
log.Debugf("resourceComputeCreate: creating Compute of type KVM VM PowerPC")
} else { // note that we do not validate arch value for explicit "KVM_X86" here
log.Debugf("resourceComputeCreate: creating Compute of type KVM VM x86")
reqPPC.Pool = pool.(string)
reqX86.Pool = pool.(string)
}
argVal, argSet = d.GetOk("cloud_init")
if argSet {
// userdata must not be empty string and must not be a reserved keyword "applied"
userdata := argVal.(string)
if userdata != "" && userdata != "applied" {
urlValues.Add("userdata", userdata)
reqPPC.Userdata = userdata
reqX86.Userdata = userdata
}
}
apiResp, err := c.DecortAPICall(ctx, "POST", computeCreateAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
// Compute create API returns ID of the new Compute instance on success
var createdID uint64
driver := d.Get("driver").(string)
if driver == "KVM_PPC" {
log.Debugf("resourceComputeCreate: creating Compute of type KVM VM PowerPC")
id, err := c.CloudBroker().KVMPPC().Create(ctx, reqPPC)
if err != nil {
return diag.FromErr(err)
}
d.SetId(apiResp) // update ID of the resource to tell Terraform that the resource exists, albeit partially
compId, _ := strconv.Atoi(apiResp)
createdID = id
} else {
log.Debugf("resourceComputeCreate: creating Compute of type KVM VM x86")
id, err := c.CloudBroker().KVMX86().Create(ctx, reqX86)
if err != nil {
return diag.FromErr(err)
}
createdID = id
}
d.SetId(strconv.FormatUint(createdID, 10))
cleanup := false
defer func() {
if cleanup {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("permanently", "1")
urlValues.Add("detachDisks", "1")
req := compute.DeleteRequest{
ComputeID: createdID,
Permanently: true,
DetachDisks: true,
}
if _, err := c.DecortAPICall(ctx, "POST", ComputeDeleteAPI, urlValues); err != nil {
if _, err := c.CloudBroker().Compute().Delete(ctx, req); err != nil {
log.Errorf("resourceComputeCreate: could not delete compute after failed creation: %v", err)
}
d.SetId("")
}
}()
log.Debugf("resourceComputeCreate: new simple Compute ID %d, name %s created", compId, d.Get("name").(string))
log.Debugf("resourceComputeCreate: new simple Compute ID %d, name %s created", createdID, d.Get("name").(string))
// Configure data disks if any
argVal, argSet = d.GetOk("extra_disks")
if argSet && argVal.(*schema.Set).Len() > 0 {
// urlValues.Add("desc", argVal.(string))
log.Debugf("resourceComputeCreate: calling utilityComputeExtraDisksConfigure to attach %d extra disk(s)", argVal.(*schema.Set).Len())
err = utilityComputeExtraDisksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
err := utilityComputeExtraDisksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
if err != nil {
log.Errorf("resourceComputeCreate: error when attaching extra disk(s) to a new Compute ID %d: %v", compId, err)
log.Errorf("resourceComputeCreate: error when attaching extra disk(s) to a new Compute ID %d: %v", createdID, err)
cleanup = true
return diag.FromErr(err)
}
@@ -161,32 +165,28 @@ func resourceComputeCreate(ctx context.Context, d *schema.ResourceData, m interf
argVal, argSet = d.GetOk("network")
if argSet && argVal.(*schema.Set).Len() > 0 {
log.Debugf("resourceComputeCreate: calling utilityComputeNetworksConfigure to attach %d network(s)", argVal.(*schema.Set).Len())
err = utilityComputeNetworksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
err := utilityComputeNetworksConfigure(ctx, d, m, false) // do_delta=false, as we are working on a new compute
if err != nil {
log.Errorf("resourceComputeCreate: error when attaching networks to a new Compute ID %d: %s", compId, err)
log.Errorf("resourceComputeCreate: error when attaching networks to a new Compute ID %d: %s", createdID, err)
cleanup = true
return diag.FromErr(err)
}
}
// Note bene: we created compute in a STOPPED state (this is required to properly attach 1st network interface),
// now we need to start it before we report the sequence complete
if d.Get("started").(bool) {
reqValues := &url.Values{}
reqValues.Add("computeId", fmt.Sprintf("%d", compId))
log.Debugf("resourceComputeCreate: starting Compute ID %d after completing its resource configuration", compId)
if _, err := c.DecortAPICall(ctx, "POST", ComputeStartAPI, reqValues); err != nil {
req := compute.StartRequest{
ComputeID: createdID,
}
log.Debugf("resourceComputeCreate: starting Compute ID %d after completing its resource configuration", createdID)
if _, err := c.CloudBroker().Compute().Start(ctx, req); err != nil {
cleanup = true
return diag.FromErr(err)
}
}
log.Debugf("resourceComputeCreate: new Compute ID %d, name %s creation sequence complete", compId, d.Get("name").(string))
log.Debugf("resourceComputeCreate: new Compute ID %d, name %s creation sequence complete", createdID, d.Get("name").(string))
// We may reuse dataSourceComputeRead here as we maintain similarity
// between Compute resource and Compute data source schemas
// Compute read function will also update resource ID on success, so that Terraform
// will know the resource exists
return dataSourceComputeRead(ctx, d, m)
}
@@ -195,11 +195,11 @@ func resourceComputeRead(ctx context.Context, d *schema.ResourceData, m interfac
d.Get("name").(string), d.Get("rg_id").(int))
compFacts, err := utilityComputeCheckPresence(ctx, d, m)
if compFacts == "" {
if compFacts == nil {
if err != nil {
return diag.FromErr(err)
}
// Compute with such name and RG ID was not found
return nil
}
@@ -218,6 +218,7 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
d.Id(), d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
computeID, _ := strconv.ParseUint(d.Id(), 10, 64)
/*
1. Resize CPU/RAM
@@ -228,32 +229,34 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
*/
// 1. Resize CPU/RAM
params := &url.Values{}
resizeReq := compute.ResizeRequest{
ComputeID: computeID,
Force: true,
}
doUpdate := false
params.Add("computeId", d.Id())
oldCpu, newCpu := d.GetChange("cpu")
if oldCpu.(int) != newCpu.(int) {
params.Add("cpu", fmt.Sprintf("%d", newCpu.(int)))
resizeReq.CPU = uint64(newCpu.(int))
doUpdate = true
} else {
params.Add("cpu", "0") // no change to CPU allocation
resizeReq.CPU = 0
}
oldRam, newRam := d.GetChange("ram")
if oldRam.(int) != newRam.(int) {
params.Add("ram", fmt.Sprintf("%d", newRam.(int)))
resizeReq.RAM = uint64(newRam.(int))
doUpdate = true
} else {
params.Add("ram", "0")
resizeReq.RAM = 0
}
if doUpdate {
log.Debugf("resourceComputeUpdate: changing CPU %d -> %d and/or RAM %d -> %d",
oldCpu.(int), newCpu.(int),
oldRam.(int), newRam.(int))
params.Add("force", "true")
_, err := c.DecortAPICall(ctx, "POST", ComputeResizeAPI, params)
_, err := c.CloudBroker().Compute().Resize(ctx, resizeReq)
if err != nil {
return diag.FromErr(err)
}
@@ -262,12 +265,15 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
// 2. Resize (grow) Boot disk
oldSize, newSize := d.GetChange("boot_disk_size")
if oldSize.(int) < newSize.(int) {
bdsParams := &url.Values{}
bdsParams.Add("diskId", fmt.Sprintf("%d", d.Get("boot_disk_id").(int)))
bdsParams.Add("size", fmt.Sprintf("%d", newSize.(int)))
req := disks.ResizeRequest{
DiskID: uint64(d.Get("boot_disk_id").(int)),
Size: uint64(newSize.(int)),
}
log.Debugf("resourceComputeUpdate: compute ID %s, boot disk ID %d resize %d -> %d",
d.Id(), d.Get("boot_disk_id").(int), oldSize.(int), newSize.(int))
_, err := c.DecortAPICall(ctx, "POST", DisksResizeAPI, bdsParams)
_, err := c.CloudBroker().Disks().Resize(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -288,14 +294,18 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
}
if d.HasChange("started") {
params := &url.Values{}
params.Add("computeId", d.Id())
if d.Get("started").(bool) {
if _, err := c.DecortAPICall(ctx, "POST", ComputeStartAPI, params); err != nil {
req := compute.StartRequest{
ComputeID: computeID,
}
if _, err := c.CloudBroker().Compute().Start(ctx, req); err != nil {
return diag.FromErr(err)
}
} else {
if _, err := c.DecortAPICall(ctx, "POST", ComputeStopAPI, params); err != nil {
req := compute.StopRequest{
ComputeID: computeID,
}
if _, err := c.CloudBroker().Compute().Stop(ctx, req); err != nil {
return diag.FromErr(err)
}
}
@@ -307,21 +317,19 @@ func resourceComputeUpdate(ctx context.Context, d *schema.ResourceData, m interf
}
func resourceComputeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// NOTE: this function destroys target Compute instance "permanently", so
// there is no way to restore it.
// If compute being destroyed has some extra disks attached, they are
// detached from the compute
log.Debugf("resourceComputeDelete: called for Compute name %s, RG ID %d",
d.Get("name").(string), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
computeID, _ := strconv.ParseUint(d.Id(), 10, 64)
params := &url.Values{}
params.Add("computeId", d.Id())
params.Add("permanently", "1")
params.Add("detachDisks", "1")
req := compute.DeleteRequest{
ComputeID: computeID,
Permanently: d.Get("permanently").(bool),
DetachDisks: d.Get("detach_disks").(bool),
}
if _, err := c.DecortAPICall(ctx, "POST", ComputeDeleteAPI, params); err != nil {
if _, err := c.CloudBroker().Compute().Delete(ctx, req); err != nil {
return diag.FromErr(err)
}

View File

@@ -33,31 +33,23 @@ package kvmvm
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceData, m interface{}, do_delta bool) error {
// d is filled with data according to computeResource schema, so extra disks config is retrieved via "extra_disks" key
// If do_delta is true, this function will identify changes between new and existing specs for extra disks and try to
// update compute configuration accordingly
// Otherwise it will apply whatever is found in the new set of "extra_disks" right away.
// Primary use of do_delta=false is when calling this function from compute Create handler.
// Note that this function will not abort on API errors, but will continue to configure (attach / detach) other individual
// disks via atomic API calls. However, it will not retry failed manipulation on the same disk.
c := m.(*controller.ControllerCfg)
computeID, _ := strconv.ParseUint(d.Id(), 10, 64)
log.Debugf("utilityComputeExtraDisksConfigure: called for Compute ID %s with do_delta = %t", d.Id(), do_delta)
// NB: as of rc-1.25 "extra_disks" are TypeSet with the elem of TypeInt
old_set, new_set := d.GetChange("extra_disks")
apiErrCount := 0
@@ -69,12 +61,13 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
}
for _, disk := range new_set.(*schema.Set).List() {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", disk.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskAttachAPI, urlValues)
req := compute.DiskAttachRequest{
ComputeID: computeID,
DiskID: uint64(disk.(int)),
}
_, err := c.CloudBroker().Compute().DiskAttach(ctx, req)
if err != nil {
// failed to attach extra disk - partial resource update
apiErrCount++
lastSavedError = err
}
@@ -92,10 +85,12 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
detach_set := old_set.(*schema.Set).Difference(new_set.(*schema.Set))
log.Debugf("utilityComputeExtraDisksConfigure: detach set has %d items for Compute ID %s", detach_set.Len(), d.Id())
for _, diskId := range detach_set.List() {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", diskId.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskDetachAPI, urlValues)
req := compute.DiskDetachRequest{
ComputeID: computeID,
DiskID: uint64(diskId.(int)),
}
_, err := c.CloudBroker().Compute().DiskDetach(ctx, req)
if err != nil {
// failed to detach disk - there will be partial resource update
log.Errorf("utilityComputeExtraDisksConfigure: failed to detach disk ID %d from Compute ID %s: %s", diskId.(int), d.Id(), err)
@@ -107,10 +102,12 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
attach_set := new_set.(*schema.Set).Difference(old_set.(*schema.Set))
log.Debugf("utilityComputeExtraDisksConfigure: attach set has %d items for Compute ID %s", attach_set.Len(), d.Id())
for _, diskId := range attach_set.List() {
urlValues := &url.Values{}
urlValues.Add("computeId", d.Id())
urlValues.Add("diskId", fmt.Sprintf("%d", diskId.(int)))
_, err := c.DecortAPICall(ctx, "POST", ComputeDiskAttachAPI, urlValues)
req := compute.DiskAttachRequest{
ComputeID: computeID,
DiskID: uint64(diskId.(int)),
}
_, err := c.CloudBroker().Compute().DiskAttach(ctx, req)
if err != nil {
// failed to attach disk - there will be partial resource update
log.Errorf("utilityComputeExtraDisksConfigure: failed to attach disk ID %d to Compute ID %s: %s", diskId.(int), d.Id(), err)
@@ -129,13 +126,8 @@ func utilityComputeExtraDisksConfigure(ctx context.Context, d *schema.ResourceDa
}
func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData, m interface{}, do_delta bool) error {
// "d" is filled with data according to computeResource schema, so extra networks config is retrieved via "network" key
// If do_delta is true, this function will identify changes between new and existing specs for network and try to
// update compute configuration accordingly
// Otherwise it will apply whatever is found in the new set of "network" right away.
// Primary use of do_delta=false is when calling this function from compute Create handler.
c := m.(*controller.ControllerCfg)
computeID, _ := strconv.ParseUint(d.Id(), 10, 64)
old_set, new_set := d.GetChange("network")
@@ -148,18 +140,19 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
}
for _, runner := range new_set.(*schema.Set).List() {
urlValues := &url.Values{}
net_data := runner.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("netType", net_data["net_type"].(string))
urlValues.Add("netId", fmt.Sprintf("%d", net_data["net_id"].(int)))
ipaddr, ipSet := net_data["ip_address"] // "ip_address" key is optional
if ipSet {
urlValues.Add("ipAddr", ipaddr.(string))
req := compute.NetAttachRequest{
ComputeID: computeID,
NetType: net_data["net_type"].(string),
NetID: uint64(net_data["net_id"].(int)),
}
_, err := c.DecortAPICall(ctx, "POST", ComputeNetAttachAPI, urlValues)
ipaddr, ipSet := net_data["ip_address"]
if ipSet {
req.IPAddr = ipaddr.(string)
}
_, err := c.CloudBroker().Compute().NetAttach(ctx, req)
if err != nil {
// failed to attach network - partial resource update
apiErrCount++
lastSavedError = err
}
@@ -176,12 +169,14 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
detach_set := old_set.(*schema.Set).Difference(new_set.(*schema.Set))
log.Debugf("utilityComputeNetworksConfigure: detach set has %d items for Compute ID %s", detach_set.Len(), d.Id())
for _, runner := range detach_set.List() {
urlValues := &url.Values{}
net_data := runner.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("ipAddr", net_data["ip_address"].(string))
urlValues.Add("mac", net_data["mac"].(string))
_, err := c.DecortAPICall(ctx, "POST", ComputeNetDetachAPI, urlValues)
req := compute.NetDetachRequest{
ComputeID: computeID,
IPAddr: net_data["ip_address"].(string),
MAC: net_data["mac"].(string),
}
_, err := c.CloudBroker().Compute().NetDetach(ctx, req)
if err != nil {
// failed to detach this network - there will be partial resource update
log.Errorf("utilityComputeNetworksConfigure: failed to detach net ID %d of type %s from Compute ID %s: %s",
@@ -194,15 +189,18 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
attach_set := new_set.(*schema.Set).Difference(old_set.(*schema.Set))
log.Debugf("utilityComputeNetworksConfigure: attach set has %d items for Compute ID %s", attach_set.Len(), d.Id())
for _, runner := range attach_set.List() {
urlValues := &url.Values{}
net_data := runner.(map[string]interface{})
urlValues.Add("computeId", d.Id())
urlValues.Add("netId", fmt.Sprintf("%d", net_data["net_id"].(int)))
urlValues.Add("netType", net_data["net_type"].(string))
if net_data["ip_address"].(string) != "" {
urlValues.Add("ipAddr", net_data["ip_address"].(string))
req := compute.NetAttachRequest{
ComputeID: computeID,
NetID: uint64(net_data["net_id"].(int)),
NetType: net_data["net_type"].(string),
}
_, err := c.DecortAPICall(ctx, "POST", ComputeNetAttachAPI, urlValues)
if net_data["ip_address"].(string) != "" {
req.IPAddr = net_data["ip_address"].(string)
}
_, err := c.CloudBroker().Compute().NetAttach(ctx, req)
if err != nil {
// failed to attach this network - there will be partial resource update
log.Errorf("utilityComputeNetworksConfigure: failed to attach net ID %d of type %s to Compute ID %s: %s",
@@ -221,31 +219,15 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
return nil
}
func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate Compute by one of the following approaches:
// - if compute_id is specified - locate by compute ID
// - if compute_name is specified - locate by a combination of compute name and resource
// group ID
//
// If succeeded, it returns non-empty string that contains JSON formatted facts about the
// Compute as returned by compute/get API call.
// Otherwise it returns empty string and meaningful error.
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for resource's Exists method.
//
func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*compute.RecordCompute, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with compute ID set so
// that Import of Compute resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
computeID, err := strconv.ParseUint(d.Id(), 10, 64)
if err != nil || computeID <= 0 {
computeId, argSet := d.GetOk("compute_id") // NB: compute_id is NOT present in computeResource schema!
if argSet {
theId = computeId.(int)
computeID = uint64(computeId.(int))
idSet = true
}
} else {
@@ -254,11 +236,14 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
if idSet {
// compute ID is specified, try to get compute instance straight by this ID
log.Debugf("utilityComputeCheckPresence: locating compute by its ID %d", theId)
urlValues.Add("computeId", fmt.Sprintf("%d", theId))
computeFacts, err := c.DecortAPICall(ctx, "POST", ComputeGetAPI, urlValues)
log.Debugf("utilityComputeCheckPresence: locating compute by its ID %d", computeID)
req := compute.GetRequest{
ComputeID: computeID,
}
computeFacts, err := c.CloudBroker().Compute().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return computeFacts, nil
}
@@ -267,44 +252,40 @@ func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m
// and RG ID
computeName, argSet := d.GetOk("name")
if !argSet {
return "", fmt.Errorf("Cannot locate compute instance if name is empty and no compute ID specified")
return nil, fmt.Errorf("Cannot locate compute instance if name is empty and no compute ID specified")
}
rgId, argSet := d.GetOk("rg_id")
if !argSet {
return "", fmt.Errorf("Cannot locate compute by name %s if no resource group ID is set", computeName.(string))
return nil, fmt.Errorf("Cannot locate compute by name %s if no resource group ID is set", computeName.(string))
}
urlValues.Add("rgId", fmt.Sprintf("%d", rgId))
apiResp, err := c.DecortAPICall(ctx, "POST", RgListComputesAPI, urlValues)
rgListComputesReq := rg.ListComputesRequest{
RGID: uint64(rgId.(int)),
}
computeList, err := c.CloudBroker().RG().ListComputes(ctx, rgListComputesReq)
if err != nil {
return "", err
return nil, err
}
log.Debugf("utilityComputeCheckPresence: ready to unmarshal string %s", apiResp)
computeList := RgListComputesResp{}
err = json.Unmarshal([]byte(apiResp), &computeList)
if err != nil {
return "", err
}
// log.Printf("%#v", computeList)
log.Debugf("utilityComputeCheckPresence: traversing decoded JSON of length %d", len(computeList))
for index, item := range computeList {
// need to match Compute by name, skip Computes with the same name in DESTROYED satus
if item.Name == computeName.(string) && item.Status != "DESTROYED" {
log.Debugf("utilityComputeCheckPresence: index %d, matched name %s", index, item.Name)
// we found the Compute we need - now get detailed information via compute/get API
cgetValues := &url.Values{}
cgetValues.Add("computeId", fmt.Sprintf("%d", item.ID))
apiResp, err = c.DecortAPICall(ctx, "POST", ComputeGetAPI, cgetValues)
req := compute.GetRequest{
ComputeID: item.ID,
}
apiResp, err := c.CloudBroker().Compute().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return apiResp, nil
}
}
return "", nil // there should be no error if Compute does not exist
return nil, nil
}

View File

@@ -1,38 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package pcidevice
const pcideviceListAPI = "/restmachine/cloudbroker/pcidevice/list"
const pcideviceDisableAPI = "/restmachine/cloudbroker/pcidevice/disable"
const pcideviceEnableAPI = "/restmachine/cloudbroker/pcidevice/enable"
const pcideviceCreateAPI = "/restmachine/cloudbroker/pcidevice/create"
const pcideviceDeleteAPI = "/restmachine/cloudbroker/pcidevice/delete"

View File

@@ -49,11 +49,11 @@ func dataSourcePcideviceRead(ctx context.Context, d *schema.ResourceData, m inte
d.Set("ckey", pcidevice.CKey)
d.Set("meta", flattens.FlattenMeta(pcidevice.Meta))
d.Set("compute_id", pcidevice.Computeid)
d.Set("compute_id", pcidevice.ComputeID)
d.Set("description", pcidevice.Description)
d.Set("guid", pcidevice.Guid)
d.Set("guid", pcidevice.GUID)
d.Set("hw_path", pcidevice.HwPath)
d.Set("rg_id", pcidevice.RgID)
d.Set("rg_id", pcidevice.RGID)
d.Set("name", pcidevice.Name)
d.Set("stack_id", pcidevice.StackID)
d.Set("status", pcidevice.Status)

View File

@@ -37,22 +37,23 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/pcidevice"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenPcideviceList(pl PcideviceList) []map[string]interface{} {
func flattenPcideviceList(pl pcidevice.ListPCIDevices) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range pl {
temp := map[string]interface{}{
"ckey": item.CKey,
"meta": flattens.FlattenMeta(item.Meta),
"compute_id": item.Computeid,
"compute_id": item.ComputeID,
"description": item.Description,
"guid": item.Guid,
"guid": item.GUID,
"hw_path": item.HwPath,
"device_id": item.ID,
"rg_id": item.RgID,
"rg_id": item.RGID,
"name": item.Name,
"stack_id": item.StackID,
"status": item.Status,

View File

@@ -1,49 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package pcidevice
type Pcidevice struct {
CKey string `json:"_ckey"`
Meta []interface{} `json:"_meta"`
Computeid int `json:"computeId"`
Description string `json:"description"`
Guid int `json:"guid"`
HwPath string `json:"hwPath"`
ID int `json:"id"`
Name string `json:"name"`
RgID int `json:"rgId"`
StackID int `json:"stackId"`
Status string `json:"status"`
SystemName string `json:"systemName"`
}
type PcideviceList []Pcidevice

View File

@@ -33,45 +33,41 @@ package pcidevice
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/pcidevice"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
log "github.com/sirupsen/logrus"
)
func resourcePcideviceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourcePcideviceCreate: called for pcidevice %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("hwPath", d.Get("hw_path").(string))
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
urlValues.Add("stackId", strconv.Itoa(d.Get("stack_id").(int)))
if description, ok := d.GetOk("description"); ok {
urlValues.Add("description", description.(string))
req := pcidevice.CreateRequest{
Name: d.Get("name").(string),
HWPath: d.Get("hw_path").(string),
RGID: uint64(d.Get("rg_id").(int)),
StackID: uint64(d.Get("stack_id").(int)),
}
pcideviceId, err := c.DecortAPICall(ctx, "POST", pcideviceCreateAPI, urlValues)
if description, ok := d.GetOk("description"); ok {
req.Description = description.(string)
}
pcideviceId, err := c.CloudBroker().PCIDevice().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(pcideviceId)
d.SetId(strconv.FormatUint(pcideviceId, 10))
d.Set("device_id", pcideviceId)
diagnostics := resourcePcideviceRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourcePcideviceRead(ctx, d, m)
}
func resourcePcideviceRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -80,15 +76,14 @@ func resourcePcideviceRead(ctx context.Context, d *schema.ResourceData, m interf
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(pcidevice.ID))
d.Set("ckey", pcidevice.CKey)
d.Set("meta", flattens.FlattenMeta(pcidevice.Meta))
d.Set("compute_id", pcidevice.Computeid)
d.Set("compute_id", pcidevice.ComputeID)
d.Set("description", pcidevice.Description)
d.Set("guid", pcidevice.Guid)
d.Set("guid", pcidevice.GUID)
d.Set("hw_path", pcidevice.HwPath)
d.Set("device_id", pcidevice.ID)
d.Set("rg_id", pcidevice.RgID)
d.Set("rg_id", pcidevice.RGID)
d.Set("name", pcidevice.Name)
d.Set("stack_id", pcidevice.StackID)
d.Set("status", pcidevice.Status)
@@ -101,11 +96,13 @@ func resourcePcideviceDelete(ctx context.Context, d *schema.ResourceData, m inte
log.Debugf("resourcePcideviceDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("deviceId", d.Id())
urlValues.Add("force", strconv.FormatBool(d.Get("force").(bool)))
deviceID, _ := strconv.ParseUint(d.Id(), 10, 64)
req := pcidevice.DeleteRequest{
DeviceID: deviceID,
Force: d.Get("force").(bool),
}
_, err := c.DecortAPICall(ctx, "POST", pcideviceDeleteAPI, urlValues)
_, err := c.CloudBroker().PCIDevice().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -115,33 +112,33 @@ func resourcePcideviceDelete(ctx context.Context, d *schema.ResourceData, m inte
return nil
}
func resourcePcideviceEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourcePcideviceUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
if d.HasChange("enable") {
state := d.Get("enable").(bool)
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
api := ""
urlValues.Add("deviceId", strconv.Itoa(d.Get("device_id").(int)))
if state {
api = pcideviceEnableAPI
req := pcidevice.EnableRequest{
DeviceID: uint64(d.Get("device_id").(int)),
}
_, err := c.CloudBroker().PCIDevice().Enable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
} else {
api = pcideviceDisableAPI
}
req := pcidevice.DisableRequest{
DeviceID: uint64(d.Get("device_id").(int)),
}
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return diag.FromErr(err)
_, err := c.CloudBroker().PCIDevice().Disable(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
diagnostics := resourcePcideviceRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourcePcideviceRead(ctx, d, m)
}
func resourcePcideviceSchemaMake() map[string]*schema.Schema {
@@ -225,7 +222,7 @@ func ResourcePcidevice() *schema.Resource {
CreateContext: resourcePcideviceCreate,
ReadContext: resourcePcideviceRead,
UpdateContext: resourcePcideviceEdit,
UpdateContext: resourcePcideviceUpdate,
DeleteContext: resourcePcideviceDelete,
Importer: &schema.ResourceImporter{

View File

@@ -36,19 +36,20 @@ import (
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/pcidevice"
)
func utilityPcideviceCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Pcidevice, error) {
func utilityPcideviceCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*pcidevice.ItemPCIDevice, error) {
pcideviceList, err := utilityPcideviceListCheckPresence(ctx, m)
if err != nil {
return nil, err
}
pcideviceId := 0
var pcideviceId uint64
if (d.Get("device_id").(int)) != 0 {
pcideviceId = d.Get("device_id").(int)
pcideviceId = uint64(d.Get("device_id").(int))
} else {
id, _ := strconv.Atoi(d.Id())
id, _ := strconv.ParseUint(d.Id(), 10, 64)
pcideviceId = id
}

View File

@@ -33,23 +33,15 @@ package pcidevice
import (
"context"
"encoding/json"
"net/url"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/pcidevice"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityPcideviceListCheckPresence(ctx context.Context, m interface{}) (PcideviceList, error) {
pcideviceList := PcideviceList{}
func utilityPcideviceListCheckPresence(ctx context.Context, m interface{}) (pcidevice.ListPCIDevices, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
pcideviceListRaw, err := c.DecortAPICall(ctx, "POST", pcideviceListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(pcideviceListRaw), &pcideviceList)
pcideviceList, err := c.CloudBroker().PCIDevice().List(ctx)
if err != nil {
return nil, err
}

View File

@@ -1,45 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package pfw
type PfwRecord struct {
ID int `json:"id"`
LocalIP string `json:"localIp"`
LocalPort int `json:"localPort"`
Protocol string `json:"protocol"`
PublicPortEnd int `json:"publicPortEnd"`
PublicPortStart int `json:"publicPortStart"`
ComputeID int `json:"vmId"`
}
type ComputePfwListResp []PfwRecord

View File

@@ -34,37 +34,36 @@ package pfw
import (
"context"
"fmt"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourcePfwCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourcePfwCreate: called for compute %d", d.Get("compute_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("publicPortStart", strconv.Itoa(d.Get("public_port_start").(int)))
urlValues.Add("localBasePort", strconv.Itoa(d.Get("local_base_port").(int)))
urlValues.Add("proto", d.Get("proto").(string))
req := compute.PFWAddRequest{}
req.ComputeID = uint64(d.Get("compute_id").(int))
req.PublicPortStart = uint64(d.Get("public_port_start").(int))
req.LocalBasePort = uint64(d.Get("local_base_port").(int))
req.Proto = d.Get("proto").(string)
if portEnd, ok := d.GetOk("public_port_end"); ok {
urlValues.Add("publicPortEnd", strconv.Itoa(portEnd.(int)))
req.PublicPortEnd = uint64(portEnd.(int))
}
pfwId, err := c.DecortAPICall(ctx, "POST", ComputePfwAddAPI, urlValues)
pfwId, err := c.CloudBroker().Compute().PFWAdd(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(fmt.Sprintf("%d-%s", d.Get("compute_id").(int), pfwId))
d.SetId(fmt.Sprintf("%d-%d", d.Get("compute_id").(int), pfwId))
pfw, err := utilityPfwCheckPresence(ctx, d, m)
if err != nil {
@@ -88,7 +87,7 @@ func resourcePfwRead(ctx context.Context, d *schema.ResourceData, m interface{})
return diag.FromErr(err)
}
d.Set("compute_id", pfw.ComputeID)
d.Set("compute_id", pfw.VMID)
d.Set("public_port_start", pfw.PublicPortStart)
d.Set("public_port_end", pfw.PublicPortEnd)
d.Set("local_ip", pfw.LocalIP)
@@ -110,15 +109,18 @@ func resourcePfwDelete(ctx context.Context, d *schema.ResourceData, m interface{
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("ruleId", strconv.Itoa(pfw.ID))
req := compute.PFWDelRequest{
ComputeID: uint64(d.Get("compute_id").(int)),
RuleID: pfw.ID,
}
_, err = c.DecortAPICall(ctx, "POST", ComputePfwDelAPI, urlValues)
_, err = c.CloudBroker().Compute().PFWDel(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}

View File

@@ -33,27 +33,23 @@ package pfw
import (
"context"
"encoding/json"
"net/url"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityPfwCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*PfwRecord, error) {
func utilityPfwCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*compute.ItemPFW, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
resp, err := c.DecortAPICall(ctx, "POST", ComputePfwListAPI, urlValues)
if err != nil {
return nil, err
req := compute.PFWListRequest{
ComputeID: uint64(d.Get("compute_id").(int)),
}
if resp == "" {
return nil, nil
pfws, err := c.CloudBroker().Compute().PFWList(ctx, req)
if err != nil {
return nil, err
}
idS := strings.Split(d.Id(), "-")[1]
@@ -62,13 +58,8 @@ func utilityPfwCheckPresence(ctx context.Context, d *schema.ResourceData, m inte
return nil, err
}
var pfws []PfwRecord
if err := json.Unmarshal([]byte(resp), &pfws); err != nil {
return nil, err
}
for _, pfw := range pfws {
if pfw.ID == id {
if pfw.ID == uint64(id) {
return &pfw, nil
}
}

View File

@@ -33,58 +33,42 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
// "net/url"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func flattenResgroup(d *schema.ResourceData, rg_facts string) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceRsgroupExists(...) method
// log.Debugf("%s", rg_facts)
log.Debugf("flattenResgroup: ready to decode response body from API")
details := ResgroupGetResp{}
err := json.Unmarshal([]byte(rg_facts), &details)
if err != nil {
return err
}
func flattenResgroup(d *schema.ResourceData, rgData *rg.RecordRG) error {
log.Debugf("flattenResgroup: decoded RG name %q / ID %d, account ID %d",
details.Name, details.ID, details.AccountID)
rgData.Name, rgData.ID, rgData.AccountID)
d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("rg_id", details.ID)
d.Set("name", details.Name)
d.Set("account_name", details.AccountName)
d.Set("account_id", details.AccountID)
// d.Set("grid_id", details.GridID)
d.Set("description", details.Desc)
d.Set("status", details.Status)
d.Set("def_net_type", details.DefaultNetType)
d.Set("def_net_id", details.DefaultNetID)
/*
d.Set("vins", details.Vins)
d.Set("computes", details.Computes)
*/
d.SetId(fmt.Sprintf("%d", rgData.ID))
d.Set("rg_id", rgData.ID)
d.Set("name", rgData.Name)
d.Set("account_name", rgData.AccountName)
d.Set("account_id", rgData.AccountID)
// d.Set("grid_id", rgData.GridID)
d.Set("description", rgData.Description)
d.Set("status", rgData.Status)
d.Set("def_net_type", rgData.DefNetType)
d.Set("def_net_id", rgData.DefNetID)
log.Debugf("flattenResgroup: calling flattenQuota()")
if err = d.Set("quota", parseQuota(details.Quota)); err != nil {
return err
}
// log.Debugf("flattenResgroup: calling flattenQuota()")
// if err := d.Set("quota", parseQuota(rgData.Resources)); err != nil {
// return err
// }
return nil
}
func dataSourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
if rg_facts == "" {
if rg_facts == nil {
// if empty string is returned from utilityResgroupCheckPresence then there is no
// such resource group and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty in this case

View File

@@ -37,24 +37,25 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenRgList(rgl ResgroupListResp) []map[string]interface{} {
func flattenRgList(rgl rg.ListRG) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rg := range rgl {
temp := map[string]interface{}{
"account_id": rg.AccountID,
"account_name": rg.AccountName,
"acl": flattenRgAcl(rg.ACLs),
"acl": flattenRgAcl(rg.ACL),
"created_by": rg.CreatedBy,
"created_time": rg.CreatedTime,
"def_net_id": rg.DefaultNetID,
"def_net_type": rg.DefaultNetType,
"def_net_id": rg.DefNetID,
"def_net_type": rg.DefNetType,
"deleted_by": rg.DeletedBy,
"deleted_time": rg.DeletedTime,
"desc": rg.Decsription,
"gid": rg.GridID,
"desc": rg.Description,
"gid": rg.GID,
"guid": rg.GUID,
"rg_id": rg.ID,
"lock_status": rg.LockStatus,
@@ -66,8 +67,8 @@ func flattenRgList(rgl ResgroupListResp) []map[string]interface{} {
"status": rg.Status,
"updated_by": rg.UpdatedBy,
"updated_time": rg.UpdatedTime,
"vins": rg.Vins,
"vms": rg.Computes,
"vins": rg.VINS,
"vms": rg.VMs,
}
res = append(res, temp)
}
@@ -75,31 +76,31 @@ func flattenRgList(rgl ResgroupListResp) []map[string]interface{} {
}
func flattenRgAcl(rgAcls []AccountAclRecord) []map[string]interface{} {
func flattenRgAcl(rgAcls rg.ListACL) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rgAcl := range rgAcls {
temp := map[string]interface{}{
"explicit": rgAcl.IsExplicit,
"guid": rgAcl.Guid,
"right": rgAcl.Rights,
"explicit": rgAcl.Explicit,
"guid": rgAcl.GUID,
"right": rgAcl.Right,
"status": rgAcl.Status,
"type": rgAcl.Type,
"user_group_id": rgAcl.UgroupID,
"user_group_id": rgAcl.UserGroupID,
}
res = append(res, temp)
}
return res
}
func flattenRgResourceLimits(rl ResourceLimits) []map[string]interface{} {
func flattenRgResourceLimits(rl rg.ResourceLimits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cu_c": rl.CUC,
"cu_d": rl.CUD,
"cu_d": rl.CuD,
"cu_i": rl.CUI,
"cu_m": rl.CUM,
"cu_np": rl.CUNP,
"gpu_units": rl.GpuUnits,
"gpu_units": rl.GPUUnits,
}
res = append(res, temp)

View File

@@ -126,12 +126,12 @@ type UserAclRecord struct {
}
type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get
Cpu int `json:"CU_C"` // CPU count in pcs
Cpu float64 `json:"CU_C"` // CPU count in pcs
Ram float64 `json:"CU_M"` // RAM volume in MB, it is STILL reported as FLOAT
Disk int `json:"CU_D"` // Disk capacity in GB
ExtIPs int `json:"CU_I"` // Ext IPs count
ExtTraffic int `json:"CU_NP"` // Ext network traffic
GpuUnits int `json:"gpu_units"` // GPU count
Disk float64 `json:"CU_D"` // Disk capacity in GB
ExtIPs float64 `json:"CU_I"` // Ext IPs count
ExtTraffic float64 `json:"CU_NP"` // Ext network traffic
GpuUnits float64 `json:"gpu_units"` // GPU count
}
type ResourceRecord struct { // this is how actual usage is reported by /api/.../rg/get

View File

@@ -33,6 +33,7 @@ package rg
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
)
func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
@@ -47,41 +48,41 @@ func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
subres_data := arg_list[0].(map[string]interface{})
if subres_data["cpu"].(int) > 0 {
quota.Cpu = subres_data["cpu"].(int)
quota.Cpu = subres_data["cpu"].(float64)
}
if subres_data["disk"].(int) > 0 {
quota.Disk = subres_data["disk"].(int) // Disk capacity ib GB
quota.Disk = subres_data["disk"].(float64)
}
if subres_data["ram"].(float64) > 0 {
quota.Ram = subres_data["ram"].(float64) // RAM volume in MB, as float64!
quota.Ram = subres_data["ram"].(float64)
}
if subres_data["ext_traffic"].(int) > 0 {
quota.ExtTraffic = subres_data["ext_traffic"].(int)
quota.ExtTraffic = subres_data["ext_traffic"].(float64)
}
if subres_data["ext_ips"].(int) > 0 {
quota.ExtIPs = subres_data["ext_ips"].(int)
quota.ExtIPs = subres_data["ext_ips"].(float64)
}
if subres_data["gpu_units"].(int) > 0 {
quota.GpuUnits = subres_data["gpu_units"].(int)
quota.GpuUnits = subres_data["gpu_units"].(float64)
}
return quota
}
func parseQuota(quota QuotaRecord) []interface{} {
func parseQuota(quota rg.ResourceLimits) []interface{} {
quota_map := make(map[string]interface{})
quota_map["cpu"] = quota.Cpu
quota_map["ram"] = quota.Ram // NB: this is float64, unlike the rest of values
quota_map["disk"] = quota.Disk
quota_map["ext_traffic"] = quota.ExtTraffic
quota_map["ext_ips"] = quota.ExtIPs
quota_map["gpu_units"] = quota.GpuUnits
quota_map["cpu"] = quota.CUC
quota_map["ram"] = quota.CUM
quota_map["disk"] = quota.CuD
quota_map["ext_traffic"] = quota.CUNP
quota_map["ext_ips"] = quota.CUI
quota_map["gpu_units"] = quota.GPUUnits
result := make([]interface{}, 1)
result[0] = quota_map
@@ -92,7 +93,7 @@ func parseQuota(quota QuotaRecord) []interface{} {
func quotaRgSubresourceSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"cpu": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Optional: true,
Default: -1,
Description: "Limit on the total number of CPUs in this resource group.",
@@ -106,28 +107,28 @@ func quotaRgSubresourceSchemaMake() map[string]*schema.Schema {
},
"disk": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Optional: true,
Default: -1,
Description: "Limit on the total volume of storage resources in this resource group, specified in GB.",
},
"ext_traffic": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Optional: true,
Default: -1,
Description: "Limit on the total ingress network traffic for this resource group, specified in GB.",
},
"ext_ips": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Optional: true,
Default: -1,
Description: "Limit on the total number of external IP addresses this resource group can use.",
},
"gpu_units": {
Type: schema.TypeInt,
Type: schema.TypeFloat,
Optional: true,
Default: -1,
Description: "Limit on the total number of virtual GPUs this resource group can use.",

View File

@@ -33,14 +33,14 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/location"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -48,32 +48,13 @@ import (
)
func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// First validate that we have all parameters required to create the new Resource Group
// Valid account ID is required to create new resource group
// obtain Account ID by account name - it should not be zero on success
rg_name, arg_set := d.GetOk("name")
if !arg_set {
return diag.FromErr(fmt.Errorf("Cannot create new RG: missing name."))
}
/* Current version of provider works with default grid id (same is true for disk resources)
grid_id, arg_set := d.GetOk("grid_id")
if !arg_set {
return fmt.Errorf("Cannot create new RG %q in account ID %d: missing Grid ID.",
rg_name.(string), validated_account_id)
}
if grid_id.(int) < 1 {
grid_id = DefaultGridID
}
*/
// all required parameters are set in the schema - we can continue with RG creation
log.Debugf("resourceResgroupCreate: called for RG name %s, account ID %d",
rg_name.(string), d.Get("account_id").(int))
// quota settings are optional
set_quota := false
var quota_record QuotaRecord
arg_value, arg_set := d.GetOk("quota")
@@ -88,62 +69,57 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
c.GetDecortUsername(),
rg_name.(string), d.Get("account_id").(int))
url_values := &url.Values{}
url_values.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
url_values.Add("name", rg_name.(string))
url_values.Add("gid", fmt.Sprintf("%d", location.DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
url_values.Add("owner", c.GetDecortUsername())
req := rg.CreateRequest{
AccountID: uint64(d.Get("account_id").(int)),
Name: rg_name.(string),
GID: uint64(location.DefaultGridID),
Owner: c.GetDecortUsername(),
}
// pass quota values as set
if set_quota {
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quota_record.Cpu))
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quota_record.Disk))
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quota_record.Ram)) // RAM quota is float; this may change in the future
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quota_record.ExtTraffic))
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quota_record.ExtIPs))
req.MaxCPUCapacity = int64(quota_record.Cpu)
req.MaxVDiskCapacity = int64(quota_record.Disk)
req.MaxMemoryCapacity = int64(quota_record.Ram)
req.MaxNetworkPeerTransfer = int64(quota_record.ExtTraffic)
req.MaxNumPublicIP = int64(quota_record.ExtIPs)
// url_values.Add("???", fmt.Sprintf("%d", quota_record.GpuUnits))
}
// parse and handle network settings
def_net_type, arg_set := d.GetOk("def_net_type")
if arg_set {
url_values.Add("def_net", def_net_type.(string)) // NOTE: in API default network type is set by "def_net" parameter
req.DefNet = def_net_type.(string)
}
ipcidr, arg_set := d.GetOk("ipcidr")
if arg_set {
url_values.Add("ipcidr", ipcidr.(string))
req.IPCIDR = ipcidr.(string)
}
ext_net_id, arg_set := d.GetOk("ext_net_id")
if arg_set {
url_values.Add("extNetId", fmt.Sprintf("%d", ext_net_id.(int)))
req.ExtNetID = uint64(ext_net_id.(int))
}
ext_ip, arg_set := d.GetOk("ext_ip")
if arg_set {
url_values.Add("extIp", ext_ip.(string))
req.ExtIP = ext_ip.(string)
}
api_resp, err := c.DecortAPICall(ctx, "POST", ResgroupCreateAPI, url_values)
rgId, err := c.CloudBroker().RG().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(api_resp) // rg/create API returns ID of the newly creted resource group on success
// rg.ID, _ = strconv.Atoi(api_resp)
d.SetId(strconv.FormatUint(rgId, 10))
if !set_quota {
resp, err := utilityResgroupCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
rg := ResgroupGetResp{}
if err := json.Unmarshal([]byte(resp), &rg); err != nil {
return diag.FromErr(err)
}
d.Set("quota", parseQuota(rg.Quota))
d.Set("quota", parseQuota(resp.ResourceLimits))
}
// re-read newly created RG to make sure schema contains complete and up to date set of specifications
@@ -155,9 +131,7 @@ func resourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interfa
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
if rg_facts == "" {
// if empty string is returned from utilityResgroupCheckPresence then there is no
// such resource group and err tells so - just return it to the calling party
if rg_facts == nil {
d.SetId("") // ensure ID is empty
return diag.FromErr(err)
}
@@ -192,8 +166,10 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
do_general_update := false // will be true if general RG update is necessary (API rg/update)
c := m.(*controller.ControllerCfg)
url_values := &url.Values{}
url_values.Add("rgId", d.Id())
rgId, _ := strconv.ParseUint(d.Id(), 10, 64)
req := rg.UpdateRequest{
RGID: rgId,
}
name_new, name_set := d.GetOk("name")
if name_set {
@@ -201,7 +177,7 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
name_old, _ := d.GetChange("name")
if name_old.(string) != name_new.(string) {
do_general_update = true
url_values.Add("name", name_new.(string))
req.Name = name_new.(string)
}
}
@@ -215,31 +191,31 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
if quotarecord_new.Cpu != quotarecord_old.Cpu {
do_general_update = true
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotarecord_new.Cpu, quotarecord_old.Cpu)
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotarecord_new.Cpu))
req.MaxCPUCapacity = int64(quotarecord_new.Cpu)
}
if quotarecord_new.Disk != quotarecord_old.Disk {
do_general_update = true
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotarecord_new.Disk, quotarecord_old.Disk)
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotarecord_new.Disk))
req.MaxVDiskCapacity = int64(quotarecord_new.Disk)
}
if quotarecord_new.Ram != quotarecord_old.Ram { // NB: quota on RAM is stored as float32, in units of MB
do_general_update = true
log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotarecord_new.Ram, quotarecord_old.Ram)
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotarecord_new.Ram))
req.MaxMemoryCapacity = int64(quotarecord_new.Ram)
}
if quotarecord_new.ExtTraffic != quotarecord_old.ExtTraffic {
do_general_update = true
log.Debugf("resourceResgroupUpdate: ExtTraffic diff %d <- %d", quotarecord_new.ExtTraffic, quotarecord_old.ExtTraffic)
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quotarecord_new.ExtTraffic))
req.MaxNetworkPeerTransfer = int64(quotarecord_new.ExtTraffic)
}
if quotarecord_new.ExtIPs != quotarecord_old.ExtIPs {
do_general_update = true
log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotarecord_new.ExtIPs, quotarecord_old.ExtIPs)
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quotarecord_new.ExtIPs))
req.MaxNumPublicIP = int64(quotarecord_new.ExtIPs)
}
}
@@ -249,13 +225,13 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
desc_old, _ := d.GetChange("description")
if desc_old.(string) != desc_new.(string) {
do_general_update = true
url_values.Add("desc", desc_new.(string))
req.Description = desc_new.(string)
}
}
if do_general_update {
log.Debugf("resourceResgroupUpdate: detected delta between new and old RG specs - updating the RG")
_, err := c.DecortAPICall(ctx, "POST", ResgroupUpdateAPI, url_values)
_, err := c.CloudBroker().RG().Update(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -267,29 +243,26 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
}
func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// NOTE: this method forcibly destroys target resource group with flag "permanently", so there is no way to
// restore the destroyed resource group as well all Computes & VINSes that existed in it
log.Debugf("resourceResgroupDelete: called for RG name %s, account ID %d",
d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m)
if rg_facts == "" {
if rg_facts == nil {
if err != nil {
return diag.FromErr(err)
}
// the target RG does not exist - in this case according to Terraform best practice
// we exit from Destroy method without error
return nil
}
url_values := &url.Values{}
url_values.Add("rgId", d.Id())
url_values.Add("force", "1")
url_values.Add("permanently", "1")
url_values.Add("reason", "Destroyed by DECORT Terraform provider")
req := rg.DeleteRequest{
RGID: rg_facts.ID,
Force: true,
Permanently: true,
Reason: "Destroyed by DECORT Terraform provider",
}
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", ResgroupDeleteAPI, url_values)
_, err = c.CloudBroker().RG().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}

View File

@@ -33,48 +33,25 @@ package rg
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// On success this function returns a string, as returned by API rg/get, which could be unmarshalled
// into ResgroupGetResp structure
func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate resource group by one of the following algorithms depending
// on the parameters passed:
// - if resource group ID is specified -> by RG ID
// - if resource group name is specifeid -> by RG name and either account ID or account name
//
// If succeeded, it returns non empty string that contains JSON formatted facts about the
// resource group as returned by rg/get API call.
// Otherwise it returns empty string and a meaningful error.
//
// NOTE: As our provider always deletes RGs permanently, there is no "restore" method and
// consequently we are not interested in matching RGs in DELETED state. Hence, we call
// .../rg/list API with includedeleted=false
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for the Terraform resource Exists method.
//
func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*rg.RecordRG, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with RG ID set so
// that Import of RG resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
theId, err := strconv.ParseUint(d.Id(), 10, 64)
if err != nil || theId <= 0 {
rgId, argSet := d.GetOk("rg_id")
if argSet {
theId = rgId.(int)
theId = uint64(rgId.(int))
idSet = true
}
} else {
@@ -82,58 +59,50 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
}
if idSet {
// go straight for the RG by its ID
log.Debugf("utilityResgroupCheckPresence: locating RG by its ID %d", theId)
urlValues.Add("rgId", fmt.Sprintf("%d", theId))
rgFacts, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
req := rg.GetRequest{
RGID: theId,
}
rgFacts, err := c.CloudBroker().RG().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return rgFacts, nil
}
rgName, argSet := d.GetOk("name")
if !argSet {
// no RG ID and no RG name - we cannot locate resource group in this case
return "", fmt.Errorf("Cannot check resource group presence if name is empty and no resource group ID specified")
return nil, fmt.Errorf("Cannot check resource group presence if name is empty and no resource group ID specified")
}
// Valid account ID is required to locate a resource group
// obtain Account ID by account name - it should not be zero on success
urlValues.Add("includedeleted", "false")
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupListAPI, urlValues)
if err != nil {
return "", err
listReq := rg.ListRequest{
IncludeDeleted: false,
}
// log.Debugf("%s", apiResp)
log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %s", ResgroupListAPI)
model := ResgroupListResp{}
err = json.Unmarshal([]byte(apiResp), &model)
model, err := c.CloudBroker().RG().List(ctx, listReq)
if err != nil {
return "", err
return nil, err
}
log.Debugf("utilityResgroupCheckPresence: traversing decoded Json of length %d", len(model))
for index, item := range model {
// match by RG name & account ID
if item.Name == rgName.(string) && item.AccountID == d.Get("account_id").(int) {
if item.Name == rgName.(string) && item.AccountID == uint64(d.Get("account_id").(int)) {
log.Debugf("utilityResgroupCheckPresence: match RG name %s / ID %d, account ID %d at index %d",
item.Name, item.ID, item.AccountID, index)
// not all required information is returned by rg/list API, so we need to initiate one more
// call to rg/get to obtain extra data to complete Resource population.
// Namely, we need resource quota settings
reqValues := &url.Values{}
reqValues.Add("rgId", fmt.Sprintf("%d", item.ID))
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, reqValues)
req := rg.GetRequest{
RGID: item.ID,
}
apiResp, err := c.CloudBroker().RG().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return apiResp, nil
}
}
return "", fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, d.Get("account_id").(int))
return nil, fmt.Errorf("Cannot find RG name %s owned by account ID %d", rgName, d.Get("account_id").(int))
}

View File

@@ -33,39 +33,30 @@ package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityRgListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ResgroupListResp, error) {
func utilityRgListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (rg.ListRG, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgList := ResgroupListResp{}
req := rg.ListRequest{}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if includedeleted, ok := d.GetOk("includedeleted"); ok {
urlValues.Add("includedeleted", strconv.FormatBool(includedeleted.(bool)))
req.IncludeDeleted = includedeleted.(bool)
}
log.Debugf("utilityRgListCheckPresence: load rg list")
rgListRaw, err := c.DecortAPICall(ctx, "POST", ResgroupListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(rgListRaw), &rgList)
rgList, err := c.CloudBroker().RG().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -50,13 +50,13 @@ func dataSourceSepRead(ctx context.Context, d *schema.ResourceData, m interface{
id := uuid.New()
d.SetId(id.String())
d.Set("ckey", desSep.Ckey)
d.Set("ckey", desSep.CKey)
d.Set("meta", flattens.FlattenMeta(desSep.Meta))
d.Set("consumed_by", desSep.ConsumedBy)
d.Set("desc", desSep.Desc)
d.Set("gid", desSep.Gid)
d.Set("guid", desSep.Guid)
d.Set("sep_id", desSep.Id)
d.Set("desc", desSep.Description)
d.Set("gid", desSep.GID)
d.Set("guid", desSep.GUID)
d.Set("sep_id", desSep.ID)
d.Set("milestones", desSep.Milestones)
d.Set("name", desSep.Name)
d.Set("obj_status", desSep.ObjStatus)

View File

@@ -37,9 +37,11 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
// TODO: how to marshal byPool????
func dataSourceSepConsumptionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
sepCons, err := utilitySepConsumptionCheckPresence(ctx, d, m)
if err != nil {
@@ -50,7 +52,7 @@ func dataSourceSepConsumptionRead(ctx context.Context, d *schema.ResourceData, m
d.Set("type", sepCons.Type)
d.Set("total", flattenSepConsumption(sepCons.Total))
d.Set("by_pool", flattenSepConsumptionPools(sepCons.ByPool))
// d.Set("by_pool", flattenSepConsumptionPools(sepCons.ByPool))
return nil
}
@@ -72,7 +74,7 @@ func flattenSepConsumptionPools(mp map[string]SepConsumptionInd) []map[string]in
return sh
}
func flattenSepConsumption(sc SepConsumptionTotal) []map[string]interface{} {
func flattenSepConsumption(sc sep.Total) []map[string]interface{} {
sh := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"capacity_limit": sc.CapacityLimit,

View File

@@ -38,22 +38,23 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
)
func flattenSepList(sl SepList) []map[string]interface{} {
func flattenSepList(sl sep.ListSEP) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range sl {
data, _ := json.Marshal(item.Config)
temp := map[string]interface{}{
"ckey": item.Ckey,
"ckey": item.CKey,
"meta": flattens.FlattenMeta(item.Meta),
"consumed_by": item.ConsumedBy,
"desc": item.Desc,
"gid": item.Gid,
"guid": item.Guid,
"sep_id": item.Id,
"desc": item.Description,
"gid": item.GID,
"guid": item.GUID,
"sep_id": item.ID,
"milestones": item.Milestones,
"name": item.Name,
"obj_status": item.ObjStatus,

View File

@@ -34,78 +34,60 @@ package sep
import (
"context"
"encoding/json"
"errors"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/flattens"
log "github.com/sirupsen/logrus"
)
func resourceSepCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceSepCreate: called for sep %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := sep.CreateRequest{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("gid", strconv.Itoa(d.Get("gid").(int)))
urlValues.Add("sep_type", d.Get("type").(string))
req.Name = d.Get("name").(string)
req.GID = uint64(d.Get("gid").(int))
req.SEPType = d.Get("type").(string)
if desc, ok := d.GetOk("desc"); ok {
urlValues.Add("description", desc.(string))
req.Description = desc.(string)
}
if configString, ok := d.GetOk("config"); ok {
urlValues.Add("config", configString.(string))
req.Config = configString.(string)
}
if enable, ok := d.GetOk("enable"); ok {
urlValues.Add("enable", strconv.FormatBool(enable.(bool)))
req.Enable = enable.(bool)
}
tstr := d.Get("consumed_by").([]interface{})
temp := ""
l := len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s
var consumedNIDs []uint64
for _, item := range d.Get("consumed_by").([]interface{}) {
consumedNIDs = append(consumedNIDs, uint64(item.(int)))
}
temp = "[" + temp + "]"
urlValues.Add("consumer_nids", temp)
tstr = d.Get("provided_by").([]interface{})
temp = ""
l = len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s
req.ConsumerNIDs = consumedNIDs
var providerNIDs []uint64
for _, item := range d.Get("provided_by").([]interface{}) {
providerNIDs = append(providerNIDs, uint64(item.(int)))
}
temp = "[" + temp + "]"
urlValues.Add("provider_nids", temp)
sepId, err := c.DecortAPICall(ctx, "POST", sepCreateAPI, urlValues)
req.ProviderNIDs = providerNIDs
sepId, err := c.CloudBroker().SEP().Create(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(sepId)
d.SetId(strconv.FormatUint(sepId, 10))
d.Set("sep_id", sepId)
diagnostics := resourceSepRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourceSepRead(ctx, d, m)
}
func resourceSepRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -117,13 +99,13 @@ func resourceSepRead(ctx context.Context, d *schema.ResourceData, m interface{})
return diag.FromErr(err)
}
d.Set("ckey", sep.Ckey)
d.Set("ckey", sep.CKey)
d.Set("meta", flattens.FlattenMeta(sep.Meta))
d.Set("consumed_by", sep.ConsumedBy)
d.Set("desc", sep.Desc)
d.Set("gid", sep.Gid)
d.Set("guid", sep.Guid)
d.Set("sep_id", sep.Id)
d.Set("desc", sep.Description)
d.Set("gid", sep.GID)
d.Set("guid", sep.GUID)
d.Set("sep_id", sep.ID)
d.Set("milestones", sep.Milestones)
d.Set("name", sep.Name)
d.Set("obj_status", sep.ObjStatus)
@@ -148,78 +130,91 @@ func resourceSepDelete(ctx context.Context, d *schema.ResourceData, m interface{
}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
req := sep.DeleteRequest{
SEPID: sepDes.ID,
}
_, err = c.DecortAPICall(ctx, "POST", sepDeleteAPI, urlValues)
_, err = c.CloudBroker().SEP().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceSepEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceSepUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceSepEdit: called for %s, id: %d", d.Get("name").(string), d.Get("sep_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if d.HasChange("decommission") {
decommission := d.Get("decommission").(bool)
if decommission {
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("clear_physically", strconv.FormatBool(d.Get("clear_physically").(bool)))
_, err := c.DecortAPICall(ctx, "POST", sepDecommissionAPI, urlValues)
req := sep.DecommissionRequest{
SEPID: uint64(d.Get("sep_id").(int)),
ClearPhisically: d.Get("clear_physically").(bool),
}
_, err := c.CloudBroker().SEP().Decommission(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
urlValues = &url.Values{}
if d.HasChange("upd_capacity_limit") {
updCapacityLimit := d.Get("upd_capacity_limit").(bool)
if updCapacityLimit {
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
_, err := c.DecortAPICall(ctx, "POST", sepUpdateCapacityLimitAPI, urlValues)
req := sep.UpdateCapacityLimitRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
_, err := c.CloudBroker().SEP().UpdateCapacityLimit(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
urlValues = &url.Values{}
if d.HasChange("config") {
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("config", d.Get("config").(string))
_, err := c.DecortAPICall(ctx, "POST", sepConfigValidateAPI, urlValues)
validateReq := sep.ConfigValidateRequest{
SEPID: uint64(d.Get("sep_id").(int)),
Config: d.Get("config").(string),
}
insertReq := sep.ConfigInsertRequest{
SEPID: uint64(d.Get("sep_id").(int)),
Config: d.Get("config").(string),
}
_, err := c.CloudBroker().SEP().ConfigValidate(ctx, validateReq)
if err != nil {
return diag.FromErr(err)
}
_, err = c.DecortAPICall(ctx, "POST", sepConfigInsertAPI, urlValues)
_, err = c.CloudBroker().SEP().ConfigInsert(ctx, insertReq)
if err != nil {
return diag.FromErr(err)
}
}
urlValues = &url.Values{}
if d.HasChange("field_edit") {
fieldConfig := d.Get("field_edit").([]interface{})
field := fieldConfig[0].(map[string]interface{})
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("field_name", field["field_name"].(string))
urlValues.Add("field_value", field["field_value"].(string))
urlValues.Add("field_type", field["field_type"].(string))
req := sep.ConfigFieldEditRequest{
SEPID: uint64(d.Get("sep_id").(int)),
FieldName: field["field_name"].(string),
FieldValue: field["field_value"].(string),
FieldType: field["field_type"].(string),
}
_, err := c.DecortAPICall(ctx, "POST", sepConfigFieldEditAPI, urlValues)
_, err := c.CloudBroker().SEP().ConfigFieldEdit(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
urlValues = &url.Values{}
if d.HasChange("enable") {
err := resourceSepChangeEnabled(ctx, d, m)
if err != nil {
@@ -227,7 +222,6 @@ func resourceSepEdit(ctx context.Context, d *schema.ResourceData, m interface{})
}
}
urlValues = &url.Values{}
if d.HasChange("consumed_by") {
err := resourceSepUpdateNodes(ctx, d, m)
if err != nil {
@@ -235,7 +229,6 @@ func resourceSepEdit(ctx context.Context, d *schema.ResourceData, m interface{})
}
}
urlValues = &url.Values{}
if d.HasChange("provided_by") {
err := resourceSepUpdateProviders(ctx, d, m)
if err != nil {
@@ -243,7 +236,6 @@ func resourceSepEdit(ctx context.Context, d *schema.ResourceData, m interface{})
}
}
urlValues = &url.Values{}
if diagnostics := resourceSepRead(ctx, d, m); diagnostics != nil {
return diagnostics
}
@@ -252,42 +244,48 @@ func resourceSepEdit(ctx context.Context, d *schema.ResourceData, m interface{})
}
func resourceSepChangeEnabled(ctx context.Context, d *schema.ResourceData, m interface{}) error {
var api string
sepID := uint64(d.Get("sep_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
if d.Get("enable").(bool) {
api = sepEnableAPI
req := sep.EnableRequest{
SEPID: sepID,
}
_, err := c.CloudBroker().SEP().Enable(ctx, req)
if err != nil {
return err
}
} else {
api = sepDisableAPI
}
resp, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return err
}
res, err := strconv.ParseBool(resp)
if err != nil {
return err
}
if !res {
return errors.New("Cannot enable/disable")
req := sep.DisableRequest{
SEPID: sepID,
}
_, err := c.CloudBroker().SEP().Disable(ctx, req)
if err != nil {
return err
}
}
return nil
}
func resourceSepUpdateNodes(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceSepUpdateNodes: called for %s, id: %d", d.Get("name").(string), d.Get("sep_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
delReq := sep.DelConsumerNodesRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
addReq := sep.AddConsumerNodesRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
toDel := false
t1, t2 := d.GetChange("consumed_by")
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
consumedIds := make([]interface{}, 0)
temp := ""
api := ""
if d1, d2 := t1.([]interface{}), t2.([]interface{}); len(d1) > len(d2) {
for _, n := range d2 {
@@ -295,25 +293,30 @@ func resourceSepUpdateNodes(ctx context.Context, d *schema.ResourceData, m inter
consumedIds = append(consumedIds, n)
}
}
api = sepDelConsumerNodesAPI
toDel = true
} else {
consumedIds = d.Get("consumed_by").([]interface{})
api = sepAddConsumerNodesAPI
}
l := len(consumedIds)
for i, consumedId := range consumedIds {
s := strconv.Itoa(consumedId.(int))
if i != (l - 1) {
s += ","
}
temp = temp + s
var consumerNIDs []uint64
for _, consumedId := range consumedIds {
consumerNIDs = append(consumerNIDs, uint64(consumedId.(int)))
}
temp = "[" + temp + "]"
urlValues.Add("consumer_nids", temp)
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
return err
if toDel {
delReq.ConsumerNIDs = consumerNIDs
_, err := c.CloudBroker().SEP().DelConsumerNodes(ctx, delReq)
if err != nil {
return err
}
} else {
addReq.ConsumerNIDs = consumerNIDs
_, err := c.CloudBroker().SEP().AddConsumerNodes(ctx, addReq)
if err != nil {
return err
}
}
return nil
@@ -331,21 +334,17 @@ func findElInt(sl []interface{}, el interface{}) bool {
func resourceSepUpdateProviders(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceSepUpdateProviders: called for %s, id: %d", d.Get("name").(string), d.Get("sep_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
providerIds := d.Get("provided_by").([]interface{})
temp := ""
l := len(providerIds)
for i, providerId := range providerIds {
s := strconv.Itoa(providerId.(int))
if i != (l - 1) {
s += ","
}
temp = temp + s
req := sep.AddProviderNodesRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
temp = "[" + temp + "]"
urlValues.Add("provider_nids", temp)
_, err := c.DecortAPICall(ctx, "POST", sepAddProviderNodesAPI, urlValues)
var providerNIDs []uint64
for _, item := range d.Get("provided_by").([]interface{}) {
providerNIDs = append(providerNIDs, uint64(item.(int)))
}
req.ProviderNIDs = providerNIDs
_, err := c.CloudBroker().SEP().AddProviderNodes(ctx, req)
if err != nil {
return err
}
@@ -488,7 +487,7 @@ func ResourceSep() *schema.Resource {
CreateContext: resourceSepCreate,
ReadContext: resourceSepRead,
UpdateContext: resourceSepEdit,
UpdateContext: resourceSepUpdate,
DeleteContext: resourceSepDelete,
Importer: &schema.ResourceImporter{

View File

@@ -34,15 +34,14 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceSepConfigCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -100,35 +99,43 @@ func resourceSepConfigExists(ctx context.Context, d *schema.ResourceData, m inte
return true, nil
}
func resourceSepConfigEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceSepConfigUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceSepConfigEdit: called for sep id: %d", d.Get("sep_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if d.HasChange("config") {
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("config", d.Get("config").(string))
_, err := c.DecortAPICall(ctx, "POST", sepConfigValidateAPI, urlValues)
validateReq := sep.ConfigValidateRequest{
SEPID: uint64(d.Get("sep_id").(int)),
Config: d.Get("config").(string),
}
insertReq := sep.ConfigInsertRequest{
SEPID: uint64(d.Get("sep_id").(int)),
Config: d.Get("config").(string),
}
_, err := c.CloudBroker().SEP().ConfigValidate(ctx, validateReq)
if err != nil {
return diag.FromErr(err)
}
_, err = c.DecortAPICall(ctx, "POST", sepConfigInsertAPI, urlValues)
_, err = c.CloudBroker().SEP().ConfigInsert(ctx, insertReq)
if err != nil {
return diag.FromErr(err)
}
}
urlValues = &url.Values{}
if d.HasChange("field_edit") {
fieldConfig := d.Get("field_edit").([]interface{})
field := fieldConfig[0].(map[string]interface{})
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("field_name", field["field_name"].(string))
urlValues.Add("field_value", field["field_value"].(string))
urlValues.Add("field_type", field["field_type"].(string))
req := sep.ConfigFieldEditRequest{
SEPID: uint64(d.Get("sep_id").(int)),
FieldName: field["field_name"].(string),
FieldValue: field["field_value"].(string),
FieldType: field["field_type"].(string),
}
_, err := c.DecortAPICall(ctx, "POST", sepConfigFieldEditAPI, urlValues)
_, err := c.CloudBroker().SEP().ConfigFieldEdit(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -184,7 +191,7 @@ func ResourceSepConfig() *schema.Resource {
CreateContext: resourceSepConfigCreate,
ReadContext: resourceSepConfigRead,
UpdateContext: resourceSepConfigEdit,
UpdateContext: resourceSepConfigUpdate,
DeleteContext: resourceSepConfigDelete,
Importer: &schema.ResourceImporter{

View File

@@ -33,35 +33,28 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilitySepCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Sep, error) {
func utilitySepCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*sep.RecordSEP, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
sep := &Sep{}
req := sep.GetRequest{}
if d.Get("sep_id").(int) == 0 {
urlValues.Add("sep_id", d.Id())
id, _ := strconv.ParseUint(d.Id(), 10, 64)
req.SEPID = id
} else {
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
req.SEPID = uint64(d.Get("sep_id").(int))
}
log.Debugf("utilitySepCheckPresence: load sep")
sepRaw, err := c.DecortAPICall(ctx, "POST", sepGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(sepRaw), sep)
sep, err := c.CloudBroker().SEP().Get(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,31 +33,22 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilitySepConfigCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (SepConfig, error) {
func utilitySepConfigCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*sep.SEPConfig, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
sepConfig := SepConfig{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
log.Debugf("utilitySepConfigCheckPresence: load sep config")
sepConfigRaw, err := c.DecortAPICall(ctx, "POST", sepGetConfigAPI, urlValues)
if err != nil {
return nil, err
req := sep.GetConfigRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
err = json.Unmarshal([]byte(sepConfigRaw), &sepConfig)
log.Debugf("utilitySepConfigCheckPresence: load sep config")
sepConfig, err := c.CloudBroker().SEP().GetConfig(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,28 +33,19 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilitySepConsumptionCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*SepConsumption, error) {
func utilitySepConsumptionCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*sep.RecordConsumption, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
sepCons := &SepConsumption{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
sepConsRaw, err := c.DecortAPICall(ctx, "POST", sepConsumptionAPI, urlValues)
if err != nil {
return nil, err
req := sep.ConsumptionRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
err = json.Unmarshal([]byte(sepConsRaw), sepCons)
sepCons, err := c.CloudBroker().SEP().Consumption(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,35 +33,26 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilitySepDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) ([]int, error) {
func utilitySepDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) ([]uint64, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
sepDiskList := SepDiskList{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
req := sep.DiskListRequest{
SEPID: uint64(d.Get("sep_id").(int)),
}
if poolName, ok := d.GetOk("pool_name"); ok {
urlValues.Add("pool_name", poolName.(string))
req.PoolName = poolName.(string)
}
log.Debugf("utilitySepDiskListCheckPresence: load sep")
sepDiskListRaw, err := c.DecortAPICall(ctx, "POST", sepDiskListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(sepDiskListRaw), &sepDiskList)
sepDiskList, err := c.CloudBroker().SEP().DiskList(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,35 +33,27 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilitySepListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (SepList, error) {
sepList := SepList{}
func utilitySepListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (sep.ListSEP, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := sep.ListRequest{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilitySepListCheckPresence: load image list")
sepListRaw, err := c.DecortAPICall(ctx, "POST", sepListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(sepListRaw), &sepList)
sepList, err := c.CloudBroker().SEP().List(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -33,32 +33,23 @@ package sep
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/sep"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilitySepPoolCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (SepPool, error) {
func utilitySepPoolCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*sep.RecordPool, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
sepPool := SepPool{}
urlValues.Add("sep_id", strconv.Itoa(d.Get("sep_id").(int)))
urlValues.Add("pool_name", d.Get("pool_name").(string))
log.Debugf("utilitySepDesPoolCheckPresence: load sep")
sepPoolRaw, err := c.DecortAPICall(ctx, "POST", sepGetPoolAPI, urlValues)
if err != nil {
return nil, err
req := sep.GetPoolRequest{
SEPID: uint64(d.Get("sep_id").(int)),
PoolName: d.Get("pool_name").(string),
}
err = json.Unmarshal([]byte(sepPoolRaw), &sepPool)
log.Debugf("utilitySepDesPoolCheckPresence: load sep")
sepPool, err := c.CloudBroker().SEP().GetPool(ctx, req)
if err != nil {
return nil, err
}

View File

@@ -37,15 +37,16 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenSnapshotList(gl SnapshotList) []map[string]interface{} {
func flattenSnapshotList(gl compute.ListSnapshots) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range gl {
temp := map[string]interface{}{
"label": item.Label,
"guid": item.Guid,
"guid": item.GUID,
"disks": item.Disks,
"timestamp": item.Timestamp,
}

View File

@@ -1,41 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package snapshot
type Snapshot struct {
Disks []int `json:"disks"`
Guid string `json:"guid"`
Label string `json:"label"`
Timestamp uint64 `json:"timestamp"`
}
type SnapshotList []Snapshot

View File

@@ -33,26 +33,26 @@ package snapshot
import (
"context"
"net/url"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func resourceSnapshotCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceSnapshotCreate: called for snapshot %s", d.Get("label").(string))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("label", d.Get("label").(string))
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
req := compute.SnapshotCreateRequest{
Label: d.Get("label").(string),
ComputeID: uint64(d.Get("compute_id").(int)),
}
snapshotId, err := c.DecortAPICall(ctx, "POST", snapshotCreateAPI, urlValues)
snapshotId, err := c.CloudBroker().Compute().SnapshotCreate(ctx, req)
if err != nil {
return diag.FromErr(err)
}
@@ -62,12 +62,7 @@ func resourceSnapshotCreate(ctx context.Context, d *schema.ResourceData, m inter
d.SetId(snapshotId)
d.Set("guid", snapshotId)
diagnostics := resourceSnapshotRead(ctx, d, m)
if diagnostics != nil {
return diagnostics
}
return nil
return resourceSnapshotRead(ctx, d, m)
}
func resourceSnapshotRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
@@ -77,7 +72,7 @@ func resourceSnapshotRead(ctx context.Context, d *schema.ResourceData, m interfa
}
d.Set("timestamp", snapshot.Timestamp)
d.Set("guid", snapshot.Guid)
d.Set("guid", snapshot.GUID)
d.Set("disks", snapshot.Disks)
d.Set("label", snapshot.Label)
@@ -88,20 +83,22 @@ func resourceSnapshotDelete(ctx context.Context, d *schema.ResourceData, m inter
log.Debugf("resourceSnapshotDelete: called for %s, id: %s", d.Get("label").(string), d.Id())
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("label", d.Get("label").(string))
req := compute.SnapshotDeleteRequest{
ComputeID: uint64(d.Get("compute_id").(int)),
Label: d.Get("label").(string),
}
_, err := c.DecortAPICall(ctx, "POST", snapshotDeleteAPI, urlValues)
_, err := c.CloudBroker().Compute().SnapshotDelete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceSnapshotEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func resourceSnapshotUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
if d.HasChange("rollback") {
if d.Get("rollback").(bool) {
err := resourceSnapshotRollback(ctx, d, m)
@@ -116,12 +113,12 @@ func resourceSnapshotEdit(ctx context.Context, d *schema.ResourceData, m interfa
func resourceSnapshotRollback(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := compute.SnapshotRollbackRequest{
ComputeID: uint64(d.Get("compute_id").(int)),
Label: d.Get("label").(string),
}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("label", d.Get("label").(string))
_, err := c.DecortAPICall(ctx, "POST", snapshotRollbackAPI, urlValues)
_, err := c.CloudBroker().Compute().SnapshotRollback(ctx, req)
if err != nil {
return err
}
@@ -174,7 +171,7 @@ func ResourceSnapshot() *schema.Resource {
CreateContext: resourceSnapshotCreate,
ReadContext: resourceSnapshotRead,
UpdateContext: resourceSnapshotEdit,
UpdateContext: resourceSnapshotUpdate,
DeleteContext: resourceSnapshotDelete,
Importer: &schema.ResourceImporter{

View File

@@ -36,9 +36,10 @@ import (
"errors"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
)
func utilitySnapshotCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Snapshot, error) {
func utilitySnapshotCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*compute.ItemSnapshot, error) {
snapShotList, err := utilitySnapshotListCheckPresence(ctx, d, m)
if err != nil {
return nil, err
@@ -53,7 +54,7 @@ func utilitySnapshotCheckPresence(ctx context.Context, d *schema.ResourceData, m
}
for _, s := range snapShotList {
if s.Guid == findId {
if s.GUID == findId {
return &s, nil
}
}

View File

@@ -33,33 +33,22 @@ package snapshot
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilitySnapshotListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (SnapshotList, error) {
func utilitySnapshotListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (compute.ListSnapshots, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
req := compute.SnapshotListRequest{
ComputeID: uint64(d.Get("compute_id").(int)),
}
resp, err := c.DecortAPICall(ctx, "POST", snapshotListAPI, urlValues)
snapshotList, err := c.CloudBroker().Compute().SnapshotList(ctx, req)
if err != nil {
return nil, err
}
if resp == "" {
return nil, nil
}
snapshotList := SnapshotList{}
if err := json.Unmarshal([]byte(resp), &snapshotList); err != nil {
return nil, err
}
return snapshotList, nil
}

View File

@@ -46,16 +46,16 @@ func dataSourceVGPURead(ctx context.Context, d *schema.ResourceData, m interface
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(vgpu.ID))
d.SetId(strconv.FormatUint(vgpu.ID, 10))
d.Set("vgpu_id", vgpu.ID)
d.Set("account_id", vgpu.AccountID)
d.Set("mode", vgpu.Mode)
d.Set("pgpu", vgpu.PgpuID)
d.Set("pgpu", vgpu.PGPUID)
d.Set("profile_id", vgpu.ProfileID)
d.Set("ram", vgpu.RAM)
d.Set("status", vgpu.Status)
d.Set("type", vgpu.Type)
d.Set("vm_id", vgpu.VmID)
d.Set("vm_id", vgpu.VMID)
return nil
}

View File

@@ -1,44 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package vgpu
type VGPU struct {
AccountID int `json:"accountId"`
ID int `json:"id"`
Mode string `json:"mode"`
PgpuID int `json:"pgpuid"`
ProfileID int `json:"profileId"`
RAM int `json:"ram"`
Status string `json:"status"`
Type string `json:"type"`
VmID int `json:"vmid"`
}

View File

@@ -33,47 +33,38 @@ package vgpu
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vgpu"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityVGPUCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*VGPU, error) {
func utilityVGPUCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*vgpu.ItemVGPU, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("size", "50")
req := vgpu.ListRequest{
Size: 50,
}
var vgpuId int
var vgpuId uint64
var err error
if vId, ok := d.GetOk("vgpu_id"); ok {
vgpuId = vId.(int)
vgpuId = uint64(vId.(int))
} else {
vgpuId, err = strconv.Atoi(d.Id())
vgpuId, err = strconv.ParseUint(d.Id(), 10, 64)
if err != nil {
return nil, err
}
}
for page := 1; ; page++ {
urlValues.Set("page", strconv.Itoa(page))
resp, err := c.DecortAPICall(ctx, "POST", vgpuListAPI, urlValues)
req.Page = uint64(page)
vgpus, err := c.CloudBroker().VGPU().List(ctx, req)
if err != nil {
return nil, err
}
if resp == "[]" {
return nil, nil
}
var vgpus []VGPU
if err := json.Unmarshal([]byte(resp), &vgpus); err != nil {
return nil, err
}
for _, vgpu := range vgpus {
if vgpu.ID == vgpuId {
return &vgpu, nil

View File

@@ -33,11 +33,12 @@ package vins
import (
"context"
"encoding/json"
"fmt"
"reflect"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
// "net/url"
@@ -46,44 +47,32 @@ import (
// "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)
// vins_facts is a response string from API vins/get
func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
// NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceVinsExists(...) method
// log.Debugf("flattenVins: ready to decode response body from API %s", vins_facts)
vinsRecord := VinsRecord{}
err := json.Unmarshal([]byte(vins_facts), &vinsRecord)
if err != nil {
return diag.FromErr(err)
}
func flattenVins(d *schema.ResourceData, vinsRecord *vins.RecordVINS) diag.Diagnostics {
log.Debugf("flattenVins: decoded ViNS name:ID %s:%d, account ID %d, RG ID %d",
vinsRecord.Name, vinsRecord.ID, vinsRecord.AccountID, vinsRecord.RgID)
vinsRecord.Name, vinsRecord.ID, vinsRecord.AccountID, vinsRecord.RGID)
d.SetId(fmt.Sprintf("%d", vinsRecord.ID))
d.Set("name", vinsRecord.Name)
d.Set("account_id", vinsRecord.AccountID)
d.Set("account_name", vinsRecord.AccountName)
d.Set("rg_id", vinsRecord.RgID)
d.Set("description", vinsRecord.Desc)
d.Set("ipcidr", vinsRecord.IPCidr)
// d.Set("account_name", vinsRecord.AccountName)
d.Set("rg_id", vinsRecord.RGID)
d.Set("description", vinsRecord.Description)
d.Set("ipcidr", vinsRecord.Network)
noExtNetConnection := true
for _, value := range vinsRecord.VNFs {
if value.Type == "GW" {
log.Debugf("flattenVins: discovered GW VNF ID %d in ViNS ID %d", value.ID, vinsRecord.ID)
extNetID, idOk := value.Config["ext_net_id"] // NOTE: unknown numbers are unmarshalled to float64. This is by design!
extNetIP, ipOk := value.Config["ext_net_ip"]
if idOk && ipOk {
log.Debugf("flattenVins: ViNS ext_net_id=%d, ext_net_ip=%s", int(extNetID.(float64)), extNetIP.(string))
d.Set("ext_ip_addr", extNetIP.(string))
d.Set("ext_net_id", int(extNetID.(float64)))
} else {
return diag.Errorf("Failed to unmarshal VNF GW Config - structure is invalid.")
}
noExtNetConnection = false
break
gw := vinsRecord.VNFs.GW
if !reflect.ValueOf(gw).IsZero() {
log.Debugf("flattenVins: discovered GW VNF ID %d in ViNS ID %d", gw.ID, vinsRecord.ID)
extNetID := gw.Config.ExtNetID
extNetIP := gw.Config.ExtNetIP
if extNetID != 0 && extNetIP != "" {
log.Debugf("flattenVins: ViNS ext_net_id=%d, ext_net_ip=%s", extNetID, extNetIP)
d.Set("ext_ip_addr", extNetIP)
d.Set("ext_net_id", extNetID)
} else {
return diag.Errorf("Failed to unmarshal VNF GW Config - structure is invalid.")
}
noExtNetConnection = false
}
if noExtNetConnection {
@@ -98,10 +87,8 @@ func flattenVins(d *schema.ResourceData, vins_facts string) diag.Diagnostics {
func dataSourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
// if empty string is returned from utilityVinsCheckPresence then there is no
// such ViNS and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty in this case
if vinsFacts == nil {
d.SetId("")
return diag.FromErr(err)
}

View File

@@ -37,14 +37,15 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func flattenVinsList(vl VinsList) []map[string]interface{} {
func flattenVinsList(vl vins.ListVINS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, v := range vl {
temp := map[string]interface{}{
"account_id": v.AccountId,
"account_id": v.AccountID,
"account_name": v.AccountName,
"created_by": v.CreatedBy,
"created_time": v.CreatedTime,
@@ -59,7 +60,7 @@ func flattenVinsList(vl VinsList) []map[string]interface{} {
"status": v.Status,
"updated_by": v.UpdatedBy,
"updated_time": v.UpdatedTime,
"vxlan_id": v.VXLanID,
"vxlan_id": v.VXLANID,
}
res = append(res, temp)
}

View File

@@ -1,94 +0,0 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package vins
type Vins struct {
AccountId int `json:"accountId"`
AccountName string `json:"accountName"`
CreatedBy string `json:"createdBy"`
CreatedTime int `json:"createdTime"`
DeletedBy string `json:"deletedBy"`
DeletedTime int `json:"deletedTime"`
ExternalIP string `json:"externalIP"`
ID int `json:"id"`
Name string `json:"name"`
Network string `json:"network"`
RGID int `json:"rgId"`
RGName string `json:"rgName"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime int `json:"updatedTime"`
VXLanID int `json:"vxlanId"`
}
type VinsList []Vins
type VinsSearchResp []VinsSearchRecord
type VnfRecord struct {
ID int `json:"id"`
AccountID int `json:"accountId"`
Type string `json:"type"` // "DHCP", "NAT", "GW" etc
Config map[string]interface{} `json:"config"` // NOTE: VNF specs vary by VNF type
}
type VnfGwConfigRecord struct { // describes GW VNF config structure inside ViNS, as returned by API vins/get
ExtNetID int `json:"ext_net_id"`
ExtNetIP string `json:"ext_net_ip"`
ExtNetMask int `json:"ext_net_mask"`
DefaultGW string `json:"default_gw"`
}
type VinsRecord struct { // represents part of the response from API vins/get
ID int `json:"id"`
Name string `json:"name"`
IPCidr string `json:"network"`
VxLanID int `json:"vxlanId"`
ExternalIP string `json:"externalIP"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
RgID int `json:"rgid"`
RgName string `json:"rgName"`
VNFs map[string]VnfRecord `json:"vnfs"`
Desc string `json:"desc"`
}
type VinsSearchRecord struct {
ID int `json:"id"`
Name string `json:"name"`
IPCidr string `json:"network"`
VxLanID int `json:"vxlanId"`
ExternalIP string `json:"externalIP"`
AccountID int `json:"accountId"`
AccountName string `json:"accountName"`
RgID int `json:"rgId"`
RgName string `json:"rgName"`
}

View File

@@ -33,13 +33,12 @@ package vins
import (
"context"
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -62,82 +61,78 @@ func resourceVinsCreate(ctx context.Context, d *schema.ResourceData, m interface
log.Debugf("resourceVinsCreate: called for ViNS name %s, Account ID %d, RG ID %d",
d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
apiToCall := VinsCreateInAccountAPI
createInAcc := true
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
inAccReq := vins.CreateInAccountRequest{
Name: d.Get("name").(string),
}
inRGReq := vins.CreateInRGRequest{
Name: d.Get("name").(string),
}
argVal, argSet := d.GetOk("rg_id")
if argSet && argVal.(int) > 0 {
apiToCall = VinsCreateInRgAPI
urlValues.Add("rgId", fmt.Sprintf("%d", argVal.(int)))
createInAcc = false
inRGReq.RGID = uint64(argVal.(int))
} else {
// RG ID either not set at all or set to 0 - user may want ViNS at account level
argVal, argSet = d.GetOk("account_id")
if !argSet || argVal.(int) <= 0 {
// No valid Account ID (and no RG ID either) - cannot create ViNS
return diag.Errorf("resourceVinsCreate: ViNS name %s - no valid account and/or resource group ID specified", d.Id())
}
urlValues.Add("accountId", fmt.Sprintf("%d", argVal.(int)))
inAccReq.AccountID = uint64(argVal.(int))
}
argVal, argSet = d.GetOk("ext_net_id") // NB: even if ext_net_id value is explicitly set to 0, argSet = false anyway
if argSet {
if argVal.(int) > 0 {
// connect to specific external network
urlValues.Add("extNetId", fmt.Sprintf("%d", argVal.(int)))
/*
Commented out, as we've made "ext_net_ip" parameter non-configurable via Terraform!
// in case of specific ext net connection user may also want a particular IP address
argVal, argSet = d.GetOk("ext_net_ip")
if argSet && argVal.(string) != "" {
urlValues.Add("extIp", argVal.(string))
}
*/
inRGReq.ExtNetID = uint64(argVal.(int))
} else {
// ext_net_id is set to a negative value - connect to default external network
// no particular IP address selection in this case
urlValues.Add("extNetId", "0")
inRGReq.ExtNetID = 0
}
}
argVal, argSet = d.GetOk("ipcidr")
if argSet && argVal.(string) != "" {
log.Debugf("resourceVinsCreate: ipcidr is set to %s", argVal.(string))
urlValues.Add("ipcidr", argVal.(string))
inAccReq.IPCIDR = argVal.(string)
inRGReq.IPCIDR = argVal.(string)
}
argVal, argSet = d.GetOk("description")
if argSet {
urlValues.Add("desc", argVal.(string))
inAccReq.Description = argVal.(string)
inRGReq.Description = argVal.(string)
}
apiResp, err := c.DecortAPICall(ctx, "POST", apiToCall, urlValues)
if err != nil {
return diag.FromErr(err)
var vinsID uint64
if createInAcc {
apiResp, err := c.CloudBroker().VINS().CreateInAccount(ctx, inAccReq)
if err != nil {
return diag.FromErr(err)
}
vinsID = apiResp
} else {
apiResp, err := c.CloudBroker().VINS().CreateInRG(ctx, inRGReq)
if err != nil {
return diag.FromErr(err)
}
vinsID = apiResp
}
d.SetId(apiResp) // update ID of the resource to tell Terraform that the ViNS resource exists
vinsId, _ := strconv.Atoi(apiResp)
d.SetId(strconv.FormatUint(vinsID, 10))
log.Debugf("resourceVinsCreate: new ViNS ID / name %d / %s creation sequence complete", vinsId, d.Get("name").(string))
log.Debugf("resourceVinsCreate: new ViNS ID / name %d / %s creation sequence complete", vinsID, d.Get("name").(string))
// We may reuse dataSourceVinsRead here as we maintain similarity
// between ViNS resource and ViNS data source schemas
// ViNS resource read function will also update resource ID on success, so that Terraform
// will know the resource exists (however, we already did it a few lines before)
return dataSourceVinsRead(ctx, d, m)
}
func resourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
// if empty string is returned from utilityVinsCheckPresence then there is no
// such ViNS and err tells so - just return it to the calling party
d.SetId("") // ensure ID is empty
if vinsFacts == nil {
d.SetId("")
return diag.FromErr(err)
}
@@ -145,40 +140,39 @@ func resourceVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}
}
func resourceVinsUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceVinsUpdate: called for ViNS ID / name %s / %s, Account ID %d, RG ID %d",
d.Id(), d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
vinsID, _ := strconv.ParseUint(d.Id(), 10, 64)
// 1. Handle external network connection change
oldExtNetId, newExtNedId := d.GetChange("ext_net_id")
if oldExtNetId.(int) != newExtNedId.(int) {
log.Debugf("resourceVinsUpdate: changing ViNS ID %s - ext_net_id %d -> %d", d.Id(), oldExtNetId.(int), newExtNedId.(int))
extnetParams := &url.Values{}
extnetParams.Add("vinsId", d.Id())
if oldExtNetId.(int) > 0 {
// there was preexisting external net connection - disconnect ViNS
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetDisconnectAPI, extnetParams)
req := vins.ExtNetDisconnectRequest{VINSID: vinsID}
_, err := c.CloudBroker().VINS().ExtNetDisconnect(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
if newExtNedId.(int) > 0 {
// new external network connection requested - connect ViNS
extnetParams.Add("netId", fmt.Sprintf("%d", newExtNedId.(int)))
_, err := c.DecortAPICall(ctx, "POST", VinsExtNetConnectAPI, extnetParams)
req := vins.ExtNetConnectRequest{
VINSID: vinsID,
NetID: uint64(newExtNedId.(int)),
}
_, err := c.CloudBroker().VINS().ExtNetConnect(ctx, req)
if err != nil {
return diag.FromErr(err)
}
}
}
// we may reuse dataSourceVinsRead here as we maintain similarity
// between Compute resource and Compute data source schemas
return dataSourceVinsRead(ctx, d, m)
}
@@ -187,7 +181,7 @@ func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface
d.Id(), d.Get("name").(string), d.Get("account_id").(int), d.Get("rg_id").(int))
vinsFacts, err := utilityVinsCheckPresence(ctx, d, m)
if vinsFacts == "" {
if vinsFacts == nil {
if err != nil {
return diag.FromErr(err)
}
@@ -196,13 +190,14 @@ func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface
return nil
}
params := &url.Values{}
params.Add("vinsId", d.Id())
params.Add("force", "1") // disconnect all computes before deleting ViNS
params.Add("permanently", "1") // delete ViNS immediately bypassing recycle bin
c := m.(*controller.ControllerCfg)
_, err = c.DecortAPICall(ctx, "POST", VinsDeleteAPI, params)
req := vins.DeleteRequest{
VINSID: vinsFacts.ID,
Force: true,
Permanently: true,
}
_, err = c.CloudBroker().VINS().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}

View File

@@ -33,44 +33,25 @@ package vins
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// On success this function returns a string, as returned by API vins/get, which could be unmarshalled
// into VinsGetResp structure
func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
// This function tries to locate ViNS by one of the following algorithms depending
// on the parameters passed:
// - if resource group ID is specified -> it looks for a ViNS at the RG level
// - if account ID is specifeid -> it looks for a ViNS at the account level
//
// If succeeded, it returns non empty string that contains JSON formatted facts about the
// ViNS as returned by vins/get API call.
// Otherwise it returns empty string and a meaningful error.
//
// This function does not modify its ResourceData argument, so it is safe to use it as core
// method for the Terraform resource Exists method.
//
func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*vins.RecordVINS, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
// make it possible to use "read" & "check presence" functions with ViNS ID set so
// that Import of ViNS resource is possible
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
vinsID, err := strconv.ParseUint(d.Id(), 10, 64)
if err != nil || vinsID <= 0 {
vinsId, argSet := d.GetOk("vins_id") // NB: vins_id is NOT present in vinsResource schema!
if argSet {
theId = vinsId.(int)
vinsID = uint64(vinsId.(int))
idSet = true
}
} else {
@@ -78,76 +59,65 @@ func utilityVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m int
}
if idSet {
// ViNS ID is specified, try to get compute instance straight by this ID
log.Debugf("utilityVinsCheckPresence: locating ViNS by its ID %d", theId)
urlValues.Add("vinsId", fmt.Sprintf("%d", theId))
vinsFacts, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, urlValues)
log.Debugf("utilityVinsCheckPresence: locating ViNS by its ID %d", vinsID)
req := vins.GetRequest{VINSID: vinsID}
vinsFacts, err := c.CloudBroker().VINS().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return vinsFacts, nil
}
// ID was not set in the schema upon entering this function - work through ViNS name
// and Account / RG ID
vinsName, argSet := d.GetOk("name")
if !argSet {
// if ViNS name is not set. then we cannot locate ViNS
return "", fmt.Errorf("Cannot check ViNS presence if ViNS name is empty")
return nil, fmt.Errorf("Cannot check ViNS presence if ViNS name is empty")
}
req := vins.SearchRequest{
Name: vinsName.(string),
ShowAll: false,
}
urlValues.Add("name", vinsName.(string))
urlValues.Add("show_all", "false")
log.Debugf("utilityVinsCheckPresence: preparing to locate ViNS name %s", vinsName.(string))
rgId, rgSet := d.GetOk("rg_id")
if rgSet {
log.Debugf("utilityVinsCheckPresence: limiting ViNS search to RG ID %d", rgId.(int))
urlValues.Add("rgId", fmt.Sprintf("%d", rgId.(int)))
req.RGID = uint64(rgId.(int))
}
accountId, accountSet := d.GetOk("account_id")
if accountSet {
log.Debugf("utilityVinsCheckPresence: limiting ViNS search to Account ID %d", accountId.(int))
urlValues.Add("accountId", fmt.Sprintf("%d", accountId.(int)))
req.AccountID = uint64(accountId.(int))
}
apiResp, err := c.DecortAPICall(ctx, "POST", VinsSearchAPI, urlValues)
vinsList, err := c.CloudBroker().VINS().Search(ctx, req)
if err != nil {
return "", err
return nil, err
}
// log.Debugf("%s", apiResp)
// log.Debugf("utilityResgroupCheckPresence: ready to decode response body from %s", VinsSearchAPI)
model := VinsSearchResp{}
err = json.Unmarshal([]byte(apiResp), &model)
if err != nil {
return "", err
}
log.Debugf("utilityVinsCheckPresence: traversing decoded Json of length %d", len(model))
for index, item := range model {
log.Debugf("utilityVinsCheckPresence: traversing decoded Json of length %d", len(vinsList))
for index, item := range vinsList {
if item.Name == vinsName.(string) {
if (accountSet && item.AccountID != accountId.(int)) ||
(rgSet && item.RgID != rgId.(int)) {
// double check that account ID and Rg ID match, if set in the schema
if (accountSet && item.AccountID != uint64(accountId.(int))) ||
(rgSet && item.RGID != uint64(rgId.(int))) {
continue
}
log.Debugf("utilityVinsCheckPresence: match ViNS name %s / ID %d, account ID %d, RG ID %d at index %d",
item.Name, item.ID, item.AccountID, item.RgID, index)
item.Name, item.ID, item.AccountID, item.RGID, index)
// element returned by API vins/search does not contain all information we may need to
// manage ViNS, so we have to get detailed info by calling API vins/get
rqValues := &url.Values{}
rqValues.Add("vinsId", fmt.Sprintf("%d", item.ID))
vinsGetResp, err := c.DecortAPICall(ctx, "POST", VinsGetAPI, rqValues)
req := vins.GetRequest{VINSID: item.ID}
vinsGetResp, err := c.CloudBroker().VINS().Get(ctx, req)
if err != nil {
return "", err
return nil, err
}
return vinsGetResp, nil
}
}
return "", fmt.Errorf("Cannot find ViNS name %s. Check name and/or RG ID & Account ID and your access rights", vinsName.(string))
return nil, fmt.Errorf("Cannot find ViNS name %s. Check name and/or RG ID & Account ID and your access rights", vinsName.(string))
}

View File

@@ -33,38 +33,27 @@ package vins
import (
"context"
"encoding/json"
"net/url"
"strconv"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (VinsList, error) {
vinsList := VinsList{}
func utilityVinsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (vins.ListVINS, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
req := vins.ListRequest{}
if includeDeleted, ok := d.GetOk("include_deleted"); ok {
urlValues.Add("includeDeleted", strconv.FormatBool(includeDeleted.(bool)))
}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
req.Size = uint64(size.(int))
}
log.Debugf("utilityVinsListCheckPresence")
vinsListRaw, err := c.DecortAPICall(ctx, "POST", VinsListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(vinsListRaw), &vinsList)
vinsList, err := c.CloudBroker().VINS().List(ctx, req)
if err != nil {
return nil, err
}