diff --git a/README.md b/README.md index 70d951f..de78676 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,13 @@ variables to configure the GoIsilon client: #### Environment Variables Name | Description ---- | ----------- -`GOISILON_ENDPOINT` | the API endpoint, ex. `https://172.17.177.230:8080` -`GOISILON_USERNAME` | the username -`GOISILON_GROUP` | the user's group -`GOISILON_PASSWORD` | the password -`GOISILON_INSECURE` | whether to skip SSL validation -`GOISILON_VOLUMEPATH` | which base path to use when looking for volume directories +`GOISILON_ENDPOINT` | the API endpoint, ex. `https://172.17.177.230:8080` +`GOISILON_USERNAME` | the username +`GOISILON_GROUP` | the user's group +`GOISILON_PASSWORD` | the password +`GOISILON_INSECURE` | whether to skip SSL validation +`GOISILON_VOLUMEPATH` | which filesystem base path to use when looking for volume directories +`GOISILON_ACCESSPATH` | (optional) URL base path to volume directories including access point. Defaults to `GOISILON_VOLUMEPATH` if not specified. ### Initialize a new client with options The following example demonstrates how to explicitly specify options when @@ -51,12 +52,30 @@ client, err := NewClientWithArgs( "userName", "password", true, + "", "/ifs/volumes") if err != nil { panic(err) } ``` +Another example with Access Point, for users with limited permissions: + +```go +client, err := NewClientWithArgs( + context.Background(), + "https://172.17.177.230:8080", + "groupName", + "userName", + "password", + true, + "/user1_access_point", + "/ifs/data/user1_volumes") +if err != nil { + panic(err) +} +``` + ### Create a Volume This snippet creates a new volume named "testing" at "/ifs/volumes/loremipsum". The volume path is generated by concatenating the client's volume path and the diff --git a/api/api.go b/api/api.go index 4301c7a..378ba10 100644 --- a/api/api.go +++ b/api/api.go @@ -87,9 +87,15 @@ type Client interface { // Group returns the group name used to access the OneFS API. Group() string + // VolumesAccessPath returns the client's configured volumes URL path. + VolumesAccessPath() string + // VolumesPath returns the client's configured volumes path. VolumesPath() string + // VolumeAccessPath returns the URL path to a volume with the provided name + VolumeAccessPath(name string) string + // VolumePath returns the path to a volume with the provided name. VolumePath(name string) string } @@ -100,6 +106,7 @@ type client struct { auth string user string grup string + vola string volp string apiv uint8 } @@ -126,6 +133,10 @@ type ClientOptions struct { // Insecure is a flag that indicates whether or not to supress SSL errors. Insecure bool + // VolumesAccessPath is the URL location on the Isilon server where volumes + // are stored. + VolumesAccessPath string + // VolumesPath is the location on the Isilon server where volumes are // stored. VolumesPath string @@ -149,6 +160,7 @@ func New( user: user, grup: group, auth: fmtAuthHeaderVal(user, pass), + vola: defaultVolumesPath, volp: defaultVolumesPath, } @@ -158,6 +170,13 @@ func New( if opts.VolumesPath != "" { c.volp = opts.VolumesPath } + // If VolumesAccessPath is not set, fall back to VolumesPath for + // backward compatibility (make sure VolumesAccessPath is optional). + if opts.VolumesAccessPath != "" { + c.vola = opts.VolumesAccessPath + } else { + c.vola = c.volp + } if opts.Timeout != 0 { c.http.Timeout = opts.Timeout @@ -467,6 +486,14 @@ func (c *client) Group() string { return c.grup } +func (c *client) VolumesAccessPath() string { + return c.vola +} + +func (c *client) VolumeAccessPath(volumeName string) string { + return path.Join(c.vola, volumeName) +} + func (c *client) VolumesPath() string { return c.volp } diff --git a/api/v1/api_v1.go b/api/v1/api_v1.go index 5d63d94..3566398 100644 --- a/api/v1/api_v1.go +++ b/api/v1/api_v1.go @@ -4,7 +4,6 @@ import ( "os" "path" "strconv" - "strings" "github.com/thecodeteam/goisilon/api" ) @@ -14,7 +13,7 @@ const ( exportsPath = "platform/1/protocols/nfs/exports" quotaPath = "platform/1/quota/quotas" snapshotsPath = "platform/1/snapshot/snapshots" - volumesnapshotsPath = "/ifs/.snapshot" + volumesnapshotsPath = ".snapshot" ) var ( @@ -22,14 +21,13 @@ var ( ) func realNamespacePath(client api.Client) string { - return path.Join(namespacePath, client.VolumesPath()) + return path.Join(namespacePath, client.VolumesAccessPath()) } func realexportsPath(client api.Client) string { - return path.Join(exportsPath, client.VolumesPath()) + return path.Join(exportsPath, client.VolumesAccessPath()) } func realVolumeSnapshotPath(client api.Client, name string) string { - parts := strings.SplitN(realNamespacePath(client), "/ifs/", 2) - return path.Join(parts[0], volumesnapshotsPath, name, parts[1]) + return path.Join(realNamespacePath(client), volumesnapshotsPath, name) } diff --git a/api/v2/api_v2.go b/api/v2/api_v2.go index 8b2582a..fb8a9de 100644 --- a/api/v2/api_v2.go +++ b/api/v2/api_v2.go @@ -4,7 +4,6 @@ import ( "os" "path" "strconv" - "strings" "github.com/thecodeteam/goisilon/api" ) @@ -14,7 +13,7 @@ const ( exportsPath = "platform/2/protocols/nfs/exports" quotaPath = "platform/2/quota/quotas" snapshotsPath = "platform/2/snapshot/snapshots" - volumeSnapshotsPath = "/ifs/.snapshot" + volumeSnapshotsPath = ".snapshot" ) var ( @@ -23,14 +22,13 @@ var ( ) func realNamespacePath(c api.Client) string { - return path.Join(namespacePath, c.VolumesPath()) + return path.Join(namespacePath, c.VolumesAccessPath()) } func realExportsPath(c api.Client) string { - return path.Join(exportsPath, c.VolumesPath()) + return path.Join(exportsPath, c.VolumesAccessPath()) } func realVolumeSnapshotPath(c api.Client, name string) string { - parts := strings.SplitN(realNamespacePath(c), "/ifs/", 2) - return path.Join(parts[0], volumeSnapshotsPath, name, parts[1]) + return path.Join(realNamespacePath(c), volumeSnapshotsPath, name) } diff --git a/api/v2/api_v2_acls.go b/api/v2/api_v2_acls.go index 672b65e..0a2bd9b 100644 --- a/api/v2/api_v2_acls.go +++ b/api/v2/api_v2_acls.go @@ -8,8 +8,8 @@ import ( "strconv" "strings" - "github.com/thecodeteam/goisilon/api" "context" + "github.com/thecodeteam/goisilon/api" ) // AuthoritativeType is a possible value used with an ACL's Authoritative field. diff --git a/api/v2/api_v2_fs.go b/api/v2/api_v2_fs.go index 5d9b6a2..e33525d 100644 --- a/api/v2/api_v2_fs.go +++ b/api/v2/api_v2_fs.go @@ -8,8 +8,8 @@ import ( "strings" "sync" - "github.com/thecodeteam/goisilon/api" "context" + "github.com/thecodeteam/goisilon/api" ) // ContainerChild is a child object of a container. diff --git a/client.go b/client.go index 6f7a14f..1c695a1 100644 --- a/client.go +++ b/client.go @@ -25,6 +25,7 @@ func NewClient(ctx context.Context) (*Client, error) { os.Getenv("GOISILON_USERNAME"), os.Getenv("GOISILON_GROUP"), os.Getenv("GOISILON_PASSWORD"), + os.Getenv("GOISILON_ACCESSPATH"), os.Getenv("GOISILON_VOLUMEPATH")) } @@ -32,16 +33,18 @@ func NewClientWithArgs( ctx context.Context, endpoint string, insecure bool, - user, group, pass, volumesPath string) (*Client, error) { + user, group, pass, + volumesAccessPath string, volumesPath string) (*Client, error) { timeout, _ := time.ParseDuration(os.Getenv("GOISILON_TIMEOUT")) client, err := api.New( ctx, endpoint, user, pass, group, &api.ClientOptions{ - Insecure: insecure, - VolumesPath: volumesPath, - Timeout: timeout, + Insecure: insecure, + VolumesAccessPath: volumesAccessPath, + VolumesPath: volumesPath, + Timeout: timeout, }) if err != nil { return nil, err diff --git a/goisilon_test.go b/goisilon_test.go index e7d90ec..af82606 100644 --- a/goisilon_test.go +++ b/goisilon_test.go @@ -6,10 +6,10 @@ import ( "os" "testing" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" log "github.com/akutz/gournal" glogrus "github.com/akutz/gournal/logrus" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" ) var ( diff --git a/volume.go b/volume.go index e0e1d91..eb9f039 100644 --- a/volume.go +++ b/volume.go @@ -87,7 +87,7 @@ func (c *Client) ForceDeleteVolume(ctx context.Context, name string) error { var ( user = c.API.User() - vpl = len(c.API.VolumesPath()) + 1 + vpl = len(c.API.VolumesAccessPath()) + 1 errs = make(chan error) queryDone = make(chan int) childPaths = make(chan string)