Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Volumes management #69

Merged
merged 4 commits into from
Aug 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 109 additions & 54 deletions civo/resource_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package civo
import (
"fmt"
"log"
"time"

"github.com/civo/civogo"
"github.com/civo/terraform-provider-civo/internal/utils"
Expand All @@ -26,33 +25,29 @@ func resourceVolume() *schema.Resource {
Required: true,
Description: "A minimum of 1 and a maximum of your available disk space from your quota specifies the size of the volume in gigabytes ",
},
"bootable": {
Type: schema.TypeBool,
Required: true,
Description: "Mark the volume as bootable",
},
"region": {
Type: schema.TypeString,
Optional: true,
Description: "The region for the volume",
},
"network_id": {
Type: schema.TypeString,
Required: true,
Description: "The network that the volume belongs to",
},
// Computed resource
"mount_point": {
Type: schema.TypeString,
Computed: true,
},
"created_at": {
Type: schema.TypeString,
Computed: true,
},
},
Create: resourceVolumeCreate,
Read: resourceVolumeRead,
Update: resourceVolumeUpdate,
Delete: resourceVolumeDelete,
//Exists: resourceExistsItem,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
State: resourceVolumeImport,
},
}
}
Expand All @@ -61,17 +56,23 @@ func resourceVolume() *schema.Resource {
func resourceVolumeCreate(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

log.Printf("[INFO] configuring the volume %s", d.Get("name").(string))
config := &civogo.VolumeConfig{
Name: d.Get("name").(string),
SizeGigabytes: d.Get("size_gb").(int),
NetworkID: d.Get("network_id").(string),
}

// overwrite the region if is define in the datasource
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
currentRegion := region.(string)
apiClient.Region = currentRegion
config.Region = currentRegion
}

log.Printf("[INFO] configuring the volume %s", d.Get("name").(string))
config := &civogo.VolumeConfig{Name: d.Get("name").(string), SizeGigabytes: d.Get("size_gb").(int), Bootable: d.Get("bootable").(bool)}

volume, err := apiClient.NewVolume(config)
if err != nil {
return fmt.Errorf("[ERR] failed to create a new config: %s", err)
return fmt.Errorf("[ERR] failed to create a new volume: %s", err)
}

d.SetId(volume.ID)
Expand Down Expand Up @@ -99,59 +100,71 @@ func resourceVolumeRead(d *schema.ResourceData, m interface{}) error {
}

d.Set("name", resp.Name)
d.Set("network_id", resp.NetworkID)
d.Set("size_gb", resp.SizeGigabytes)
d.Set("bootable", resp.Bootable)
d.Set("mount_point", resp.MountPoint)
d.Set("created_at", resp.CreatedAt.UTC().String())

return nil
}

// function to update the volume
func resourceVolumeUpdate(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)
/*
apiClient := m.(*civogo.Client)

// overwrite the region if is define in the datasource
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}
// overwrite the region if is define in the datasource
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}

log.Printf("[INFO] retrieving the volume %s", d.Id())
resp, err := apiClient.FindVolume(d.Id())
if err != nil {
return fmt.Errorf("[ERR] failed retrieving the volume: %s", err)
}
log.Printf("[INFO] retrieving the volume %s", d.Id())
resp, err := apiClient.FindVolume(d.Id())
if err != nil {
return fmt.Errorf("[ERR] failed retrieving the volume: %s", err)
}
*/

if d.HasChange("size_gb") {
if resp.InstanceID != "" {
_, err := apiClient.DetachVolume(d.Id())
if err != nil {
return fmt.Errorf("[WARN] an error occurred while tring to detach volume %s, %s", d.Id(), err)
}

time.Sleep(10 * time.Second)

newSize := d.Get("size_gb").(int)
_, err = apiClient.ResizeVolume(d.Id(), newSize)
if err != nil {
return fmt.Errorf("[ERR] the volume (%s) size not change %s", d.Id(), err)
}

time.Sleep(2 * time.Second)

_, err = apiClient.AttachVolume(d.Id(), resp.InstanceID)
if err != nil {
return fmt.Errorf("[ERR] an error occurred while tring to attach the volume %s", d.Id())
return fmt.Errorf("[ERR] Resize operation is not available at this moment - we are working to re-enable it soon")

/*
if resp.InstanceID != "" {
_, err := apiClient.DetachVolume(d.Id())
if err != nil {
return fmt.Errorf("[WARN] an error occurred while trying to detach volume %s, %s", d.Id(), err)
}

time.Sleep(10 * time.Second)

newSize := d.Get("size_gb").(int)
_, err = apiClient.ResizeVolume(d.Id(), newSize)
if err != nil {
return fmt.Errorf("[ERR] the volume (%s) size not change %s", d.Id(), err)
}

time.Sleep(2 * time.Second)

_, err = apiClient.AttachVolume(d.Id(), resp.InstanceID)
if err != nil {
return fmt.Errorf("[ERR] an error occurred while tring to attach the volume %s", d.Id())
}

} else {
newSize := d.Get("size_gb").(int)
_, err = apiClient.ResizeVolume(d.Id(), newSize)
if err != nil {
return fmt.Errorf("[ERR] the volume (%s) size not change %s", d.Id(), err)
}
}
*/
}

} else {
newSize := d.Get("size_gb").(int)
_, err = apiClient.ResizeVolume(d.Id(), newSize)
if err != nil {
return fmt.Errorf("[ERR] the volume (%s) size not change %s", d.Id(), err)
}
}
if d.HasChange("network_id") {
return fmt.Errorf("[ERR] Network change for volume is not supported at this moment")
}

if d.HasChange("name") {
return fmt.Errorf("[ERR] Name change for volume is not supported at this moment")
}

return resourceVolumeRead(d, m)
Expand All @@ -173,3 +186,45 @@ func resourceVolumeDelete(d *schema.ResourceData, m interface{}) error {
}
return nil
}

// custom import to able to import a volume
func resourceVolumeImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
apiClient := m.(*civogo.Client)
regions, err := apiClient.ListRegions()
if err != nil {
return nil, err
}

volumeFound := false
for _, region := range regions {
if volumeFound {
break
}

currentRegion := region.Code
apiClient.Region = currentRegion

volumes, err := apiClient.ListVolumes()
if err != nil {
return nil, err
}

for _, volume := range volumes {
if volume.ID == d.Id() {
volumeFound = true
d.SetId(volume.ID)
d.Set("name", volume.Name)
d.Set("network_id", volume.NetworkID)
d.Set("region", currentRegion)
d.Set("size_gb", volume.SizeGigabytes)
d.Set("mount_point", volume.MountPoint)
}
}
}

if !volumeFound {
return nil, fmt.Errorf("[ERR] Volume %s not found", d.Id())
}

return []*schema.ResourceData{d}, nil
}
21 changes: 21 additions & 0 deletions civo/resource_volume_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ func resourceVolumeAttachment() *schema.Resource {
ForceNew: true,
ValidateFunc: validation.NoZeroValues,
},
"region": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: "The region for the volume attachment",
},
},
Create: resourceVolumeAttachmentCreate,
Read: resourceVolumeAttachmentRead,
Expand All @@ -39,6 +45,11 @@ func resourceVolumeAttachment() *schema.Resource {
func resourceVolumeAttachmentCreate(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

// overwrite the region if it's defined
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}

instanceID := d.Get("instance_id").(string)
volumeID := d.Get("volume_id").(string)

Expand Down Expand Up @@ -66,6 +77,11 @@ func resourceVolumeAttachmentCreate(d *schema.ResourceData, m interface{}) error
func resourceVolumeAttachmentRead(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

// overwrite the region if it's defined
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}

instanceID := d.Get("instance_id").(string)
volumeID := d.Get("volume_id").(string)

Expand All @@ -92,6 +108,11 @@ func resourceVolumeAttachmentRead(d *schema.ResourceData, m interface{}) error {
func resourceVolumeAttachmentDelete(d *schema.ResourceData, m interface{}) error {
apiClient := m.(*civogo.Client)

// overwrite the region if it's defined
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}

volumeID := d.Get("volume_id").(string)

log.Printf("[INFO] Detaching the volume %s", d.Id())
Expand Down
11 changes: 5 additions & 6 deletions docs/resources/volume.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ resource "civo_volume" "db" {

The following arguments are supported:

* `name` - (Required) A name that you wish to use to refer to this volume .
* `size_gb` - (Required) A minimum of 1 and a maximum of your available disk space from your quota specifies the size of the volume in gigabytes .
* `bootable` - (Required) Mark the volume as bootable.
* `name` - (Required) A name that you wish to use to refer to this volume.
* `size_gb` - (Required) A minimum of 1 and a maximum of your available disk space from your quota specifies the size of the volume in gigabytes.
* `network_id` - (Required) The network that the volume belongs to.

## Attributes Reference

Expand All @@ -35,9 +35,8 @@ The following attributes are exported:
* `id` - The unique identifier for the volume.
* `name` - Name of the volume.
* `size_gb` - The size of the volume.
* `bootable` - if is bootable or not.
* `mount_point` - The mount point of the volume.
* `created_at` - The date of the creation of the volume.
* `mount_point` - The mount point of the volume.
* `network_id` - The network that the volume belongs to.

## Import

Expand Down