Skip to content
Open
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
17 changes: 10 additions & 7 deletions digitalocean/nfs/datasource_nfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ func DataSourceDigitalOceanNfs() *schema.Resource {
Type: schema.TypeInt,
Computed: true,
Description: "the size of the share in gigabytes",
},
"status": {
}, "performance_tier": {
Type: schema.TypeString,
Computed: true,
Description: "the performance tier of the share",
}, "status": {
Type: schema.TypeString,
Computed: true,
},
Expand All @@ -63,16 +66,15 @@ func dataSourceDigitalOceanNfsRead(ctx context.Context, d *schema.ResourceData,

name := d.Get("name").(string)

region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

opts := &godo.ListOptions{
PerPage: 200,
}

if s, ok := d.GetOk("region"); ok {
region = s.(string)
}

sharesList := []*godo.Nfs{}

for {
Expand Down Expand Up @@ -106,6 +108,7 @@ func dataSourceDigitalOceanNfsRead(ctx context.Context, d *schema.ResourceData,
d.Set("name", share.Name)
d.Set("region", share.Region)
d.Set("size", share.SizeGib)
d.Set("performance_tier", share.PerformanceTier)
d.Set("status", share.Status)
d.Set("host", share.Host)
d.Set("mount_path", share.MountPath)
Expand Down
7 changes: 5 additions & 2 deletions digitalocean/nfs/datasource_nfs_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ func dataSourceDigitalOceanNfsSnapshotRead(ctx context.Context, d *schema.Resour

name, hasName := d.GetOk("name")
nameRegex, hasNameRegex := d.GetOk("name_regex")
region := d.Get("region")
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}
shareID := d.Get("share_id").(string)

if !hasName && !hasNameRegex {
Expand All @@ -83,7 +86,7 @@ func dataSourceDigitalOceanNfsSnapshotRead(ctx context.Context, d *schema.Resour
var snapshotList []godo.NfsSnapshot

for {
snapshots, resp, err := client.Nfs.ListSnapshots(context.Background(), opts, shareID, region.(string))
snapshots, resp, err := client.Nfs.ListSnapshots(context.Background(), opts, shareID, region)

if err != nil {
return diag.Errorf("Error retrieving share snapshots: %s", err)
Expand Down
76 changes: 68 additions & 8 deletions digitalocean/nfs/resource_nfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ func ResourceDigitalOceanNfs() *schema.Resource {
Required: true,
ValidateFunc: validation.IntAtLeast(50),
},
"performance_tier": {
Type: schema.TypeString,
Optional: true,
Default: "standard",
ValidateFunc: validation.StringInSlice([]string{
"standard",
"high",
}, false),
Description: "Performance tier for the NFS share (standard or high)",
},
"status": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -105,6 +115,9 @@ func resourceDigitalOceanNfsCreate(ctx context.Context, d *schema.ResourceData,
if v, ok := d.GetOk("vpc_id"); ok && v.(string) != "" {
opts.VpcIDs = []string{v.(string)}
}
if v, ok := d.GetOk("performance_tier"); ok {
opts.PerformanceTier = v.(string)
}

log.Printf("[DEBUG] Nfs create configuration: %#v", opts)
share, _, err := client.Nfs.Create(context.Background(), opts)
Expand All @@ -126,8 +139,10 @@ func resourceDigitalOceanNfsCreate(ctx context.Context, d *schema.ResourceData,

func resourceDigitalOceanNfsUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.CombinedConfig).GodoClient()
region := strings.ToLower(d.Get("region").(string))

region := ""
if v, ok := d.GetOk("region"); ok {
region = strings.ToLower(v.(string))
}
if d.HasChange("size") {
size := d.Get("size").(int)

Expand All @@ -137,7 +152,16 @@ func resourceDigitalOceanNfsUpdate(ctx context.Context, d *schema.ResourceData,
}

// Wait for resize to complete
err = waitForNfsResize(ctx, client, d.Id(), d.Get("region").(string), d.Get("size").(int))
err = waitForNfsResize(ctx, client, d.Id(), region, d.Get("size").(int))
if err != nil {
return diag.FromErr(err)
}
}

if d.HasChange("performance_tier") {
tier := d.Get("performance_tier").(string)

err := switchNfsPerformanceTier(ctx, client, d.Id(), region, tier)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -180,10 +204,39 @@ func waitForNfsActive(ctx context.Context, client *godo.Client, id, region strin
return fmt.Errorf("timeout waiting for NFS share to become active")
}

// switchNfsPerformanceTier switches the performance tier of an NFS share
// and waits for the operation to complete
func switchNfsPerformanceTier(ctx context.Context, client *godo.Client, id, region, tier string) error {
log.Printf("[INFO] Switching NFS share %s to performance tier: %s", id, tier)

// Validate tier
if tier != "standard" && tier != "high" && tier != "high_performance" {
return fmt.Errorf("invalid performance tier: %s. Must be 'standard' or 'high'", tier)
}

// Initiate the tier switch
_, _, err := client.NfsActions.SwitchPerformanceTier(ctx, id, tier)
if err != nil {
return fmt.Errorf("error switching performance tier: %s", err)
}

// Wait for the operation to complete
err = waitForNfsActive(ctx, client, id, region)
if err != nil {
return fmt.Errorf("error waiting for performance tier switch: %s", err)
}

log.Printf("[INFO] Successfully switched NFS share %s to performance tier: %s", id, tier)
return nil
}

func resourceDigitalOceanNfsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.CombinedConfig).GodoClient()

share, resp, err := client.Nfs.Get(context.Background(), d.Id(), d.Get("region").(string))
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}
share, resp, err := client.Nfs.Get(context.Background(), d.Id(), region)
if err != nil {
// If the share is somehow already destroyed, mark as
// successfully gone
Expand All @@ -202,6 +255,7 @@ func resourceDigitalOceanNfsRead(ctx context.Context, d *schema.ResourceData, me
d.Set("vpc_id", share.VpcIDs[0])
d.Set("host", share.Host)
d.Set("mount_path", share.MountPath)
d.Set("performance_tier", share.PerformanceTier)

if err = d.Set("vpc_ids", flattenDigitalOceanShareVpcIds(share.VpcIDs)); err != nil {
return diag.Errorf("[DEBUG] Error setting vpc_ids: %#v", err)
Expand All @@ -212,9 +266,12 @@ func resourceDigitalOceanNfsRead(ctx context.Context, d *schema.ResourceData, me

func resourceDigitalOceanNfsDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.CombinedConfig).GodoClient()

region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}
log.Printf("[INFO] Deleting share: %s", d.Id())
_, err := client.Nfs.Delete(context.Background(), d.Id(), d.Get("region").(string))
_, err := client.Nfs.Delete(context.Background(), d.Id(), region)
if err != nil {
return diag.Errorf("Error deleting share: %s", err)
}
Expand All @@ -241,7 +298,10 @@ func resourceDigitalOceanNfsImport(ctx context.Context, d *schema.ResourceData,

// Verify the resource exists before calling Read
client := meta.(*config.CombinedConfig).GodoClient()
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

_, resp, err := client.Nfs.Get(ctx, d.Id(), region)
if err != nil {
Expand Down
15 changes: 12 additions & 3 deletions digitalocean/nfs/resource_nfs_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ func resourceDigitalOceanNfsAttachmentCreate(ctx context.Context, d *schema.Reso

vpcId := d.Get("vpc_id").(string)
shareId := d.Get("share_id").(string)
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

share, _, err := client.Nfs.Get(context.Background(), shareId, region)
if err != nil {
Expand Down Expand Up @@ -144,7 +147,10 @@ func resourceDigitalOceanNfsAttachmentRead(ctx context.Context, d *schema.Resour

vpcId := d.Get("vpc_id").(string)
shareId := d.Get("share_id").(string)
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

share, resp, err := client.Nfs.Get(context.Background(), shareId, region)
if err != nil {
Expand All @@ -171,7 +177,10 @@ func resourceDigitalOceanNfsAttachmentDelete(ctx context.Context, d *schema.Reso

vpcId := d.Get("vpc_id").(string)
shareId := d.Get("share_id").(string)
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

// Only one nfs can be detached at one time to a single vpc.
err := retry.RetryContext(ctx, 5*time.Minute, func() *retry.RetryError {
Expand Down
15 changes: 12 additions & 3 deletions digitalocean/nfs/resource_nfs_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ func resourceDigitalOceanNfsSnapshotCreate(ctx context.Context, d *schema.Resour

name := d.Get("name").(string)
shareID := d.Get("share_id").(string)
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

snapshot, _, err := client.NfsActions.Snapshot(context.Background(), shareID, name, region)
if err != nil {
Expand All @@ -81,7 +84,10 @@ func resourceDigitalOceanNfsSnapshotCreate(ctx context.Context, d *schema.Resour

func resourceDigitalOceanNfsSnapshotRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.CombinedConfig).GodoClient()
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}
snapshot, resp, err := client.Nfs.GetSnapshot(context.Background(), d.Id(), region)
if err != nil {
// If the snapshot is somehow already destroyed, mark as
Expand All @@ -106,7 +112,10 @@ func resourceDigitalOceanNfsSnapshotRead(ctx context.Context, d *schema.Resource

func resourceDigitalOceanNfsSnapshotDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*config.CombinedConfig).GodoClient()
region := d.Get("region").(string)
region := ""
if v, ok := d.GetOk("region"); ok {
region = v.(string)
}

log.Printf("[INFO] Deleting snapshot: %s", d.Id())
_, err := client.Nfs.DeleteSnapshot(context.Background(), d.Id(), region)
Expand Down
83 changes: 83 additions & 0 deletions digitalocean/nfs/resource_nfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ resource "digitalocean_vpc" "foobar" {
}`, name, size, name)
}

func testAccCheckDigitalOceanNfsConfig_performanceTier(name, tier string) string {
return fmt.Sprintf(`
resource "digitalocean_nfs" "foobar" {
region = "atl1"
name = "%s"
size = 60
vpc_id = digitalocean_vpc.foobar.id
performance_tier = "%s"
}

resource "digitalocean_vpc" "foobar" {
name = "%s-vpc"
region = "atl1"
}`, name, tier, name)
}

func TestAccDigitalOceanNfs_Basic(t *testing.T) {
name := acceptance.RandomTestName("nfs")
var share godo.Nfs
Expand All @@ -57,6 +73,7 @@ func TestAccDigitalOceanNfs_Basic(t *testing.T) {
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "name", name),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "region", "atl1"),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "size", "60"),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "performance_tier", "standard"),
resource.TestCheckResourceAttrSet("digitalocean_nfs.foobar", "host"),
resource.TestCheckResourceAttrSet("digitalocean_nfs.foobar", "mount_path"),
),
Expand Down Expand Up @@ -117,6 +134,42 @@ func TestAccDigitalOceanNfs_ShrinkError(t *testing.T) {
})
}

func TestAccDigitalOceanNfs_PerformanceTier(t *testing.T) {
resourceName := "digitalocean_nfs.foobar"
name := acceptance.RandomTestName("nfs")
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheck(t) },
ProviderFactories: acceptance.TestAccProviderFactories,
CheckDestroy: testAccCheckDigitalOceanNfsDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckDigitalOceanNfsConfig_performanceTier(name, "standard"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDataSourceDigitalOceanNfsIsActive(resourceName),
testAccCheckDigitalOceanNfsPerformanceTier(resourceName, "standard"),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "performance_tier", "standard"),
),
},
{
Config: testAccCheckDigitalOceanNfsConfig_performanceTier(name, "high"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDataSourceDigitalOceanNfsIsActive(resourceName),
testAccCheckDigitalOceanNfsPerformanceTier(resourceName, "high"),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "performance_tier", "high"),
),
},
{
Config: testAccCheckDigitalOceanNfsConfig_performanceTier(name, "standard"),
Check: resource.ComposeTestCheckFunc(
testAccCheckDataSourceDigitalOceanNfsIsActive(resourceName),
testAccCheckDigitalOceanNfsPerformanceTier(resourceName, "standard"),
resource.TestCheckResourceAttr("digitalocean_nfs.foobar", "performance_tier", "standard"),
),
},
},
})
}

func testAccCheckDigitalOceanNfsExists(rn string, share *godo.Nfs) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[rn]
Expand Down Expand Up @@ -161,3 +214,33 @@ func testAccCheckDigitalOceanNfsSize(resourceName string, expectedSize int) reso
return fmt.Errorf("NFS share did not reach expected size %d within timeout", expectedSize)
}
}

func testAccCheckDigitalOceanNfsPerformanceTier(resourceName string, expectedTier string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}

client := acceptance.TestAccProvider.Meta().(*config.CombinedConfig).GodoClient()
region := rs.Primary.Attributes["region"]

// Poll until API matches (5 minutes timeout)
for i := 0; i < 60; i++ {
share, _, err := client.Nfs.Get(context.Background(), rs.Primary.ID, region)
if err != nil {
return err
}

if share.PerformanceTier == expectedTier && share.Status == "ACTIVE" {
// Give Terraform a moment to refresh state after API is ready
time.Sleep(2 * time.Second)
return nil
}

time.Sleep(5 * time.Second)
}

return fmt.Errorf("NFS share did not reach expected performance tier %s within timeout", expectedTier)
}
}
1 change: 1 addition & 0 deletions docs/data-sources/nfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ The following attributes are exported:
* `name` - Name of the NFS share.
* `region` - The region where the NFS share is located.
* `size` - The size of the NFS share in GiB.
* `performance_tier` - The performance tier of the NFS share (`standard` or `high`).
* `status` - The current status of the NFS share.
* `host` - The host IP of the NFS server accessible from the associated VPC.
* `mount_path` - The mount path for accessing the NFS share.
Loading