Skip to content

Commit

Permalink
Add support for creating instances with custom volume type (#350)
Browse files Browse the repository at this point in the history
* Add support for creating instances with custom volume type
  • Loading branch information
uzaxirr authored Oct 7, 2024
1 parent d586185 commit ebd1997
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 10 deletions.
10 changes: 10 additions & 0 deletions civo/instances/resource_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ func ResourceInstance() *schema.Resource {
ValidateFunc: utils.ValidateUUID,
Description: "The ID of the firewall to use, from the current list. If left blank or not sent, the default firewall will be used (open to all)",
},
"volume_type": {
Type: schema.TypeString,
Optional: true,
Description: "The type of volume to use, either 'ssd' or 'bssd' (optional; default 'ssd')",
},
"tags": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -240,6 +245,10 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
config.ReservedIPv4 = v.(string)
}

if v, ok := d.GetOk("volume_type"); ok {
config.VolumeType = v.(string)
}

if networtID, ok := d.GetOk("network_id"); ok {
config.NetworkID = networtID.(string)
} else {
Expand Down Expand Up @@ -395,6 +404,7 @@ func resourceInstanceRead(_ context.Context, d *schema.ResourceData, m interface
d.Set("created_at", resp.CreatedAt.UTC().String())
d.Set("notes", resp.Notes)
d.Set("disk_image", diskImg.ID)
d.Set("volume_type", resp.VolumeType)

if resp.PublicIP != "" {
d.Set("public_ip_required", "create")
Expand Down
6 changes: 3 additions & 3 deletions civo/kubernetes/resource_kubernetes_cluster_nodepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func ResourceKubernetesClusterNodePool() *schema.Resource {
func resourceKubernetesClusterNodePoolCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
apiClient := m.(*civogo.Client)

// overwrite the region if is define in the datasource
// overwrite the region if is defined in the datasource
if region, ok := d.GetOk("region"); ok {
apiClient.Region = region.(string)
}
Expand Down Expand Up @@ -95,7 +95,7 @@ func resourceKubernetesClusterNodePoolCreate(ctx context.Context, d *schema.Reso
}
}

newPool := &civogo.KubernetesClusterPoolUpdateConfig{
newPool := &civogo.KubernetesClusterPoolConfig{
ID: nodePoolLabel,
Count: count,
Size: size,
Expand Down Expand Up @@ -211,7 +211,7 @@ func resourceKubernetesClusterNodePoolUpdate(ctx context.Context, d *schema.Reso
}

if d.HasChange("node_count") {
poolUpdate.Count = d.Get("node_count").(int)
poolUpdate.Count = d.Get("node_count").(*int)
}

if d.HasChange("labels") {
Expand Down
70 changes: 70 additions & 0 deletions civo/volume/datasource_volumetype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package volume

import (
"context"
"github.com/civo/civogo"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// DataSourceVolumeType function returns a schema.Resource that represents a Volume.
// This can be used to query and retrieve details about a specific Volume in the infrastructure using its id or name.
func DataSourceVolumeType() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceCivoVolumeTypeRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"labels": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func dataSourceCivoVolumeTypeRead(_ context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*civogo.Client)

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

// Get the name of the volume type from the Terraform configuration
volumeTypeName := d.Get("name").(string)

// Fetch all volume types
volumeTypes, err := client.ListVolumeTypes()
if err != nil {
return diag.Errorf("[ERR] failed to retrieve volume type: %s", err)
}

// Find the specific volume type by name
var foundVolumeType *civogo.VolumeType
for _, vt := range volumeTypes {
if vt.Name == volumeTypeName {
foundVolumeType = &vt
break
}
}

// If the volume type is not found, return an error
if foundVolumeType == nil {
return diag.Errorf("volume type with name '%s' not found", volumeTypeName)
}

// Set the data source's ID and output fields
d.SetId(foundVolumeType.Name)
if err := d.Set("labels", foundVolumeType.Labels); err != nil {
return diag.Errorf("[ERR] failed to set volume labels: %s", err)
}

return nil
}
13 changes: 12 additions & 1 deletion civo/volume/resource_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func ResourceVolume() *schema.Resource {
Computed: true,
Description: "The mount point of the volume (from instance's perspective)",
},
"volume_type": {
Type: schema.TypeString,
Optional: true,
Description: "The type of the volume",
},
},
CreateContext: resourceVolumeCreate,
ReadContext: resourceVolumeRead,
Expand All @@ -61,19 +66,24 @@ func ResourceVolume() *schema.Resource {
func resourceVolumeCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
apiClient := m.(*civogo.Client)

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

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),
Region: apiClient.Region,
}

if v, ok := d.GetOk("volume_type"); ok {
config.VolumeType = v.(string)
}

_, err := apiClient.FindNetwork(config.NetworkID)
if err != nil {
return diag.Errorf("[ERR] Unable to find network ID %q in %q region", config.NetworkID, config.Region)
Expand Down Expand Up @@ -132,6 +142,7 @@ func resourceVolumeRead(_ context.Context, d *schema.ResourceData, m interface{}
d.Set("network_id", resp.NetworkID)
d.Set("size_gb", resp.SizeGigabytes)
d.Set("mount_point", resp.MountPoint)
d.Set("volume_type", resp.VolumeType)

return nil
}
Expand Down
21 changes: 20 additions & 1 deletion civo/volume/resource_volume_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func ResourceVolumeAttachment() *schema.Resource {
// function to create the new volume
func resourceVolumeAttachmentCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
apiClient := m.(*civogo.Client)
var diags diag.Diagnostics

// overwrite the region if it's defined
if region, ok := d.GetOk("region"); ok {
Expand All @@ -57,6 +58,7 @@ func resourceVolumeAttachmentCreate(ctx context.Context, d *schema.ResourceData,

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

log.Printf("[INFO] retrieving the volume %s", volumeID)
volume, err := apiClient.FindVolume(volumeID)
Expand All @@ -65,8 +67,25 @@ func resourceVolumeAttachmentCreate(ctx context.Context, d *schema.ResourceData,
}

if volume.InstanceID == "" || volume.InstanceID != instanceID {

vuc := civogo.VolumeAttachConfig{
InstanceID: instanceID,
Region: apiClient.Region,
}

if attachAtBoot {
// Notify the terminal
msg := fmt.Sprintf("To use the volume %s, The instance %s needs to be rebooted", volumeID, instanceID)
diags = append(diags, diag.Diagnostic{
Severity: diag.Warning,
Summary: msg,
})

vuc.AttachAtBoot = true
}

log.Printf("[INFO] attaching the volume %s to instance %s", volumeID, instanceID)
_, err := apiClient.AttachVolume(volumeID, instanceID)
_, err := apiClient.AttachVolume(volumeID, vuc)
if err != nil {
return diag.Errorf("[ERR] error attaching volume to instance %s", err)
}
Expand Down
2 changes: 2 additions & 0 deletions docs/resources/instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ resource "civo_instance" "example" {
network_id = civo_network.example.id
size = "g3.xsmall"
disk_image = data.civo_disk_image.debian.diskimages[0].id
volume_type = "csi-s3"
}
```
Expand Down Expand Up @@ -145,6 +146,7 @@ resource "civo_instance" "example" {
- `tags` (Set of String) An optional list of tags, represented as a key, value pair
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) defines timeouts for cluster creation, read and update, default is 30 minutes for all
- `write_password` (Boolean) If set to true then initial_password for the instance will be saved to terraform state file. (default: false)
- `volume_type` (string) Type of volume that instance should be created with, e.g: ms-xfs-2-replicas, px-csi-db (default: csi-s3)

<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module github.com/civo/terraform-provider-civo

require (
github.com/civo/civogo v0.3.74
github.com/civo/civogo v0.3.84
github.com/google/uuid v1.3.1
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmms
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/civo/civogo v0.3.73 h1:thkNnkziU+xh+MEOChIUwRZI1forN20+SSAPe/VFDME=
github.com/civo/civogo v0.3.73/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
github.com/civo/civogo v0.3.74 h1:MPrInhgOIuNOfcg1soyX2pm2L0nUa3/+No5hEgFgAuc=
github.com/civo/civogo v0.3.74/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
github.com/civo/civogo v0.3.84 h1:jf5IT7VJFPaReO6g8B0zqKhsYCIizaGo4PjDLY7Sl6Y=
github.com/civo/civogo v0.3.84/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
Expand Down

0 comments on commit ebd1997

Please sign in to comment.