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

Manila: add List for share-access-rules API #2512

Merged
merged 1 commit into from
Feb 23, 2023
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
55 changes: 55 additions & 0 deletions acceptance/openstack/sharedfilesystems/v2/shareaccessrules.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package v2

import (
"fmt"
"testing"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shareaccessrules"
"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shares"
)

func ShareAccessRuleGet(t *testing.T, client *gophercloud.ServiceClient, accessID string) (*shareaccessrules.ShareAccess, error) {
Expand All @@ -16,3 +19,55 @@ func ShareAccessRuleGet(t *testing.T, client *gophercloud.ServiceClient, accessI

return accessRule, nil
}

// AccessRightToShareAccess is a helper function that converts
// shares.AccessRight into shareaccessrules.ShareAccess struct.
func AccessRightToShareAccess(accessRight *shares.AccessRight) *shareaccessrules.ShareAccess {
return &shareaccessrules.ShareAccess{
ShareID: accessRight.ShareID,
AccessType: accessRight.AccessType,
AccessTo: accessRight.AccessTo,
AccessKey: accessRight.AccessKey,
AccessLevel: accessRight.AccessLevel,
State: accessRight.State,
ID: accessRight.ID,
}
}
Comment on lines +23 to +35
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing -- we have shares.AccessRight and shareaccessrules.ShareAccess. shareaccessrules describes a new API, so technically it ought to be its own package and struct, but in the end it describes the same information as shares.AccessRight does. I'm just pointing this out, but if reviewers are ok with this split, we can move on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me. We can always split that into a separate package later if that bothers us.


func WaitForShareAccessRule(t *testing.T, client *gophercloud.ServiceClient, accessRule *shareaccessrules.ShareAccess, status string) error {
if accessRule.State == status {
return nil
}

return tools.WaitFor(func() (bool, error) {
latest, err := ShareAccessRuleGet(t, client, accessRule.ID)
if err != nil {
gman0 marked this conversation as resolved.
Show resolved Hide resolved
if _, ok := err.(gophercloud.ErrDefault404); ok {
return false, nil
}

return false, err
}

if latest.State == status {
*accessRule = *latest
return true, nil
}

if latest.State == "error" {
return false, fmt.Errorf("share access rule %s for share %s is in error state", accessRule.ID, accessRule.ShareID)
}

return false, nil
})
}

func ShareAccessRuleList(t *testing.T, client *gophercloud.ServiceClient, shareID string) ([]shareaccessrules.ShareAccess, error) {
accessRules, err := shareaccessrules.List(client, shareID).Extract()
if err != nil {
t.Logf("Failed to list share access rules for share %s: %v", shareID, err)
return nil, err
}

return accessRules, nil
}
75 changes: 65 additions & 10 deletions acceptance/openstack/sharedfilesystems/v2/shareaccessrules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,78 @@ func TestShareAccessRulesGet(t *testing.T) {

defer DeleteShare(t, client, share)

shareAccessRight, err := GrantAccess(t, client, share)
addedAccessRight, err := GrantAccess(t, client, share)
if err != nil {
t.Fatalf("Unable to grant access to share %s: %v", share.ID, err)
}

accessRule, err := ShareAccessRuleGet(t, client, shareAccessRight.ID)
addedShareAccess := AccessRightToShareAccess(addedAccessRight)

accessRule, err := ShareAccessRuleGet(t, client, addedShareAccess.ID)
if err != nil {
t.Logf("Unable to get share access rule for share %s: %v", share.ID, err)
t.Fatalf("Unable to get share access rule for share %s: %v", share.ID, err)
}

if err = WaitForShareAccessRule(t, client, accessRule, "active"); err != nil {
t.Fatalf("Unable to wait for share access rule to achieve 'active' state: %v", err)
}

tools.PrintResource(t, accessRule)

th.AssertEquals(t, shareAccessRight.ID, accessRule.ID)
th.AssertEquals(t, shareAccessRight.ShareID, accessRule.ShareID)
th.AssertEquals(t, shareAccessRight.AccessType, accessRule.AccessType)
th.AssertEquals(t, shareAccessRight.AccessLevel, accessRule.AccessLevel)
th.AssertEquals(t, shareAccessRight.AccessTo, accessRule.AccessTo)
th.AssertEquals(t, shareAccessRight.AccessKey, accessRule.AccessKey)
th.AssertEquals(t, shareAccessRight.State, accessRule.State)
th.AssertEquals(t, addedShareAccess.ID, accessRule.ID)
th.AssertEquals(t, addedShareAccess.AccessType, accessRule.AccessType)
th.AssertEquals(t, addedShareAccess.AccessLevel, accessRule.AccessLevel)
th.AssertEquals(t, addedShareAccess.AccessTo, accessRule.AccessTo)
th.AssertEquals(t, addedShareAccess.AccessKey, accessRule.AccessKey)
th.AssertEquals(t, share.ID, accessRule.ShareID)
th.AssertEquals(t, "active", accessRule.State)
}

func TestShareAccessRulesList(t *testing.T) {
client, err := clients.NewSharedFileSystemV2Client()
if err != nil {
t.Fatalf("Unable to create a shared file system client: %v", err)
}

client.Microversion = "2.49"

share, err := CreateShare(t, client)
if err != nil {
t.Fatalf("Unable to create a share: %v", err)
}

defer DeleteShare(t, client, share)

addedAccessRight, err := GrantAccess(t, client, share)
if err != nil {
t.Fatalf("Unable to grant access to share %s: %v", share.ID, err)
}

addedShareAccess := AccessRightToShareAccess(addedAccessRight)

if err = WaitForShareAccessRule(t, client, addedShareAccess, "active"); err != nil {
t.Fatalf("Unable to wait for share access rule to achieve 'active' state: %v", err)
}

accessRules, err := ShareAccessRuleList(t, client, share.ID)
if err != nil {
t.Logf("Unable to list share access rules for share %s: %v", share.ID, err)
}

tools.PrintResource(t, accessRules)

th.AssertEquals(t, 1, len(accessRules))

accessRule := accessRules[0]

if err = WaitForShareAccessRule(t, client, &accessRule, "active"); err != nil {
t.Fatalf("Unable to wait for share access rule to achieve 'active' state: %v", err)
}

th.AssertEquals(t, addedShareAccess.ID, accessRule.ID)
th.AssertEquals(t, addedShareAccess.AccessType, accessRule.AccessType)
th.AssertEquals(t, addedShareAccess.AccessLevel, accessRule.AccessLevel)
th.AssertEquals(t, addedShareAccess.AccessTo, accessRule.AccessTo)
th.AssertEquals(t, addedShareAccess.AccessKey, accessRule.AccessKey)
th.AssertEquals(t, addedShareAccess.State, accessRule.State)
}
7 changes: 7 additions & 0 deletions openstack/sharedfilesystems/v2/shareaccessrules/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ func Get(client *gophercloud.ServiceClient, accessID string) (r GetResult) {
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}

// List gets all access rules of a share.
func List(client *gophercloud.ServiceClient, shareID string) (r ListResult) {
resp, err := client.Get(listURL(client, shareID), &r.Body, nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
13 changes: 13 additions & 0 deletions openstack/sharedfilesystems/v2/shareaccessrules/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,16 @@ func (r GetResult) Extract() (*ShareAccess, error) {
err := r.ExtractInto(&s)
return s.ShareAccess, err
}

// ListResult contains the response body and error from a List request.
type ListResult struct {
gophercloud.Result
}

func (r ListResult) Extract() ([]ShareAccess, error) {
var s struct {
AccessList []ShareAccess `json:"access_list"`
}
err := r.ExtractInto(&s)
return s.AccessList, err
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,36 @@ func MockGetResponse(t *testing.T) {
fmt.Fprintf(w, getResponse)
})
}

var listResponse = `{
"access_list": [
{
"access_level": "rw",
"state": "error",
"id": "507bf114-36f2-4f56-8cf4-857985ca87c1",
"access_type": "cert",
"access_to": "example.com",
"access_key": null,
"created_at": "2018-07-17T02:01:04.000000",
"updated_at": "2018-07-17T02:01:04.000000",
"metadata": {
"key1": "value1",
"key2": "value2"
}
},
{
"access_level": "rw",
"state": "active",
"id": "a25b2df3-90bd-4add-afa6-5f0dbbd50452",
"access_type": "ip",
"access_to": "0.0.0.0/0",
"access_key": null,
"created_at": "2018-07-16T01:03:21.000000",
"updated_at": "2018-07-16T01:03:21.000000",
"metadata": {
"key3": "value3",
"key4": "value4"
}
}
]
}`
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package testing

import (
"fmt"
"net/http"
"testing"
"time"

"github.com/gophercloud/gophercloud/openstack/sharedfilesystems/v2/shareaccessrules"
th "github.com/gophercloud/gophercloud/testhelper"
"github.com/gophercloud/gophercloud/testhelper/client"
fake "github.com/gophercloud/gophercloud/testhelper/client"
)

func TestGet(t *testing.T) {
Expand Down Expand Up @@ -37,3 +40,14 @@ func TestGet(t *testing.T) {
},
}, accessRule)
}

func MockListResponse(t *testing.T) {
th.Mux.HandleFunc(shareAccessRulesEndpoint, func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Accept", "application/json")
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, listResponse)
})
}
6 changes: 6 additions & 0 deletions openstack/sharedfilesystems/v2/shareaccessrules/urls.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package shareaccessrules

import (
"fmt"

"github.com/gophercloud/gophercloud"
)

Expand All @@ -9,3 +11,7 @@ const shareAccessRulesEndpoint = "share-access-rules"
func getURL(c *gophercloud.ServiceClient, accessID string) string {
return c.ServiceURL(shareAccessRulesEndpoint, accessID)
}

func listURL(c *gophercloud.ServiceClient, shareID string) string {
return fmt.Sprintf("%s?share_id=%s", c.ServiceURL(shareAccessRulesEndpoint), shareID)
}