Add files
This commit is contained in:
@@ -73,51 +73,6 @@ func flattenRgAcl(rgAcls []AccountAclRecord) []map[string]interface{} {
|
||||
return res
|
||||
}
|
||||
|
||||
/*uncomment for cloudbroker
|
||||
func flattenAccountList(al AccountList) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0)
|
||||
for _, acc := range al {
|
||||
temp := map[string]interface{}{
|
||||
"dc_location": acc.DCLocation,
|
||||
"ckey": acc.CKey,
|
||||
"meta": flattenMeta(acc.Meta),
|
||||
|
||||
"acl": flattenRgAcl(acc.Acl),
|
||||
|
||||
"company": acc.Company,
|
||||
"companyurl": acc.CompanyUrl,
|
||||
"created_by": acc.CreatedBy,
|
||||
|
||||
"created_time": acc.CreatedTime,
|
||||
|
||||
"deactivation_time": acc.DeactiovationTime,
|
||||
"deleted_by": acc.DeletedBy,
|
||||
|
||||
"deleted_time": acc.DeletedTime,
|
||||
|
||||
"displayname": acc.DisplayName,
|
||||
"guid": acc.GUID,
|
||||
|
||||
"account_id": acc.ID,
|
||||
"account_name": acc.Name,
|
||||
|
||||
"resource_limits": flattenRgResourceLimits(acc.ResourceLimits),
|
||||
"send_access_emails": acc.SendAccessEmails,
|
||||
"service_account": acc.ServiceAccount,
|
||||
|
||||
"status": acc.Status,
|
||||
"updated_time": acc.UpdatedTime,
|
||||
|
||||
"version": acc.Version,
|
||||
"vins": acc.Vins,
|
||||
|
||||
}
|
||||
res = append(res, temp)
|
||||
}
|
||||
return res
|
||||
}
|
||||
*/
|
||||
|
||||
func dataSourceAccountListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
accountList, err := utilityAccountListCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
@@ -148,22 +103,6 @@ func dataSourceAccountListSchemaMake() map[string]*schema.Schema {
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
/*uncomment for cloudbroker
|
||||
"dc_location": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"ckey": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"meta": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},*/
|
||||
"acl": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
@@ -196,48 +135,14 @@ func dataSourceAccountListSchemaMake() map[string]*schema.Schema {
|
||||
},
|
||||
},
|
||||
},
|
||||
/*uncomment for cloudbroker
|
||||
"company": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"companyurl": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"created_by": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
*/
|
||||
"created_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
/*uncomment for cloudbroker
|
||||
"deactivation_time": {
|
||||
Type: schema.TypeFloat,
|
||||
Computed: true,
|
||||
},
|
||||
"deleted_by": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
*/
|
||||
"deleted_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
/*uncomment for cloudbroker
|
||||
"displayname": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"guid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
*/
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
@@ -246,49 +151,6 @@ func dataSourceAccountListSchemaMake() map[string]*schema.Schema {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
/*uncomment for cloudbroker
|
||||
"resource_limits": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"send_access_emails": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"service_account": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
*/
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
@@ -297,19 +159,6 @@ func dataSourceAccountListSchemaMake() map[string]*schema.Schema {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
/*uncomment for cloudbroker
|
||||
"version": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"vins": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
},
|
||||
},
|
||||
*/
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -37,7 +37,6 @@ import (
|
||||
"strconv"
|
||||
"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"
|
||||
@@ -49,22 +48,6 @@ import (
|
||||
func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceAccountCreate")
|
||||
|
||||
if accountId, ok := d.GetOk("account_id"); ok {
|
||||
if exists, err := resourceAccountExists(ctx, d, m); exists {
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
d.SetId(strconv.Itoa(accountId.(int)))
|
||||
diagnostics := resourceAccountRead(ctx, d, m)
|
||||
if diagnostics != nil {
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("provided account id does not exist")
|
||||
}
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
@@ -138,7 +121,6 @@ func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interf
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
d.SetId(accountId)
|
||||
d.Set("account_id", accountId)
|
||||
|
||||
@@ -147,7 +129,42 @@ func resourceAccountCreate(ctx context.Context, d *schema.ResourceData, m interf
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
d.SetId(id.String())
|
||||
urlValues = &url.Values{}
|
||||
|
||||
if enable, ok := d.GetOk("enable"); ok {
|
||||
api := accountDisableAPI
|
||||
enable := enable.(bool)
|
||||
if enable {
|
||||
api = accountEnableAPI
|
||||
}
|
||||
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
|
||||
|
||||
_, err := c.DecortAPICall(ctx, "POST", api, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
|
||||
if users, ok := d.GetOk("users"); ok {
|
||||
addedUsers := users.([]interface{})
|
||||
|
||||
if len(addedUsers) > 0 {
|
||||
for _, user := range addedUsers {
|
||||
userConv := user.(map[string]interface{})
|
||||
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
|
||||
urlValues.Add("userId", userConv["user_id"].(string))
|
||||
urlValues.Add("accesstype", strings.ToUpper(userConv["access_type"].(string)))
|
||||
_, err := c.DecortAPICall(ctx, "POST", accountAddUserAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"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"
|
||||
@@ -47,24 +46,6 @@ import (
|
||||
func resourceBasicServiceCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceBasicServiceCreate")
|
||||
|
||||
if serviceId, ok := d.GetOk("service_id"); ok {
|
||||
if exists, err := resourceBasicServiceExists(ctx, d, m); exists {
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
id := uuid.New()
|
||||
d.SetId(strconv.Itoa(serviceId.(int)))
|
||||
d.Set("service_id", strconv.Itoa(serviceId.(int)))
|
||||
diagnostics := resourceBasicServiceRead(ctx, d, m)
|
||||
if diagnostics != nil {
|
||||
return diagnostics
|
||||
}
|
||||
d.SetId(id.String())
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("provided service id does not exist")
|
||||
}
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
@@ -83,7 +64,6 @@ func resourceBasicServiceCreate(ctx context.Context, d *schema.ResourceData, m i
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
d.SetId(serviceId)
|
||||
d.Set("service_id", serviceId)
|
||||
|
||||
@@ -92,8 +72,6 @@ func resourceBasicServiceCreate(ctx context.Context, d *schema.ResourceData, m i
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
d.SetId(id.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
@@ -49,26 +48,6 @@ import (
|
||||
func resourceBasicServiceGroupCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceBasicServiceGroupCreate")
|
||||
|
||||
if compgroupId, ok := d.GetOk("compgroup_id"); ok {
|
||||
if _, ok := d.GetOk("service_id"); ok {
|
||||
if exists, err := resourceBasicServiceGroupExists(ctx, d, m); exists {
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
id := uuid.New()
|
||||
d.SetId(strconv.Itoa(compgroupId.(int)))
|
||||
d.Set("compgroup_id", strconv.Itoa(compgroupId.(int)))
|
||||
diagnostics := resourceBasicServiceGroupRead(ctx, d, m)
|
||||
if diagnostics != nil {
|
||||
return diagnostics
|
||||
}
|
||||
d.SetId(id.String())
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("provided compgroup id does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
@@ -124,7 +103,6 @@ func resourceBasicServiceGroupCreate(ctx context.Context, d *schema.ResourceData
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
d.SetId(compgroupId)
|
||||
d.Set("compgroup_id", compgroupId)
|
||||
|
||||
@@ -133,8 +111,6 @@ func resourceBasicServiceGroupCreate(ctx context.Context, d *schema.ResourceData
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
d.SetId(id.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,11 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
|
||||
package disks
|
||||
|
||||
const DisksCreateAPI = "/restmachine/cloudapi/disks/create"
|
||||
const DisksGetAPI = "/restmachine/cloudapi/disks/get" // Returns single DiskRecord on success
|
||||
const DisksListAPI = "/restmachine/cloudapi/disks/list" // Returns list of DiskRecord on success
|
||||
const DisksResizeAPI = "/restmachine/cloudapi/disks/resize2"
|
||||
const DisksRenameAPI = "/restmachine/cloudapi/disks/rename"
|
||||
const DisksDeleteAPI = "/restmachine/cloudapi/disks/delete"
|
||||
const disksCreateAPI = "/restmachine/cloudapi/disks/create"
|
||||
const disksGetAPI = "/restmachine/cloudapi/disks/get"
|
||||
const disksListAPI = "/restmachine/cloudapi/disks/list"
|
||||
const disksResizeAPI = "/restmachine/cloudapi/disks/resize2"
|
||||
const disksRenameAPI = "/restmachine/cloudapi/disks/rename"
|
||||
const disksDeleteAPI = "/restmachine/cloudapi/disks/delete"
|
||||
const disksIOLimitAPI = "/restmachine/cloudapi/disks/limitIO"
|
||||
const disksRestoreAPI = "/restmachine/cloudapi/disks/restore"
|
||||
|
||||
@@ -34,162 +34,340 @@ package disks
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
// "net/url"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/constants"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func flattenDisk(d *schema.ResourceData, disk_facts string) error {
|
||||
// This function expects disk_facts string to contain a response from disks/get API
|
||||
//
|
||||
// NOTE: this function modifies ResourceData argument - as such it should never be called
|
||||
// from resourceDiskExists(...) method. Use utilityDiskCheckPresence instead.
|
||||
|
||||
log.Debugf("flattenDisk: ready to unmarshal string %s", disk_facts)
|
||||
|
||||
model := DiskRecord{}
|
||||
|
||||
err := json.Unmarshal([]byte(disk_facts), &model)
|
||||
func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
disk, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
return err
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
log.Debugf("flattenDisk: disk ID %d, disk AccountID %d", model.ID, model.AccountID)
|
||||
id := uuid.New()
|
||||
d.SetId(id.String())
|
||||
|
||||
d.SetId(fmt.Sprintf("%d", model.ID))
|
||||
// d.Set("disk_id", model.ID) - we should NOT update disk_id in the schema. If it was set - it is already set, if it wasn't - we shouldn't
|
||||
d.Set("name", model.Name)
|
||||
d.Set("account_id", model.AccountID)
|
||||
d.Set("account_name", model.AccountName)
|
||||
d.Set("size", model.SizeMax)
|
||||
// d.Set("sizeUsed", model.SizeUsed)
|
||||
d.Set("type", model.Type)
|
||||
d.Set("image_id", model.ImageID)
|
||||
d.Set("sep_id", model.SepID)
|
||||
d.Set("sep_type", model.SepType)
|
||||
d.Set("pool", model.Pool)
|
||||
// d.Set("compute_id", model.ComputeID)
|
||||
diskAcl, _ := json.Marshal(disk.Acl)
|
||||
|
||||
d.Set("description", model.Desc)
|
||||
d.Set("account_id", disk.AccountID)
|
||||
d.Set("account_name", disk.AccountName)
|
||||
d.Set("acl", string(diskAcl))
|
||||
d.Set("boot_partition", disk.BootPartition)
|
||||
d.Set("compute_id", disk.ComputeID)
|
||||
d.Set("compute_name", disk.ComputeName)
|
||||
d.Set("created_time", disk.CreatedTime)
|
||||
d.Set("deleted_time", disk.DeletedTime)
|
||||
d.Set("desc", disk.Desc)
|
||||
d.Set("destruction_time", disk.DestructionTime)
|
||||
d.Set("devicename", disk.DeviceName)
|
||||
d.Set("disk_path", disk.DiskPath)
|
||||
d.Set("gid", disk.GridID)
|
||||
d.Set("guid", disk.GUID)
|
||||
d.Set("disk_id", disk.ID)
|
||||
d.Set("image_id", disk.ImageID)
|
||||
d.Set("images", disk.Images)
|
||||
d.Set("iotune", flattenIOTune(disk.IOTune))
|
||||
d.Set("iqn", disk.IQN)
|
||||
d.Set("login", disk.Login)
|
||||
d.Set("milestones", disk.Milestones)
|
||||
d.Set("disk_name", disk.Name)
|
||||
d.Set("order", disk.Order)
|
||||
d.Set("params", disk.Params)
|
||||
d.Set("parent_id", disk.ParentId)
|
||||
d.Set("passwd", disk.Passwd)
|
||||
d.Set("pci_slot", disk.PciSlot)
|
||||
d.Set("pool", disk.Pool)
|
||||
d.Set("purge_attempts", disk.PurgeAttempts)
|
||||
d.Set("purge_time", disk.PurgeTime)
|
||||
d.Set("reality_device_number", disk.RealityDeviceNumber)
|
||||
d.Set("reference_id", disk.ReferenceId)
|
||||
d.Set("res_id", disk.ResID)
|
||||
d.Set("res_name", disk.ResName)
|
||||
d.Set("role", disk.Role)
|
||||
d.Set("sep_id", disk.SepID)
|
||||
d.Set("sep_type", disk.SepType)
|
||||
d.Set("size_max", disk.SizeMax)
|
||||
d.Set("size_used", disk.SizeUsed)
|
||||
d.Set("snapshots", flattendDiskSnapshotList(disk.Snapshots))
|
||||
d.Set("status", disk.Status)
|
||||
d.Set("tech_status", disk.TechStatus)
|
||||
d.Set("type", disk.Type)
|
||||
d.Set("vmid", disk.VMID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dataSourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
disk_facts, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if disk_facts == "" {
|
||||
// if empty string is returned from utilityDiskCheckPresence then there is no
|
||||
// such Disk and err tells so - just return it to the calling party
|
||||
d.SetId("") // ensure ID is empty
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return diag.FromErr(flattenDisk(d, disk_facts))
|
||||
}
|
||||
|
||||
func dataSourceDiskSchemaMake() map[string]*schema.Schema {
|
||||
rets := map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Name of this disk. NOTE: disk names are NOT unique within an account. If disk ID is specified, disk name is ignored.",
|
||||
},
|
||||
|
||||
"disk_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "ID of the disk to get. If disk ID is specified, then disk name and account ID are ignored.",
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "ID of the account this disk belongs to. If disk ID is specified, then account ID is ignored.",
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
// The rest of the data source Disk schema are all computed
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Storage end-point provider serving this disk.",
|
||||
},
|
||||
|
||||
"pool": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Pool where this disk is located.",
|
||||
},
|
||||
|
||||
"size": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Size of the disk in GB.",
|
||||
},
|
||||
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Type of this disk. E.g. D for data disks, B for boot.",
|
||||
},
|
||||
|
||||
"description": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "User-defined text description of this disk.",
|
||||
},
|
||||
|
||||
"account_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Name of the account this disk belongs to. If account ID is specified, account name is ignored.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"acl": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"boot_partition": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"compute_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"compute_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"created_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"deleted_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"desc": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"destruction_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"devicename": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"disk_path": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"gid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"guid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"image_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "ID of the image, which this disk was cloned from (valid for disk clones only).",
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"sep_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Type of the storage end-point provider serving this disk.",
|
||||
"images": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
"snapshots": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource {
|
||||
Schema: snapshotSubresourceSchemaMake(),
|
||||
"iotune": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"read_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"size_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
Description: "List of user-created snapshots for this disk."
|
||||
},
|
||||
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Current model status of this disk.",
|
||||
},
|
||||
|
||||
"tech_status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Current technical status of this disk.",
|
||||
},
|
||||
"iqn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"login": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"milestones": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"disk_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"order": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"params": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"parent_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"passwd": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"pci_slot": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"pool": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"purge_attempts": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"purge_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"reality_device_number": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"reference_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"role": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"sep_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"size_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"size_used": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"snapshots": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"guid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"label": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"snap_set_guid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"snap_set_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"timestamp": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"compute_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "ID of the compute instance where this disk is attached to, or 0 for unattached disk.",
|
||||
},
|
||||
*/
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"tech_status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"vmid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
}
|
||||
|
||||
return rets
|
||||
|
||||
@@ -41,11 +41,32 @@ import (
|
||||
"github.com/rudecs/terraform-provider-decort/internal/constants"
|
||||
)
|
||||
|
||||
func flattenDiskList(dl DisksListResp) []map[string]interface{} {
|
||||
func flattenIOTune(iot IOTune) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0)
|
||||
temp := map[string]interface{}{
|
||||
"read_bytes_sec": iot.ReadBytesSec,
|
||||
"read_bytes_sec_max": iot.ReadBytesSecMax,
|
||||
"read_iops_sec": iot.ReadIopsSec,
|
||||
"read_iops_sec_max": iot.ReadIopsSecMax,
|
||||
"size_iops_sec": iot.SizeIopsSec,
|
||||
"total_bytes_sec": iot.TotalBytesSec,
|
||||
"total_bytes_sec_max": iot.TotalBytesSecMax,
|
||||
"total_iops_sec": iot.TotalIopsSec,
|
||||
"total_iops_sec_max": iot.TotalIopsSecMax,
|
||||
"write_bytes_sec": iot.WriteBytesSec,
|
||||
"write_bytes_sec_max": iot.WriteBytesSecMax,
|
||||
"write_iops_sec": iot.WriteIopsSec,
|
||||
"write_iops_sec_max": iot.WriteIopsSecMax,
|
||||
}
|
||||
|
||||
res = append(res, temp)
|
||||
return res
|
||||
}
|
||||
|
||||
func flattenDiskList(dl DisksList) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0)
|
||||
for _, disk := range dl {
|
||||
diskAcl, _ := json.Marshal(disk.Acl)
|
||||
diskIotune, _ := json.Marshal(disk.IOTune)
|
||||
temp := map[string]interface{}{
|
||||
"account_id": disk.AccountID,
|
||||
"account_name": disk.AccountName,
|
||||
@@ -64,13 +85,13 @@ func flattenDiskList(dl DisksListResp) []map[string]interface{} {
|
||||
"disk_id": disk.ID,
|
||||
"image_id": disk.ImageID,
|
||||
"images": disk.Images,
|
||||
"iotune": string(diskIotune),
|
||||
"iotune": flattenIOTune(disk.IOTune),
|
||||
"iqn": disk.IQN,
|
||||
"login": disk.Login,
|
||||
"machine_id": disk.MachineId,
|
||||
"machine_name": disk.MachineName,
|
||||
"milestones": disk.Milestones,
|
||||
"name": disk.Name,
|
||||
"disk_name": disk.Name,
|
||||
"order": disk.Order,
|
||||
"params": disk.Params,
|
||||
"parent_id": disk.ParentId,
|
||||
@@ -93,7 +114,6 @@ func flattenDiskList(dl DisksListResp) []map[string]interface{} {
|
||||
"tech_status": disk.TechStatus,
|
||||
"type": disk.Type,
|
||||
"vmid": disk.VMID,
|
||||
"update_by": disk.UpdateBy,
|
||||
}
|
||||
res = append(res, temp)
|
||||
}
|
||||
@@ -101,7 +121,7 @@ func flattenDiskList(dl DisksListResp) []map[string]interface{} {
|
||||
|
||||
}
|
||||
|
||||
func flattendDiskSnapshotList(sl SnapshotRecordList) []interface{} {
|
||||
func flattendDiskSnapshotList(sl SnapshotList) []interface{} {
|
||||
res := make([]interface{}, 0)
|
||||
for _, snapshot := range sl {
|
||||
temp := map[string]interface{}{
|
||||
@@ -231,8 +251,64 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
|
||||
},
|
||||
},
|
||||
"iotune": {
|
||||
Type: schema.TypeString,
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"read_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"size_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"iqn": {
|
||||
Type: schema.TypeString,
|
||||
@@ -254,7 +330,7 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"name": {
|
||||
"disk_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
@@ -374,10 +450,6 @@ func dataSourceDiskListSchemaMake() map[string]*schema.Schema {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"update_by": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -31,7 +31,7 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
|
||||
package disks
|
||||
|
||||
type DiskRecord struct {
|
||||
type Disk struct {
|
||||
Acl map[string]interface{} `json:"acl"`
|
||||
AccountID int `json:"accountId"`
|
||||
AccountName string `json:"accountName"`
|
||||
@@ -49,7 +49,7 @@ type DiskRecord struct {
|
||||
ID uint `json:"id"`
|
||||
ImageID int `json:"imageId"`
|
||||
Images []int `json:"images"`
|
||||
IOTune map[string]interface{} `json:"iotune"`
|
||||
IOTune IOTune `json:"iotune"`
|
||||
IQN string `json:"iqn"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
@@ -73,7 +73,7 @@ type DiskRecord struct {
|
||||
SepID int `json:"sepId"` // NOTE: absent from compute/get output
|
||||
SizeMax int `json:"sizeMax"`
|
||||
SizeUsed int `json:"sizeUsed"` // sum over all snapshots of this disk to report total consumed space
|
||||
Snapshots []SnapshotRecord `json:"snapshots"`
|
||||
Snapshots []Snapshot `json:"snapshots"`
|
||||
Status string `json:"status"`
|
||||
TechStatus string `json:"techStatus"`
|
||||
Type string `json:"type"`
|
||||
@@ -81,7 +81,7 @@ type DiskRecord struct {
|
||||
VMID int `json:"vmid"`
|
||||
}
|
||||
|
||||
type SnapshotRecord struct {
|
||||
type Snapshot struct {
|
||||
Guid string `json:"guid"`
|
||||
Label string `json:"label"`
|
||||
ResId string `json:"resId"`
|
||||
@@ -90,6 +90,22 @@ type SnapshotRecord struct {
|
||||
TimeStamp uint64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
type SnapshotRecordList []SnapshotRecord
|
||||
type SnapshotList []Snapshot
|
||||
|
||||
type DisksListResp []DiskRecord
|
||||
type DisksList []Disk
|
||||
|
||||
type IOTune struct {
|
||||
ReadBytesSec int `json:"read_bytes_sec"`
|
||||
ReadBytesSecMax int `json:"read_bytes_sec_max"`
|
||||
ReadIopsSec int `json:"read_iops_sec"`
|
||||
ReadIopsSecMax int `json:"read_iops_sec_max"`
|
||||
SizeIopsSec int `json:"size_iops_sec"`
|
||||
TotalBytesSec int `json:"total_bytes_sec"`
|
||||
TotalBytesSecMax int `json:"total_bytes_sec_max"`
|
||||
TotalIopsSec int `json:"total_iops_sec"`
|
||||
TotalIopsSecMax int `json:"total_iops_sec_max"`
|
||||
WriteBytesSec int `json:"write_bytes_sec"`
|
||||
WriteBytesSecMax int `json:"write_bytes_sec_max"`
|
||||
WriteIopsSec int `json:"write_iops_sec"`
|
||||
WriteIopsSecMax int `json:"write_iops_sec_max"`
|
||||
}
|
||||
|
||||
@@ -32,15 +32,15 @@ Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
package disks
|
||||
|
||||
import (
|
||||
// "encoding/json"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rudecs/terraform-provider-decort/internal/constants"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/controller"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/location"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
@@ -49,16 +49,18 @@ import (
|
||||
)
|
||||
|
||||
func resourceDiskCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceDiskCreate: called for Disk name %q, Account ID %d", d.Get("name").(string), d.Get("account_id").(int))
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
// accountId, gid, name, description, size, type, sep_id, pool
|
||||
|
||||
urlValues.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
|
||||
urlValues.Add("gid", fmt.Sprintf("%d", location.DefaultGridID)) // we use default Grid ID, which was obtained along with DECORT Controller init
|
||||
urlValues.Add("name", d.Get("name").(string))
|
||||
urlValues.Add("size", fmt.Sprintf("%d", d.Get("size").(int)))
|
||||
urlValues.Add("type", "D") // NOTE: only disks of Data type are managed via plugin
|
||||
urlValues.Add("gid", fmt.Sprintf("%d", d.Get("gid").(int)))
|
||||
urlValues.Add("name", d.Get("disk_name").(string))
|
||||
urlValues.Add("size", fmt.Sprintf("%d", d.Get("size_max").(int)))
|
||||
if typeRaw, ok := d.GetOk("type"); ok {
|
||||
urlValues.Add("type", strings.ToUpper(typeRaw.(string)))
|
||||
} else {
|
||||
urlValues.Add("type", "D")
|
||||
}
|
||||
|
||||
if sepId, ok := d.GetOk("sep_id"); ok {
|
||||
urlValues.Add("sep_id", strconv.Itoa(sepId.(int)))
|
||||
@@ -68,126 +70,210 @@ func resourceDiskCreate(ctx context.Context, d *schema.ResourceData, m interface
|
||||
urlValues.Add("pool", poolName.(string))
|
||||
}
|
||||
|
||||
argVal, argSet := d.GetOk("description")
|
||||
argVal, argSet := d.GetOk("desc")
|
||||
if argSet {
|
||||
urlValues.Add("description", argVal.(string))
|
||||
}
|
||||
|
||||
apiResp, err := c.DecortAPICall(ctx, "POST", DisksCreateAPI, urlValues)
|
||||
diskId, err := c.DecortAPICall(ctx, "POST", disksCreateAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
d.SetId(apiResp) // update ID of the resource to tell Terraform that the disk resource exists
|
||||
diskId, _ := strconv.Atoi(apiResp)
|
||||
urlValues = &url.Values{}
|
||||
|
||||
log.Debugf("resourceDiskCreate: new Disk ID / name %d / %s creation sequence complete", diskId, d.Get("name").(string))
|
||||
d.SetId(diskId) // update ID of the resource to tell Terraform that the disk resource exists
|
||||
|
||||
// We may reuse dataSourceDiskRead here as we maintain similarity
|
||||
// between Disk resource and Disk data source schemas
|
||||
// Disk resource read function will also update resource ID on success, so that Terraform
|
||||
// will know the resource exists (however, we already did it a few lines before)
|
||||
return dataSourceDiskRead(ctx, d, m)
|
||||
if iotuneRaw, ok := d.GetOk("iotune"); ok {
|
||||
iot := iotuneRaw.([]interface{})[0]
|
||||
iotune := iot.(map[string]interface{})
|
||||
urlValues.Add("diskId", diskId)
|
||||
urlValues.Add("iops", strconv.Itoa(iotune["total_iops_sec"].(int)))
|
||||
urlValues.Add("read_bytes_sec", strconv.Itoa(iotune["read_bytes_sec"].(int)))
|
||||
urlValues.Add("read_bytes_sec_max", strconv.Itoa(iotune["read_bytes_sec_max"].(int)))
|
||||
urlValues.Add("read_iops_sec", strconv.Itoa(iotune["read_iops_sec"].(int)))
|
||||
urlValues.Add("read_iops_sec_max", strconv.Itoa(iotune["read_iops_sec_max"].(int)))
|
||||
urlValues.Add("size_iops_sec", strconv.Itoa(iotune["size_iops_sec"].(int)))
|
||||
urlValues.Add("total_bytes_sec", strconv.Itoa(iotune["total_bytes_sec"].(int)))
|
||||
urlValues.Add("total_bytes_sec_max", strconv.Itoa(iotune["total_bytes_sec_max"].(int)))
|
||||
urlValues.Add("total_iops_sec_max", strconv.Itoa(iotune["total_iops_sec_max"].(int)))
|
||||
urlValues.Add("write_bytes_sec", strconv.Itoa(iotune["write_bytes_sec"].(int)))
|
||||
urlValues.Add("write_bytes_sec_max", strconv.Itoa(iotune["write_bytes_sec_max"].(int)))
|
||||
urlValues.Add("write_iops_sec", strconv.Itoa(iotune["write_iops_sec"].(int)))
|
||||
urlValues.Add("write_iops_sec_max", strconv.Itoa(iotune["write_iops_sec_max"].(int)))
|
||||
|
||||
_, err := c.DecortAPICall(ctx, "POST", disksIOLimitAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
|
||||
dgn := resourceDiskRead(ctx, d, m)
|
||||
if dgn != nil {
|
||||
return dgn
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
diskFacts, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if diskFacts == "" {
|
||||
// if empty string is returned from utilityDiskCheckPresence then there is no
|
||||
// such Disk and err tells so - just return it to the calling party
|
||||
d.SetId("") // ensure ID is empty
|
||||
return diag.FromErr(err)
|
||||
disk, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if disk == nil {
|
||||
d.SetId("")
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return diag.FromErr(flattenDisk(d, diskFacts))
|
||||
diskAcl, _ := json.Marshal(disk.Acl)
|
||||
|
||||
d.Set("account_id", disk.AccountID)
|
||||
d.Set("account_name", disk.AccountName)
|
||||
d.Set("acl", string(diskAcl))
|
||||
d.Set("boot_partition", disk.BootPartition)
|
||||
d.Set("compute_id", disk.ComputeID)
|
||||
d.Set("compute_name", disk.ComputeName)
|
||||
d.Set("created_time", disk.CreatedTime)
|
||||
d.Set("deleted_time", disk.DeletedTime)
|
||||
d.Set("desc", disk.Desc)
|
||||
d.Set("destruction_time", disk.DestructionTime)
|
||||
d.Set("devicename", disk.DeviceName)
|
||||
d.Set("disk_path", disk.DiskPath)
|
||||
d.Set("gid", disk.GridID)
|
||||
d.Set("guid", disk.GUID)
|
||||
d.Set("disk_id", disk.ID)
|
||||
d.Set("image_id", disk.ImageID)
|
||||
d.Set("images", disk.Images)
|
||||
d.Set("iotune", flattenIOTune(disk.IOTune))
|
||||
d.Set("iqn", disk.IQN)
|
||||
d.Set("login", disk.Login)
|
||||
d.Set("milestones", disk.Milestones)
|
||||
d.Set("disk_name", disk.Name)
|
||||
d.Set("order", disk.Order)
|
||||
d.Set("params", disk.Params)
|
||||
d.Set("parent_id", disk.ParentId)
|
||||
d.Set("passwd", disk.Passwd)
|
||||
d.Set("pci_slot", disk.PciSlot)
|
||||
d.Set("pool", disk.Pool)
|
||||
d.Set("purge_attempts", disk.PurgeAttempts)
|
||||
d.Set("purge_time", disk.PurgeTime)
|
||||
d.Set("reality_device_number", disk.RealityDeviceNumber)
|
||||
d.Set("reference_id", disk.ReferenceId)
|
||||
d.Set("res_id", disk.ResID)
|
||||
d.Set("res_name", disk.ResName)
|
||||
d.Set("role", disk.Role)
|
||||
d.Set("sep_id", disk.SepID)
|
||||
d.Set("sep_type", disk.SepType)
|
||||
d.Set("size_max", disk.SizeMax)
|
||||
d.Set("size_used", disk.SizeUsed)
|
||||
d.Set("snapshots", flattendDiskSnapshotList(disk.Snapshots))
|
||||
d.Set("status", disk.Status)
|
||||
d.Set("tech_status", disk.TechStatus)
|
||||
d.Set("type", disk.Type)
|
||||
d.Set("vmid", disk.VMID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
// Update will only change the following attributes of the disk:
|
||||
// - Size; to keep data safe, shrinking disk is not allowed.
|
||||
// - Name
|
||||
//
|
||||
// Attempt to change disk type will throw an error and mark disk
|
||||
// resource as partially updated
|
||||
log.Debugf("resourceDiskUpdate: called for Disk ID / name %s / %s, Account ID %d",
|
||||
d.Id(), d.Get("name").(string), d.Get("account_id").(int))
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
oldSize, newSize := d.GetChange("size")
|
||||
if oldSize.(int) < newSize.(int) {
|
||||
log.Debugf("resourceDiskUpdate: resizing disk ID %s - %d GB -> %d GB",
|
||||
d.Id(), oldSize.(int), newSize.(int))
|
||||
sizeParams := &url.Values{}
|
||||
sizeParams.Add("diskId", d.Id())
|
||||
sizeParams.Add("size", fmt.Sprintf("%d", newSize.(int)))
|
||||
_, err := c.DecortAPICall(ctx, "POST", DisksResizeAPI, sizeParams)
|
||||
if d.HasChange("size_max") {
|
||||
oldSize, newSize := d.GetChange("size_max")
|
||||
if oldSize.(int) < newSize.(int) {
|
||||
log.Debugf("resourceDiskUpdate: resizing disk ID %s - %d GB -> %d GB",
|
||||
d.Id(), oldSize.(int), newSize.(int))
|
||||
urlValues.Add("diskId", d.Id())
|
||||
urlValues.Add("size", fmt.Sprintf("%d", newSize.(int)))
|
||||
_, err := c.DecortAPICall(ctx, "POST", disksResizeAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
d.Set("size_max", newSize)
|
||||
} else if oldSize.(int) > newSize.(int) {
|
||||
return diag.FromErr(fmt.Errorf("resourceDiskUpdate: Disk ID %s - reducing disk size is not allowed", d.Id()))
|
||||
}
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
|
||||
if d.HasChange("disk_name") {
|
||||
urlValues.Add("diskId", d.Id())
|
||||
urlValues.Add("name", d.Get("disk_name").(string))
|
||||
_, err := c.DecortAPICall(ctx, "POST", disksRenameAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
d.Set("size", newSize)
|
||||
} else if oldSize.(int) > newSize.(int) {
|
||||
return diag.FromErr(fmt.Errorf("resourceDiskUpdate: Disk ID %s - reducing disk size is not allowed", d.Id()))
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
|
||||
oldName, newName := d.GetChange("name")
|
||||
if oldName.(string) != newName.(string) {
|
||||
log.Debugf("resourceDiskUpdate: renaming disk ID %d - %s -> %s",
|
||||
d.Get("disk_id").(int), oldName.(string), newName.(string))
|
||||
renameParams := &url.Values{}
|
||||
renameParams.Add("diskId", d.Id())
|
||||
renameParams.Add("name", newName.(string))
|
||||
_, err := c.DecortAPICall(ctx, "POST", DisksRenameAPI, renameParams)
|
||||
if d.HasChange("iotune") {
|
||||
iot := d.Get("iotune").([]interface{})[0]
|
||||
iotune := iot.(map[string]interface{})
|
||||
urlValues.Add("diskId", d.Id())
|
||||
urlValues.Add("iops", strconv.Itoa(iotune["total_iops_sec"].(int)))
|
||||
urlValues.Add("read_bytes_sec", strconv.Itoa(iotune["read_bytes_sec"].(int)))
|
||||
urlValues.Add("read_bytes_sec_max", strconv.Itoa(iotune["read_bytes_sec_max"].(int)))
|
||||
urlValues.Add("read_iops_sec", strconv.Itoa(iotune["read_iops_sec"].(int)))
|
||||
urlValues.Add("read_iops_sec_max", strconv.Itoa(iotune["read_iops_sec_max"].(int)))
|
||||
urlValues.Add("size_iops_sec", strconv.Itoa(iotune["size_iops_sec"].(int)))
|
||||
urlValues.Add("total_bytes_sec", strconv.Itoa(iotune["total_bytes_sec"].(int)))
|
||||
urlValues.Add("total_bytes_sec_max", strconv.Itoa(iotune["total_bytes_sec_max"].(int)))
|
||||
urlValues.Add("total_iops_sec_max", strconv.Itoa(iotune["total_iops_sec_max"].(int)))
|
||||
urlValues.Add("write_bytes_sec", strconv.Itoa(iotune["write_bytes_sec"].(int)))
|
||||
urlValues.Add("write_bytes_sec_max", strconv.Itoa(iotune["write_bytes_sec_max"].(int)))
|
||||
urlValues.Add("write_iops_sec", strconv.Itoa(iotune["write_iops_sec"].(int)))
|
||||
urlValues.Add("write_iops_sec_max", strconv.Itoa(iotune["write_iops_sec_max"].(int)))
|
||||
|
||||
_, err := c.DecortAPICall(ctx, "POST", disksIOLimitAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: plugin will manage disks of type "Data" only, and type cannot be changed once disk is created
|
||||
if d.HasChange("restore") {
|
||||
if d.Get("restore").(bool) {
|
||||
urlValues.Add("diskId", d.Id())
|
||||
urlValues.Add("reason", d.Get("reason").(string))
|
||||
|
||||
oldType, newType := d.GetChange("type")
|
||||
if oldType.(string) != newType.(string) {
|
||||
return fmt.Errorf("resourceDiskUpdate: Disk ID %s - changing type of existing disk not allowed", d.Id())
|
||||
_, err := c.DecortAPICall(ctx, "POST", disksRestoreAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
urlValues = &url.Values{}
|
||||
}
|
||||
*/
|
||||
|
||||
// we may reuse dataSourceDiskRead here as we maintain similarity
|
||||
// between Compute resource and Compute data source schemas
|
||||
return dataSourceDiskRead(ctx, d, m)
|
||||
}
|
||||
|
||||
return resourceDiskRead(ctx, d, m)
|
||||
}
|
||||
|
||||
func resourceDiskDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
// NOTE: this function tries to detach and destroy target Disk "permanently", so
|
||||
// there is no way to restore it.
|
||||
// If, however, the disk is attached to a compute, the method will
|
||||
// fail (by failing the underpinning DECORt API call, which is issued with detach=false)
|
||||
log.Debugf("resourceDiskDelete: called for Disk ID / name %d / %s, Account ID %d",
|
||||
d.Get("disk_id").(int), d.Get("name").(string), d.Get("account_id").(int))
|
||||
|
||||
diskFacts, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if diskFacts == "" {
|
||||
disk, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if disk == nil {
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
// the specified Disk does not exist - in this case according to Terraform best practice
|
||||
// we exit from Destroy method without error
|
||||
return nil
|
||||
}
|
||||
|
||||
params := &url.Values{}
|
||||
params.Add("diskId", d.Id())
|
||||
// NOTE: we are not force-detaching disk from a compute (if attached) thus protecting
|
||||
// data that may be on that disk from destruction.
|
||||
// However, this may change in the future, as TF state management logic may want
|
||||
// to delete disk resource BEFORE it is detached from compute instance, and, while
|
||||
// perfectly OK from data preservation viewpoint, this is breaking expected TF workflow
|
||||
// in the eyes of an experienced TF user
|
||||
params.Add("detach", "0")
|
||||
params.Add("permanently", "1")
|
||||
params.Add("detach", strconv.FormatBool(d.Get("detach").(bool)))
|
||||
params.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
|
||||
params.Add("reason", d.Get("reason").(string))
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
_, err = c.DecortAPICall(ctx, "POST", DisksDeleteAPI, params)
|
||||
_, err = c.DecortAPICall(ctx, "POST", disksDeleteAPI, params)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
@@ -196,12 +282,9 @@ func resourceDiskDelete(ctx context.Context, d *schema.ResourceData, m interface
|
||||
}
|
||||
|
||||
func resourceDiskExists(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
|
||||
// Reminder: according to Terraform rules, this function should not modify its ResourceData argument
|
||||
log.Debugf("resourceDiskExists: called for Disk ID / name %d / %s, Account ID %d",
|
||||
d.Get("disk_id").(int), d.Get("name").(string), d.Get("account_id").(int))
|
||||
|
||||
diskFacts, err := utilityDiskCheckPresence(ctx, d, m)
|
||||
if diskFacts == "" {
|
||||
if diskFacts == nil {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -212,101 +295,318 @@ func resourceDiskExists(ctx context.Context, d *schema.ResourceData, m interface
|
||||
|
||||
func resourceDiskSchemaMake() map[string]*schema.Schema {
|
||||
rets := map[string]*schema.Schema{
|
||||
"name": {
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"disk_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"size_max": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"gid": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"pool": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"desc": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"D", "B", "T"}, false),
|
||||
},
|
||||
|
||||
"detach": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "detach disk from machine first",
|
||||
},
|
||||
"permanently": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "whether to completely delete the disk, works only with non attached disks",
|
||||
},
|
||||
"reason": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Name of this disk. NOTE: disk names are NOT unique within an account. If disk ID is specified, disk name is ignored.",
|
||||
Optional: true,
|
||||
Default: "",
|
||||
Description: "reason for an action",
|
||||
},
|
||||
"restore": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "restore deleting disk",
|
||||
},
|
||||
|
||||
"disk_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "ID of the disk to get. If disk ID is specified, then disk name and account ID are ignored.",
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
Description: "ID of the account this disk belongs to.",
|
||||
},
|
||||
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Description: "Storage end-point provider serving this disk. Cannot be changed for existing disk.",
|
||||
},
|
||||
|
||||
"pool": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Description: "Pool where this disk is located. Cannot be changed for existing disk.",
|
||||
},
|
||||
|
||||
"size": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ValidateFunc: validation.IntAtLeast(1),
|
||||
Description: "Size of the disk in GB. Note, that existing disks can only be grown in size.",
|
||||
},
|
||||
|
||||
/* We moved "type" attribute to computed attributes section, as plugin manages disks of only
|
||||
one type - "D", e.g. data disks.
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "D",
|
||||
StateFunc: stateFuncToUpper,
|
||||
ValidateFunc: validation.StringInSlice([]string{"B", "D"}, false),
|
||||
Description: "Optional type of this disk. Defaults to D, i.e. data disk. Cannot be changed for existing disks.",
|
||||
},
|
||||
*/
|
||||
|
||||
"description": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "Disk resource managed by Terraform",
|
||||
Description: "Optional user-defined text description of this disk.",
|
||||
},
|
||||
|
||||
// The rest of the attributes are all computed
|
||||
"account_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Name of the account this disk belongs to.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"acl": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"boot_partition": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"compute_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"compute_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"created_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"deleted_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"destruction_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"devicename": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"disk_path": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"guid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"image_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "ID of the image, which this disk was cloned from (if ever cloned).",
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"images": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
"iotune": {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"read_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"read_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"read_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"size_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"total_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"total_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"write_bytes_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"write_iops_sec_max": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"iqn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"login": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"milestones": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Type of this disk.",
|
||||
"order": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"params": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"parent_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"passwd": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"pci_slot": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"purge_attempts": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"purge_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"reality_device_number": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"reference_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"role": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"sep_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Type of the storage end-point provider serving this disk.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
/*
|
||||
"snapshots": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource {
|
||||
Schema: snapshotSubresourceSchemaMake(),
|
||||
"size_used": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"snapshots": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"guid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"label": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"res_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"snap_set_guid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"snap_set_time": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"timestamp": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
Description: "List of user-created snapshots for this disk."
|
||||
},
|
||||
*/
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"tech_status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"vmid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
}
|
||||
|
||||
return rets
|
||||
|
||||
@@ -34,7 +34,6 @@ package disks
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
@@ -44,103 +43,28 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func utilityDiskCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
|
||||
// This function tries to locate Disk by one of the following algorithms depending on
|
||||
// the parameters passed:
|
||||
// - if disk ID is specified -> by disk ID
|
||||
// - if disk name is specifeid -> by disk name and either account ID or account name
|
||||
//
|
||||
// NOTE: disk names are not unique, so the first occurence of this name in the account will
|
||||
// be returned. There is no such ambiguity when locating disk by its ID.
|
||||
//
|
||||
// If succeeded, it returns non empty string that contains JSON formatted facts about the disk
|
||||
// as returned by disks/get API call.
|
||||
// Otherwise it returns empty string and meaningful error.
|
||||
//
|
||||
// This function does not modify its ResourceData argument, so it is safe to use it as core
|
||||
// method for resource's Exists method.
|
||||
//
|
||||
|
||||
func utilityDiskCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*Disk, error) {
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
// make it possible to use "read" & "check presence" functions with disk ID set so
|
||||
// that Import of preexisting Disk resource is possible
|
||||
idSet := false
|
||||
theId, err := strconv.Atoi(d.Id())
|
||||
if err != nil || theId <= 0 {
|
||||
diskId, argSet := d.GetOk("disk_id")
|
||||
if argSet {
|
||||
theId = diskId.(int)
|
||||
idSet = true
|
||||
}
|
||||
disk := &Disk{}
|
||||
|
||||
if d.Get("disk_id").(int) == 0 {
|
||||
urlValues.Add("diskId", d.Id())
|
||||
} else {
|
||||
idSet = true
|
||||
urlValues.Add("diskId", strconv.Itoa(d.Get("disk_id").(int)))
|
||||
}
|
||||
|
||||
if idSet {
|
||||
// disk ID is specified, try to get disk instance straight by this ID
|
||||
log.Debugf("utilityDiskCheckPresence: locating disk by its ID %d", theId)
|
||||
urlValues.Add("diskId", fmt.Sprintf("%d", theId))
|
||||
diskFacts, err := c.DecortAPICall(ctx, "POST", DisksGetAPI, urlValues)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return diskFacts, nil
|
||||
}
|
||||
|
||||
// ID or disk_di was not set in the schema upon entering this function - rely on Disk name
|
||||
// and Account ID to find the disk
|
||||
diskName, argSet := d.GetOk("name")
|
||||
if !argSet {
|
||||
// no disk ID and no disk name - we cannot locate disk in this case
|
||||
return "", fmt.Errorf("Cannot locate disk if name is empty and no disk ID specified")
|
||||
}
|
||||
|
||||
// Valid account ID is required to locate disks
|
||||
// obtain Account ID by account name - it should not be zero on success
|
||||
|
||||
urlValues.Add("accountId", fmt.Sprintf("%d", d.Get("account_id").(int)))
|
||||
diskFacts, err := c.DecortAPICall(ctx, "POST", DisksListAPI, urlValues)
|
||||
log.Debugf("utilityDiskCheckPresence: load disk")
|
||||
diskRaw, err := c.DecortAPICall(ctx, "POST", disksGetAPI, urlValues)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("utilityDiskCheckPresence: ready to unmarshal string %s", diskFacts)
|
||||
|
||||
disksList := DisksListResp{}
|
||||
err = json.Unmarshal([]byte(diskFacts), &disksList)
|
||||
err = json.Unmarshal([]byte(diskRaw), disk)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// log.Printf("%#v", vm_list)
|
||||
log.Debugf("utilityDiskCheckPresence: traversing decoded JSON of length %d", len(disksList))
|
||||
for index, item := range disksList {
|
||||
// need to match disk by name, return the first match
|
||||
if item.Name == diskName.(string) && item.Status != "DESTROYED" {
|
||||
log.Debugf("utilityDiskCheckPresence: index %d, matched disk name %q", index, item.Name)
|
||||
// we found the disk we need - not get detailed information via API call to disks/get
|
||||
/*
|
||||
// TODO: this may not be optimal as it initiates one extra call to the DECORT controller
|
||||
// in spite of the fact that we already have all required information about the disk in
|
||||
// item variable
|
||||
//
|
||||
get_urlValues := &url.Values{}
|
||||
get_urlValues.Add("diskId", fmt.Sprintf("%d", item.ID))
|
||||
diskFacts, err = controller.decortAPICall("POST", DisksGetAPI, get_urlValues)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return diskFacts, nil
|
||||
*/
|
||||
reencodedItem, err := json.Marshal(item)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(reencodedItem[:]), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil // there should be no error if disk does not exist
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func utilityDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (DisksListResp, error) {
|
||||
diskList := DisksListResp{}
|
||||
func utilityDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (DisksList, error) {
|
||||
diskList := DisksList{}
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
@@ -62,8 +62,8 @@ func utilityDiskListCheckPresence(ctx context.Context, d *schema.ResourceData, m
|
||||
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
|
||||
}
|
||||
|
||||
log.Debugf("utilityDiskListCheckPresence: load grid list")
|
||||
diskListRaw, err := c.DecortAPICall(ctx, "POST", DisksListAPI, urlValues)
|
||||
log.Debugf("utilityDiskListCheckPresence: load disk list")
|
||||
diskListRaw, err := c.DecortAPICall(ctx, "POST", disksListAPI, urlValues)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
40
internal/service/cloudapi/image/api.go
Normal file
40
internal/service/cloudapi/image/api.go
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
const imageCreateAPI = "/restmachine/cloudapi/image/createImage"
|
||||
const imageCreateVirtualAPI = "/restmachine/cloudapi/image/createVirtual"
|
||||
const imageGetAPI = "/restmachine/cloudapi/image/get"
|
||||
const imageListGetAPI = "/restmachine/cloudapi/image/list"
|
||||
const imageDeleteAPI = "/restmachine/cloudapi/image/delete"
|
||||
const imageEditNameAPI = "/restmachine/cloudapi/image/rename"
|
||||
const imageLinkAPI = "/restmachine/cloudapi/image/link"
|
||||
123
internal/service/cloudapi/image/data_source_image.go
Normal file
123
internal/service/cloudapi/image/data_source_image.go
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
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 flattenHistory(history []History) []map[string]interface{} {
|
||||
temp := make([]map[string]interface{}, 0)
|
||||
for _, item := range history {
|
||||
t := map[string]interface{}{
|
||||
"id": item.Id,
|
||||
"guid": item.Guid,
|
||||
"timestamp": item.Timestamp,
|
||||
}
|
||||
|
||||
temp = append(temp, t)
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
func flattenImage(d *schema.ResourceData, img *ImageExtend) {
|
||||
d.Set("unc_path", img.UNCPath)
|
||||
d.Set("ckey", img.CKey)
|
||||
d.Set("account_id", img.AccountId)
|
||||
d.Set("acl", img.Acl)
|
||||
d.Set("architecture", img.Architecture)
|
||||
d.Set("boot_type", img.BootType)
|
||||
d.Set("bootable", img.Bootable)
|
||||
d.Set("compute_ci_id", img.ComputeCiId)
|
||||
d.Set("deleted_time", img.DeletedTime)
|
||||
d.Set("desc", img.Description)
|
||||
d.Set("drivers", img.Drivers)
|
||||
d.Set("enabled", img.Enabled)
|
||||
d.Set("gid", img.GridId)
|
||||
d.Set("guid", img.GUID)
|
||||
d.Set("history", flattenHistory(img.History))
|
||||
d.Set("hot_resize", img.HotResize)
|
||||
d.Set("image_id", img.Id)
|
||||
d.Set("last_modified", img.LastModified)
|
||||
d.Set("link_to", img.LinkTo)
|
||||
d.Set("milestones", img.Milestones)
|
||||
d.Set("image_name", img.Name)
|
||||
d.Set("password", img.Password)
|
||||
d.Set("pool_name", img.Pool)
|
||||
d.Set("provider_name", img.ProviderName)
|
||||
d.Set("purge_attempts", img.PurgeAttempts)
|
||||
d.Set("res_id", img.ResId)
|
||||
d.Set("rescuecd", img.RescueCD)
|
||||
d.Set("sep_id", img.SepId)
|
||||
d.Set("shared_with", img.SharedWith)
|
||||
d.Set("size", img.Size)
|
||||
d.Set("status", img.Status)
|
||||
d.Set("tech_status", img.TechStatus)
|
||||
d.Set("type", img.Type)
|
||||
d.Set("username", img.Username)
|
||||
d.Set("version", img.Version)
|
||||
}
|
||||
|
||||
func dataSourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
image, err := utilityImageCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
d.SetId(id.String())
|
||||
|
||||
flattenImage(d, image)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DataSourceImage() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
SchemaVersion: 1,
|
||||
|
||||
ReadContext: dataSourceImageRead,
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Read: &constants.Timeout30s,
|
||||
Default: &constants.Timeout60s,
|
||||
},
|
||||
|
||||
Schema: dataSourceImageExtendSchemaMake(),
|
||||
}
|
||||
}
|
||||
126
internal/service/cloudapi/image/data_source_image_list.go
Normal file
126
internal/service/cloudapi/image/data_source_image_list.go
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
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 flattenImageList(il ImageList) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0)
|
||||
for _, img := range il {
|
||||
temp := map[string]interface{}{
|
||||
"account_id": img.AccountId,
|
||||
"architecture": img.Architecture,
|
||||
"boot_type": img.BootType,
|
||||
"bootable": img.Bootable,
|
||||
"cdrom": img.CDROM,
|
||||
"desc": img.Description,
|
||||
"drivers": img.Drivers,
|
||||
"hot_resize": img.HotResize,
|
||||
"image_id": img.Id,
|
||||
"link_to": img.LinkTo,
|
||||
"image_name": img.Name,
|
||||
"pool_name": img.Pool,
|
||||
"sep_id": img.SepId,
|
||||
"size": img.Size,
|
||||
"status": img.Status,
|
||||
"type": img.Type,
|
||||
"username": img.Username,
|
||||
"virtual": img.Virtual,
|
||||
}
|
||||
res = append(res, temp)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func dataSourceImageListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
imageList, err := utilityImageListCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
id := uuid.New()
|
||||
d.SetId(id.String())
|
||||
d.Set("items", flattenImageList(imageList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dataSourceImageListSchemaMake() map[string]*schema.Schema {
|
||||
rets := map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "optional account ID to include account images",
|
||||
},
|
||||
"page": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "page number",
|
||||
},
|
||||
"size": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "page size",
|
||||
},
|
||||
"items": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Description: "image list",
|
||||
Elem: &schema.Resource{
|
||||
Schema: dataSourceImageSchemaMake(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return rets
|
||||
}
|
||||
|
||||
func DataSourceImageList() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
SchemaVersion: 1,
|
||||
|
||||
ReadContext: dataSourceImageListRead,
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Read: &constants.Timeout30s,
|
||||
Default: &constants.Timeout60s,
|
||||
},
|
||||
|
||||
Schema: dataSourceImageListSchemaMake(),
|
||||
}
|
||||
}
|
||||
208
internal/service/cloudapi/image/image_ds_subresource.go
Normal file
208
internal/service/cloudapi/image/image_ds_subresource.go
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
func dataSourceImageExtendSchemaMake() map[string]*schema.Schema {
|
||||
return map[string]*schema.Schema{
|
||||
"image_id": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"show_all": {
|
||||
Type: schema.TypeBool,
|
||||
Default: false,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"unc_path": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"ckey": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"acl": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"architecture": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"boot_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"bootable": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"compute_ci_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"deleted_time": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"desc": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"drivers": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
"enabled": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"gid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"guid": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"history": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"guid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"timestamp": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"hot_resize": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"last_modified": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"link_to": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"milestones": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"image_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"password": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"pool_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"provider_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"purge_attempts": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"res_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"rescuecd": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"shared_with": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
},
|
||||
},
|
||||
"size": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"tech_status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"username": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"version": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
132
internal/service/cloudapi/image/image_item_subresource.go
Normal file
132
internal/service/cloudapi/image/image_item_subresource.go
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
|
||||
func dataSourceImageSchemaMake() map[string]*schema.Schema {
|
||||
return map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Owner account id",
|
||||
},
|
||||
"architecture": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image architecture",
|
||||
},
|
||||
"boot_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Boot image type",
|
||||
},
|
||||
"bootable": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "Flag, true if image is bootable, otherwise - false",
|
||||
},
|
||||
"cdrom": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "Flag, true if image is cdrom image, otherwise - false",
|
||||
},
|
||||
"desc": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image description",
|
||||
},
|
||||
"drivers": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
Description: "Image drivers",
|
||||
},
|
||||
"hot_resize": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "Flag, true if image supports hot resize, else if not",
|
||||
},
|
||||
"image_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Image id",
|
||||
},
|
||||
"link_to": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "For virtual images, id image, which current image linked",
|
||||
},
|
||||
"image_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image name",
|
||||
},
|
||||
"pool_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image pool",
|
||||
},
|
||||
"sep_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Image storage endpoint id",
|
||||
},
|
||||
"size": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Image size",
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image status",
|
||||
},
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "Image type",
|
||||
},
|
||||
"username": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "username",
|
||||
},
|
||||
"virtual": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "True if image is virtula, otherwise - else",
|
||||
},
|
||||
}
|
||||
}
|
||||
158
internal/service/cloudapi/image/image_rs_subresource.go
Normal file
158
internal/service/cloudapi/image/image_rs_subresource.go
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
)
|
||||
|
||||
func resourceImageSchemaMake(sch map[string]*schema.Schema) map[string]*schema.Schema {
|
||||
delete(sch, "show_all")
|
||||
sch["name"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Name of the rescue disk",
|
||||
}
|
||||
|
||||
sch["url"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "URL where to download media from",
|
||||
}
|
||||
|
||||
sch["gid"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
Description: "grid (platform) ID where this template should be create in",
|
||||
}
|
||||
|
||||
sch["image_id"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "image id",
|
||||
}
|
||||
|
||||
sch["boot_type"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
|
||||
Description: "Boot type of image bios or uefi",
|
||||
}
|
||||
|
||||
sch["type"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
|
||||
Description: "Image type linux, windows or other",
|
||||
}
|
||||
|
||||
sch["hot_resize"] = &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "Does this machine supports hot resize",
|
||||
}
|
||||
|
||||
sch["username"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "Optional username for the image",
|
||||
}
|
||||
|
||||
sch["password"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "Optional password for the image",
|
||||
}
|
||||
|
||||
sch["account_id"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "AccountId to make the image exclusive",
|
||||
}
|
||||
|
||||
sch["username_dl"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "username for upload binary media",
|
||||
}
|
||||
|
||||
sch["password_dl"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "password for upload binary media",
|
||||
}
|
||||
|
||||
sch["pool_name"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "pool for image create",
|
||||
}
|
||||
|
||||
sch["sep_id"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "storage endpoint provider ID",
|
||||
}
|
||||
|
||||
sch["architecture"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"X86_64", "PPC64_LE"}, true),
|
||||
Description: "binary architecture of this image, one of X86_64 of PPC64_LE",
|
||||
}
|
||||
|
||||
sch["drivers"] = &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
}
|
||||
|
||||
sch["permanently"] = &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "whether to completely delete the image",
|
||||
}
|
||||
|
||||
return sch
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func resourceImageVirtualSchemaMake(sch map[string]*schema.Schema) map[string]*schema.Schema {
|
||||
delete(sch, "show_all")
|
||||
sch["name"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Name of the rescue disk",
|
||||
}
|
||||
|
||||
sch["link_to"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
Description: "ID of real image to link this virtual image to upon creation",
|
||||
}
|
||||
|
||||
sch["permanently"] = &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "whether to completely delete the image",
|
||||
}
|
||||
|
||||
sch["image_id"] = &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "Image id",
|
||||
}
|
||||
|
||||
return sch
|
||||
}
|
||||
148
internal/service/cloudapi/image/models.go
Normal file
148
internal/service/cloudapi/image/models.go
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
/*
|
||||
type History struct {
|
||||
Guid string `json:"guid"`
|
||||
Id int `json:"id"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ImageId int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
Gid int `json:"gid"`
|
||||
Guid int `json:"guid"`
|
||||
Boottype string `json:"bootType"`
|
||||
Imagetype string `json:"type"`
|
||||
Drivers []string `json:"drivers"`
|
||||
Hotresize bool `json:"hotResize"`
|
||||
Bootable bool `json:"bootable"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
AccountId int `json:"accountId"`
|
||||
UsernameDL string `json:"usernameDL"`
|
||||
PasswordDL string `json:"passwordDL"`
|
||||
SepId int `json:"sepId"`
|
||||
PoolName string `json:"pool"`
|
||||
Architecture string `json:"architecture"`
|
||||
UNCPath string `json:"UNCPath"`
|
||||
LinkTo int `json:"linkTo"`
|
||||
Status string `json:"status"`
|
||||
TechStatus string `json:"techStatus"`
|
||||
Size int `json:"size"`
|
||||
Version string `json:"version"`
|
||||
Enabled bool `json:"enabled"`
|
||||
ComputeciId int `json:"computeciId"`
|
||||
Milestones int `json:"milestones"`
|
||||
ProviderName string `json:"provider_name"`
|
||||
PurgeAttempts int `json:"purgeAttempts"`
|
||||
ReferenceId string `json:"referenceId"`
|
||||
ResId string `json:"resId"`
|
||||
ResName string `json:"resName"`
|
||||
Rescuecd bool `json:"rescuecd"`
|
||||
Meta []interface{} `json:"_meta"`
|
||||
History []History `json:"history"`
|
||||
LastModified int64 `json:"lastModified"`
|
||||
Desc string `json:"desc"`
|
||||
SharedWith []int `json:"sharedWith"`
|
||||
}
|
||||
*/
|
||||
|
||||
type Image struct {
|
||||
AccountId int `json:"accountId"`
|
||||
Architecture string `json:"architecture"`
|
||||
BootType string `json:"bootType"`
|
||||
Bootable bool `json:"bootable"`
|
||||
CDROM bool `json:"cdrom"`
|
||||
Description string `json:"desc"`
|
||||
Drivers []string `json:"drivers"`
|
||||
HotResize bool `json:"hotResize"`
|
||||
Id int `json:"id"`
|
||||
LinkTo int `json:"linkTo"`
|
||||
Name string `json:"name"`
|
||||
Pool string `json:"pool"`
|
||||
SepId int `json:"sepId"`
|
||||
Size int `json:"size"`
|
||||
Status string `json:"status"`
|
||||
Type string `json:"type"`
|
||||
Username string `json:"username"`
|
||||
Virtual bool `json:"virtual"`
|
||||
}
|
||||
|
||||
type ImageList []Image
|
||||
|
||||
type History struct {
|
||||
Guid string `json:"guid"`
|
||||
Id int `json:"id"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
type ImageExtend struct {
|
||||
UNCPath string `json:"UNCPath"`
|
||||
CKey string `json:"_ckey"`
|
||||
AccountId int `json:"accountId"`
|
||||
Acl interface{} `json:"acl"`
|
||||
Architecture string `json:"architecture"`
|
||||
BootType string `json:"bootType"`
|
||||
Bootable bool `json:"bootable"`
|
||||
ComputeCiId int `json:"computeciId"`
|
||||
DeletedTime int `json:"deletedTime"`
|
||||
Description string `json:"desc"`
|
||||
Drivers []string `json:"drivers"`
|
||||
Enabled bool `json:"enabled"`
|
||||
GridId int `json:"gid"`
|
||||
GUID int `json:"guid"`
|
||||
History []History `json:"history"`
|
||||
HotResize bool `json:"hotResize"`
|
||||
Id int `json:"id"`
|
||||
LastModified int `json:"lastModified"`
|
||||
LinkTo int `json:"linkTo"`
|
||||
Milestones int `json:"milestones"`
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Pool string `json:"pool"`
|
||||
ProviderName string `json:"provider_name"`
|
||||
PurgeAttempts int `json:"purgeAttempts"`
|
||||
ResId string `json:"resId"`
|
||||
RescueCD bool `json:"rescuecd"`
|
||||
SepId int `json:"sepId"`
|
||||
SharedWith []int `json:"sharedWith"`
|
||||
Size int `json:"size"`
|
||||
Status string `json:"status"`
|
||||
TechStatus string `json:"techStatus"`
|
||||
Type string `json:"type"`
|
||||
Username string `json:"username"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
259
internal/service/cloudapi/image/resource_image.go
Normal file
259
internal/service/cloudapi/image/resource_image.go
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"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"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/controller"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func resourceImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
urlValues.Add("name", d.Get("name").(string))
|
||||
urlValues.Add("url", d.Get("url").(string))
|
||||
urlValues.Add("gid", strconv.Itoa(d.Get("gid").(int)))
|
||||
urlValues.Add("boottype", d.Get("boot_type").(string))
|
||||
urlValues.Add("imagetype", d.Get("image_type").(string))
|
||||
|
||||
tstr := d.Get("drivers").([]interface{})
|
||||
temp := ""
|
||||
l := len(tstr)
|
||||
for i, str := range tstr {
|
||||
s := "\"" + str.(string) + "\""
|
||||
if i != (l - 1) {
|
||||
s += ","
|
||||
}
|
||||
temp = temp + s
|
||||
}
|
||||
temp = "[" + temp + "]"
|
||||
urlValues.Add("drivers", temp)
|
||||
|
||||
if hotresize, ok := d.GetOk("hot_resize"); ok {
|
||||
urlValues.Add("hotresize", strconv.FormatBool(hotresize.(bool)))
|
||||
}
|
||||
if username, ok := d.GetOk("username"); ok {
|
||||
urlValues.Add("username", username.(string))
|
||||
}
|
||||
if password, ok := d.GetOk("password"); ok {
|
||||
urlValues.Add("password", password.(string))
|
||||
}
|
||||
if accountId, ok := d.GetOk("account_id"); ok {
|
||||
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
|
||||
}
|
||||
if usernameDL, ok := d.GetOk("username_dl"); ok {
|
||||
urlValues.Add("usernameDL", usernameDL.(string))
|
||||
}
|
||||
if passwordDL, ok := d.GetOk("password_dl"); ok {
|
||||
urlValues.Add("passwordDL", passwordDL.(string))
|
||||
}
|
||||
if sepId, ok := d.GetOk("sep_id"); ok {
|
||||
urlValues.Add("sepId", strconv.Itoa(sepId.(int)))
|
||||
}
|
||||
if poolName, ok := d.GetOk("pool_name"); ok {
|
||||
urlValues.Add("poolName", poolName.(string))
|
||||
}
|
||||
if architecture, ok := d.GetOk("architecture"); ok {
|
||||
urlValues.Add("architecture", architecture.(string))
|
||||
}
|
||||
|
||||
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
d.SetId(imageId)
|
||||
d.Set("image_id", imageId)
|
||||
|
||||
_, err = utilityImageCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
diagnostics := resourceImageRead(ctx, d, m)
|
||||
if diagnostics != nil {
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageRead: called for %s id: %s", d.Get("name").(string), d.Id())
|
||||
|
||||
img, err := utilityImageCheckPresence(ctx, d, m)
|
||||
if img == nil {
|
||||
d.SetId("")
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
d.Set("unc_path", img.UNCPath)
|
||||
d.Set("ckey", img.CKey)
|
||||
d.Set("account_id", img.AccountId)
|
||||
d.Set("acl", img.Acl)
|
||||
d.Set("architecture", img.Architecture)
|
||||
d.Set("boot_type", img.BootType)
|
||||
d.Set("bootable", img.Bootable)
|
||||
d.Set("compute_ci_id", img.ComputeCiId)
|
||||
d.Set("deleted_time", img.DeletedTime)
|
||||
d.Set("desc", img.Description)
|
||||
d.Set("drivers", img.Drivers)
|
||||
d.Set("enabled", img.Enabled)
|
||||
d.Set("gid", img.GridId)
|
||||
d.Set("guid", img.GUID)
|
||||
d.Set("history", flattenHistory(img.History))
|
||||
d.Set("hot_resize", img.HotResize)
|
||||
d.Set("image_id", img.Id)
|
||||
d.Set("last_modified", img.LastModified)
|
||||
d.Set("link_to", img.LinkTo)
|
||||
d.Set("milestones", img.Milestones)
|
||||
d.Set("image_name", img.Name)
|
||||
d.Set("password", img.Password)
|
||||
d.Set("pool_name", img.Pool)
|
||||
d.Set("provider_name", img.ProviderName)
|
||||
d.Set("purge_attempts", img.PurgeAttempts)
|
||||
d.Set("res_id", img.ResId)
|
||||
d.Set("rescuecd", img.RescueCD)
|
||||
d.Set("sep_id", img.SepId)
|
||||
d.Set("shared_with", img.SharedWith)
|
||||
d.Set("size", img.Size)
|
||||
d.Set("status", img.Status)
|
||||
d.Set("tech_status", img.TechStatus)
|
||||
d.Set("type", img.Type)
|
||||
d.Set("username", img.Username)
|
||||
d.Set("version", img.Version)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
|
||||
image, err := utilityImageCheckPresence(ctx, d, m)
|
||||
if image == nil {
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
|
||||
|
||||
if permanently, ok := d.GetOk("permanently"); ok {
|
||||
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
|
||||
}
|
||||
|
||||
_, err = c.DecortAPICall(ctx, "POST", imageDeleteAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
d.SetId("")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceImageExists(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
|
||||
log.Debugf("resourceImageExists: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
|
||||
image, err := utilityImageCheckPresence(ctx, d, m)
|
||||
if image == nil {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func resourceImageEditName(ctx context.Context, d *schema.ResourceData, m interface{}) error {
|
||||
log.Debugf("resourceImageEditName: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
|
||||
urlValues.Add("name", d.Get("name").(string))
|
||||
_, err := c.DecortAPICall(ctx, "POST", imageEditNameAPI, urlValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceImageEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
|
||||
if d.HasChange("name") {
|
||||
err := resourceImageEditName(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
return resourceImageRead(ctx, d, m)
|
||||
}
|
||||
|
||||
func ResourceImage() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
SchemaVersion: 1,
|
||||
|
||||
CreateContext: resourceImageCreate,
|
||||
ReadContext: resourceImageRead,
|
||||
UpdateContext: resourceImageEdit,
|
||||
DeleteContext: resourceImageDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Create: &constants.Timeout60s,
|
||||
Read: &constants.Timeout30s,
|
||||
Update: &constants.Timeout60s,
|
||||
Delete: &constants.Timeout60s,
|
||||
Default: &constants.Timeout60s,
|
||||
},
|
||||
|
||||
Schema: resourceImageSchemaMake(dataSourceImageExtendSchemaMake()),
|
||||
}
|
||||
}
|
||||
132
internal/service/cloudapi/image/resource_image_virtual.go
Normal file
132
internal/service/cloudapi/image/resource_image_virtual.go
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"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"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/controller"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func resourceImageVirtualCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageVirtualCreate: called for image %s", d.Get("name").(string))
|
||||
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
urlValues.Add("name", d.Get("name").(string))
|
||||
urlValues.Add("targetId", strconv.Itoa(d.Get("target_id").(int)))
|
||||
|
||||
imageId, err := c.DecortAPICall(ctx, "POST", imageCreateVirtualAPI, urlValues)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
d.SetId(imageId)
|
||||
d.Set("image_id", imageId)
|
||||
|
||||
_, err = utilityImageCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
diagnostics := resourceImageRead(ctx, d, m)
|
||||
if diagnostics != nil {
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceImageVirtualEdit(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
|
||||
if d.HasChange("name") {
|
||||
err := resourceImageEditName(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("link_to") {
|
||||
err := resourceImageVirtualLink(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
return resourceImageRead(ctx, d, m)
|
||||
}
|
||||
|
||||
func resourceImageVirtualLink(ctx context.Context, d *schema.ResourceData, m interface{}) error {
|
||||
log.Debugf("resourceVirtualImageLink: called for %s, id: %s", d.Get("name").(string), d.Id())
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
|
||||
urlValues.Add("targetId", strconv.Itoa(d.Get("link_to").(int)))
|
||||
_, err := c.DecortAPICall(ctx, "POST", imageLinkAPI, urlValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResourceImageVirtual() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
SchemaVersion: 1,
|
||||
|
||||
CreateContext: resourceImageVirtualCreate,
|
||||
ReadContext: resourceImageRead,
|
||||
UpdateContext: resourceImageVirtualEdit,
|
||||
DeleteContext: resourceImageDelete,
|
||||
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Create: &constants.Timeout60s,
|
||||
Read: &constants.Timeout30s,
|
||||
Update: &constants.Timeout60s,
|
||||
Delete: &constants.Timeout60s,
|
||||
Default: &constants.Timeout60s,
|
||||
},
|
||||
|
||||
Schema: resourceImageVirtualSchemaMake(dataSourceImageExtendSchemaMake()),
|
||||
}
|
||||
}
|
||||
75
internal/service/cloudapi/image/utility_image.go
Normal file
75
internal/service/cloudapi/image/utility_image.go
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/rudecs/terraform-provider-decort/internal/controller"
|
||||
)
|
||||
|
||||
func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*ImageExtend, error) {
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
if (strconv.Itoa(d.Get("image_id").(int))) != "0" {
|
||||
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
|
||||
} else {
|
||||
urlValues.Add("imageId", d.Id())
|
||||
}
|
||||
|
||||
if showAll, ok := d.GetOk("show_all"); ok {
|
||||
urlValues.Add("page", strconv.FormatBool(showAll.(bool)))
|
||||
}
|
||||
|
||||
resp, err := c.DecortAPICall(ctx, "POST", imageGetAPI, urlValues)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
image := &ImageExtend{}
|
||||
if err := json.Unmarshal([]byte(resp), image); err != nil {
|
||||
return nil, errors.New(fmt.Sprint("Can not unmarshall data to image: ", resp, " ", image))
|
||||
}
|
||||
|
||||
return image, nil
|
||||
}
|
||||
74
internal/service/cloudapi/image/utility_image_list.go
Normal file
74
internal/service/cloudapi/image/utility_image_list.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://github.com/rudecs/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/rudecs/terraform-provider-decort/internal/controller"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (ImageList, error) {
|
||||
imageList := ImageList{}
|
||||
c := m.(*controller.ControllerCfg)
|
||||
urlValues := &url.Values{}
|
||||
|
||||
if accountId, ok := d.GetOk("account_id"); ok {
|
||||
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
|
||||
}
|
||||
|
||||
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)))
|
||||
}
|
||||
|
||||
log.Debugf("utilityImageListCheckPresence: load image list")
|
||||
imageListRaw, err := c.DecortAPICall(ctx, "POST", imageListGetAPI, urlValues)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(imageListRaw), &imageList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return imageList, nil
|
||||
}
|
||||
Reference in New Issue
Block a user