gos_tech_4.4.3 3.5.0
KasimBaybikov 2 years ago
parent f5e0a53364
commit af82decadd

@ -1,11 +1,56 @@
### Version 3.4.3 ### Version 3.5.0
### Features ## Features
- Change field type disksize from int to float in: #### Resgroup
- resource decort_resgroup - Add data source rg_affinity_group_computes
- resource decort_account - Add data source rg_affinity_groups_get
- data source decort_rg - Add data source rg_affinity_groups_list
- data source decort_account - Add data source rg_audits
- data source decort_account_rg_list - Add data source rg_list
- Models of the resources - Add data source rg_list_computes
- Add data source rg_list_deleted
- Add data source rg_list_lb
- Add data source rg_list_pfw
- Add data source rg_list_vins
- Add data source rg_usage
- Update data source rg
- Update block 'qouta' to change resource limits
- Add block 'access' to access/revoke rights for rg
- Add block 'def_net' to set default network in rg
- Add field 'enable' to disable/enable rg
- Add processing of input parameters (account_id, gid, ext_net_id) when creating and updating a resource
#### Kvmvm
- Update data source decort_kvmvm
- Add data source decort_kvmvm_list
- Add data source decort_kvmvm_audits
- Add data source decort_kvmvm_get_audits
- Add data source decort_kvmvm_get_console_url
- Add data source decort_kvmvm_get_log
- Add data source decort_kvmvm_pfw_list
- Add data source decort_kvmvm_user_list
- Update block 'disks' in the resource decort_kvmvm
- Add block 'tags' to add/delete tags
- Add block 'port_forwarding' to add/delete pfws
- Add block 'user_access' to access/revoke user rights for comptue
- Add block 'snapshot' to create/delete snapshots
- Add block 'rollback' to rollback in snapshot
- Add block 'cd' to insert/Eject cdROM disks
- Add field 'pin_to_stack' to pin compute to stack
- Add field 'pause' to pause/resume compute
- Add field 'reset' to reset compute
- Add the ability to redeploy the compute when changing the image_id
- Add field 'data_disks' to redeploy compute
- Add field 'auto_start' to redeploy compute
- Add field 'force_stop' to redeploy compute
- Add warnings in Create resource decort_kvmvm
- Add processing of input parameters (rg_id, image_id and all vins_id's in blocks 'network') when creating and updating a resource
## Bug Fix
- When deleting the 'quote' block, the limits are not set to the default value
- Block 'disks' in resource decort_kvmvm breaks the state
- Import decort_resgroup resource breaks the state
- Import decort_kvmvm resource breaks the state
- If the boot_disk_size is not specified at creation, further changing it leads to an error

@ -40,6 +40,13 @@ func NewDataSourcesMap() map[string]*schema.Resource {
"decort_account": account.DataSourceAccount(), "decort_account": account.DataSourceAccount(),
"decort_resgroup": rg.DataSourceResgroup(), "decort_resgroup": rg.DataSourceResgroup(),
"decort_kvmvm": kvmvm.DataSourceCompute(), "decort_kvmvm": kvmvm.DataSourceCompute(),
"decort_kvmvm_list": kvmvm.DataSourceComputeList(),
"decort_kvmvm_audits": kvmvm.DataSourceComputeAudits(),
"decort_kvmvm_get_audits": kvmvm.DataSourceComputeGetAudits(),
"decort_kvmvm_get_console_url": kvmvm.DataSourceComputeGetConsoleUrl(),
"decort_kvmvm_get_log": kvmvm.DataSourceComputeGetLog(),
"decort_kvmvm_pfw_list": kvmvm.DataSourceComputePfwList(),
"decort_kvmvm_user_list": kvmvm.DataSourceComputeUserList(),
"decort_k8s": k8s.DataSourceK8s(), "decort_k8s": k8s.DataSourceK8s(),
"decort_k8s_list": k8s.DataSourceK8sList(), "decort_k8s_list": k8s.DataSourceK8sList(),
"decort_k8s_list_deleted": k8s.DataSourceK8sListDeleted(), "decort_k8s_list_deleted": k8s.DataSourceK8sListDeleted(),
@ -56,6 +63,16 @@ func NewDataSourcesMap() map[string]*schema.Resource {
"decort_disk": disks.DataSourceDisk(), "decort_disk": disks.DataSourceDisk(),
"decort_disk_list": disks.DataSourceDiskList(), "decort_disk_list": disks.DataSourceDiskList(),
"decort_rg_list": rg.DataSourceRgList(), "decort_rg_list": rg.DataSourceRgList(),
"decort_rg_affinity_group_computes": rg.DataSourceRgAffinityGroupComputes(),
"decort_rg_affinity_groups_list": rg.DataSourceRgAffinityGroupsList(),
"decort_rg_affinity_groups_get": rg.DataSourceRgAffinityGroupsGet(),
"decort_rg_audits": rg.DataSourceRgAudits(),
"decort_rg_list_computes": rg.DataSourceRgListComputes(),
"decort_rg_list_deleted": rg.DataSourceRgListDeleted(),
"decort_rg_list_lb": rg.DataSourceRgListLb(),
"decort_rg_list_pfw": rg.DataSourceRgListPfw(),
"decort_rg_list_vins": rg.DataSourceRgListVins(),
"decort_rg_usage": rg.DataSourceRgUsage(),
"decort_disk_list_types_detailed": disks.DataSourceDiskListTypesDetailed(), "decort_disk_list_types_detailed": disks.DataSourceDiskListTypesDetailed(),
"decort_disk_list_types": disks.DataSourceDiskListTypes(), "decort_disk_list_types": disks.DataSourceDiskListTypes(),
"decort_disk_list_deleted": disks.DataSourceDiskListDeleted(), "decort_disk_list_deleted": disks.DataSourceDiskListDeleted(),

@ -52,8 +52,6 @@ const (
ComputeRestoreAPI = "/restmachine/cloudapi/compute/restore" ComputeRestoreAPI = "/restmachine/cloudapi/compute/restore"
ComputeEnableAPI = "/restmachine/cloudapi/compute/enable" ComputeEnableAPI = "/restmachine/cloudapi/compute/enable"
ComputeDisableAPI = "/restmachine/cloudapi/compute/disable" ComputeDisableAPI = "/restmachine/cloudapi/compute/disable"
//affinity and anti-affinity
ComputeAffinityLabelSetAPI = "/restmachine/cloudapi/compute/affinityLabelSet" ComputeAffinityLabelSetAPI = "/restmachine/cloudapi/compute/affinityLabelSet"
ComputeAffinityLabelRemoveAPI = "/restmachine/cloudapi/compute/affinityLabelRemove" ComputeAffinityLabelRemoveAPI = "/restmachine/cloudapi/compute/affinityLabelRemove"
ComputeAffinityRuleAddAPI = "/restmachine/cloudapi/compute/affinityRuleAdd" ComputeAffinityRuleAddAPI = "/restmachine/cloudapi/compute/affinityRuleAdd"
@ -62,4 +60,28 @@ const (
ComputeAntiAffinityRuleAddAPI = "/restmachine/cloudapi/compute/antiAffinityRuleAdd" ComputeAntiAffinityRuleAddAPI = "/restmachine/cloudapi/compute/antiAffinityRuleAdd"
ComputeAntiAffinityRuleRemoveAPI = "/restmachine/cloudapi/compute/antiAffinityRuleRemove" ComputeAntiAffinityRuleRemoveAPI = "/restmachine/cloudapi/compute/antiAffinityRuleRemove"
ComputeAntiAffinityRulesClearAPI = "/restmachine/cloudapi/compute/antiAffinityRulesClear" ComputeAntiAffinityRulesClearAPI = "/restmachine/cloudapi/compute/antiAffinityRulesClear"
ComputeListAPI = "/restmachine/cloudapi/compute/list"
ComputeAuditsAPI = "/restmachine/cloudapi/compute/audits"
ComputeGetAuditsAPI = "/restmachine/cloudapi/compute/getAudits"
ComputeGetConsoleUrlAPI = "/restmachine/cloudapi/compute/getConsoleUrl"
ComputeGetLogAPI = "/restmachine/cloudapi/compute/getLog"
ComputePfwListAPI = "/restmachine/cloudapi/compute/pfwList"
ComputeUserListAPI = "/restmachine/cloudapi/compute/userList"
ComputeTagAddAPI = "/restmachine/cloudapi/compute/tagAdd"
ComputeTagRemoveAPI = "/restmachine/cloudapi/compute/tagRemove"
ComputePinToStackAPI = "/restmachine/cloudapi/compute/pinToStack"
ComputeUnpinFromStackAPI = "/restmachine/cloudapi/compute/unpinFromStack"
ComputePfwAddAPI = "/restmachine/cloudapi/compute/pfwAdd"
ComputePfwDelAPI = "/restmachine/cloudapi/compute/pfwDel"
ComputeUserGrantAPI = "/restmachine/cloudapi/compute/userGrant"
ComputeUserRevokeAPI = "/restmachine/cloudapi/compute/userRevoke"
ComputeSnapshotCreateAPI = "/restmachine/cloudapi/compute/snapshotCreate"
ComputeSnapshotDeleteAPI = "/restmachine/cloudapi/compute/snapshotCreate"
ComputeSnapshotRollbackAPI = "/restmachine/cloudapi/compute/snapshotRollback"
ComputePauseAPI = "/restmachine/cloudapi/compute/pause"
ComputeResumeAPI = "/restmachine/cloudapi/compute/resume"
ComputeCdInsertAPI = "/restmachine/cloudapi/compute/cdInsert"
ComputeCdEjectAPI = "/restmachine/cloudapi/compute/cdEject"
ComputeResetAPI = "/restmachine/cloudapi/compute/reset"
ComputeRedeployAPI = "/restmachine/cloudapi/compute/redeploy"
) )

File diff suppressed because it is too large Load Diff

@ -0,0 +1,74 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeAuditsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeAudits, err := utilityComputeAuditsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenComputeAudits(computeAudits))
return nil
}
func dataSourceComputeAuditsSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"call": {
Type: schema.TypeString,
Computed: true,
},
"responsetime": {
Type: schema.TypeFloat,
Computed: true,
},
"statuscode": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeFloat,
Computed: true,
},
"user": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
}
func DataSourceComputeAudits() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeAuditsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputeAuditsSchemaMake(),
}
}

@ -0,0 +1,62 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeGetAuditsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeAudits, err := utilityComputeGetAuditsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenComputeGetAudits(computeAudits))
return nil
}
func dataSourceComputeGetAuditsSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"epoch": {
Type: schema.TypeFloat,
Computed: true,
},
"message": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
}
func DataSourceComputeGetAudits() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeGetAuditsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputeGetAuditsSchemaMake(),
}
}

@ -0,0 +1,52 @@
package kvmvm
import (
"context"
"strings"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeGetConsoleUrlRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeConsoleUrl, err := utilityComputeGetConsoleUrlCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
result := strings.ReplaceAll(string(computeConsoleUrl), "\"", "")
result = strings.ReplaceAll(string(result), "\\", "")
d.Set("console_url", result)
return nil
}
func dataSourceComputeGetConsoleUrlSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
},
"console_url": {
Type: schema.TypeString,
Computed: true,
},
}
}
func DataSourceComputeGetConsoleUrl() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeGetConsoleUrlRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputeGetConsoleUrlSchemaMake(),
}
}

@ -0,0 +1,53 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeGetLogRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeGetLog, err := utilityComputeGetLogCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("log", computeGetLog)
return nil
}
func dataSourceComputeGetLogSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
},
"path": {
Type: schema.TypeString,
Required: true,
},
"log": {
Type: schema.TypeString,
Computed: true,
},
}
}
func DataSourceComputeGetLog() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeGetLogRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputeGetLogSchemaMake(),
}
}

@ -0,0 +1,335 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeList, err := utilityDataComputeListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenComputeList(computeList))
return nil
}
func computeDisksSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Computed: true,
},
"pci_slot": {
Type: schema.TypeInt,
Computed: true,
},
}
}
func itemComputeSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"acl": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeListACLSchemaMake(),
},
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"affinity_label": {
Type: schema.TypeString,
Computed: true,
},
"affinity_rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeListRulesSchemaMake(),
},
},
"affinity_weight": {
Type: schema.TypeInt,
Computed: true,
},
"anti_affinity_rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeListRulesSchemaMake(),
},
},
"arch": {
Type: schema.TypeString,
Computed: true,
},
"boot_order": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"bootdisk_size": {
Type: schema.TypeInt,
Computed: true,
},
"clone_reference": {
Type: schema.TypeInt,
Computed: true,
},
"clones": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"computeci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cpus": {
Type: schema.TypeInt,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"custom_fields": { //NEED
Type: schema.TypeString,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"devices": { //NEED
Type: schema.TypeString,
Computed: true,
},
"disks": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeDisksSchemaMake(),
},
},
"driver": {
Type: schema.TypeString,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"interfaces": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeInterfacesSchemaMake(),
},
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"manager_id": {
Type: schema.TypeInt,
Computed: true,
},
"manager_type": {
Type: schema.TypeString,
Computed: true,
},
"migrationjob": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"pinned": {
Type: schema.TypeBool,
Computed: true,
},
"ram": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"registered": {
Type: schema.TypeBool,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"snap_sets": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: computeSnapSetsSchemaMake(),
},
},
"stateless_sep_id": {
Type: schema.TypeInt,
Computed: true,
},
"stateless_sep_type": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tags": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
},
"val": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"total_disk_size": {
Type: schema.TypeInt,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"user_managed": {
Type: schema.TypeBool,
Computed: true,
},
"vgpus": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"vins_connected": {
Type: schema.TypeInt,
Computed: true,
},
"virtual_image_id": {
Type: schema.TypeInt,
Computed: true,
},
}
}
func dataSourceCompputeListSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"includedeleted": {
Type: schema.TypeBool,
Optional: true,
},
"page": {
Type: schema.TypeInt,
Optional: true,
},
"size": {
Type: schema.TypeInt,
Optional: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: itemComputeSchemaMake(),
},
},
}
return res
}
func DataSourceComputeList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceCompputeListSchemaMake(),
}
}

@ -0,0 +1,81 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputePfwListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computePfwList, err := utilityComputePfwListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenPfwList(computePfwList))
return nil
}
func dataSourceComputePfwListSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"pfw_id": {
Type: schema.TypeInt,
Computed: true,
},
"local_ip": {
Type: schema.TypeString,
Computed: true,
},
"local_port": {
Type: schema.TypeInt,
Computed: true,
},
"protocol": {
Type: schema.TypeString,
Computed: true,
},
"public_port_end": {
Type: schema.TypeInt,
Computed: true,
},
"public_port_start": {
Type: schema.TypeInt,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
}
func DataSourceComputePfwList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputePfwListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputePfwListSchemaMake(),
}
}

@ -0,0 +1,45 @@
package kvmvm
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceComputeUserListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeUserList, err := utilityComputeUserListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
flattenUserList(d, computeUserList)
return nil
}
func dataSourceComputeUserListSchemaMake() map[string]*schema.Schema {
res := computeACLSchemaMake()
res["compute_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
}
return res
}
func DataSourceComputeUserList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceComputeUserListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceComputeUserListSchemaMake(),
}
}

@ -2,17 +2,195 @@ package kvmvm
import ( import (
"encoding/json" "encoding/json"
"fmt" "sort"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/status" "github.com/rudecs/terraform-provider-decort/internal/status"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) []map[string]interface{} { func flattenDisks(disks []InfoDisk) []map[string]interface{} {
res := make([]map[string]interface{}, 0) res := make([]map[string]interface{}, 0)
for _, disk := range disks {
temp := map[string]interface{}{
"disk_id": disk.ID,
"pci_slot": disk.PCISlot,
}
res = append(res, temp)
}
return res
}
func flattenQOS(qos QOS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"e_rate": qos.ERate,
"guid": qos.GUID,
"in_brust": qos.InBurst,
"in_rate": qos.InRate,
}
res = append(res, temp)
return res
}
func flattenInterfaces(interfaces ListInterfaces) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, interfaceItem := range interfaces {
temp := map[string]interface{}{
"conn_id": interfaceItem.ConnID,
"conn_type": interfaceItem.ConnType,
"def_gw": interfaceItem.DefGW,
"flip_group_id": interfaceItem.FLIPGroupID,
"guid": interfaceItem.GUID,
"ip_address": interfaceItem.IPAddress,
"listen_ssh": interfaceItem.ListenSSH,
"mac": interfaceItem.MAC,
"name": interfaceItem.Name,
"net_id": interfaceItem.NetID,
"netmask": interfaceItem.NetMask,
"net_type": interfaceItem.NetType,
"pci_slot": interfaceItem.PCISlot,
"qos": flattenQOS(interfaceItem.QOS),
"target": interfaceItem.Target,
"type": interfaceItem.Type,
"vnfs": interfaceItem.VNFs,
}
res = append(res, temp)
}
return res
}
func flattenSnapSets(snapSets ListSnapSets) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, snapSet := range snapSets {
temp := map[string]interface{}{
"disks": snapSet.Disks,
"guid": snapSet.GUID,
"label": snapSet.Label,
"timestamp": snapSet.Timestamp,
}
res = append(res, temp)
}
return res
}
func flattenTags(tags map[string]string) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for key, val := range tags {
temp := map[string]interface{}{
"key": key,
"val": val,
}
res = append(res, temp)
}
return res
}
func flattenListRules(listRules ListRules) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rule := range listRules {
temp := map[string]interface{}{
"guid": rule.GUID,
"key": rule.Key,
"mode": rule.Mode,
"policy": rule.Policy,
"topology": rule.Topology,
"value": rule.Value,
}
res = append(res, temp)
}
return res
}
func flattenListACL(listAcl ListACL) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, acl := range listAcl {
var explicit interface{}
switch acl.Explicit.(type) { //Платформенный хак
case bool:
explicit = acl.Explicit.(bool)
case string:
explicit, _ = strconv.ParseBool(acl.Explicit.(string))
}
temp := map[string]interface{}{
"explicit": explicit,
"guid": acl.GUID,
"right": acl.Right,
"status": acl.Status,
"type": acl.Type,
"user_group_id": acl.UserGroupID,
}
res = append(res, temp)
}
return res
}
func flattenComputeList(computes ListComputes) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, compute := range computes {
customFields, _ := json.Marshal(compute.CustomFields)
devices, _ := json.Marshal(compute.Devices)
temp := map[string]interface{}{
"acl": flattenListACL(compute.ACL),
"account_id": compute.AccountID,
"account_name": compute.AccountName,
"affinity_label": compute.AffinityLabel,
"affinity_rules": flattenListRules(compute.AffinityRules),
"affinity_weight": compute.AffinityWeight,
"anti_affinity_rules": flattenListRules(compute.AntiAffinityRules),
"arch": compute.Architecture,
"boot_order": compute.BootOrder,
"bootdisk_size": compute.BootDiskSize,
"clone_reference": compute.CloneReference,
"clones": compute.Clones,
"computeci_id": compute.ComputeCIID,
"cpus": compute.CPU,
"created_by": compute.CreatedBy,
"created_time": compute.CreatedTime,
"custom_fields": string(customFields),
"deleted_by": compute.DeletedBy,
"deleted_time": compute.DeletedTime,
"desc": compute.Description,
"devices": string(devices),
"disks": flattenDisks(compute.Disks),
"driver": compute.Driver,
"gid": compute.GID,
"guid": compute.GUID,
"compute_id": compute.ID,
"image_id": compute.ImageID,
"interfaces": flattenInterfaces(compute.Interfaces),
"lock_status": compute.LockStatus,
"manager_id": compute.ManagerID,
"manager_type": compute.ManagerType,
"migrationjob": compute.MigrationJob,
"milestones": compute.Milestones,
"name": compute.Name,
"pinned": compute.Pinned,
"ram": compute.RAM,
"reference_id": compute.ReferenceID,
"registered": compute.Registered,
"res_name": compute.ResName,
"rg_id": compute.RGID,
"rg_name": compute.RGName,
"snap_sets": flattenSnapSets(compute.SnapSets),
"stateless_sep_id": compute.StatelessSepID,
"stateless_sep_type": compute.StatelessSepType,
"status": compute.Status,
"tags": flattenTags(compute.Tags),
"tech_status": compute.TechStatus,
"total_disk_size": compute.TotalDiskSize,
"updated_by": compute.UpdatedBy,
"updated_time": compute.UpdatedTime,
"user_managed": compute.UserManaged,
"vgpus": compute.VGPUs,
"vins_connected": compute.VINSConnected,
"virtual_image_id": compute.VirtualImageID,
}
res = append(res, temp)
}
return res
}
func flattenComputeDisksDemo(disksList ListComputeDisks, extraDisks []interface{}) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(disksList))
for _, disk := range disksList { for _, disk := range disksList {
if disk.Name == "bootdisk" || findInExtraDisks(disk.ID, extraDisks) { //skip main bootdisk and extraDisks if disk.Name == "bootdisk" || findInExtraDisks(uint(disk.ID), extraDisks) { //skip main bootdisk and extraDisks
continue continue
} }
temp := map[string]interface{}{ temp := map[string]interface{}{
@ -24,66 +202,139 @@ func flattenComputeDisksDemo(disksList []DiskRecord, extraDisks []interface{}) [
"size_max": disk.SizeMax, "size_max": disk.SizeMax,
"size_used": disk.SizeUsed, "size_used": disk.SizeUsed,
"pool": disk.Pool, "pool": disk.Pool,
"desc": disk.Desc, "desc": disk.Description,
"image_id": disk.ImageID, "image_id": disk.ImageID,
"size": disk.SizeMax, "size": disk.SizeMax,
} }
res = append(res, temp) res = append(res, temp)
} }
sort.Slice(res, func(i, j int) bool {
return res[i]["disk_id"].(uint64) < res[j]["disk_id"].(uint64)
})
return res
}
func flattenNetwork(interfaces ListInterfaces) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(interfaces))
//index := 0
for _, network := range interfaces {
temp := map[string]interface{}{
"net_id": network.NetID,
"net_type": network.NetType,
"ip_address": network.IPAddress,
"mac": network.MAC,
}
res = append(res, temp)
}
return res return res
} }
func flattenCompute(d *schema.ResourceData, compFacts string) error { func findBootDisk(disks ListComputeDisks) *ItemComputeDisk {
for _, disk := range disks {
if disk.Name == "bootdisk" {
return &disk
}
}
return nil
}
func flattenCompute(d *schema.ResourceData, compute RecordCompute) error {
// This function expects that compFacts string contains response from API compute/get, // This function expects that compFacts string contains response from API compute/get,
// i.e. detailed information about compute instance. // i.e. detailed information about compute instance.
// //
// NOTE: this function modifies ResourceData argument - as such it should never be called // NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceComputeExists(...) method // from resourceComputeExists(...) method
model := ComputeGetResp{} log.Debugf("flattenCompute: ID %d, RG ID %d", compute.ID, compute.RGID)
log.Debugf("flattenCompute: ready to unmarshal string %s", compFacts)
err := json.Unmarshal([]byte(compFacts), &model) devices, _ := json.Marshal(compute.Devices)
userdata, _ := json.Marshal(compute.Userdata)
//check extraDisks, ipa_type, is,
d.SetId(strconv.FormatUint(compute.ID, 10))
d.Set("acl", flattenACL(compute.ACL))
d.Set("account_id", compute.AccountID)
d.Set("account_name", compute.AccountName)
d.Set("affinity_weight", compute.AffinityWeight)
d.Set("arch", compute.Architecture)
d.Set("boot_order", compute.BootOrder)
d.Set("boot_disk_size", compute.BootDiskSize)
bootDisk := findBootDisk(compute.Disks)
d.Set("boot_disk_id", bootDisk.ID)
d.Set("sep_id", bootDisk.SepID)
d.Set("pool", bootDisk.Pool)
d.Set("clone_reference", compute.CloneReference)
d.Set("clones", compute.Clones)
if string(userdata) != "{}" {
d.Set("cloud_init", string(userdata))
}
d.Set("computeci_id", compute.ComputeCIID)
d.Set("created_by", compute.CreatedBy)
d.Set("created_time", compute.CreatedTime)
d.Set("custom_fields", flattenCustomFields(compute.CustomFields))
d.Set("deleted_by", compute.DeletedBy)
d.Set("deleted_time", compute.DeletedTime)
d.Set("description", compute.Description)
d.Set("devices", string(devices))
err := d.Set("disks", flattenComputeDisksDemo(compute.Disks, d.Get("extra_disks").(*schema.Set).List()))
if err != nil { if err != nil {
return err return err
} }
d.Set("driver", compute.Driver)
log.Debugf("flattenCompute: ID %d, RG ID %d", model.ID, model.RgID) d.Set("cpu", compute.CPU)
d.Set("gid", compute.GID)
d.SetId(fmt.Sprintf("%d", model.ID)) d.Set("guid", compute.GUID)
// 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("compute_id", compute.ID)
d.Set("name", model.Name) if compute.VirtualImageID != 0 {
d.Set("rg_id", model.RgID) d.Set("image_id", compute.VirtualImageID)
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
if model.VirtualImageID != 0 {
d.Set("image_id", model.VirtualImageID)
} else { } else {
d.Set("image_id", model.ImageID) d.Set("image_id", compute.ImageID)
}
d.Set("interfaces", flattenInterfaces(compute.Interfaces))
d.Set("lock_status", compute.LockStatus)
d.Set("manager_id", compute.ManagerID)
d.Set("manager_type", compute.ManagerType)
d.Set("migrationjob", compute.MigrationJob)
d.Set("milestones", compute.Milestones)
d.Set("name", compute.Name)
d.Set("natable_vins_id", compute.NatableVINSID)
d.Set("natable_vins_ip", compute.NatableVINSIP)
d.Set("natable_vins_name", compute.NatableVINSName)
d.Set("natable_vins_network", compute.NatableVINSNetwork)
d.Set("natable_vins_network_name", compute.NatableVINSNetworkName)
if err := d.Set("os_users", parseOsUsers(compute.OSUsers)); err != nil {
return err
} }
d.Set("description", model.Desc) d.Set("pinned", compute.Pinned)
d.Set("ram", compute.RAM)
d.Set("reference_id", compute.ReferenceID)
d.Set("registered", compute.Registered)
d.Set("res_name", compute.ResName)
d.Set("rg_id", compute.RGID)
d.Set("rg_name", compute.RGName)
d.Set("snap_sets", flattenSnapSets(compute.SnapSets))
d.Set("stateless_sep_id", compute.StatelessSepID)
d.Set("stateless_sep_type", compute.StatelessSepType)
d.Set("status", compute.Status)
d.Set("tags", flattenTags(compute.Tags))
d.Set("tech_status", compute.TechStatus)
d.Set("updated_by", compute.UpdatedBy)
d.Set("updated_time", compute.UpdatedTime)
d.Set("user_managed", compute.UserManaged)
d.Set("vgpus", compute.VGPUs)
d.Set("virtual_image_id", compute.VirtualImageID)
d.Set("virtual_image_name", compute.VirtualImageName)
d.Set("enabled", false) d.Set("enabled", false)
if model.Status == status.Enabled { if compute.Status == status.Enabled {
d.Set("enabled", true) d.Set("enabled", true)
} }
//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.Set("started", false) d.Set("started", false)
if model.TechStatus == "STARTED" { if compute.TechStatus == "STARTED" {
d.Set("started", true) d.Set("started", true)
} }
bootDisk := findBootDisk(model.Disks) d.Set("network", flattenNetwork(compute.Interfaces))
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("pool", bootDisk.Pool)
//if len(model.Disks) > 0 { //if len(model.Disks) > 0 {
//log.Debugf("flattenCompute: calling parseComputeDisksToExtraDisks for %d disks", len(model.Disks)) //log.Debugf("flattenCompute: calling parseComputeDisksToExtraDisks for %d disks", len(model.Disks))
@ -92,24 +343,288 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
//} //}
//} //}
if len(model.Interfaces) > 0 { return nil
log.Debugf("flattenCompute: calling parseComputeInterfacesToNetworks for %d interfaces", len(model.Interfaces)) }
if err = d.Set("network", parseComputeInterfacesToNetworks(model.Interfaces)); err != nil {
return err func flattenDataComputeDisksDemo(disksList ListComputeDisks, extraDisks []interface{}) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range disksList {
if findInExtraDisks(uint(disk.ID), extraDisks) { //skip main bootdisk and extraDisks
continue
}
temp := map[string]interface{}{
"disk_name": disk.Name,
"disk_id": disk.ID,
"disk_type": disk.Type,
"sep_id": disk.SepID,
"shareable": disk.Shareable,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"pool": disk.Pool,
"desc": disk.Description,
"image_id": disk.ImageID,
"size": disk.SizeMax,
} }
res = append(res, temp)
} }
return res
}
if len(model.OsUsers) > 0 { func flattenACL(acl RecordACL) []map[string]interface{} {
log.Debugf("flattenCompute: calling parseOsUsers for %d logins", len(model.OsUsers)) res := make([]map[string]interface{}, 0)
if err = d.Set("os_users", parseOsUsers(model.OsUsers)); err != nil { temp := map[string]interface{}{
return err "account_acl": flattenListACL(acl.AccountACL),
"compute_acl": flattenListACL(acl.ComputeACL),
"rg_acl": flattenListACL(acl.RGACL),
} }
res = append(res, temp)
return res
}
func flattenAffinityRules(affinityRules ListRules) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, affinityRule := range affinityRules {
temp := map[string]interface{}{
"guid": affinityRule.GUID,
"key": affinityRule.Key,
"mode": affinityRule.Mode,
"policy": affinityRule.Policy,
"topology": affinityRule.Topology,
"value": affinityRule.Value,
}
res = append(res, temp)
} }
err = d.Set("disks", flattenComputeDisksDemo(model.Disks, d.Get("extra_disks").(*schema.Set).List())) return res
if err != nil { }
return err
func flattenIotune(iotune IOTune) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"read_bytes_sec": iotune.ReadBytesSec,
"read_bytes_sec_max": iotune.ReadBytesSecMax,
"read_iops_sec": iotune.ReadIOPSSec,
"read_iops_sec_max": iotune.ReadIOPSSecMax,
"size_iops_sec": iotune.SizeIOPSSec,
"total_bytes_sec": iotune.TotalBytesSec,
"total_bytes_sec_max": iotune.TotalBytesSecMax,
"total_iops_sec": iotune.TotalIOPSSec,
"total_iops_sec_max": iotune.TotalIOPSSecMax,
"write_bytes_sec": iotune.WriteBytesSec,
"write_bytes_sec_max": iotune.WriteBytesSecMax,
"write_iops_sec": iotune.WriteIOPSSec,
"write_iops_sec_max": iotune.WriteIOPSSecMax,
} }
res = append(res, temp)
return nil return res
}
func flattenSnapshots(snapshots SnapshotExtendList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, snapshot := range snapshots {
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 flattenListComputeDisks(disks ListComputeDisks) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, disk := range disks {
acl, _ := json.Marshal(disk.ACL)
temp := map[string]interface{}{
"_ckey": disk.CKey,
"acl": string(acl),
"account_id": disk.AccountID,
"boot_partition": disk.BootPartition,
"created_time": disk.CreatedTime,
"deleted_time": disk.DeletedTime,
"description": disk.Description,
"destruction_time": disk.DestructionTime,
"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,
"milestones": disk.Milestones,
"name": disk.Name,
"order": disk.Order,
"params": disk.Params,
"parent_id": disk.ParentID,
"passwd": disk.Passwd,
"pci_slot": disk.PCISlot,
"pool": disk.Pool,
"present_to": disk.PresentTo,
"purge_time": disk.PurgeTime,
"reality_device_number": disk.RealityDeviceNumber,
"res_id": disk.ResID,
"role": disk.Role,
"sep_id": disk.SepID,
"shareable": disk.Shareable,
"size_max": disk.SizeMax,
"size_used": disk.SizeUsed,
"snapshots": flattenSnapshots(disk.Snapshots),
"status": disk.Status,
"tech_status": disk.TechStatus,
"type": disk.Type,
"vmid": disk.VMID,
}
res = append(res, temp)
}
return res
}
func flattenCustomFields(customFileds map[string]interface{}) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for key, val := range customFileds {
value, _ := json.Marshal(val)
temp := map[string]interface{}{
"key": key,
"val": string(value),
}
res = append(res, temp)
}
return res
}
func flattenOsUsers(osUsers ListOSUser) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, user := range osUsers {
temp := map[string]interface{}{
"guid": user.GUID,
"login": user.Login,
"password": user.Password,
"public_key": user.PubKey,
}
res = append(res, temp)
}
return res
}
func flattenDataCompute(d *schema.ResourceData, compute RecordCompute) {
devices, _ := json.Marshal(compute.Devices)
userdata, _ := json.Marshal(compute.Userdata)
d.Set("acl", flattenACL(compute.ACL))
d.Set("account_id", compute.AccountID)
d.Set("account_name", compute.AccountName)
d.Set("affinity_label", compute.AffinityLabel)
d.Set("affinity_rules", flattenAffinityRules(compute.AffinityRules))
d.Set("affinity_weight", compute.AffinityWeight)
d.Set("anti_affinity_rules", flattenListRules(compute.AntiAffinityRules))
d.Set("arch", compute.Architecture)
d.Set("boot_order", compute.BootOrder)
d.Set("bootdisk_size", compute.BootDiskSize)
d.Set("clone_reference", compute.CloneReference)
d.Set("clones", compute.Clones)
d.Set("computeci_id", compute.ComputeCIID)
d.Set("cpus", compute.CPU)
d.Set("created_by", compute.CreatedBy)
d.Set("created_time", compute.CreatedTime)
d.Set("custom_fields", flattenCustomFields(compute.CustomFields))
d.Set("deleted_by", compute.DeletedBy)
d.Set("deleted_time", compute.DeletedTime)
d.Set("desc", compute.Description)
d.Set("devices", string(devices))
d.Set("disks", flattenListComputeDisks(compute.Disks))
d.Set("driver", compute.Driver)
d.Set("gid", compute.GID)
d.Set("guid", compute.GUID)
d.Set("compute_id", compute.ID)
d.Set("image_id", compute.ImageID)
d.Set("interfaces", flattenInterfaces(compute.Interfaces))
d.Set("lock_status", compute.LockStatus)
d.Set("manager_id", compute.ManagerID)
d.Set("manager_type", compute.ManagerType)
d.Set("migrationjob", compute.MigrationJob)
d.Set("milestones", compute.Milestones)
d.Set("name", compute.Name)
d.Set("natable_vins_id", compute.NatableVINSID)
d.Set("natable_vins_ip", compute.NatableVINSIP)
d.Set("natable_vins_name", compute.NatableVINSName)
d.Set("natable_vins_network", compute.NatableVINSNetwork)
d.Set("natable_vins_network_name", compute.NatableVINSNetworkName)
d.Set("os_users", flattenOsUsers(compute.OSUsers))
d.Set("pinned", compute.Pinned)
d.Set("ram", compute.RAM)
d.Set("reference_id", compute.ReferenceID)
d.Set("registered", compute.Registered)
d.Set("res_name", compute.ResName)
d.Set("rg_id", compute.RGID)
d.Set("rg_name", compute.RGName)
d.Set("snap_sets", flattenSnapSets(compute.SnapSets))
d.Set("stateless_sep_id", compute.StatelessSepID)
d.Set("stateless_sep_type", compute.StatelessSepType)
d.Set("status", compute.Status)
d.Set("tags", compute.Tags)
d.Set("tech_status", compute.TechStatus)
d.Set("updated_by", compute.UpdatedBy)
d.Set("updated_time", compute.UpdatedTime)
d.Set("user_managed", compute.UserManaged)
d.Set("userdata", string(userdata))
d.Set("vgpus", compute.VGPUs)
d.Set("virtual_image_id", compute.VirtualImageID)
d.Set("virtual_image_name", compute.VirtualImageName)
}
func flattenComputeAudits(computeAudits ListAudits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, computeAudit := range computeAudits {
temp := map[string]interface{}{
"call": computeAudit.Call,
"responsetime": computeAudit.ResponseTime,
"statuscode": computeAudit.StatusCode,
"timestamp": computeAudit.Timestamp,
"user": computeAudit.User,
}
res = append(res, temp)
}
return res
}
func flattenPfwList(computePfws ListPFWs) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, computePfw := range computePfws {
temp := map[string]interface{}{
"pfw_id": computePfw.ID,
"local_ip": computePfw.LocalIP,
"local_port": computePfw.LocalPort,
"protocol": computePfw.Protocol,
"public_port_end": computePfw.PublicPortEnd,
"public_port_start": computePfw.PublicPortStart,
"vm_id": computePfw.VMID,
}
res = append(res, temp)
}
return res
}
func flattenUserList(d *schema.ResourceData, userList RecordACL) {
d.Set("account_acl", flattenListACL(userList.AccountACL))
d.Set("compute_acl", flattenListACL(userList.ComputeACL))
d.Set("rg_acl", flattenListACL(userList.RGACL))
}
func flattenComputeGetAudits(computeAudits ListShortAudits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, computeAudit := range computeAudits {
temp := map[string]interface{}{
"epoch": computeAudit.Epoch,
"message": computeAudit.Message,
}
res = append(res, temp)
}
return res
} }

@ -117,7 +117,7 @@ type SnapshotRecord struct {
TimeStamp uint64 `json:"timestamp"` TimeStamp uint64 `json:"timestamp"`
} }
type SnapshotRecordList []SnapshotRecord //type SnapshotRecordList []SnapshotRecord
type ComputeGetResp struct { type ComputeGetResp struct {
// ACLs `json:"ACL"` - it is a dictionary, special parsing required // ACLs `json:"ACL"` - it is a dictionary, special parsing required
@ -190,3 +190,888 @@ type ComputeBriefRecord struct { // this is a brief compute specifiaction as ret
} }
type RgListComputesResp []ComputeBriefRecord type RgListComputesResp []ComputeBriefRecord
//#############
// Access Control List
type RecordACL struct {
// Account ACL list
AccountACL ListACL `json:"accountAcl"`
// Compute ACL list
ComputeACL ListACL `json:"computeAcl"`
// Resource group ACL list
RGACL ListACL `json:"rgAcl"`
}
// ACL information
type ItemACL struct {
// Explicit
Explicit interface{} `json:"explicit"`
// GUID
GUID string `json:"guid"`
// Right
Right string `json:"right"`
// Status
Status string `json:"status"`
// Type
Type string `json:"type"`
// User group ID
UserGroupID string `json:"userGroupId"`
}
// List ACL
type ListACL []ItemACL
// Main information about usage snapshot
type ItemUsageSnapshot struct {
// Count
Count uint64 `json:"count,omitempty"`
// Stored
Stored float64 `json:"stored"`
// Label
Label string `json:"label,omitempty"`
// Timestamp
Timestamp uint64 `json:"timestamp,omitempty"`
}
// List of usage snapshot
type ListUsageSnapshots []ItemUsageSnapshot
// Main information about snapshot
type ItemSnapshot struct {
// List disk ID
Disks []uint64 `json:"disks"`
// GUID
GUID string `json:"guid"`
// Label
Label string `json:"label"`
// Timestamp
Timestamp uint64 `json:"timestamp"`
}
// List of snapshots
type ListSnapShots []ItemSnapshot
// Main information about port forward
type ItemPFW struct {
// ID
ID uint64 `json:"id"`
// Local IP
LocalIP string `json:"localIp"`
// Local port
LocalPort uint64 `json:"localPort"`
// Protocol
Protocol string `json:"protocol"`
// Public port end
PublicPortEnd uint64 `json:"publicPortEnd"`
// Public port start
PublicPortStart uint64 `json:"publicPortStart"`
// Virtuel machine ID
VMID uint64 `json:"vmId"`
}
// List port forwards
type ListPFWs []ItemPFW
// Main information about affinity relations
type RecordAffinityRelations struct {
// Other node
OtherNode []interface{} `json:"otherNode"`
// Other node indirect
OtherNodeIndirect []interface{} `json:"otherNodeIndirect"`
// Other node indirect soft
OtherNodeIndirectSoft []interface{} `json:"otherNodeIndirectSoft"`
// Other node soft
OtherNodeSoft []interface{} `json:"otherNodeSoft"`
// Same node
SameNode []interface{} `json:"sameNode"`
// Same node soft
SameNodeSoft []interface{} `json:"sameNodeSoft"`
}
// Main information about attached network
type RecordNetAttach struct {
// Connection ID
ConnID uint64 `json:"connId"`
// Connection type
ConnType string `json:"connType"`
// Default GW
DefGW string `json:"defGw"`
// FLIPGroup ID
FLIPGroupID uint64 `json:"flipgroupId"`
// GUID
GUID string `json:"guid"`
// IP address
IPAddress string `json:"ipAddress"`
// Listen SSH
ListenSSH bool `json:"listenSsh"`
// MAC
MAC string `json:"mac"`
// Name
Name string `json:"name"`
// Network ID
NetID uint64 `json:"netId"`
// Network mask
NetMask uint64 `json:"netMask"`
// Network type
NetType string `json:"netType"`
// PCI slot
PCISlot uint64 `json:"pciSlot"`
// QOS
QOS QOS `json:"qos"`
// Target
Target string `json:"target"`
// Type
Type string `json:"type"`
// List VNF IDs
VNFs []uint64 `json:"vnfs"`
}
// Detailed information about audit
type ItemAudit struct {
// Call
Call string `json:"call"`
// Response time
ResponseTime float64 `json:"responsetime"`
// Status code
StatusCode uint64 `json:"statuscode"`
// Timestamp
Timestamp float64 `json:"timestamp"`
// User
User string `json:"user"`
}
// List Detailed audits
type ListAudits []ItemAudit
// Short information about audit
type ItemShortAudit struct {
// Epoch
Epoch float64 `json:"epoch"`
// Message
Message string `json:"message"`
}
// List short audits
type ListShortAudits []ItemShortAudit
// Main information about rule
type ItemRule struct {
// GUID
GUID string `json:"guid"`
// Key
Key string `json:"key"`
// Mode
Mode string `json:"mode"`
// Policy
Policy string `json:"policy"`
// Topology
Topology string `json:"topology"`
// Value
Value string `json:"value"`
}
// List rules
type ListRules []ItemRule
// Detailed information about compute
type RecordCompute struct {
// Access Control List
ACL RecordACL `json:"ACL"`
// Account ID
AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"`
// Affinity label
AffinityLabel string `json:"affinityLabel"`
// List affinity rules
AffinityRules ListRules `json:"affinityRules"`
// Affinity weight
AffinityWeight uint64 `json:"affinityWeight"`
// List anti affinity rules
AntiAffinityRules ListRules `json:"antiAffinityRules"`
// Architecture
Architecture string `json:"arch"`
// Boot order
BootOrder []string `json:"bootOrder"`
// Boot disk size
BootDiskSize uint64 `json:"bootdiskSize"`
// Clone reference
CloneReference uint64 `json:"cloneReference"`
// List clone IDs
Clones []uint64 `json:"clones"`
// Compute CI ID
ComputeCIID uint64 `json:"computeciId"`
// Number of cores
CPU uint64 `json:"cpus"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Custom fields items
CustomFields map[string]interface{} `json:"customFields"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Description
Description string `json:"desc"`
// Devices
Devices interface{} `json:"devices"`
// List disks in compute
Disks ListComputeDisks `json:"disks"`
// Driver
Driver string `json:"driver"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// Image name
ImageName string `json:"imageName"`
// List interfaces
Interfaces ListInterfaces `json:"interfaces"`
// Lock status
LockStatus string `json:"lockStatus"`
// Manager ID
ManagerID uint64 `json:"managerId"`
// Manager type
ManagerType string `json:"managerType"`
// Migration job
MigrationJob uint64 `json:"migrationjob"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Natable VINS ID
NatableVINSID uint64 `json:"natableVinsId"`
// Natable VINS IP
NatableVINSIP string `json:"natableVinsIp"`
// Natable VINS Name
NatableVINSName string `json:"natableVinsName"`
// Natable VINS network
NatableVINSNetwork string `json:"natableVinsNetwork"`
// Natable VINS network name
NatableVINSNetworkName string `json:"natableVinsNetworkName"`
// List OS Users
OSUsers ListOSUser `json:"osUsers"`
// Pinned or not
Pinned bool `json:"pinned"`
// Number of RAM
RAM uint64 `json:"ram"`
// Reference ID
ReferenceID string `json:"referenceId"`
// Registered or not
Registered bool `json:"registered"`
// Resource name
ResName string `json:"resName"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// List snapsets
SnapSets ListSnapSets `json:"snapSets"`
// Stateless SepID
StatelessSepID uint64 `json:"statelessSepId"`
// Stateless SepType
StatelessSepType string `json:"statelessSepType"`
// Status
Status string `json:"status"`
// Tags
Tags map[string]string `json:"tags"`
// Tech status
TechStatus string `json:"techStatus"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// User Managed or not
UserManaged bool `json:"userManaged"`
// Userdata
Userdata interface{} `json:"userdata"`
// vGPU IDs
VGPUs []uint64 `json:"vgpus"`
// Virtual image ID
VirtualImageID uint64 `json:"virtualImageId"`
// Virtual image name
VirtualImageName string `json:"virtualImageName"`
}
// Main information about OS user
type ItemOSUser struct {
// GUID
GUID string `json:"guid"`
// Login
Login string `json:"login"`
// Password
Password string `json:"password"`
// Public key
PubKey string `json:"pubkey"`
}
// List OS users
type ListOSUser []ItemOSUser
// Main information about snapsets
type ItemSnapSet struct {
// List disk IDs
Disks []uint64 `json:"disks"`
// GUID
GUID string `json:"guid"`
// Label
Label string `json:"label"`
// Timestamp
Timestamp uint64 `json:"timestamp"`
}
// List snapsets
type ListSnapSets []ItemSnapSet
// Main information about VNF
type ItemVNFInterface struct {
// Connection ID
ConnID uint64 `json:"connId"`
// Connection type
ConnType string `json:"connType"`
// Default GW
DefGW string `json:"defGw"`
// FLIPGroup ID
FLIPGroupID uint64 `json:"flipgroupId"`
// GUID
GUID string `json:"guid"`
// IP address
IPAddress string `json:"ipAddress"`
// Listen SSH or not
ListenSSH bool `json:"listenSsh"`
// MAC
MAC string `json:"mac"`
// Name
Name string `json:"name"`
// Network ID
NetID uint64 `json:"netId"`
// Network mask
NetMask uint64 `json:"netMask"`
// Network type
NetType string `json:"netType"`
// PCI slot
PCISlot uint64 `json:"pciSlot"`
// QOS
QOS QOS `json:"qos"`
// Target
Target string `json:"target"`
// Type
Type string `json:"type"`
// List VNF IDs
VNFs []uint64 `json:"vnfs"`
}
type QOS struct {
ERate uint64 `json:"eRate"`
GUID string `json:"guid"`
InBurst uint64 `json:"inBurst"`
InRate uint64 `json:"inRate"`
}
// List VNF interfaces
type ListInterfaces []ItemVNFInterface
// List compute disks
type ListComputeDisks []ItemComputeDisk
// Main information about compute disk
type ItemComputeDisk struct {
// CKey
CKey string `json:"_ckey"`
// Access Control List
ACL map[string]interface{} `json:"acl"`
// Account ID
AccountID uint64 `json:"accountId"`
// Boot partition
BootPartition uint64 `json:"bootPartition"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Description
Description string `json:"desc"`
// Destruction time
DestructionTime uint64 `json:"destructionTime"`
// Disk path
DiskPath string `json:"diskPath"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// List image IDs
Images []uint64 `json:"images"`
// IO tune
IOTune IOTune `json:"iotune"`
// IQN
IQN string `json:"iqn"`
// Login
Login string `json:"login"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Order
Order uint64 `json:"order"`
// Params
Params string `json:"params"`
// Parent ID
ParentID uint64 `json:"parentId"`
// Password
Passwd string `json:"passwd"`
// PCI slot
PCISlot uint64 `json:"pciSlot"`
// Pool
Pool string `json:"pool"`
// Present to
PresentTo []uint64 `json:"presentTo"`
// Purge time
PurgeTime uint64 `json:"purgeTime"`
// Reality device number
RealityDeviceNumber uint64 `json:"realityDeviceNumber"`
// Resource ID
ResID string `json:"resId"`
// Role
Role string `json:"role"`
// SepID
SepID uint64 `json:"sepId"`
// Shareable
Shareable bool `json:"shareable"`
// Size max
SizeMax uint64 `json:"sizeMax"`
//Size used
SizeUsed float64 `json:"sizeUsed"`
// List extend snapshots
Snapshots SnapshotExtendList `json:"snapshots"`
// Status
Status string `json:"status"`
// Tech status
TechStatus string `json:"techStatus"`
// Type
Type string `json:"type"`
// Virtual machine ID
VMID uint64 `json:"vmid"`
}
// Main information about snapshot extend
type SnapshotExtend struct {
// GUID
GUID string `json:"guid"`
// Label
Label string `json:"label"`
// Resource ID
ResID string `json:"resId"`
// SnapSetGUID
SnapSetGUID string `json:"snapSetGuid"`
// SnapSetTime
SnapSetTime uint64 `json:"snapSetTime"`
// TimeStamp
TimeStamp uint64 `json:"timestamp"`
}
// List Snapshot Extend
type SnapshotExtendList []SnapshotExtend
// Main information about IO tune
type IOTune struct {
// ReadBytesSec
ReadBytesSec uint64 `json:"read_bytes_sec"`
// ReadBytesSecMax
ReadBytesSecMax uint64 `json:"read_bytes_sec_max"`
// ReadIOPSSec
ReadIOPSSec uint64 `json:"read_iops_sec"`
// ReadIOPSSecMax
ReadIOPSSecMax uint64 `json:"read_iops_sec_max"`
// SizeIOPSSec
SizeIOPSSec uint64 `json:"size_iops_sec"`
// TotalBytesSec
TotalBytesSec uint64 `json:"total_bytes_sec"`
// TotalBytesSecMax
TotalBytesSecMax uint64 `json:"total_bytes_sec_max"`
// TotalIOPSSec
TotalIOPSSec uint64 `json:"total_iops_sec"`
// TotalIOPSSecMax
TotalIOPSSecMax uint64 `json:"total_iops_sec_max"`
// WriteBytesSec
WriteBytesSec uint64 `json:"write_bytes_sec"`
// WriteBytesSecMax
WriteBytesSecMax uint64 `json:"write_bytes_sec_max"`
// WriteIOPSSec
WriteIOPSSec uint64 `json:"write_iops_sec"`
// WriteIOPSSecMax
WriteIOPSSecMax uint64 `json:"write_iops_sec_max"`
}
// Main information about compute
type ItemCompute struct {
// Access Control List
ACL ListACL `json:"acl"`
// Account ID
AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"`
// Affinity label
AffinityLabel string `json:"affinityLabel"`
// List affinity rules
AffinityRules ListRules `json:"affinityRules"`
// Affinity weight
AffinityWeight uint64 `json:"affinityWeight"`
// List anti affinity rules
AntiAffinityRules ListRules `json:"antiAffinityRules"`
// Architecture
Architecture string `json:"arch"`
// Boot order
BootOrder []string `json:"bootOrder"`
// Boot disk size
BootDiskSize uint64 `json:"bootdiskSize"`
// Clone reference
CloneReference uint64 `json:"cloneReference"`
// List clone IDs
Clones []uint64 `json:"clones"`
// Compute CI ID
ComputeCIID uint64 `json:"computeciId"`
// Number of cores
CPU uint64 `json:"cpus"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Custom fields list
CustomFields map[string]interface{} `json:"customFields"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Description
Description string `json:"desc"`
// Devices
Devices interface{} `json:"devices"`
// List disk items
Disks []InfoDisk `json:"disks"`
// Driver
Driver string `json:"driver"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// List interfaces
Interfaces ListInterfaces `json:"interfaces"`
// Lock status
LockStatus string `json:"lockStatus"`
// Manager ID
ManagerID uint64 `json:"managerId"`
// Manager type
ManagerType string `json:"managerType"`
// Migration job
MigrationJob uint64 `json:"migrationjob"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Pinned or not
Pinned bool `json:"pinned"`
// Number of RAM
RAM uint64 `json:"ram"`
// Reference ID
ReferenceID string `json:"referenceId"`
// Registered
Registered bool `json:"registered"`
// Resource name
ResName string `json:"resName"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// List snapsets
SnapSets ListSnapSets `json:"snapSets"`
// Stateless SepID
StatelessSepID uint64 `json:"statelessSepId"`
// Stateless SepType
StatelessSepType string `json:"statelessSepType"`
// Status
Status string `json:"status"`
// Tags
Tags map[string]string `json:"tags"`
// Tech status
TechStatus string `json:"techStatus"`
// Total disk size
TotalDiskSize uint64 `json:"totalDisksSize"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// User Managed or not
UserManaged bool `json:"userManaged"`
// List vGPU IDs
VGPUs []uint64 `json:"vgpus"`
// VINS connected
VINSConnected uint64 `json:"vinsConnected"`
// Virtual image ID
VirtualImageID uint64 `json:"virtualImageId"`
}
// Information Disk
type InfoDisk struct {
// ID
ID uint64 `json:"id"`
// PCISlot
PCISlot uint64 `json:"pciSlot"`
}
// List information about computes
type ListComputes []ItemCompute

@ -38,13 +38,13 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
) )
func parseOsUsers(logins []OsUserRecord) []interface{} { func parseOsUsers(logins ListOSUser) []interface{} {
var result = make([]interface{}, len(logins)) var result = make([]interface{}, len(logins))
for index, value := range logins { for index, value := range logins {
elem := make(map[string]interface{}) elem := make(map[string]interface{})
elem["guid"] = value.Guid elem["guid"] = value.GUID
elem["login"] = value.Login elem["login"] = value.Login
elem["password"] = value.Password elem["password"] = value.Password
elem["public_key"] = value.PubKey elem["public_key"] = value.PubKey
@ -72,7 +72,7 @@ func osUsersSubresourceSchemaMake() map[string]*schema.Schema {
"password": { "password": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
Sensitive: true, //Sensitive: true,
Description: "Password of this guest OS user.", Description: "Password of this guest OS user.",
}, },

@ -0,0 +1,106 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
)
func existRgID(ctx context.Context, d *schema.ResourceData, m interface{}) bool {
log.Debugf("resourceComputeCreate: check access for RG ID: %v", d.Get("rg_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgList := []struct {
ID int `json:"id"`
}{}
rgListAPI := "/restmachine/cloudapi/rg/list"
urlValues.Add("includedeleted", "false")
rgListRaw, err := c.DecortAPICall(ctx, "POST", rgListAPI, urlValues)
if err != nil {
return false
}
err = json.Unmarshal([]byte(rgListRaw), &rgList)
if err != nil {
return false
}
rgId := d.Get("rg_id").(int)
for _, rg := range rgList {
if rg.ID == rgId {
return true
}
}
return false
}
func existImageId(ctx context.Context, d *schema.ResourceData, m interface{}) bool {
log.Debugf("resourceComputeCreate: check access for image ID: %v", d.Get("image_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
imageList := []struct {
ID int `json:"id"`
}{}
imageListAPI := "/restmachine/cloudapi/image/list"
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListAPI, urlValues)
if err != nil {
return false
}
err = json.Unmarshal([]byte(imageListRaw), &imageList)
if err != nil {
return false
}
imageId := d.Get("image_id").(int)
for _, image := range imageList {
if image.ID == imageId {
return true
}
}
return false
}
func existVinsIdInList(vinsId int, vinsList []struct {
ID int `json:"id"`
}) bool {
for _, vins := range vinsList {
if vinsId == vins.ID {
return true
}
}
return false
}
func existVinsId(ctx context.Context, d *schema.ResourceData, m interface{}) (int, bool) {
log.Debugf("resourceComputeCreate: check access for vinses IDs")
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
vinsListAPI := "/restmachine/cloudapi/vins/list"
urlValues.Add("includeDeleted", "false")
vinsList := []struct {
ID int `json:"id"`
}{}
vinsListRaw, err := c.DecortAPICall(ctx, "POST", vinsListAPI, urlValues)
if err != nil {
return 0, false
}
err = json.Unmarshal([]byte(vinsListRaw), &vinsList)
if err != nil {
return 0, false
}
networks := d.Get("network").(*schema.Set).List()
for _, networkInterface := range networks {
networkItem := networkInterface.(map[string]interface{})
if !existVinsIdInList(networkItem["net_id"].(int), vinsList) {
return networkItem["net_id"].(int), false
}
}
return 0, true
}

File diff suppressed because it is too large Load Diff

@ -37,7 +37,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/controller" "github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -242,90 +241,20 @@ func utilityComputeNetworksConfigure(ctx context.Context, d *schema.ResourceData
return nil return nil
} }
func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) { func utilityComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (RecordCompute, 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.
//
c := m.(*controller.ControllerCfg) c := m.(*controller.ControllerCfg)
urlValues := &url.Values{} urlValues := &url.Values{}
compute := &RecordCompute{}
// make it possible to use "read" & "check presence" functions with compute ID set so urlValues.Add("computeId", d.Id())
// that Import of Compute resource is possible computeRaw, err := c.DecortAPICall(ctx, "POST", ComputeGetAPI, urlValues)
idSet := false
theId, err := strconv.Atoi(d.Id())
if err != nil || theId <= 0 {
computeId, argSet := d.GetOk("compute_id") // NB: compute_id is NOT present in computeResource schema!
if argSet {
theId = computeId.(int)
idSet = true
}
} else {
idSet = true
}
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)
if err != nil {
return "", err
}
return computeFacts, nil
}
// ID was not set in the schema upon entering this function - work through Compute name
// 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")
}
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))
}
urlValues.Add("rgId", fmt.Sprintf("%d", rgId))
apiResp, err := c.DecortAPICall(ctx, "POST", RgListComputesAPI, urlValues)
if err != nil {
return "", err
}
log.Debugf("utilityComputeCheckPresence: ready to unmarshal string %s", apiResp)
computeList := RgListComputesResp{}
err = json.Unmarshal([]byte(apiResp), &computeList)
if err != nil { if err != nil {
return "", err return *compute, err
} }
// log.Printf("%#v", computeList) err = json.Unmarshal([]byte(computeRaw), &compute)
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)
if err != nil { if err != nil {
return "", err return *compute, err
}
return apiResp, nil
} }
} return *compute, nil
return "", nil // there should be no error if Compute does not exist
} }

@ -0,0 +1,29 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputeAuditsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListAudits, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
computeAudits := &ListAudits{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computeAuditsRaw, err := c.DecortAPICall(ctx, "POST", ComputeAuditsAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(computeAuditsRaw), &computeAudits)
if err != nil {
return nil, err
}
return *computeAudits, nil
}

@ -0,0 +1,23 @@
package kvmvm
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityComputeBootDiskCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ItemComputeDisk, error) {
compute, err := utilityComputeCheckPresence(ctx, d, m)
if err != nil {
return nil, err
}
bootDisk := &ItemComputeDisk{}
for _, disk := range compute.Disks {
if disk.Name == "bootdisk" {
*bootDisk = disk
break
}
}
return bootDisk, nil
}

@ -0,0 +1,29 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputeGetAuditsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListShortAudits, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
computeAudits := &ListShortAudits{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computeAuditsRaw, err := c.DecortAPICall(ctx, "POST", ComputeGetAuditsAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(computeAuditsRaw), &computeAudits)
if err != nil {
return nil, err
}
return *computeAudits, nil
}

@ -0,0 +1,23 @@
package kvmvm
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputeGetConsoleUrlCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computeConsoleUrlRaw, err := c.DecortAPICall(ctx, "POST", ComputeGetConsoleUrlAPI, urlValues)
if err != nil {
return "", err
}
return string(computeConsoleUrlRaw), nil
}

@ -0,0 +1,24 @@
package kvmvm
import (
"context"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputeGetLogCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
urlValues.Add("path", d.Get("path").(string))
computeGetLogRaw, err := c.DecortAPICall(ctx, "POST", ComputeGetLogAPI, urlValues)
if err != nil {
return "", err
}
return string(computeGetLogRaw), nil
}

@ -0,0 +1,39 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityDataComputeListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListComputes, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listComputes := &ListComputes{}
if includeDeleted, ok := d.GetOk("includedeleted"); ok {
urlValues.Add("includeDeleted", strconv.FormatBool(includeDeleted.(bool)))
}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
}
listComputesRaw, err := c.DecortAPICall(ctx, "POST", ComputeListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listComputesRaw), &listComputes)
if err != nil {
return nil, err
}
return *listComputes, nil
}

@ -0,0 +1,30 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputePfwListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListPFWs, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listPFWs := &ListPFWs{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computePfwListRaw, err := c.DecortAPICall(ctx, "POST", ComputePfwListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(computePfwListRaw), &listPFWs)
if err != nil {
return nil, err
}
return *listPFWs, err
}

@ -0,0 +1,28 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityComputeUserListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (RecordACL, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
userList := &RecordACL{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computeUserListRaw, err := c.DecortAPICall(ctx, "POST", ComputeUserListAPI, urlValues)
if err != nil {
return *userList, err
}
err = json.Unmarshal([]byte(computeUserListRaw), &userList)
if err != nil {
return *userList, err
}
return *userList, err
}

@ -0,0 +1,29 @@
package kvmvm
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityDataComputeCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (RecordCompute, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
compute := &RecordCompute{}
urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int)))
computeRaw, err := c.DecortAPICall(ctx, "POST", ComputeGetAPI, urlValues)
if err != nil {
return *compute, err
}
err = json.Unmarshal([]byte(computeRaw), &compute)
if err != nil {
return *compute, err
}
return *compute, nil
}

@ -32,9 +32,26 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
package rg package rg
const ResgroupCreateAPI = "/restmachine/cloudapi/rg/create" const (
const ResgroupUpdateAPI = "/restmachine/cloudapi/rg/update" ResgroupCreateAPI = "/restmachine/cloudapi/rg/create"
const ResgroupListAPI = "/restmachine/cloudapi/rg/list" ResgroupUpdateAPI = "/restmachine/cloudapi/rg/update"
const ResgroupGetAPI = "/restmachine/cloudapi/rg/get" ResgroupListAPI = "/restmachine/cloudapi/rg/list"
const ResgroupDeleteAPI = "/restmachine/cloudapi/rg/delete" ResgroupListDeletedAPI = "/restmachine/cloudapi/rg/listDeleted"
const RgListComputesAPI = "/restmachine/cloudapi/rg/listComputes" ResgroupListPfwAPI = "/restmachine/cloudapi/rg/listPFW"
ResgroupGetAPI = "/restmachine/cloudapi/rg/get"
ResgroupListVinsAPI = "/restmachine/cloudapi/rg/listVins"
ResgroupListLbAPI = "/restmachine/cloudapi/rg/listLb"
ResgroupDeleteAPI = "/restmachine/cloudapi/rg/delete"
RgListComputesAPI = "/restmachine/cloudapi/rg/listComputes"
RgAffinityGroupComputesAPI = "/restmachine/cloudapi/rg/affinityGroupComputes"
RgAffinityGroupsGetAPI = "/restmachine/cloudapi/rg/affinityGroupsGet"
RgAffinityGroupsListAPI = "/restmachine/cloudapi/rg/affinityGroupsList"
RgAuditsAPI = "/restmachine/cloudapi/rg/audits"
RgEnableAPI = "/restmachine/cloudapi/rg/enable"
RgDisableAPI = "/restmachine/cloudapi/rg/disable"
ResgroupUsageAPI = "/restmachine/cloudapi/rg/usage"
RgAccessGrantAPI = "/restmachine/cloudapi/rg/accessGrant"
RgAccessRevokeAPI = "/restmachine/cloudapi/rg/accessRevoke"
RgSetDefNetAPI = "/restmachine/cloudapi/rg/setDefNet"
RgRestoreAPI = "/restmachine/cloudapi/rg/restore"
)

@ -34,119 +34,95 @@ package rg
import ( import (
"context" "context"
"encoding/json"
"net/url"
"strconv" "strconv"
"github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
// "net/url"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" "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/schema"
) )
func utilityDataResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ResgroupGetResp, error) { func sepsSchemaMake() map[string]*schema.Schema {
c := m.(*controller.ControllerCfg) res := map[string]*schema.Schema{
urlValues := &url.Values{} "sep_id": {
rgData := &ResgroupGetResp{} Type: schema.TypeString,
Computed: true,
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(rgRaw), rgData)
if err != nil {
return nil, err
}
return rgData, nil
}
func dataSourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rg, err := utilityDataResgroupCheckPresence(ctx, d, m)
if err != nil {
d.SetId("") // ensure ID is empty in this case
return diag.FromErr(err)
}
return diag.FromErr(flattenDataResgroup(d, *rg))
}
func DataSourceResgroup() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceResgroupRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
}, },
"data_name": {
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Computed: true,
Description: "Name of the resource group. Names are case sensitive and unique within the context of an account.",
}, },
"disk_size": {
"rg_id": { Type: schema.TypeFloat,
Type: schema.TypeInt, Computed: true,
Optional: true,
Description: "Unique ID of the resource group. If this ID is specified, then resource group name is ignored.",
}, },
"disk_size_max": {
"account_name": { Type: schema.TypeInt,
Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Name of the account, which this resource group belongs to.",
}, },
}
"account_id": { return res
}
func resourcesSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"current": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Computed: true,
Description: "Unique ID of the account, which this resource group belongs to.",
}, },
"disk_size": {
"description": { Type: schema.TypeFloat,
Type: schema.TypeString,
Computed: true, Computed: true,
Description: "User-defined text description of this resource group.",
}, },
"gid": { "disk_size_max": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
Description: "Unique ID of the grid, where this resource group is deployed.",
}, },
"quota": { "extips": {
Type: schema.TypeList, Type: schema.TypeInt,
Computed: true, Computed: true,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(), // this is a dictionary
}, },
Description: "Quota settings for this resource group.", "exttraffic": {
Type: schema.TypeInt,
Computed: true,
}, },
"gpu": {
"def_net_type": { Type: schema.TypeInt,
Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Type of the default network for this resource group.",
}, },
"ram": {
"def_net_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
Description: "ID of the default network for this resource group (if any).",
}, },
"seps": {
"resources": { Type: schema.TypeSet,
Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"current": { "sep_id": {
Type: schema.TypeString,
Computed: true,
},
"map": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
},
},
"reserved": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
@ -155,7 +131,11 @@ func DataSourceResgroup() *schema.Resource {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"disksize": { "disk_size": {
Type: schema.TypeFloat,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
@ -176,7 +156,7 @@ func DataSourceResgroup() *schema.Resource {
Computed: true, Computed: true,
}, },
"seps": { "seps": {
Type: schema.TypeList, Type: schema.TypeSet,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -184,107 +164,252 @@ func DataSourceResgroup() *schema.Resource {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"data_name": { "map": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
},
},
}
return res
}
func aclSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"explicit": {
Type: schema.TypeBool,
Computed: true,
},
"guid": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"disk_size": { "right": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"user_group_id": {
Type: schema.TypeString,
Computed: true,
},
}
return res
}
func resourceLimitsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"cu_c": {
Type: schema.TypeFloat, Type: schema.TypeFloat,
Computed: true, Computed: true,
}, },
"disk_size_max": { "cu_d": {
Type: schema.TypeInt, Type: schema.TypeFloat,
Computed: true, Computed: true,
}, },
"cu_i": {
Type: schema.TypeFloat,
Computed: true,
}, },
"cu_m": {
Type: schema.TypeFloat,
Computed: true,
}, },
"cu_np": {
Type: schema.TypeFloat,
Computed: true,
}, },
"gpu_units": {
Type: schema.TypeFloat,
Computed: true,
}, },
}
return res
}
func dataSourceRgSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
}, },
"reason": {
Type: schema.TypeString,
Optional: true,
}, },
"reserved": {
"resources": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: resourcesSchemaMake(),
"cpu": { },
},
"account_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"disksize": { "account_name": {
Type: schema.TypeInt, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"extips": { "acl": {
Type: schema.TypeInt, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{
Schema: aclSchemaMake(),
}, },
"exttraffic": { },
Type: schema.TypeInt, "created_by": {
Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"gpu": { "created_time": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"ram": { "def_net_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"seps": { "def_net_type": {
Type: schema.TypeList, Type: schema.TypeString,
Computed: true, Computed: true,
Elem: &schema.Resource{ },
Schema: map[string]*schema.Schema{ "deleted_by": {
"sep_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"data_name": { "deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"disk_size": { "dirty": {
Type: schema.TypeFloat, Type: schema.TypeBool,
Computed: true, Computed: true,
}, },
"disk_size_max": { "gid": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"guid": {
Type: schema.TypeInt,
Computed: true,
}, },
"lock_status": {
Type: schema.TypeString,
Computed: true,
}, },
"milestones": {
Type: schema.TypeInt,
Computed: true,
}, },
"name": {
Type: schema.TypeString,
Computed: true,
}, },
"register_computes": {
Type: schema.TypeBool,
Computed: true,
}, },
"resource_limits": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: resourceLimitsSchemaMake(),
}, },
}, },
"secret": {
Type: schema.TypeString,
Computed: true,
}, },
},
"status": { "status": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Current status of this resource group.",
}, },
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vins": { "vins": {
Type: schema.TypeList, // this is a list of ints Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Schema{ Elem: &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
}, },
Description: "List of VINs deployed in this resource group.",
}, },
"computes": {
"vms": { Type: schema.TypeList,
Type: schema.TypeList, //t his is a list of ints
Computed: true, Computed: true,
Elem: &schema.Schema{ Elem: &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
}, },
Description: "List of computes deployed in this resource group.",
}, },
"res_types": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"uniq_pools": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
}
return res
}
func dataSourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rg, err := utilityDataResgroupCheckPresence(ctx, d, m)
if err != nil {
d.SetId("") // ensure ID is empty in this case
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
flattenRg(d, *rg)
return nil
}
func DataSourceResgroup() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceResgroupRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
}, },
Schema: dataSourceRgSchemaMake(),
} }
} }

@ -0,0 +1,108 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgAffinityGroupComputesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rgComputes, err := utilityRgAffinityGroupComputesCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("items", flattenRgAffinityGroupComputes(rgComputes))
return nil
}
func dataSourceRgAffinityGroupComputesSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"affinity_group": {
Type: schema.TypeString,
Required: true,
Description: "Affinity group label",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"other_node": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"other_node_indirect": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"other_node_indirect_soft": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"other_node_soft": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"same_node": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"same_node_soft": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
},
},
},
}
return res
}
func DataSourceRgAffinityGroupComputes() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgAffinityGroupComputesRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgAffinityGroupComputesSchemaMake(),
}
}

@ -0,0 +1,60 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgAffinityGroupsGetRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computes, err := utilityRgAffinityGroupsGetCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("ids", computes)
return nil
}
func dataSourceRgAffinityGroupsGetSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"affinity_group": {
Type: schema.TypeString,
Required: true,
Description: "Affinity group label",
},
"ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
}
return res
}
func DataSourceRgAffinityGroupsGet() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgAffinityGroupsGetRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgAffinityGroupsGetSchemaMake(),
}
}

@ -0,0 +1,67 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgAffinityGroupsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
list, err := utilityRgAffinityGroupsListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("affinity_groups", flattenRgListGroups(list))
return nil
}
func dataSourceRgAffinityGroupsListSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"affinity_groups": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"label": {
Type: schema.TypeString,
Computed: true,
},
"ids": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
},
},
},
}
return res
}
func DataSourceRgAffinityGroupsList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgAffinityGroupsListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgAffinityGroupsListSchemaMake(),
}
}

@ -0,0 +1,77 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgAuditsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rgAudits, err := utilityRgAuditsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("items", flattenRgAudits(rgAudits))
return nil
}
func dataSourceRgAuditsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"call": {
Type: schema.TypeString,
Computed: true,
},
"responsetime": {
Type: schema.TypeFloat,
Computed: true,
},
"statuscode": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeFloat,
Computed: true,
},
"user": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceRgAudits() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgAuditsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgAuditsSchemaMake(),
}
}

@ -41,73 +41,6 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/constants"
) )
func flattenRgList(rgl ResgroupListResp) []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),
"created_by": rg.CreatedBy,
"created_time": rg.CreatedTime,
"def_net_id": rg.DefaultNetID,
"def_net_type": rg.DefaultNetType,
"deleted_by": rg.DeletedBy,
"deleted_time": rg.DeletedTime,
"desc": rg.Decsription,
"gid": rg.GridID,
"guid": rg.GUID,
"rg_id": rg.ID,
"lock_status": rg.LockStatus,
"milestones": rg.Milestones,
"name": rg.Name,
"register_computes": rg.RegisterComputes,
"resource_limits": flattenRgResourceLimits(rg.ResourceLimits),
"secret": rg.Secret,
"status": rg.Status,
"updated_by": rg.UpdatedBy,
"updated_time": rg.UpdatedTime,
"vins": rg.Vins,
"vms": rg.Computes,
}
res = append(res, temp)
}
return res
}
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 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 dataSourceRgListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { func dataSourceRgListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rgList, err := utilityRgListCheckPresence(ctx, d, m) rgList, err := utilityRgListCheckPresence(ctx, d, m)
if err != nil { if err != nil {
@ -139,11 +72,19 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
Optional: true, Optional: true,
Description: "Page size", Description: "Page size",
}, },
"items": { "items": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"account_acl": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: aclSchemaMake(),
},
},
"account_id": { "account_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
@ -156,32 +97,7 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: aclSchemaMake(),
"explicit": {
Type: schema.TypeBool,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"right": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"user_group_id": {
Type: schema.TypeString,
Computed: true,
},
},
}, },
}, },
"created_by": { "created_by": {
@ -212,6 +128,10 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"dirty": {
Type: schema.TypeBool,
Computed: true,
},
"gid": { "gid": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
@ -244,32 +164,7 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: resourceLimitsSchemaMake(),
"cu_c": {
Type: schema.TypeFloat,
Computed: true,
},
"cu_d": {
Type: schema.TypeFloat,
Computed: true,
},
"cu_i": {
Type: schema.TypeFloat,
Computed: true,
},
"cu_m": {
Type: schema.TypeFloat,
Computed: true,
},
"cu_np": {
Type: schema.TypeFloat,
Computed: true,
},
"gpu_units": {
Type: schema.TypeFloat,
Computed: true,
},
},
}, },
}, },
"secret": { "secret": {
@ -302,6 +197,20 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
Type: schema.TypeInt, Type: schema.TypeInt,
}, },
}, },
"resource_types": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"uniq_pools": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
}, },
}, },
}, },

@ -0,0 +1,193 @@
package rg
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgListComputesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
listComputes, err := utilityRgListComputesCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenRgListComputes(listComputes))
return nil
}
func rulesSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"key": {
Type: schema.TypeString,
Computed: true,
},
"mode": {
Type: schema.TypeString,
Computed: true,
},
"policy": {
Type: schema.TypeString,
Computed: true,
},
"topology": {
Type: schema.TypeString,
Computed: true,
},
"value": {
Type: schema.TypeString,
Computed: true,
},
}
return res
}
func dataSourceRgListComputesSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"reason": {
Type: schema.TypeString,
Optional: true,
Description: "reason for action",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"affinity_label": {
Type: schema.TypeString,
Computed: true,
},
"affinity_rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: rulesSchemaMake(),
},
},
"affinity_weight": {
Type: schema.TypeInt,
Computed: true,
},
"antiaffinity_rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: rulesSchemaMake(),
},
},
"cpus": {
Type: schema.TypeInt,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"ram": {
Type: schema.TypeInt,
Computed: true,
},
"registered": {
Type: schema.TypeBool,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"total_disks_size": {
Type: schema.TypeInt,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"user_managed": {
Type: schema.TypeBool,
Computed: true,
},
"vins_connected": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceRgListComputes() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgListComputesRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgListComputesSchemaMake(),
}
}

@ -0,0 +1,196 @@
package rg
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgListDeletedRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
rgList, err := utilityRgListDeletedCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenRgList(rgList))
return nil
}
func dataSourceRgListDeletedSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "Page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "Page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_acl": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: aclSchemaMake(),
},
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: aclSchemaMake(),
},
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"def_net_id": {
Type: schema.TypeInt,
Computed: true,
},
"def_net_type": {
Type: schema.TypeString,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"dirty": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"rg_id": {
Type: schema.TypeInt,
Computed: true,
},
"lock_status": {
Type: schema.TypeString,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"register_computes": {
Type: schema.TypeBool,
Computed: true,
},
"resource_limits": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: resourceLimitsSchemaMake(),
},
},
"secret": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vins": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"vms": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"resource_types": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"uniq_pools": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
}
return res
}
func DataSourceRgListDeleted() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgListDeletedRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgListDeletedSchemaMake(),
}
}

@ -0,0 +1,357 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgListLbRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
listLb, err := utilityRgListLbCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("items", flattenRgListLb(listLb))
return nil
}
func serversSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"address": {
Type: schema.TypeString,
Computed: true,
},
"check": {
Type: schema.TypeString,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"port": {
Type: schema.TypeInt,
Computed: true,
},
"server_settings": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: serverSettingsSchemaMake(),
},
},
}
return res
}
func serverSettingsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"inter": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"down_inter": {
Type: schema.TypeInt,
Computed: true,
},
"rise": {
Type: schema.TypeInt,
Computed: true,
},
"fall": {
Type: schema.TypeInt,
Computed: true,
},
"slow_start": {
Type: schema.TypeInt,
Computed: true,
},
"max_conn": {
Type: schema.TypeInt,
Computed: true,
},
"max_queue": {
Type: schema.TypeInt,
Computed: true,
},
"weight": {
Type: schema.TypeInt,
Computed: true,
},
}
return res
}
func backendsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"algorithm": {
Type: schema.TypeString,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"server_default_settings": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: serverSettingsSchemaMake(),
},
},
"servers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: serversSchemaMake(),
},
},
}
return res
}
func bindingsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"address": {
Type: schema.TypeString,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"port": {
Type: schema.TypeInt,
Computed: true,
},
}
return res
}
func frontendsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"backend": {
Type: schema.TypeString,
Computed: true,
},
"bindings": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: bindingsSchemaMake(),
},
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
}
return res
}
func nodeSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"backend_ip": {
Type: schema.TypeString,
Computed: true,
},
"compute_id": {
Type: schema.TypeInt,
Computed: true,
},
"frontend_ip": {
Type: schema.TypeString,
Computed: true,
},
"guid": {
Type: schema.TypeString,
Computed: true,
},
"mgmt_ip": {
Type: schema.TypeString,
Computed: true,
},
"network_id": {
Type: schema.TypeInt,
Computed: true,
},
}
return res
}
func dataSourceRgListLbSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ha_mode": {
Type: schema.TypeBool,
Computed: true,
},
"acl": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: aclSchemaMake(),
},
},
"backends": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: backendsSchemaMake(),
},
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"dp_api_user": {
Type: schema.TypeString,
Computed: true,
},
"extnet_id": {
Type: schema.TypeInt,
Computed: true,
},
"frontends": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: frontendsSchemaMake(),
},
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"primary_node": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: nodeSchemaMake(),
},
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"secondary_node": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: nodeSchemaMake(),
},
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
"vins_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceRgListLb() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgListLbRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgListLbSchemaMake(),
}
}

@ -0,0 +1,89 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgListPfwRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
listPfw, err := utilityRgListPfwCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("items", flattenRgListPfw(listPfw))
return nil
}
func dataSourceRgListPfwSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"public_port_end": {
Type: schema.TypeInt,
Computed: true,
},
"public_port_start": {
Type: schema.TypeInt,
Computed: true,
},
"vm_id": {
Type: schema.TypeInt,
Computed: true,
},
"vm_ip": {
Type: schema.TypeString,
Computed: true,
},
"vm_name": {
Type: schema.TypeString,
Computed: true,
},
"vm_port": {
Type: schema.TypeInt,
Computed: true,
},
"vins_id": {
Type: schema.TypeInt,
Computed: true,
},
"vins_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceRgListPfw() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgListPfwRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgListPfwSchemaMake(),
}
}

@ -0,0 +1,126 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgListVinsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
listVins, err := utilityRgListVinsCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
d.Set("items", flattenRgListVins(listVins))
return nil
}
func dataSourceRgListVinsSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of the RG",
},
"reason": {
Type: schema.TypeString,
Optional: true,
Description: "Reason for action",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"account_name": {
Type: schema.TypeString,
Computed: true,
},
"computes": {
Type: schema.TypeInt,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"created_time": {
Type: schema.TypeInt,
Computed: true,
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"external_ip": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"network": {
Type: schema.TypeString,
Computed: true,
},
"pri_vnf_dev_id": {
Type: schema.TypeInt,
Computed: true,
},
"rg_name": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
},
"updated_time": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
return res
}
func DataSourceRgListVins() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgListVinsRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgListVinsSchemaMake(),
}
}

@ -0,0 +1,99 @@
package rg
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceRgUsageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
usage, err := utilityDataRgUsageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(d.Get("rg_id").(int)))
flattenRgUsageResource(d, *usage)
return nil
}
func dataSourceRgUsageSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"rg_id": {
Type: schema.TypeInt,
Required: true,
},
"reason": {
Type: schema.TypeString,
Optional: true,
},
"cpu": {
Type: schema.TypeInt,
Computed: true,
},
"disk_size": {
Type: schema.TypeInt,
Computed: true,
},
"disk_size_max": {
Type: schema.TypeInt,
Computed: true,
},
"extips": {
Type: schema.TypeInt,
Computed: true,
},
"exttraffic": {
Type: schema.TypeInt,
Computed: true,
},
"gpu": {
Type: schema.TypeInt,
Computed: true,
},
"ram": {
Type: schema.TypeInt,
Computed: true,
},
"seps": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString,
Computed: true,
},
"map": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
}
return res
}
func DataSourceRgUsage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceRgUsageRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceRgUsageSchemaMake(),
}
}

@ -33,13 +33,14 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
package rg package rg
import ( import (
"encoding/json"
"fmt" "fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func flattenAccountSeps(seps map[string]map[string]ResourceSep) []map[string]interface{} { func flattenAccountSeps(seps map[string]map[string]DiskUsage) []map[string]interface{} {
res := make([]map[string]interface{}, 0) res := make([]map[string]interface{}, 0)
for sepKey, sepVal := range seps { for sepKey, sepVal := range seps {
for dataKey, dataVal := range sepVal { for dataKey, dataVal := range sepVal {
@ -52,6 +53,7 @@ func flattenAccountSeps(seps map[string]map[string]ResourceSep) []map[string]int
res = append(res, temp) res = append(res, temp)
} }
} }
return res return res
} }
@ -59,14 +61,15 @@ func flattenAccResource(r Resource) []map[string]interface{} {
res := make([]map[string]interface{}, 0) res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{ temp := map[string]interface{}{
"cpu": r.CPU, "cpu": r.CPU,
"disksize": r.Disksize, "disksize": r.DiskSize,
"extips": r.Extips, "extips": r.ExtIPs,
"exttraffic": r.Exttraffic, "exttraffic": r.ExtTraffic,
"gpu": r.GPU, "gpu": r.GPU,
"ram": r.RAM, "ram": r.RAM,
"seps": flattenAccountSeps(r.SEPs), "seps": flattenAccountSeps(r.SEPs),
} }
res = append(res, temp) res = append(res, temp)
return res return res
} }
@ -80,36 +83,7 @@ func flattenRgResources(r Resources) []map[string]interface{} {
return res return res
} }
func flattenDataResgroup(d *schema.ResourceData, details ResgroupGetResp) error { func flattenResgroup(d *schema.ResourceData, details RecordResourceGroup) 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: decoded RG name %q / ID %d, account ID %d",
details.Name, details.ID, details.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("gid", 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("resources", flattenRgResources(details.Resources))
d.Set("vins", details.Vins)
d.Set("vms", details.Computes)
log.Debugf("flattenResgroup: calling flattenQuota()")
if err := d.Set("quota", parseQuota(details.Quota)); err != nil {
return err
}
return nil
}
func flattenResgroup(d *schema.ResourceData, details ResgroupGetResp) error {
// NOTE: this function modifies ResourceData argument - as such it should never be called // NOTE: this function modifies ResourceData argument - as such it should never be called
// from resourceRsgroupExists(...) method // from resourceRsgroupExists(...) method
// log.Debugf("%s", rg_facts) // log.Debugf("%s", rg_facts)
@ -124,22 +98,482 @@ func flattenResgroup(d *schema.ResourceData, details ResgroupGetResp) error {
details.Name, details.ID, details.AccountID) details.Name, details.ID, details.AccountID)
d.SetId(fmt.Sprintf("%d", details.ID)) d.SetId(fmt.Sprintf("%d", details.ID))
d.Set("rg_id", details.ID)
d.Set("account_id", details.AccountID)
d.Set("gid", details.GID)
d.Set("def_net_type", details.DefNetType)
d.Set("name", details.Name) d.Set("name", details.Name)
d.Set("resources", flattenRgResource(details.Resources))
d.Set("account_name", details.AccountName) d.Set("account_name", details.AccountName)
d.Set("account_id", details.AccountID) d.Set("acl", flattenRgAcl(details.ACL))
d.Set("gid", 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("resources", flattenRgResources(details.Resources))
d.Set("vins", details.Vins)
d.Set("vms", details.Computes) d.Set("vms", details.Computes)
log.Debugf("flattenResgroup: calling flattenQuota()") d.Set("created_by", details.CreatedBy)
if err := d.Set("quota", parseQuota(details.Quota)); err != nil { d.Set("created_time", details.CreatedTime)
return err d.Set("def_net_id", details.DefNetID)
} d.Set("deleted_by", details.DeletedBy)
d.Set("deleted_time", details.DeletedTime)
d.Set("description", details.Description)
d.Set("dirty", details.Dirty)
d.Set("guid", details.GUID)
d.Set("rg_id", details.ID)
d.Set("lock_status", details.LockStatus)
d.Set("milestones", details.Milestones)
d.Set("register_computes", details.RegisterComputes)
d.Set("res_types", details.ResTypes)
d.Set("secret", details.Secret)
d.Set("status", details.Status)
d.Set("updated_by", details.UpdatedBy)
d.Set("updated_time", details.UpdatedTime)
d.Set("uniq_pools", details.UniqPools)
d.Set("vins", details.VINS)
return nil return nil
} }
func flattenRgSeps(seps map[string]map[string]DiskUsage) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for sepKey, sepVal := range seps {
SepMap := map[string]interface{}{}
for dataKey, dataVal := range sepVal {
val, _ := json.Marshal(dataVal)
SepMap[dataKey] = string(val)
}
temp := map[string]interface{}{
"sep_id": sepKey,
"map": SepMap,
}
res = append(res, temp)
}
return res
}
func flattenResource(resource Resource) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"cpu": resource.CPU,
"disk_size": resource.DiskSize,
"disk_size_max": resource.DiskSizeMax,
"extips": resource.ExtIPs,
"exttraffic": resource.ExtTraffic,
"gpu": resource.GPU,
"ram": resource.RAM,
"seps": flattenRgSeps(resource.SEPs),
}
res = append(res, temp)
return res
}
func flattenRgResource(itemResource Resources) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"current": flattenResource(itemResource.Current),
"reserved": flattenResource(itemResource.Reserved),
}
res = append(res, temp)
return res
}
func flattenRg(d *schema.ResourceData, itemRg RecordResourceGroup) {
d.Set("resources", flattenRgResource(itemRg.Resources))
d.Set("account_id", itemRg.AccountID)
d.Set("account_name", itemRg.AccountName)
d.Set("acl", flattenRgAcl(itemRg.ACL))
d.Set("computes", itemRg.Computes)
d.Set("created_by", itemRg.CreatedBy)
d.Set("created_time", itemRg.CreatedTime)
d.Set("def_net_id", itemRg.DefNetID)
d.Set("def_net_type", itemRg.DefNetType)
d.Set("deleted_by", itemRg.DeletedBy)
d.Set("deleted_time", itemRg.DeletedTime)
d.Set("desc", itemRg.Description)
d.Set("dirty", itemRg.Dirty)
d.Set("gid", itemRg.GID)
d.Set("guid", itemRg.GUID)
d.Set("rg_id", itemRg.ID)
d.Set("lock_status", itemRg.LockStatus)
d.Set("milestones", itemRg.Milestones)
d.Set("name", itemRg.Name)
d.Set("register_computes", itemRg.RegisterComputes)
d.Set("res_types", itemRg.ResTypes)
d.Set("resource_limits", flattenRgResourceLimits(itemRg.ResourceLimits))
d.Set("secret", itemRg.Secret)
d.Set("status", itemRg.Status)
d.Set("updated_by", itemRg.UpdatedBy)
d.Set("updated_time", itemRg.UpdatedTime)
d.Set("uniq_pools", itemRg.UniqPools)
d.Set("vins", itemRg.VINS)
}
func flattenRgAudits(rgAudits ListAudits) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rgAudit := range rgAudits {
temp := map[string]interface{}{
"call": rgAudit.Call,
"responsetime": rgAudit.ResponseTime,
"statuscode": rgAudit.StatusCode,
"timestamp": rgAudit.Timestamp,
"user": rgAudit.User,
}
res = append(res, temp)
}
return res
}
func flattenRgList(rgl ListResourceGroups) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rg := range rgl {
temp := map[string]interface{}{
"account_acl": flattenRgAcl(rg.ACL),
"account_id": rg.AccountID,
"account_name": rg.AccountName,
"acl": flattenRgAcl(rg.ACL),
"created_by": rg.CreatedBy,
"created_time": rg.CreatedTime,
"def_net_id": rg.DefNetID,
"def_net_type": rg.DefNetType,
"deleted_by": rg.DeletedBy,
"deleted_time": rg.DeletedTime,
"desc": rg.Description,
"dirty": rg.Dirty,
"gid": rg.GID,
"guid": rg.GUID,
"rg_id": rg.ID,
"lock_status": rg.LockStatus,
"milestones": rg.Milestones,
"name": rg.Name,
"register_computes": rg.RegisterComputes,
"resource_limits": flattenRgResourceLimits(rg.ResourceLimits),
"secret": rg.Secret,
"status": rg.Status,
"updated_by": rg.UpdatedBy,
"updated_time": rg.UpdatedTime,
"vins": rg.VINS,
"vms": rg.Computes,
"resource_types": rg.ResTypes,
"uniq_pools": rg.UniqPools,
}
res = append(res, temp)
}
return res
}
func flattenRgAcl(rgAcls ListACL) []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 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 flattenRules(list ListRules) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, rule := range list {
temp := map[string]interface{}{
"guid": rule.GUID,
"key": rule.Key,
"mode": rule.Mode,
"policy": rule.Policy,
"topology": rule.Topology,
"value": rule.Value,
}
res = append(res, temp)
}
return res
}
func flattenRgListComputes(lc ListComputes) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, compute := range lc {
temp := map[string]interface{}{
"account_id": compute.AccountID,
"account_name": compute.AccountName,
"affinity_label": compute.AffinityLabel,
"affinity_rules": flattenRules(compute.AffinityRules),
"affinity_weight": compute.AffinityWeight,
"antiaffinity_rules": flattenRules(compute.AntiAffinityRules),
"cpus": compute.CPUs,
"created_by": compute.CreatedBy,
"created_time": compute.CreatedTime,
"deleted_by": compute.DeletedBy,
"deleted_time": compute.DeletedTime,
"id": compute.ID,
"name": compute.Name,
"ram": compute.RAM,
"registered": compute.Registered,
"rg_name": compute.RGName,
"status": compute.Status,
"tech_status": compute.TechStatus,
"total_disks_size": compute.TotalDisksSize,
"updated_by": compute.DeletedBy,
"updated_time": compute.DeletedTime,
"user_managed": compute.UserManaged,
"vins_connected": compute.VINSConnected,
}
res = append(res, temp)
}
return res
}
func flattenServerSettings(settings ServerSettings) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"inter": settings.Inter,
"guid": settings.GUID,
"down_inter": settings.DownInter,
"rise": settings.Rise,
"fall": settings.Fall,
"slow_start": settings.SlowStart,
"max_conn": settings.MaxConn,
"max_queue": settings.MaxQueue,
"weight": settings.Weight,
}
res = append(res, temp)
return res
}
func flattenListServers(list ListServers) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, serv := range list {
temp := map[string]interface{}{
"address": serv.Address,
"check": serv.Check,
"guid": serv.GUID,
"name": serv.Name,
"port": serv.Port,
"server_settings": flattenServerSettings(serv.ServerSettings),
}
res = append(res, temp)
}
return res
}
func flattenBackends(b ListBackends) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range b {
temp := map[string]interface{}{
"algorithm": item.Algorithm,
"guid": item.GUID,
"name": item.Name,
"server_default_settings": flattenServerSettings(item.ServerDefaultSettings),
"servers": flattenListServers(item.Servers),
}
res = append(res, temp)
}
return res
}
func flattenBindings(list ListBindings) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, bind := range list {
temp := map[string]interface{}{
"address": bind.Address,
"guid": bind.GUID,
"name": bind.Name,
"port": bind.Port,
}
res = append(res, temp)
}
return res
}
func flattenFrontends(list ListFrontends) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, front := range list {
temp := map[string]interface{}{
"backend": front.Backend,
"bindings": flattenBindings(front.Bindings),
"guid": front.GUID,
"name": front.Name,
}
res = append(res, temp)
}
return res
}
func flattenNode(node RecordNode) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"backend_ip": node.BackendIP,
"compute_id": node.ComputeID,
"frontend_ip": node.FrontendIP,
"guid": node.GUID,
"mgmt_ip": node.MGMTIP,
"network_id": node.NetworkID,
}
res = append(res, temp)
return res
}
func flattenRgListLb(listLb ListLB) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, lb := range listLb {
temp := map[string]interface{}{
"ha_mode": lb.HAMode,
"acl": lb.ACL,
"backends": flattenBackends(lb.Backends),
"created_by": lb.CreatedBy,
"created_time": lb.CreatedTime,
"deleted_by": lb.DeletedBy,
"deleted_time": lb.DeletedTime,
"desc": lb.Description,
"dp_api_user": lb.DPAPIUser,
"extnet_id": lb.ExtNetID,
"frontends": flattenFrontends(lb.Frontends),
"gid": lb.GID,
"guid": lb.GUID,
"id": lb.ID,
"image_id": lb.ImageID,
"milestones": lb.Milestones,
"name": lb.Name,
"primary_node": flattenNode(lb.PrimaryNode),
"rg_name": lb.RGName,
"secondary_node": flattenNode(lb.SecondaryNode),
"status": lb.Status,
"tech_status": lb.TechStatus,
"updated_by": lb.UpdatedBy,
"updated_time": lb.UpdatedTime,
"vins_id": lb.VINSID,
}
res = append(res, temp)
}
return res
}
func flattenRgListPfw(listPfw ListPFW) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, pfw := range listPfw {
temp := map[string]interface{}{
"public_port_end": pfw.PublicPortEnd,
"public_port_start": pfw.PublicPortStart,
"vm_id": pfw.VMID,
"vm_ip": pfw.VMIP,
"vm_name": pfw.VMName,
"vm_port": pfw.VMPort,
"vins_id": pfw.VINSID,
"vins_name": pfw.VINSName,
}
res = append(res, temp)
}
return res
}
func flattenRgListVins(lv ListVINS) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, vins := range lv {
temp := map[string]interface{}{
"account_id": vins.AccountID,
"account_name": vins.AccountName,
"computes": vins.Computes,
"created_by": vins.CreatedBy,
"created_time": vins.CreatedTime,
"deleted_by": vins.DeletedBy,
"deleted_time": vins.DeletedTime,
"external_ip": vins.ExternalIP,
"id": vins.ID,
"name": vins.Name,
"network": vins.Network,
"pri_vnf_dev_id": vins.PriVNFDevID,
"rg_name": vins.RGName,
"status": vins.Status,
"updated_by": vins.UpdatedBy,
"updated_time": vins.UpdatedTime,
}
res = append(res, temp)
}
return res
}
func flattenRgAffinityGroupComputes(list ListAffinityGroupCompute) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, item := range list {
temp := map[string]interface{}{
"compute_id": item.ComputeID,
"other_node": item.OtherNode,
"other_node_indirect": item.OtherNodeIndirect,
"other_node_indirect_soft": item.OtherNodeIndirectSoft,
"other_node_soft": item.OtherNodeSoft,
"same_node": item.SameNode,
"same_node_soft": item.SameNodeSoft,
}
res = append(res, temp)
}
return res
}
func flattenRgAffinityGroupsGet(list []uint64) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
temp := map[string]interface{}{
"items": list,
}
res = append(res, temp)
return res
}
func flattenRgListGroups(list map[string][]uint64) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for groupKey, groupVal := range list {
temp := map[string]interface{}{
"label": groupKey,
"ids": groupVal,
}
res = append(res, temp)
}
return res
}
func flattenRgUsageResource(d *schema.ResourceData, usage Resource) {
d.Set("cpu", usage.CPU)
d.Set("disk_size", usage.DiskSize)
d.Set("disk_size_max", usage.DiskSizeMax)
d.Set("extips", usage.ExtIPs)
d.Set("exttraffic", usage.ExtTraffic)
d.Set("gpu", usage.GPU)
d.Set("ram", usage.RAM)
d.Set("seps", flattenRgSeps(usage.SEPs))
}

@ -41,131 +41,709 @@ type ResourceLimits struct {
GpuUnits float64 `json:"gpu_units"` GpuUnits float64 `json:"gpu_units"`
} }
type ResgroupRecord struct { type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get
ACLs []AccountAclRecord `json:"acl"` Cpu int `json:"CU_C"` // CPU count in pcs
AccountID int `json:"accountId"` 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
}
// Main information about audit
type ItemAudit struct {
// Call
Call string `json:"call"`
// Response time
ResponseTime float64 `json:"responsetime"`
// Status code
StatusCode uint64 `json:"statuscode"`
// Timestamp
Timestamp float64 `json:"timestamp"`
// User
User string `json:"user"`
}
// List of audits
type ListAudits []ItemAudit
// Resources used
type Resource struct {
// Number of cores
CPU int64 `json:"cpu"`
// Disk size
DiskSize float64 `json:"disksize"`
// Max disk size
DiskSizeMax uint64 `json:"disksizemax"`
// Number of External IPs
ExtIPs int64 `json:"extips"`
// External traffic
ExtTraffic int64 `json:"exttraffic"`
// Number of grafic cores
GPU int64 `json:"gpu"`
// Number of RAM
RAM int64 `json:"ram"`
// SEPs
SEPs map[string]map[string]DiskUsage `json:"seps"`
}
// Disk usage
type DiskUsage struct {
// Disk size
DiskSize float64 `json:"disksize"`
// Disk size max
DiskSizeMax float64 `json:"disksizemax"`
}
// Information about resources
type Resources struct {
// Current information about resources
Current Resource `json:"Current"`
// Reserved information about resources
Reserved Resource `json:"Reserved"`
}
// Detailed information about resource group
type RecordResourceGroup struct {
// Resources
Resources Resources `json:"Resources"`
// Account ID
AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"` AccountName string `json:"accountName"`
// Access Control List
ACL ListACL `json:"acl"`
// Created by
CreatedBy string `json:"createdBy"` CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"` CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
DefaultNetType string `json:"def_net_type"` // DefNetID
DefNetID int64 `json:"def_net_id"`
// DefNetType
DefNetType string `json:"def_net_type"`
// Deleted by
DeletedBy string `json:"deletedBy"` DeletedBy string `json:"deletedBy"`
DeletedTime int `json:"deletedTime"`
Decsription string `json:"desc"` // Deleted time
GridID int `json:"gid"` DeletedTime uint64 `json:"deletedTime"`
GUID int `json:"guid"`
ID uint `json:"id"` // Description
Description string `json:"desc"`
// Dirty
Dirty bool `json:"dirty"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Lock status
LockStatus string `json:"lockStatus"` LockStatus string `json:"lockStatus"`
Milestones int `json:"milestones"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"` Name string `json:"name"`
// RegisterComputes
RegisterComputes bool `json:"registerComputes"` RegisterComputes bool `json:"registerComputes"`
// Resource limits
ResourceLimits ResourceLimits `json:"resourceLimits"` ResourceLimits ResourceLimits `json:"resourceLimits"`
// Secret
Secret string `json:"secret"` Secret string `json:"secret"`
// Status
Status string `json:"status"` Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"` UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"` UpdatedTime uint64 `json:"updatedTime"`
Vins []int `json:"vins"`
Computes []int `json:"vms"` // List of VINS IDs
VINS []uint64 `json:"vins"`
// List of compute IDs
Computes []uint64 `json:"vms"`
// List of resource types
ResTypes []string `json:"resourceTypes"`
// UniqPools
UniqPools []string `json:"uniqPools"`
} }
type ResgroupListResp []ResgroupRecord // Main information about Access Control List
type ItemACL struct {
// Explicit
Explicit bool `json:"explicit"`
type ResgroupUpdateParam struct { // GUID
RgId int `json:"rgId"` GUID string `json:"guid"`
Name string `json:"name"`
Desc string `json:"decs"` // Right
Ram int `json:"maxMemoryCapacity"` Right string `json:"right"`
Disk int `json:"maxVDiskCapacity"`
Cpu int `json:"maxCPUCapacity"` // Status
NetTraffic int `json:"maxNetworkPeerTransfer"`
Reason string `json:"reason"`
}
type AccountAclRecord struct {
IsExplicit bool `json:"explicit"`
Guid string `json:"guid"`
Rights string `json:"right"`
Status string `json:"status"` Status string `json:"status"`
// Type
Type string `json:"type"` Type string `json:"type"`
UgroupID string `json:"userGroupId"`
CanBeDeleted bool `json:"canBeDeleted"` // User group ID
UserGroupID string `json:"userGroupId"`
} }
type ResgroupGetResp struct { // List ACL
Resources Resources `json:"Resources"` type ListACL []ItemACL
ACLs []UserAclRecord `json:"ACLs"`
//Usage UsageRecord `json:"Resources"` type ItemResourceGroup struct {
AccountID int `json:"accountId"` //
AccountACL ItemACL `json:"accountAcl"`
// Account ID
AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"` AccountName string `json:"accountName"`
GridID int `json:"gid"`
// Access Control List
ACL ListACL `json:"acl"`
// Created by
CreatedBy string `json:"createdBy"` CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"` CreatedTime uint64 `json:"createdTime"`
DefaultNetID int `json:"def_net_id"`
DefaultNetType string `json:"def_net_type"` // DefNetID
DefNetID int64 `json:"def_net_id"`
// DefNetType
DefNetType string `json:"def_net_type"`
// Deleted by
DeletedBy string `json:"deletedBy"` DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"` DeletedTime uint64 `json:"deletedTime"`
Desc string `json:"desc"`
ID uint `json:"id"` // Description
Description string `json:"desc"`
// Dirty
Dirty bool `json:"dirty"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Lock status
LockStatus string `json:"lockStatus"` LockStatus string `json:"lockStatus"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"` Name string `json:"name"`
Quota QuotaRecord `json:"resourceLimits"`
// RegisterComputes
RegisterComputes bool `json:"registerComputes"`
// Resource limits
ResourceLimits ResourceLimits `json:"resourceLimits"`
// Secret
Secret string `json:"secret"`
// Status
Status string `json:"status"` Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"` UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"` UpdatedTime uint64 `json:"updatedTime"`
Vins []int `json:"vins"`
Computes []int `json:"vms"`
Ignored map[string]interface{} `json:"-"` // List of VINS IDs
VINS []uint64 `json:"vins"`
// List of compute IDs
Computes []uint64 `json:"vms"`
// List of resource types
ResTypes []string `json:"resourceTypes"`
// UniqPools
UniqPools []string `json:"uniqPools"`
} }
type UserAclRecord struct { // List of resource groups
IsExplicit bool `json:"explicit"` type ListResourceGroups []ItemResourceGroup
Rights string `json:"right"`
// Main information about affinity rule
type ItemRule struct {
// GUID
GUID string `json:"guid"`
// Key
Key string `json:"key"`
// Mode
Mode string `json:"mode"`
// Policy
Policy string `json:"policy"`
// Topology
Topology string `json:"topology"`
// Value
Value string `json:"value"`
}
// List rules
type ListRules []ItemRule
// Main information about compute
type ItemCompute struct {
// Account ID
AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"`
// Affinity label
AffinityLabel string `json:"affinityLabel"`
// List affinity rules
AffinityRules ListRules `json:"affinityRules"`
// Affinity weight
AffinityWeight uint64 `json:"affinityWeight"`
// Anti affinity rules
AntiAffinityRules ListRules `json:"antiAffinityRules"`
// Number of CPU
CPUs uint64 `json:"cpus"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
// Number of RAM
RAM uint64 `json:"ram"`
// Registered
Registered bool `json:"registered"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// Status
Status string `json:"status"` Status string `json:"status"`
Type string `json:"type"`
UgroupID string `json:"userGroupId"` // Tech status
// CanBeDeleted bool `json:"canBeDeleted"` TechStatus string `json:"techStatus"`
// Total disks size
TotalDisksSize uint64 `json:"totalDisksSize"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// User managed
UserManaged bool `json:"userManaged"`
// VINS connected
VINSConnected uint64 `json:"vinsConnected"`
} }
type QuotaRecord struct { // this is how quota is reported by /api/.../rg/get // List computes
Cpu int `json:"CU_C"` // CPU count in pcs type ListComputes []ItemCompute
Ram float64 `json:"CU_M"` // RAM volume in MB, it is STILL reported as FLOAT
Disk int `json:"CU_D"` // Disk capacity in GB // Main information about port forward
ExtIPs int `json:"CU_I"` // Ext IPs count type ItemPFW struct {
ExtTraffic int `json:"CU_NP"` // Ext network traffic // Public port end
GpuUnits int `json:"gpu_units"` // GPU count PublicPortEnd uint64 `json:"Public Port End"`
// Public port start
PublicPortStart uint64 `json:"Public Port Start"`
// Virtual machine ID
VMID uint64 `json:"VM ID"`
// Virtual machine IP
VMIP string `json:"VM IP"`
// Virtual machine name
VMName string `json:"VM Name"`
// Virtual machine port
VMPort uint64 `json:"VM Port"`
// VINS ID
VINSID uint64 `json:"ViNS ID"`
// VINS name
VINSName string `json:"ViNS Name"`
} }
type ResourceRecord struct { // this is how actual usage is reported by /api/.../rg/get // List PFWs
Cpu int `json:"cpu"` type ListPFW []ItemPFW
Disk float64 `json:"disksize"`
ExtIPs int `json:"extips"` // Main information about VINS
ExtTraffic int `json:"exttraffic"` type ItemVINS struct {
Gpu int `json:"gpu"` // Account ID
Ram int `json:"ram"` AccountID uint64 `json:"accountId"`
// Account name
AccountName string `json:"accountName"`
// Computes
Computes uint64 `json:"computes"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// External IP
ExternalIP string `json:"externalIP"`
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
// Network
Network string `json:"network"`
// PriVNFDev ID
PriVNFDevID uint64 `json:"priVnfDevId"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// Status
Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
} }
type UsageRecord struct { // List VINSes
Current ResourceRecord `json:"Current"` type ListVINS []ItemVINS
Reserved ResourceRecord `json:"Reserved"`
// Server settings
type ServerSettings struct {
// Inter
Inter uint64 `json:"inter"`
// GUID
GUID string `json:"guid"`
// Down inter
DownInter uint64 `json:"downinter"`
// Rise
Rise uint64 `json:"rise"`
// Fall
Fall uint64 `json:"fall"`
// Slow start
SlowStart uint64 `json:"slowstart"`
// Max connections
MaxConn uint64 `json:"maxconn"`
// Max queue
MaxQueue uint64 `json:"maxqueue"`
// Weight
Weight uint64 `json:"weight"`
} }
type ResourceSep struct { // Main information about server
DiskSize float64 `json:"disksize"` type ItemServer struct {
DiskSizeMax int `json:"disksizemax"` // Address
Address string `json:"address"`
// Check
Check string `json:"check"`
// GUID
GUID string `json:"guid"`
// Name
Name string `json:"name"`
// Port
Port uint64 `json:"port"`
// Server settings
ServerSettings ServerSettings `json:"serverSettings"`
} }
type Resource struct { // List of servers
CPU int `json:"cpu"` type ListServers []ItemServer
Disksize float64 `json:"disksize"`
Extips int `json:"extips"` // Main information about backend
Exttraffic int `json:"exttraffic"` type ItemBackend struct {
GPU int `json:"gpu"` // Algorithm
RAM int `json:"ram"` Algorithm string `json:"algorithm"`
SEPs map[string]map[string]ResourceSep `json:"seps"`
// GUID
GUID string `json:"guid"`
// Name
Name string `json:"name"`
// Server settings
ServerDefaultSettings ServerSettings `json:"serverDefaultSettings"`
// List of servers
Servers ListServers `json:"servers"`
} }
type Resources struct { // List of backends
Current Resource `json:"Current"` type ListBackends []ItemBackend
Reserved Resource `json:"Reserved"`
// Main information of binding
type ItemBinding struct {
// Address
Address string `json:"address"`
// GUID
GUID string `json:"guid"`
// Name
Name string `json:"name"`
// Port
Port uint64 `json:"port"`
}
// List of bindings
type ListBindings []ItemBinding
// Main information about frontend
type ItemFrontend struct {
// Backend
Backend string `json:"backend"`
// List of bindings
Bindings ListBindings `json:"bindings"`
// GUID
GUID string `json:"guid"`
// Name
Name string `json:"name"`
}
// List of frontends
type ListFrontends []ItemFrontend
// Main information about node
type RecordNode struct {
// Backend IP
BackendIP string `json:"backendIp"`
// Compute ID
ComputeID uint64 `json:"computeId"`
// Frontend IP
FrontendIP string `json:"frontendIp"`
// GUID
GUID string `json:"guid"`
// MGMT IP
MGMTIP string `json:"mgmtIp"`
// Network ID
NetworkID uint64 `json:"networkId"`
}
// Main information about load balancer
type ItemLB struct {
// HAMode
HAMode bool `json:"HAmode"`
// List ACL
ACL ListACL `json:"acl"`
// List backends
Backends ListBackends `json:"backends"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Description
Description string `json:"desc"`
// DPAPI user
DPAPIUser string `json:"dpApiUser"`
// External network ID
ExtNetID uint64 `json:"extnetId"`
// List of frontends
Frontends ListFrontends `json:"frontends"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Primary node
PrimaryNode RecordNode `json:"primaryNode"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// Secondary node
SecondaryNode RecordNode `json:"secondaryNode"`
// Status
Status string `json:"status"`
// Tech status
TechStatus string `json:"techStatus"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// VINS ID
VINSID uint64 `json:"vinsId"`
} }
// List load balancers
type ListLB []ItemLB
// Main information about affinity group
type ItemAffinityGroupCompute struct {
// Compute ID
ComputeID uint64 `json:"computeId"`
// Other node
OtherNode []uint64 `json:"otherNode"`
// Other node indirect
OtherNodeIndirect []uint64 `json:"otherNodeIndirect"`
// Other node indirect soft
OtherNodeIndirectSoft []uint64 `json:"otherNodeIndirectSoft"`
// Other node soft
OtherNodeSoft []uint64 `json:"otherNodeSoft"`
// Same node
SameNode []uint64 `json:"sameNode"`
// Same node soft
SameNodeSoft []uint64 `json:"sameNodeSoft"`
}
// List of affinity groups
type ListAffinityGroupCompute []ItemAffinityGroupCompute

@ -45,6 +45,7 @@ func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
ExtIPs: -1, ExtIPs: -1,
GpuUnits: -1, GpuUnits: -1,
} }
if len(arg_list) != 0 {
subres_data := arg_list[0].(map[string]interface{}) subres_data := arg_list[0].(map[string]interface{})
if subres_data["cpu"].(int) > 0 { if subres_data["cpu"].(int) > 0 {
@ -70,7 +71,7 @@ func makeQuotaRecord(arg_list []interface{}) QuotaRecord {
if subres_data["gpu_units"].(int) > 0 { if subres_data["gpu_units"].(int) > 0 {
quota.GpuUnits = subres_data["gpu_units"].(int) quota.GpuUnits = subres_data["gpu_units"].(int)
} }
}
return quota return quota
} }

@ -0,0 +1,111 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func existAccountID(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
accountList := []struct {
ID int `json:"id"`
}{}
accountListAPI := "/restmachine/cloudapi/account/list"
accountListRaw, err := c.DecortAPICall(ctx, "POST", accountListAPI, urlValues)
if err != nil {
return false, err
}
err = json.Unmarshal([]byte(accountListRaw), &accountList)
if err != nil {
return false, err
}
haveAccount := false
myAccount := d.Get("account_id").(int)
for _, account := range accountList {
if account.ID == myAccount {
haveAccount = true
break
}
}
return haveAccount, nil
}
func existGID(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
locationList := []struct {
GID int `json:"gid"`
}{}
locationsListAPI := "/restmachine/cloudapi/locations/list"
locationListRaw, err := c.DecortAPICall(ctx, "POST", locationsListAPI, urlValues)
if err != nil {
return false, err
}
err = json.Unmarshal([]byte(locationListRaw), &locationList)
if err != nil {
return false, err
}
haveGID := false
myGID := d.Get("gid").(int)
for _, location := range locationList {
if location.GID == myGID {
haveGID = true
break
}
}
return haveGID, nil
}
func existExtNetID(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
listExtNet := []struct {
ID int `json:"id"`
}{}
extNetListAPI := "/restmachine/cloudapi/extnet/list"
listExtNetRaw, err := c.DecortAPICall(ctx, "POST", extNetListAPI, urlValues)
if err != nil {
return false, err
}
err = json.Unmarshal([]byte(listExtNetRaw), &listExtNet)
if err != nil {
return false, err
}
haveExtNet := false
myExtNetID := d.Get("ext_net_id").(int)
for _, extNet := range listExtNet {
if extNet.ID == myExtNetID {
haveExtNet = true
break
}
}
return haveExtNet, nil
}

@ -40,10 +40,13 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants" "github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller" "github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/dc"
"github.com/rudecs/terraform-provider-decort/internal/location" "github.com/rudecs/terraform-provider-decort/internal/location"
"github.com/rudecs/terraform-provider-decort/internal/status"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
) )
@ -54,11 +57,14 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
// Valid account ID is required to create 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 // obtain Account ID by account name - it should not be zero on success
rg_name, arg_set := d.GetOk("name") rgName, argSet := d.GetOk("name")
if !arg_set { if !argSet {
return diag.FromErr(fmt.Errorf("Cannot create new RG: missing name.")) return diag.FromErr(fmt.Errorf("Cannot create new RG: missing name."))
} }
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
/* Current version of provider works with default grid id (same is true for disk resources) /* Current version of provider works with default grid id (same is true for disk resources)
grid_id, arg_set := d.GetOk("grid_id") grid_id, arg_set := d.GetOk("grid_id")
if !arg_set { if !arg_set {
@ -72,99 +78,289 @@ func resourceResgroupCreate(ctx context.Context, d *schema.ResourceData, m inter
// all required parameters are set in the schema - we can continue with RG creation // 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", log.Debugf("resourceResgroupCreate: called for RG name %s, account ID %d",
rg_name.(string), d.Get("account_id").(int)) rgName.(string), d.Get("account_id").(int))
// Check input values
// AccountID
haveAccount, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccount {
return diag.Errorf("resourceResgroupCreate: can't create RG bacause AccountID %d not allowed or does not exist", d.Get("account_id").(int))
}
// GID
haveGID, err := existGID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveGID {
return diag.Errorf("resourceResgroupCreate: can't create RG bacause GID %d not allowed or does not exist", d.Get("gid").(int))
}
// ExtNetID
if _, ok := d.GetOk("ext_net_id"); ok {
haveExtNet, err := existExtNetID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveExtNet {
return diag.Errorf("resourceResgroupCreate: can't create RG bacause ExtNetID %d not allowed or does not exist", d.Get("ext_net_id").(int))
}
}
// quota settings are optional // quota settings are optional
set_quota := false setQuota := false
var quota_record QuotaRecord var quotaRecord QuotaRecord
arg_value, arg_set := d.GetOk("quota") argValue, argSet := d.GetOk("quota")
if arg_set { if argSet {
log.Debugf("resourceResgroupCreate: setting Quota on RG requested") log.Debugf("resourceResgroupCreate: setting Quota on RG requested")
quota_record = makeQuotaRecord(arg_value.([]interface{})) quotaRecord = makeQuotaRecord(argValue.([]interface{}))
set_quota = true setQuota = true
} }
c := m.(*controller.ControllerCfg)
log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d", log.Debugf("resourceResgroupCreate: called by user %q for RG name %s, account ID %d",
c.GetDecortUsername(), c.GetDecortUsername(),
rg_name.(string), d.Get("account_id").(int)) rgName.(string), d.Get("account_id").(int))
url_values := &url.Values{} urlValues = &url.Values{}
url_values.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int))) urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
url_values.Add("name", rg_name.(string)) urlValues.Add("name", rgName.(string))
url_values.Add("gid", fmt.Sprintf("%d", location.DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention urlValues.Add("gid", strconv.Itoa(location.DefaultGridID)) // use default Grid ID, similar to disk resource mgmt convention
url_values.Add("owner", c.GetDecortUsername()) urlValues.Add("owner", c.GetDecortUsername())
// pass quota values as set // pass quota values as set
if set_quota { if setQuota {
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quota_record.Cpu)) urlValues.Add("maxCPUCapacity", strconv.Itoa(quotaRecord.Cpu))
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quota_record.Disk)) urlValues.Add("maxVDiskCapacity", strconv.Itoa(quotaRecord.Disk))
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quota_record.Ram)) // RAM quota is float; this may change in the future urlValues.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotaRecord.Ram)) // RAM quota is float; this may change in the future
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quota_record.ExtTraffic)) urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(quotaRecord.ExtTraffic))
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quota_record.ExtIPs)) urlValues.Add("maxNumPublicIP", strconv.Itoa(quotaRecord.ExtIPs))
// url_values.Add("???", fmt.Sprintf("%d", quota_record.GpuUnits))
} }
// parse and handle network settings // parse and handle network settings
def_net_type, arg_set := d.GetOk("def_net_type") defNetType, argSet := d.GetOk("def_net_type")
if arg_set { if argSet {
url_values.Add("def_net", def_net_type.(string)) // NOTE: in API default network type is set by "def_net" parameter urlValues.Add("def_net", defNetType.(string)) // NOTE: in API default network type is set by "def_net" parameter
} else {
d.Set("def_net_type", "PRIVATE")
} }
ipcidr, arg_set := d.GetOk("ipcidr") ipcidr, argSet := d.GetOk("ipcidr")
if arg_set { if argSet {
url_values.Add("ipcidr", ipcidr.(string)) urlValues.Add("ipcidr", ipcidr.(string))
} }
ext_net_id, arg_set := d.GetOk("ext_net_id") description, argSet := d.GetOk("description")
if arg_set { if argSet {
url_values.Add("extNetId", fmt.Sprintf("%d", ext_net_id.(int))) urlValues.Add("desc", description.(string))
} }
ext_ip, arg_set := d.GetOk("ext_ip") reason, argSet := d.GetOk("reason")
if arg_set { if argSet {
url_values.Add("extIp", ext_ip.(string)) urlValues.Add("reason", reason.(string))
} }
api_resp, err := c.DecortAPICall(ctx, "POST", ResgroupCreateAPI, url_values) extNetId, argSet := d.GetOk("ext_net_id")
if argSet {
urlValues.Add("extNetId", strconv.Itoa(extNetId.(int)))
}
extIp, argSet := d.GetOk("ext_ip")
if argSet {
urlValues.Add("extIp", extIp.(string))
}
apiResp, err := c.DecortAPICall(ctx, "POST", ResgroupCreateAPI, urlValues)
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }
d.SetId(apiResp) // rg/create API returns ID of the newly creted resource group on success
w := dc.Warnings{}
if access, ok := d.GetOk("access"); ok {
urlValues = &url.Values{}
var user, right string
d.SetId(api_resp) // rg/create API returns ID of the newly creted resource group on success if access.(*schema.Set).Len() > 0 {
// rg.ID, _ = strconv.Atoi(api_resp) accessList := access.(*schema.Set).List()
if !set_quota { for _, accessInterface := range accessList {
rg, err := utilityResgroupCheckPresence(ctx, d, m) access := accessInterface.(map[string]interface{})
user = access["user"].(string)
right = access["right"].(string)
urlValues.Add("rgId", d.Id())
urlValues.Add("user", user)
urlValues.Add("right", right)
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
_, err := c.DecortAPICall(ctx, "POST", RgAccessGrantAPI, urlValues)
if err != nil { if err != nil {
return diag.FromErr(err) w.Add(err)
}
}
}
}
if defNet, ok := d.GetOk("def_net"); ok {
urlValues := &url.Values{}
if defNet.(*schema.Set).Len() > 0 {
defNetList := defNet.(*schema.Set).List()
defNetItem := defNetList[0].(map[string]interface{})
netType := defNetItem["net_type"].(string)
urlValues.Add("rgId", d.Id())
urlValues.Add("netType", netType)
if netID, ok := defNetItem["net_id"]; ok {
urlValues.Add("netId", strconv.Itoa(netID.(int)))
}
if reason, ok := defNetItem["reason"]; ok {
urlValues.Add("reason", reason.(string))
}
_, err := c.DecortAPICall(ctx, "POST", RgSetDefNetAPI, urlValues)
if err != nil {
w.Add(err)
}
d.Set("def_net_type", netType)
}
}
if enable, ok := d.GetOk("enable"); ok {
urlValues = &url.Values{}
api := RgDisableAPI
enable := enable.(bool)
if enable {
api = RgEnableAPI
}
urlValues.Add("rgId", d.Id())
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
} }
d.Set("quota", parseQuota(rg.Quota)) _, err := c.DecortAPICall(ctx, "POST", api, urlValues)
if err != nil {
w.Add(err)
}
} }
// re-read newly created RG to make sure schema contains complete and up to date set of specifications // re-read newly created RG to make sure schema contains complete and up to date set of specifications
return resourceResgroupRead(ctx, d, m) defer resourceResgroupRead(ctx, d, m)
return w.Get()
} }
func resourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { func resourceResgroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceResgroupRead: called for RG name %s, account ID %d", log.Debugf("resourceResgroupRead: called for RG name %s, account ID %d",
d.Get("name").(string), d.Get("account_id").(int)) d.Get("name").(string), d.Get("account_id").(int))
rg_facts, err := utilityResgroupCheckPresence(ctx, d, m) c := m.(*controller.ControllerCfg)
rgFacts, err := utilityResgroupCheckPresence(ctx, d, m)
if err != nil { if err != 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 d.SetId("") // ensure ID is empty
return diag.FromErr(err) return diag.FromErr(err)
} }
return diag.FromErr(flattenResgroup(d, *rg_facts)) switch rgFacts.Status {
case status.Modeled:
case status.Created:
case status.Enabled:
case status.Deleted:
urlValues := &url.Values{}
urlValues.Add("rgId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", RgRestoreAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
case status.Deleting:
case status.Destroyed:
d.SetId("")
return resourceResgroupCreate(ctx, d, m)
case status.Destroying:
case status.Disabled:
case status.Disabling:
case status.Enabled:
case status.Enabling:
}
rgFacts, err = utilityResgroupCheckPresence(ctx, d, m)
if err != nil {
d.SetId("") // ensure ID is empty
return diag.FromErr(err)
}
return diag.FromErr(flattenResgroup(d, *rgFacts))
} }
func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceResgroupUpdate: called for RG name %s, account ID %d", log.Debugf("resourceResgroupUpdate: called for RG name %s, account ID %d",
d.Get("name").(string), d.Get("account_id").(int)) d.Get("name").(string), d.Get("account_id").(int))
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
// Check input values
// AccountID
haveAccount, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccount {
return diag.Errorf("resourceResgroupUpdate: can't create RG bacause AccountID %d not allowed or does not exist", d.Get("account_id").(int))
}
// GID
haveGID, err := existGID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveGID {
return diag.Errorf("resourceResgroupUpdate: can't create RG bacause GID %d not allowed or does not exist", d.Get("gid").(int))
}
// ExtNetID
if _, ok := d.GetOk("ext_net_id"); ok {
haveExtNet, err := existExtNetID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveExtNet {
return diag.Errorf("resourceResgroupUpdate: can't create RG bacause ExtNetID %d not allowed or does not exist", d.Get("ext_net_id").(int))
}
}
rgFacts, err := utilityResgroupCheckPresence(ctx, d, m)
if err != nil {
d.SetId("") // ensure ID is empty
return diag.FromErr(err)
}
switch rgFacts.Status {
case status.Modeled:
case status.Created:
case status.Enabled:
case status.Deleted:
urlValues := &url.Values{}
urlValues.Add("rgId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", RgRestoreAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
case status.Deleting:
case status.Destroyed:
d.SetId("")
return resourceResgroupCreate(ctx, d, m)
case status.Destroying:
case status.Disabled:
case status.Disabling:
case status.Enabled:
case status.Enabling:
}
/* NOTE: we do not allow changing the following attributes of an existing RG via terraform: /* NOTE: we do not allow changing the following attributes of an existing RG via terraform:
- def_net_type - def_net_type
- ipcidr - ipcidr
@ -173,6 +369,13 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
The following code fragment checks if any of these have been changed and generates error. The following code fragment checks if any of these have been changed and generates error.
*/ */
if ok := d.HasChange("def_net"); ok {
_, newDefNet := d.GetChange("def_net")
if newDefNet.(*schema.Set).Len() == 0 {
return diag.Errorf("resourceResgroupUpdate: block def_net must not be empty")
}
}
for _, attr := range []string{"def_net_type", "ipcidr", "ext_ip"} { for _, attr := range []string{"def_net_type", "ipcidr", "ext_ip"} {
attr_new, attr_old := d.GetChange("def_net_type") attr_new, attr_old := d.GetChange("def_net_type")
if attr_new.(string) != attr_old.(string) { if attr_new.(string) != attr_old.(string) {
@ -180,78 +383,85 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
} }
} }
attr_new, attr_old := d.GetChange("ext_net_id") attrNew, attrOld := d.GetChange("ext_net_id")
if attr_new.(int) != attr_old.(int) { if attrNew.(int) != attrOld.(int) {
return diag.FromErr(fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing ext_net_id for existing RG is not allowed", d.Id())) return diag.FromErr(fmt.Errorf("resourceResgroupUpdate: RG ID %s: changing ext_net_id for existing RG is not allowed", d.Id()))
} }
do_general_update := false // will be true if general RG update is necessary (API rg/update) doGeneralUpdate := false // will be true if general RG update is necessary (API rg/update)
c := m.(*controller.ControllerCfg) urlValues = &url.Values{}
url_values := &url.Values{} urlValues.Add("rgId", d.Id())
url_values.Add("rgId", d.Id())
name_new, name_set := d.GetOk("name") nameNew, nameSet := d.GetOk("name")
if name_set { if nameSet {
log.Debugf("resourceResgroupUpdate: name specified - looking for deltas from the old settings.") log.Debugf("resourceResgroupUpdate: name specified - looking for deltas from the old settings.")
name_old, _ := d.GetChange("name") nameOld, _ := d.GetChange("name")
if name_old.(string) != name_new.(string) { if nameOld.(string) != nameNew.(string) {
do_general_update = true doGeneralUpdate = true
url_values.Add("name", name_new.(string)) urlValues.Add("name", nameNew.(string))
} }
} }
quota_value, quota_set := d.GetOk("quota") quotaValue, quotaSet := d.GetOk("quota")
if quota_set { if quotaSet {
log.Debugf("resourceResgroupUpdate: quota specified - looking for deltas from the old quota.") log.Debugf("resourceResgroupUpdate: quota specified - looking for deltas from the old quota.")
quotarecord_new := makeQuotaRecord(quota_value.([]interface{})) quotarecordNew := makeQuotaRecord(quotaValue.([]interface{}))
quota_value_old, _ := d.GetChange("quota") // returns old as 1st, new as 2nd return value quotaValueOld, _ := d.GetChange("quota") // returns old as 1st, new as 2nd return value
quotarecord_old := makeQuotaRecord(quota_value_old.([]interface{})) quotarecordOld := makeQuotaRecord(quotaValueOld.([]interface{}))
log.Debug(quotaValueOld, quotarecordNew)
if quotarecord_new.Cpu != quotarecord_old.Cpu { if quotarecordNew.Cpu != quotarecordOld.Cpu {
do_general_update = true doGeneralUpdate = true
log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotarecord_new.Cpu, quotarecord_old.Cpu) log.Debugf("resourceResgroupUpdate: Cpu diff %d <- %d", quotarecordNew.Cpu, quotarecordOld.Cpu)
url_values.Add("maxCPUCapacity", fmt.Sprintf("%d", quotarecord_new.Cpu)) urlValues.Add("maxCPUCapacity", strconv.Itoa(quotarecordNew.Cpu))
} }
if quotarecord_new.Disk != quotarecord_old.Disk { if quotarecordNew.Disk != quotarecordOld.Disk {
do_general_update = true doGeneralUpdate = true
log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotarecord_new.Disk, quotarecord_old.Disk) log.Debugf("resourceResgroupUpdate: Disk diff %d <- %d", quotarecordNew.Disk, quotarecordOld.Disk)
url_values.Add("maxVDiskCapacity", fmt.Sprintf("%d", quotarecord_new.Disk)) urlValues.Add("maxVDiskCapacity", strconv.Itoa(quotarecordNew.Disk))
} }
if quotarecord_new.Ram != quotarecord_old.Ram { // NB: quota on RAM is stored as float32, in units of MB if quotarecordNew.Ram != quotarecordOld.Ram { // NB: quota on RAM is stored as float32, in units of MB
do_general_update = true doGeneralUpdate = true
log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotarecord_new.Ram, quotarecord_old.Ram) log.Debugf("resourceResgroupUpdate: Ram diff %f <- %f", quotarecordNew.Ram, quotarecordOld.Ram)
url_values.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotarecord_new.Ram)) urlValues.Add("maxMemoryCapacity", fmt.Sprintf("%f", quotarecordNew.Ram))
} }
if quotarecord_new.ExtTraffic != quotarecord_old.ExtTraffic { if quotarecordNew.ExtTraffic != quotarecordOld.ExtTraffic {
do_general_update = true doGeneralUpdate = true
log.Debugf("resourceResgroupUpdate: ExtTraffic diff %d <- %d", quotarecord_new.ExtTraffic, quotarecord_old.ExtTraffic) log.Debugf("resourceResgroupUpdate: ExtTraffic diff %d <- %d", quotarecordNew.ExtTraffic, quotarecordOld.ExtTraffic)
url_values.Add("maxNetworkPeerTransfer", fmt.Sprintf("%d", quotarecord_new.ExtTraffic)) urlValues.Add("maxNetworkPeerTransfer", strconv.Itoa(quotarecordNew.ExtTraffic))
} }
if quotarecord_new.ExtIPs != quotarecord_old.ExtIPs { if quotarecordNew.ExtIPs != quotarecordOld.ExtIPs {
do_general_update = true doGeneralUpdate = true
log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotarecord_new.ExtIPs, quotarecord_old.ExtIPs) log.Debugf("resourceResgroupUpdate: ExtIPs diff %d <- %d", quotarecordNew.ExtIPs, quotarecordOld.ExtIPs)
url_values.Add("maxNumPublicIP", fmt.Sprintf("%d", quotarecord_new.ExtIPs)) urlValues.Add("maxNumPublicIP", strconv.Itoa(quotarecordNew.ExtIPs))
} }
} else {
doGeneralUpdate = true
urlValues.Add("maxCPUCapacity", "-1")
urlValues.Add("maxVDiskCapacity", "-1")
urlValues.Add("maxMemoryCapacity", "-1")
urlValues.Add("maxNetworkPeerTransfer", "-1")
urlValues.Add("maxNumPublicIP", "-1")
} }
desc_new, desc_set := d.GetOk("description") descNew, descSet := d.GetOk("description")
if desc_set { if descSet {
log.Debugf("resourceResgroupUpdate: description specified - looking for deltas from the old settings.") log.Debugf("resourceResgroupUpdate: description specified - looking for deltas from the old settings.")
desc_old, _ := d.GetChange("description") descOld, _ := d.GetChange("description")
if desc_old.(string) != desc_new.(string) { if descOld.(string) != descNew.(string) {
do_general_update = true doGeneralUpdate = true
url_values.Add("desc", desc_new.(string)) urlValues.Add("desc", descNew.(string))
} }
} }
if do_general_update { if doGeneralUpdate {
log.Debugf("resourceResgroupUpdate: detected delta between new and old RG specs - updating the RG") log.Debugf("resourceResgroupUpdate: detected delta between new and old RG specs - updating the RG")
_, err := c.DecortAPICall(ctx, "POST", ResgroupUpdateAPI, url_values) _, err := c.DecortAPICall(ctx, "POST", ResgroupUpdateAPI, urlValues)
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }
@ -259,6 +469,94 @@ func resourceResgroupUpdate(ctx context.Context, d *schema.ResourceData, m inter
log.Debugf("resourceResgroupUpdate: no difference between old and new state - no update on the RG will be done") log.Debugf("resourceResgroupUpdate: no difference between old and new state - no update on the RG will be done")
} }
urlValues = &url.Values{}
enableOld, enableNew := d.GetChange("enable")
if enableOld.(bool) && !enableNew.(bool) {
urlValues.Add("rgId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", RgDisableAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
} else if !enableOld.(bool) && enableNew.(bool) {
urlValues.Add("rgId", d.Id())
_, err := c.DecortAPICall(ctx, "POST", RgEnableAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
}
urlValues = &url.Values{}
oldSet, newSet := d.GetChange("access")
deletedAccess := (oldSet.(*schema.Set).Difference(newSet.(*schema.Set))).List()
for _, deletedInterface := range deletedAccess {
deletedItem := deletedInterface.(map[string]interface{})
user := deletedItem["user"].(string)
urlValues.Add("rgId", d.Id())
urlValues.Add("user", user)
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
_, err := c.DecortAPICall(ctx, "POST", RgAccessRevokeAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
addedAccess := (newSet.(*schema.Set).Difference(oldSet.(*schema.Set))).List()
for _, addedInterface := range addedAccess {
addedItem := addedInterface.(map[string]interface{})
user := addedItem["user"].(string)
right := addedItem["right"].(string)
urlValues.Add("rgId", d.Id())
urlValues.Add("user", user)
urlValues.Add("right", right)
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
_, err := c.DecortAPICall(ctx, "POST", RgAccessGrantAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
urlValues = &url.Values{}
}
if ok := d.HasChange("def_net"); ok {
oldDefNet, newDefNet := d.GetChange("def_net")
if newDefNet.(*schema.Set).Len() > 0 {
changedDefNet := (newDefNet.(*schema.Set).Difference(oldDefNet.(*schema.Set))).List()
for _, changedDefNetInterface := range changedDefNet {
defNetItem := changedDefNetInterface.(map[string]interface{})
netType := defNetItem["net_type"].(string)
urlValues.Add("rgId", d.Id())
urlValues.Add("netType", netType)
if netID, ok := defNetItem["net_id"]; ok {
urlValues.Add("netId", strconv.Itoa(netID.(int)))
}
if reason, ok := defNetItem["reason"]; ok {
urlValues.Add("reason", reason.(string))
}
_, err := c.DecortAPICall(ctx, "POST", RgSetDefNetAPI, urlValues)
if err != nil {
return diag.FromErr(err)
}
}
}
}
return resourceResgroupRead(ctx, d, m) return resourceResgroupRead(ctx, d, m)
} }
@ -269,20 +567,20 @@ func resourceResgroupDelete(ctx context.Context, d *schema.ResourceData, m inter
d.Get("name").(string), d.Get("account_id").(int)) d.Get("name").(string), d.Get("account_id").(int))
c := m.(*controller.ControllerCfg) c := m.(*controller.ControllerCfg)
url_values := &url.Values{} urlValues := &url.Values{}
url_values.Add("rgId", d.Id()) urlValues.Add("rgId", d.Id())
if force, ok := d.GetOk("force"); ok { if force, ok := d.GetOk("force"); ok {
url_values.Add("force", strconv.FormatBool(force.(bool))) urlValues.Add("force", strconv.FormatBool(force.(bool)))
} }
if permanently, ok := d.GetOk("permanently"); ok { if permanently, ok := d.GetOk("permanently"); ok {
url_values.Add("permanently", strconv.FormatBool(permanently.(bool))) urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
} }
if reason, ok := d.GetOk("reason"); ok { if reason, ok := d.GetOk("reason"); ok {
url_values.Add("reason", reason.(string)) urlValues.Add("reason", reason.(string))
} }
_, err := c.DecortAPICall(ctx, "POST", ResgroupDeleteAPI, url_values) _, err := c.DecortAPICall(ctx, "POST", ResgroupDeleteAPI, urlValues)
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }
@ -315,7 +613,7 @@ func ResourceRgSchemaMake() map[string]*schema.Schema {
"def_net_type": { "def_net_type": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "PRIVATE", Computed: true,
ValidateFunc: validation.StringInSlice([]string{"PRIVATE", "PUBLIC", "NONE"}, false), ValidateFunc: validation.StringInSlice([]string{"PRIVATE", "PUBLIC", "NONE"}, false),
Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.", Description: "Type of the network, which this resource group will use as default for its computes - PRIVATE or PUBLIC or NONE.",
}, },
@ -348,7 +646,6 @@ func ResourceRgSchemaMake() map[string]*schema.Schema {
"quota": { "quota": {
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
Computed: true,
MaxItems: 1, MaxItems: 1,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(), Schema: quotaRgSubresourceSchemaMake(),
@ -356,9 +653,61 @@ func ResourceRgSchemaMake() map[string]*schema.Schema {
Description: "Quota settings for this resource group.", Description: "Quota settings for this resource group.",
}, },
"access": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"user": {
Type: schema.TypeString,
Required: true,
Description: "User or group name to grant access",
},
"right": {
Type: schema.TypeString,
Required: true,
Description: "Access rights to set, one of 'R', 'RCX' or 'ARCXDU'",
},
"reason": {
Type: schema.TypeString,
Optional: true,
Description: "Reason for action",
},
},
},
},
"def_net": {
Type: schema.TypeSet,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"net_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"PRIVATE", "PUBLIC"}, false),
Description: "Network type to set. Must be on of 'PRIVATE' or 'PUBLIC'.",
},
"net_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "Network segment ID. If netType is PUBLIC and netId is 0 then default external network segment will be selected. If netType is PRIVATE and netId=0, the first ViNS defined for this RG will be selected. Otherwise, netId identifies either existing external network segment or ViNS.",
},
"reason": {
Type: schema.TypeString,
Optional: true,
Description: "Reason for action",
},
},
},
},
"description": { "description": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "User-defined text description of this resource group.", Description: "User-defined text description of this resource group.",
}, },
"force": { "force": {
@ -378,140 +727,89 @@ func ResourceRgSchemaMake() map[string]*schema.Schema {
Optional: true, Optional: true,
Description: "Set to True if you want force delete non-empty RG", Description: "Set to True if you want force delete non-empty RG",
}, },
"register_computes": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Register computes in registration system",
},
"enable": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "flag for enable/disable RG",
},
"account_name": { "account_name": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Name of the account, which this resource group belongs to.", Description: "Name of the account, which this resource group belongs to.",
}, },
"resources": { "resources": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: resourcesSchemaMake(),
"current": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
Type: schema.TypeInt,
Computed: true,
},
"disksize": {
Type: schema.TypeInt,
Computed: true,
},
"extips": {
Type: schema.TypeInt,
Computed: true,
},
"exttraffic": {
Type: schema.TypeInt,
Computed: true,
}, },
"gpu": {
Type: schema.TypeInt,
Computed: true,
},
"ram": {
Type: schema.TypeInt,
Computed: true,
}, },
"seps": {
"acl": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: aclSchemaMake(),
"sep_id": {
Type: schema.TypeString,
Computed: true,
}, },
"data_name": {
Type: schema.TypeString,
Computed: true,
}, },
"disk_size": { "created_by": {
Type: schema.TypeFloat, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"disk_size_max": { "created_time": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
}, "deleted_by": {
}, Type: schema.TypeString,
},
},
},
},
"reserved": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"disksize": { "deleted_time": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"extips": { "dirty": {
Type: schema.TypeInt, Type: schema.TypeBool,
Computed: true, Computed: true,
}, },
"exttraffic": { "guid": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"gpu": { "lock_status": {
Type: schema.TypeInt, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"ram": { "milestones": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
"seps": { "secret": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"data_name": { "status": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Current status of this resource group.",
}, },
"disk_size": { "updated_by": {
Type: schema.TypeFloat, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"disk_size_max": { "updated_time": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
}, },
},
},
},
},
},
},
},
},
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Current status of this resource group.",
},
"vins": { "vins": {
Type: schema.TypeList, //this is a list of ints Type: schema.TypeList, //this is a list of ints
Computed: true, Computed: true,
@ -530,13 +828,19 @@ func ResourceRgSchemaMake() map[string]*schema.Schema {
Description: "List of computes deployed in this resource group.", Description: "List of computes deployed in this resource group.",
}, },
"computes": { "res_types": {
Type: schema.TypeList, //this is a list of ints Type: schema.TypeList,
Computed: true, Computed: true,
Elem: &schema.Schema{ Elem: &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeString,
},
},
"uniq_pools": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
}, },
Description: "List of computes deployed in this resource group.",
}, },
} }
} }
@ -563,5 +867,23 @@ func ResourceResgroup() *schema.Resource {
}, },
Schema: ResourceRgSchemaMake(), Schema: ResourceRgSchemaMake(),
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("def_net",
func(ctx context.Context, oldValue, newValue, meta interface{}) bool {
return true
},
func(ctx context.Context, d *schema.ResourceDiff, m interface{}) error {
oldValue, newValue := d.GetChange("def_net")
old := len(oldValue.(*schema.Set).List())
new_ := len(newValue.(*schema.Set).List())
if old == 1 && new_ == 0 {
return fmt.Errorf("CustomizeDiff: block def_net must not be empty")
}
return nil
},
),
),
} }
} }

@ -45,7 +45,7 @@ import (
// On success this function returns a string, as returned by API rg/get, which could be unmarshalled // On success this function returns a string, as returned by API rg/get, which could be unmarshalled
// into ResgroupGetResp structure // into ResgroupGetResp structure
func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ResgroupGetResp, error) { func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*RecordResourceGroup, error) {
// This function tries to locate resource group by one of the following algorithms depending // This function tries to locate resource group by one of the following algorithms depending
// on the parameters passed: // on the parameters passed:
// - if resource group ID is specified -> by RG ID // - if resource group ID is specified -> by RG ID
@ -71,8 +71,34 @@ func utilityResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m
} else { } else {
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int))) urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
} }
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
rgData := &RecordResourceGroup{}
rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(rgRaw), rgData)
if err != nil {
return nil, err
}
return rgData, nil
}
func utilityDataResgroupCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*RecordResourceGroup, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgData := &RecordResourceGroup{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
rgData := &ResgroupGetResp{}
rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues) rgRaw, err := c.DecortAPICall(ctx, "POST", ResgroupGetAPI, urlValues)
if err != nil { if err != nil {
return nil, err return nil, err

@ -0,0 +1,32 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgAffinityGroupComputesCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListAffinityGroupCompute, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listGroupComputes := ListAffinityGroupCompute{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
urlValues.Add("affinityGroup", d.Get("affinity_group").(string))
listGroupComputesRaw, err := c.DecortAPICall(ctx, "POST", RgAffinityGroupComputesAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listGroupComputesRaw), &listGroupComputes)
if err != nil {
return nil, err
}
return listGroupComputes, nil
}

@ -0,0 +1,33 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgAffinityGroupsGetCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) ([]uint64, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
computes := make([]uint64, 0)
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
urlValues.Add("affinityGroup", d.Get("affinity_group").(string))
computesRaw, err := c.DecortAPICall(ctx, "POST", RgAffinityGroupsGetAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(computesRaw), &computes)
if err != nil {
return nil, err
}
return computes, nil
}

@ -0,0 +1,32 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgAffinityGroupsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (map[string][]uint64, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
groups := make(map[string][]uint64, 0)
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
groupsRaw, err := c.DecortAPICall(ctx, "POST", RgAffinityGroupsListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(groupsRaw), &groups)
if err != nil {
return nil, err
}
return groups, nil
}

@ -0,0 +1,30 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgAuditsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListAudits, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgAudits := ListAudits{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
rgAuditsRow, err := c.DecortAPICall(ctx, "POST", RgAuditsAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(rgAuditsRow), &rgAudits)
if err != nil {
return nil, err
}
return rgAudits, nil
}

@ -44,11 +44,11 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "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{}) (ListResourceGroups, error) {
c := m.(*controller.ControllerCfg) c := m.(*controller.ControllerCfg)
urlValues := &url.Values{} urlValues := &url.Values{}
rgList := ResgroupListResp{} rgList := ListResourceGroups{}
if size, ok := d.GetOk("size"); ok { if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int))) urlValues.Add("size", strconv.Itoa(size.(int)))

@ -0,0 +1,35 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgListComputesCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListComputes, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listComputes := ListComputes{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
listComputesRaw, err := c.DecortAPICall(ctx, "POST", RgListComputesAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listComputesRaw), &listComputes)
if err != nil {
return nil, err
}
return listComputes, nil
}

@ -0,0 +1,37 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgListDeletedCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListResourceGroups, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
rgList := ListResourceGroups{}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
}
rgListRaw, err := c.DecortAPICall(ctx, "POST", ResgroupListDeletedAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(rgListRaw), &rgList)
if err != nil {
return nil, err
}
return rgList, nil
}

@ -0,0 +1,32 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgListLbCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListLB, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listLb := ListLB{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
listLbRaw, err := c.DecortAPICall(ctx, "POST", ResgroupListLbAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listLbRaw), &listLb)
if err != nil {
return nil, err
}
return listLb, nil
}

@ -0,0 +1,32 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgListPfwCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListPFW, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listPfw := ListPFW{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
listPfwRaw, err := c.DecortAPICall(ctx, "POST", ResgroupListPfwAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listPfwRaw), &listPfw)
if err != nil {
return nil, err
}
return listPfw, nil
}

@ -0,0 +1,36 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityRgListVinsCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ListVINS, error) {
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
listVins := ListVINS{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
if val, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", val.(string))
}
listVinsRaw, err := c.DecortAPICall(ctx, "POST", ResgroupListVinsAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(listVinsRaw), &listVins)
if err != nil {
return nil, err
}
return listVins, nil
}

@ -0,0 +1,35 @@
package rg
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/controller"
)
func utilityDataRgUsageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Resource, error) {
c := m.(*controller.ControllerCfg)
urlValues := url.Values{}
usage := Resource{}
urlValues.Add("rgId", strconv.Itoa(d.Get("rg_id").(int)))
if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
}
usageRaw, err := c.DecortAPICall(ctx, "POST", ResgroupUsageAPI, &urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(usageRaw), &usage)
if err != nil {
return nil, err
}
return &usage, nil
}

@ -450,7 +450,6 @@ func resourceVinsDelete(ctx context.Context, d *schema.ResourceData, m interface
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }
return nil return nil
} }

@ -26,27 +26,12 @@ provider "decort" {
} }
data "decort_kvmvm" "comp" { data "decort_kvmvm" "comp" {
#Для получения информации о виртуальной машине #получение информации по идентификатору машины - compute_id
#можно воспользоваться двумя методами:
#1. получение информации по идентификатору машины - compute_id
#2. получение информации по имени машины и идентификатору ресурсной группы - name и rg_id
#id виртуальной машины #id виртуальной машины
#опциональный параметр #обязательный параметр
#тип - число #тип - число
#compute_id = 11346 #compute_id = 11346
#название машины
#опциональный параметр
#тип - строка
#используется вместе с параметром rg_id
#name = "test-rg-temp"
#id ресурсной группы
#опциональный параметр
#тип - число
#используется вместе с параметром name
#rg_id = 1825
} }
output "test" { output "test" {

@ -0,0 +1,36 @@
/*
Пример использования
Получение данных об аудитах compute (виртулаьной машине)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_audits" "kvmvm_audits" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10154
}
output "output" {
value = data.decort_kvmvm_audits.kvmvm_audits
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение данных об аудитах compute (виртулаьной машине)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_get_audits" "kvmvm_get_audits" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10154
}
output "output" {
value = data.decort_kvmvm_get_audits.kvmvm_get_audits
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение url compute (виртулаьной машины)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_get_console_url" "kvmvm_get_console_url" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10154
}
output "output" {
value = data.decort_kvmvm_get_console_url.kvmvm_get_console_url
}

@ -0,0 +1,41 @@
/*
Пример использования
Получение логов compute (виртулаьной машины)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_get_log" "kvmvm_get_log" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10154
#путь до log файла
#обязательный параметр
#тип - строка
path = "/var/log/file.log"
}
output "output" {
value = data.decort_kvmvm_get_log.kvmvm_get_log
}

@ -0,0 +1,50 @@
/*
Пример использования
Получение данных об списке compute (виртулаьных машин)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_list" "compute_list" {
#флаг влючения в результат удаленных балансироващиков нагрузки
#опциональный параметр
#тип - булев тип
#значение по-умолчанию - false
#если не задан - выводятся все доступные неудаленные балансировщики
includedeleted = true
#номер страницы для отображения
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
page = 1
#размер страницы
#опциональный параметр
#тип - число
#если не задан - выводятся все доступные данные
size = 1
}
output "output" {
value = data.decort_kvmvm_list.compute_list
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение данных об списке port forwarding compute (виртулаьных машин)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_pfw_list" "kvmvm_pfw_list" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10524
}
output "output" {
value = data.decort_kvmvm_pfw_list.kvmvm_pfw_list
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение данных об юзерах compute (виртулаьной машины)
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_kvmvm_user_list" "kvmvm_user_list" {
#id виртуальной машины
#обязательный параметр
#тип - число
compute_id = 10154
}
output "output" {
value = data.decort_kvmvm_user_list.kvmvm_user_list
}

@ -0,0 +1,42 @@
/*
Пример использования
Получение информации о ресурсной группе RG
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_resgroup" "rg" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 1535
#причина для выполняния действия
#необязятельный параметр
#тип - строка
reason = "TEST"
}
output "output" {
value = data.decort_resgroup.rg
}

@ -0,0 +1,40 @@
/*
Пример использования
Получение информации о специальной группе компьютов
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_affinity_group_computes" "lc" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
#название специальной группы компьютов
#обязательное поле
#тип - строка
affinity_group = "TEST"
}
output "output" {
value = data.decort_rg_affinity_group_computes.lc
}

@ -0,0 +1,41 @@
/*
Пример использования
Получение информации о списке компьютов из определенной группы
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_affinity_groups_get" "get_groups" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
#название специальной группы компьютов
#обязательное поле
#тип - строка
affinity_group = "TEST"
}
output "output" {
value = data.decort_rg_affinity_groups_get.get_groups
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение информации о списке специальных групп компьютов
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_affinity_groups_list" "list_groups" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
}
output "output" {
value = data.decort_rg_affinity_groups_list.list_groups
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение информации о списке аудитов ресурсной группы
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_audits" "rg_audits" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
}
output "output" {
value = data.decort_rg_audits.rg_audits
}

@ -1,21 +1,20 @@
/* /*
Пример использования Пример использования
Получение списка всех resource groups Получение информации о списке всех ресурсных группах к которым есть доступ
*/ */
#Расскомментируйте этот код, #Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь, #и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером #чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform { /* terraform {
required_providers { required_providers {
decort = { decort = {
version = "1.1" version = "1.1"
source = "digitalenergy.online/decort/decort" source = "digitalenergy.online/decort/decort"
} }
} }
} } */
*/
provider "decort" { provider "decort" {
authenticator = "oauth2" authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL> #controller_url = <DECORT_CONTROLLER_URL>
@ -25,25 +24,23 @@ provider "decort" {
allow_unverified_ssl = true allow_unverified_ssl = true
} }
data "decort_rg_list" "rl" { data "decort_rg_list" "rg_list" {
#включение удаленных rg в результат поиска #отображать удаленные ресурсные группы или нет
#опциональный параметр #необязательный параметр
#тип - булев тип #тип - булевый
#по-умолчанию - false includedeleted = false
#includedeleted = true
#номер страницы для отображения #номер страницы
#опциональный параметр, тип - число #необязательный параметр
#если не задан - выводятся все доступные данные #тип - число
#page = 2 page = 1
#размер страницы #размер страницы
#опциональный параметр, тип - число #необязательный параметр
#если не задан - выводятся все доступные данные #тип - число
#size = 3 size = 2
} }
output "test" { output "output" {
value = data.decort_rg_list.rl value = data.decort_rg_list.rg_list
} }

@ -0,0 +1,40 @@
/*
Пример использования
Получение информации о списке компьютов в ресурсной группе
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_list_computes" "list_computes" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
#причина для действия
#необязательный параметр
#тип - строка
reason = "TEST"
}
output "output" {
value = data.decort_rg_list_computes.list_computes
}

@ -0,0 +1,41 @@
/*
Пример использования
Получение информации о списке удаленных ресурсных групп
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_list_deleted" "list_deleted" {
#номер страницы
#необязательный параметр
#тип - число
page = 1
#размер страницы
#необязательный параметр
#тип - число
size = 2
}
output "output" {
value = data.decort_rg_list_deleted.list_deleted
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение информации о списке балансировщиков в ресурсной группе
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_list_lb" "list_lb" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
}
output "output" {
value = data.decort_rg_list_lb.list_lb
}

@ -0,0 +1,36 @@
/*
Пример использования
Получение информации о списке правил переадресации портов для ресурсной группы.
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_list_pfw" "list_pfw" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
}
output "output" {
value = data.decort_rg_list_pfw.list_pfw
}

@ -0,0 +1,40 @@
/*
Пример использования
Получение информации о списке винсов в ресурсной группе
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_list_vins" "list_vins" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
#причина для действия
#необязательный параметр
#тип - строка
reason = "TEST"
}
output "output" {
value = data.decort_rg_list_vins.list_vins
}

@ -0,0 +1,40 @@
/*
Пример использования
Получение информации об использовании ресурсов на ресурсной группе
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/* terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
} */
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
data "decort_rg_usage" "rg_usage" {
#id ресурсной группы
#обязательный параметр
#тип - число
rg_id = 123
#причина для действия
#необязательный параметр
#тип - строка
reason = "TEST"
}
output "output" {
value = data.decort_rg_usage.rg_usage
}

@ -67,6 +67,16 @@ resource "decort_kvmvm" "comp" {
#тип - число #тип - число
boot_disk_size = 20 boot_disk_size = 20
#ID сепа для boot диска
#опциональный параметр
#тип - число
sep_id = 1
#Название пула
#опциональный параметр
#тип - строка
pool = "data02"
#описание compute #описание compute
#опциональный параметр #опциональный параметр
#тип - строка #тип - строка
@ -114,84 +124,80 @@ resource "decort_kvmvm" "comp" {
#опциональный параметр #опциональный параметр
#тип - bool #тип - bool
permanently = false permanently = false
}
#правила affinity #правила affinity
#опциональный параметр #опциональный параметр
#может быть один, несколько или ни одного блока #может быть один, несколько или ни одного блока
#тип - блок #тип - блок
#affinity_rules { affinity_rules {
#тип правила #тип правила
#возможные значения - compute или node #возможные значения - compute или node
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#topology = "compute" topology = "compute"
#строгость правила #строгость правила
#возможные значения - RECOMMENDED и REQUIRED #возможные значения - RECOMMENDED и REQUIRED
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#policy = "RECOMMENDED" policy = "RECOMMENDED"
#режим проверки #режим проверки
#возможные значения - ANY, EQ, NE #возможные значения - ANY, EQ, NE
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#mode = "ANY" mode = "ANY"
#ключ правила #ключ правила
#обязательный параметр #обязательный параметр
#тип строка #тип строка
#key = "testkey" key = "testkey"
#ключ правила #ключ правила
#обязательный параметр #обязательный параметр
#тип строка #тип строка
#value = "testvalue" value = "testvalue"
#} }
#правила anti-affinity #правила anti-affinity
#опциональный параметр #опциональный параметр
#может быть один, несколько или ни одного блока #может быть один, несколько или ни одного блока
#тип - блок #тип - блок
#anti_affinity_rules { anti_affinity_rules {
#тип правила #тип правила
#возможные значения - compute или node #возможные значения - compute или node
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#topology = "compute" topology = "compute"
#строгость правила #строгость правила
#возможные значения - RECOMMENDED и REQUIRED #возможные значения - RECOMMENDED и REQUIRED
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#policy = "RECOMMENDED" policy = "RECOMMENDED"
#режим проверки #режим проверки
#возможные значения - ANY, EQ, NE #возможные значения - ANY, EQ, NE
#обязательный параметр #обязательный параметр
#тип - строка #тип - строка
#mode = "ANY" mode = "ANY"
#ключ правила #ключ правила
#обязательный параметр #обязательный параметр
#тип строка #тип строка
#key = "testkey" key = "testkey"
#ключ правила #ключ правила
#обязательный параметр #обязательный параметр
#тип строка #тип строка
#value = "testvalue" value = "testvalue"
#} }
#Флаг доступности компьюта для проведения с ним операций
#опицональный параметр
#тип - bool
#enable = true
#установка метки для вм #установка метки для вм
#опциональный параметр #опциональный параметр
#тип - строка #тип - строка
#affinity_label = "test4" affinity_label = "test4"
#наименование системы #наименование системы
@ -199,17 +205,182 @@ resource "decort_kvmvm" "comp" {
#используется при создании вм #используется при создании вм
#по умолчанию - не задан #по умолчанию - не задан
#тип - строка #тип - строка
#is="" is=""
#назначение вм #назначение вм
#опциональный параметр #опциональный параметр
#используется при создании вм #используется при создании вм
#по умолчанию - не задан #по умолчанию - не задан
#тип - строка #тип - строка
#ipa_type = "" ipa_type = ""
#Id экстра дисков
#опциональный параметр
#тип - список чисел
extra_disks = [1234, 4322, 1344]
#Присоеденения сетей и удаление сетей в компьюте
#опциональный параметр
#тип - блок
network {
#Тип сети VINS/EXTNET
#Обязательный параметр
#тип - строка
net_type = "VINS"
#ID сети
#Обязательный параметр
#тип - число
net_id = 1234
#IP адрес входящий в сеть
#опциональный параметр
#тип - строка
ip_address = "127.0.0.1"
}
#добавление и удаление тэгов
#опциональный параметр
#тип - блок
tags {
#Ключ для тэга
#Обязательный параметр
#тип - строка
key = "key"
#Значения тэга
#Обязательный параметр
#тип - строка
value = "value"
} }
#добавление и удаление port forwarding
#опциональный параметр
#тип - блок
port_forwarding {
#номер внешнего начального порта для правила
#Обязательный параметр
#тип - число
public_port_start = 2023
#номер внешнего последнего порта для правила
#опциональный параметр
#тип - число
#по умолчанию - -1
public_port_end = 2023
#номер внутреннего базового порта
#Обязательный параметр
#тип - число
local_port = 80
#сетевой протокол
#Обязательный параметр
#тип - строка
proto = "tcp"
}
#предоставить/забрать пользователю доступ к компьюту
#опциональный параметр
#тип - блок
user_access {
#Имя юзера, которому предоставляем доступ
#Обязательный параметр
#тип - строка
username = "kasim_baybikov_1@decs3o"
#Права: 'R' - только на чтение, 'RCX' - чтение/запись, 'ARCXDU' - админ
#Обязательный параметр
#тип - строка
access_type = "ARCXDU"
}
#Создать/удалить снапшот компьюта
#опциональный параметр
#тип - блок
snapshot {
#Лейбл снапшота
#Обязательный параметр
#тип - строка
label = "label1"
}
#Rollback на нужный снапшот
#опциональный параметр
#Не имеет смысла при отсутсвии снапшотов
#тип - блок
rollback {
#Лейбл снапшота
#Обязательный параметр
#тип - строка
label = "label1"
}
#Вставить/удалить СD rom
#опциональный параметр
#Максимальное кол-во - 1
#тип - блок
cd {
#ID образа диска CD rom
#Обязательный параметр
#тип - число
cdrom_id = 344
}
#Добавить компьют на стэк
#опциональный параметр
#тип - булев
pin_to_stack = true
#Применяется только при создании нового экземпляра compute, игнорируется во всех остальных случаях
#опциональный параметр
#тип - строка
cloud_init = ""
#Флаг доступности компьюта для проведения с ним операций
#опциональный параметр
#тип - булев
enabled = true
#pause/resume компьюта
#опциональный параметр
#тип - булев
pause = true
#сделать компьют заново
#опциональный параметр
#тип - булев
reset = true
#флаг для редеплоя компьюта
#опциональный параметр
#тип - булев
auto_start = true
#флаг для редеплоя компьюта
#опциональный параметр
#тип - булев
force_stop = true
#поле для редеплоя компьюта
#опциональный параметр
#тип - строка
data_disks = "KEEP"
#запуск/стоп компьюта
#опциональный параметр
#тип - булев
started = true
#detach диска при удалении компьюта
#опциональный параметр
#тип - булев
detach_disks = true
#Флаг для удаления компьюта
#опциональный параметр
#тип - bool
permanently = false
} }
output "test" { output "test" {

@ -0,0 +1,170 @@
/*
Пример использования
Ресурсов RG
Ресурс позволяет:
1. Создавать
2. Редактировать
3. Удалять
*/
#Расскомментируйте этот код,
#и внесите необходимые правки в версию и путь,
#чтобы работать с установленным вручную (не через hashicorp provider registry) провайдером
/*
terraform {
required_providers {
decort = {
version = "1.1"
source = "digitalenergy.online/decort/decort"
}
}
}
*/
provider "decort" {
authenticator = "oauth2"
#controller_url = <DECORT_CONTROLLER_URL>
controller_url = "https://ds1.digitalenergy.online"
#oauth2_url = <DECORT_SSO_URL>
oauth2_url = "https://sso.digitalenergy.online"
allow_unverified_ssl = true
}
resource "decort_resgroup" "rg" {
#имя ресурсной группы
#обязательный параметр
#тип - строка
name = "testing_rg_1"
#id аккаунта которому будет принадлежать ресурсная группа
#обязательный параметр
#тип - число
account_id = 123
#id сети
#обязательный параметр
#тип - число
gid = 1234
#тип сети по умолчанию для этой ресурсной группы.
#виртуальные машины, созданные в этой RG, по умолчанию будут подключены к этой сети.
#Допустимые значения: PRIVATE, PUBLIC, NONE.
#необязательный параметр
#тип - строка
def_net_type = "NONE"
#ip cidr частной сети, если сеть по умолчанию PRIVATE
#необязательный параметр
#тип - строка
ipcidr = "1.1.1.1"
#id внешней сети
#необязательный параметр
#тип - число
ext_net_id = 123
#ip внешней сети
#необязательный параметр
#тип - строка
ext_ip = "1.1.1.1"
#причина выполнения
#необязательный параметр
#тип - строка
reason = "TEST"
#описание
#необязательный параметр
#тип - строка
description = "qwerty"
#флаг доступности ресурсной группы
#необязательный параметр
#тип - булевый
enable = true
#блок для предоставления прав на ресурсную группу
#необязательный параметр
#тип - блок
access {
#имя юзера предоставляемому права
#обязательный праметр при использовании блока
#тип - строка
user = "kasim_baybikov_1@decs3o"
#тип прав
#необязательный параметр
#тип - строка
right = "RCX"
}
#Установить сеть по умолчанию
#необязательный параметр
#тип - блок
#при добавлении блока, удалять его нельзя
def_net {
#тип сети
#обязательный параметр при использовании блока
#тип - строка
net_type = "PUBLIC"
#id сети
#идентификатор сегмента сети. Если net_type PUBLIC, а net_id 0,
#то будет выбран сегмент внешней сети по умолчанию. Если net_type
#имеет значение PRIVATE и net_id=0, будет выбран первый vins, определенный для этой ресурсной группы.
#В противном случае net_id идентифицирует либо существующий сегмент внешней сети, либо vins.
#необязательный параметр
#тип - число
net_id = 1234
#причина выполнения
#необязательный параметр
#тип - строка
reason = "TEST"
}
#лимиты ресурсов для ресурсной группы
#необязательный параметр
#тип - блок
quota {
#максимальное количество ядер процессора
#необязательный параметр
#тип - число
#значение по умолчанию: -1
cpu = 5
#максимальный размер памяти в мегабайтах
#необязательный параметр
#тип - число
#значение по умолчанию: -1
ram = 1024
#максимальный размер объединенных виртуальных дисков в ГБ
#необязательный параметр
#тип - число
#значение по умолчанию: -1
disk = 180
#максимальное количество отправленных/полученных сетевых узлов
#необязательный параметр
#тип - число
#значение по умолчанию: -1
ext_traffic = 21
#максимальное количество назначенных общедоступных IP-адресов
#необязательный параметр
#тип - число
#значение по умолчанию: -1
ext_ips = 29
}
#флаг для принудительного удаления ресурсной группы
#необязательный параметр
#тип - булевый
force = true
#флаг для моментального удаления ресурсной группы
#необязательный параметр
#тип - булевый
permanently = true
}
output "output" {
value = decort_resgroup.rg
}
Loading…
Cancel
Save