Skip to content

Commit

Permalink
Manila: minor code review and acl import support
Browse files Browse the repository at this point in the history
  • Loading branch information
kayrus committed Jan 4, 2019
1 parent 03b1764 commit 372a7b3
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package openstack

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccSFSV2ShareAccess_importBasic(t *testing.T) {
shareName := "openstack_sharedfilesystem_share_v2.share_1"
shareAccessName := "openstack_sharedfilesystem_share_access_v2.share_access_1"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheckSFS(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSFSV2ShareAccessDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccSFSV2ShareAccessConfig_basic,
},

resource.TestStep{
ResourceName: shareName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testAccSFSV2ShareAccessImportID(shareName, shareAccessName),
},
},
})
}

func testAccSFSV2ShareAccessImportID(shareResource, shareAccessResource string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
share, ok := s.RootModule().Resources[shareResource]
if !ok {
return "", fmt.Errorf("Pool not found: %s", shareResource)
}

shareAccess, ok := s.RootModule().Resources[shareAccessResource]
if !ok {
return "", fmt.Errorf("L7Rule not found: %s", shareAccessResource)
}

return fmt.Sprintf("%s/%s", share.Primary.ID, shareAccess.Primary.ID), nil
}
}
89 changes: 66 additions & 23 deletions openstack/resource_openstack_sharedfilesystem_share_access_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package openstack
import (
"fmt"
"log"
"strings"
"time"

"github.com/hashicorp/terraform/helper/resource"
Expand All @@ -15,9 +16,12 @@ import (

func resourceSharedFilesystemShareAccessV2() *schema.Resource {
return &schema.Resource{
Create: resourceSharedFilesystemShareAccessV2Grant,
Create: resourceSharedFilesystemShareAccessV2Create,
Read: resourceSharedFilesystemShareAccessV2Read,
Delete: resourceSharedFilesystemShareAccessV2Revoke,
Delete: resourceSharedFilesystemShareAccessV2Delete,
Importer: &schema.ResourceImporter{
resourceSharedFilesystemShareAccessV2Import,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Expand Down Expand Up @@ -59,7 +63,7 @@ func resourceSharedFilesystemShareAccessV2() *schema.Resource {
}
}

func resourceSharedFilesystemShareAccessV2Grant(d *schema.ResourceData, meta interface{}) error {
func resourceSharedFilesystemShareAccessV2Create(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
sfsClient, err := config.sharedfilesystemV2Client(GetRegion(d, config))
if err != nil {
Expand All @@ -68,7 +72,7 @@ func resourceSharedFilesystemShareAccessV2Grant(d *schema.ResourceData, meta int

sfsClient.Microversion = minManilaMicroversion

shareId := d.Get("share_id").(string)
shareID := d.Get("share_id").(string)

grantOpts := shares.GrantAccessOpts{
AccessType: d.Get("access_type").(string),
Expand All @@ -83,7 +87,7 @@ func resourceSharedFilesystemShareAccessV2Grant(d *schema.ResourceData, meta int
log.Printf("[DEBUG] Attempting to grant access")
var access *shares.AccessRight
err = resource.Retry(timeout, func() *resource.RetryError {
access, err = shares.GrantAccess(sfsClient, shareId, grantOpts).Extract()
access, err = shares.GrantAccess(sfsClient, shareID, grantOpts).Extract()
if err != nil {
return checkForRetryableError(err)
}
Expand All @@ -98,9 +102,9 @@ func resourceSharedFilesystemShareAccessV2Grant(d *schema.ResourceData, meta int

pending := []string{"new", "queued_to_apply", "applying"}
// Wait for access to become active before continuing
err = waitForSFV2Access(sfsClient, shareId, access.ID, "active", pending, timeout)
err = waitForSFV2Access(sfsClient, shareID, access.ID, "active", pending, timeout)
if err != nil {
return err
return fmt.Errorf("Error waiting for OpenStack share ACL on %s to be applied: %s", shareID, err)
}

return resourceSharedFilesystemShareAccessV2Read(d, meta)
Expand All @@ -115,16 +119,16 @@ func resourceSharedFilesystemShareAccessV2Read(d *schema.ResourceData, meta inte

sfsClient.Microversion = minManilaMicroversion

shareId := d.Get("share_id").(string)
shareID := d.Get("share_id").(string)

access, err := shares.ListAccessRights(sfsClient, shareId).Extract()
access, err := shares.ListAccessRights(sfsClient, shareID).Extract()
if err != nil {
return CheckDeleted(d, err, "share")
}

for _, v := range access {
if v.ID == d.Id() {
log.Printf("[DEBUG] Retrieved access %s: %#v", d.Id(), access)
log.Printf("[DEBUG] Retrieved %s share ACL: %#v", d.Id(), v)

d.Set("access_type", v.AccessType)
d.Set("access_to", v.AccessTo)
Expand All @@ -134,14 +138,13 @@ func resourceSharedFilesystemShareAccessV2Read(d *schema.ResourceData, meta inte
}
}

d.Set("access_type", "")
d.Set("access_to", "")
d.Set("access_level", "")
log.Printf("[DEBUG] Unable to find %s share access", d.Id())
d.SetId("")

return nil
}

func resourceSharedFilesystemShareAccessV2Revoke(d *schema.ResourceData, meta interface{}) error {
func resourceSharedFilesystemShareAccessV2Delete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
sfsClient, err := config.sharedfilesystemV2Client(GetRegion(d, config))
if err != nil {
Expand All @@ -150,43 +153,83 @@ func resourceSharedFilesystemShareAccessV2Revoke(d *schema.ResourceData, meta in

sfsClient.Microversion = minManilaMicroversion

shareId := d.Get("share_id").(string)
shareID := d.Get("share_id").(string)

revokeOpts := shares.RevokeAccessOpts{AccessID: d.Id()}

timeout := d.Timeout(schema.TimeoutDelete)

log.Printf("[DEBUG] Attempting to revoke access %s", d.Id())
err = resource.Retry(timeout, func() *resource.RetryError {
err = shares.RevokeAccess(sfsClient, shareId, revokeOpts).ExtractErr()
err = shares.RevokeAccess(sfsClient, shareID, revokeOpts).ExtractErr()
if err != nil {
return checkForRetryableError(err)
}
return nil
})

if err != nil {
return err
return fmt.Errorf("Error waiting for OpenStack share ACL on %s to be removed: %s", shareID, err)
}

// Wait for access to become deleted before continuing
pending := []string{"new", "queued_to_deny", "denying"}
err = waitForSFV2Access(sfsClient, shareId, d.Id(), "denied", pending, timeout)
err = waitForSFV2Access(sfsClient, shareID, d.Id(), "denied", pending, timeout)
if err != nil {
return err
return fmt.Errorf("Error waiting for OpenStack share ACL on %s to be removed: %s", shareID, err)
}

return nil
}

func resourceSharedFilesystemShareAccessV2Import(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.SplitN(d.Id(), "/", 2)
if len(parts) != 2 {
err := fmt.Errorf("Invalid format specified for Openstack share ACL. Format must be <share id>/<ACL id>")
return nil, err
}

config := meta.(*Config)
sfsClient, err := config.sharedfilesystemV2Client(GetRegion(d, config))
if err != nil {
return nil, fmt.Errorf("Error creating OpenStack sharedfilesystem client: %s", err)
}

sfsClient.Microversion = minManilaMicroversion

shareID := parts[0]
accessID := parts[1]

access, err := shares.ListAccessRights(sfsClient, shareID).Extract()
if err != nil {
return nil, fmt.Errorf("Unable to get %s Openstack share and its ACL's: %s", shareID, err)
}

for _, v := range access {
if v.ID == accessID {
log.Printf("[DEBUG] Retrieved %s share ACL: %#v", accessID, v)

d.SetId(accessID)
d.Set("share_id", shareID)
d.Set("access_type", v.AccessType)
d.Set("access_to", v.AccessTo)
d.Set("access_level", v.AccessLevel)

return []*schema.ResourceData{d}, nil
}
}

return nil, fmt.Errorf("[DEBUG] Unable to find %s share access", accessID)
}

// Full list of the share access statuses: https://developer.openstack.org/api-ref/shared-file-system/?expanded=list-services-detail,list-access-rules-detail#list-access-rules
func waitForSFV2Access(sfsClient *gophercloud.ServiceClient, shareId string, id string, target string, pending []string, timeout time.Duration) error {
func waitForSFV2Access(sfsClient *gophercloud.ServiceClient, shareID string, id string, target string, pending []string, timeout time.Duration) error {
log.Printf("[DEBUG] Waiting for access %s to become %s.", id, target)

stateConf := &resource.StateChangeConf{
Target: []string{target},
Pending: pending,
Refresh: resourceSFV2AccessRefreshFunc(sfsClient, shareId, id),
Refresh: resourceSFV2AccessRefreshFunc(sfsClient, shareID, id),
Timeout: timeout,
Delay: 1 * time.Second,
MinTimeout: 1 * time.Second,
Expand All @@ -208,9 +251,9 @@ func waitForSFV2Access(sfsClient *gophercloud.ServiceClient, shareId string, id
return nil
}

func resourceSFV2AccessRefreshFunc(sfsClient *gophercloud.ServiceClient, shareId string, id string) resource.StateRefreshFunc {
func resourceSFV2AccessRefreshFunc(sfsClient *gophercloud.ServiceClient, shareID string, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
access, err := shares.ListAccessRights(sfsClient, shareId).Extract()
access, err := shares.ListAccessRights(sfsClient, shareID).Extract()
if err != nil {
return nil, "", err
}
Expand Down
17 changes: 10 additions & 7 deletions website/docs/r/sharedfilesystem_share_access_v2.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: |-
Configure a Shared File System share access list.
---

# sharedfilesystem\_share\_access\_v2
# openstack\_sharedfilesystem\_share\_access\_v2

Use this resource to control the share access lists.

Expand All @@ -18,9 +18,6 @@ Use this resource to control the share access lists.
resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
lifecycle {
ignore_changes = ["tags"]
}
}
resource "openstack_networking_subnet_v2" "subnet_1" {
Expand Down Expand Up @@ -59,9 +56,6 @@ resource "openstack_sharedfilesystem_share_access_v2" "share_access_1" {
resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
lifecycle {
ignore_changes = ["tags"]
}
}
resource "openstack_networking_subnet_v2" "subnet_1" {
Expand Down Expand Up @@ -139,3 +133,12 @@ The following arguments are supported:
* `access_type` - See Argument Reference above.
* `access_to` - See Argument Reference above.
* `access_level` - See Argument Reference above.

## Import

This resource can be imported by specifying the ID of the share and the ID of the
share access, separated by a slash, e.g.:

```
$ terraform import openstack_sharedfilesystem_share_access_v2.share_access_1 <share id>/<share access id>
```
3 changes: 0 additions & 3 deletions website/docs/r/sharedfilesystem_share_v2.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ Use this resource to configure a share.
resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
lifecycle {
ignore_changes = ["tags"]
}
}
resource "openstack_networking_subnet_v2" "subnet_1" {
Expand Down

0 comments on commit 372a7b3

Please sign in to comment.