Skip to content

Commit ebdd135

Browse files
committed
BlockStorage: apiversions
1 parent 4ecdf7c commit ebdd135

File tree

8 files changed

+377
-0
lines changed

8 files changed

+377
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Package apiversions provides information and interaction with the different
3+
API versions for the OpenStack Block Storage service, code-named Cinder.
4+
5+
Example of Retrieving all API Versions
6+
7+
allPages, err := apiversions.List(client).AllPages()
8+
if err != nil {
9+
panic("Unable to get API versions: %s", err)
10+
}
11+
12+
allVersions, err := apiversions.ExtractAPIVersions(allPages)
13+
if err != nil {
14+
panic("Unable to extract API versions: %s", err)
15+
}
16+
17+
for _, version := range versions {
18+
fmt.Printf("%+v\n", version)
19+
}
20+
21+
22+
Example of Retrieving an API Version
23+
24+
version, err := apiversions.Get(client, "v3").Extract()
25+
if err != nil {
26+
panic("Unable to get API version: %s", err)
27+
}
28+
29+
fmt.Printf("%+v\n", version)
30+
*/
31+
package apiversions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package apiversions
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// ErrVersionNotFound is the error when the requested API version
8+
// could not be found.
9+
type ErrVersionNotFound struct{}
10+
11+
func (e ErrVersionNotFound) Error() string {
12+
return fmt.Sprintf("Unable to find requested API version")
13+
}
14+
15+
// ErrMultipleVersionsFound is the error when a request for an API
16+
// version returns multiple results.
17+
type ErrMultipleVersionsFound struct {
18+
Count int
19+
}
20+
21+
func (e ErrMultipleVersionsFound) Error() string {
22+
return fmt.Sprintf("Found %d API versions", e.Count)
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package apiversions
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/pagination"
6+
)
7+
8+
// List lists all the Cinder API versions available to end-users.
9+
func List(c *gophercloud.ServiceClient) pagination.Pager {
10+
return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page {
11+
return APIVersionPage{pagination.SinglePageBase(r)}
12+
})
13+
}
14+
15+
// Get will retrieve a specific API version. To extract the version,
16+
// call the Extract method on the GetResult.
17+
func Get(client *gophercloud.ServiceClient, v string) (r GetResult) {
18+
_, r.Err = client.Get(getURL(client, v), &r.Body, nil)
19+
return
20+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package apiversions
2+
3+
import (
4+
"time"
5+
6+
"github.com/gophercloud/gophercloud"
7+
"github.com/gophercloud/gophercloud/pagination"
8+
)
9+
10+
// APIVersion represents an API version for Cinder.
11+
type APIVersion struct {
12+
// ID is the unique identifier of the API version.
13+
ID string `json:"id"`
14+
15+
// MinVersion is the minimum microversion supported.
16+
MinVersion string `json:"min_version"`
17+
18+
// Status represents the status of the API version.
19+
Status string `json:"status"`
20+
21+
// Updated is the date the API version was updated.
22+
Updated time.Time `json:"updated"`
23+
24+
// Version is the current version and microversion.
25+
Version string `json:"version"`
26+
}
27+
28+
// APIVersionPage is the page returned by a pager when traversing over a
29+
// collection of API versions.
30+
type APIVersionPage struct {
31+
pagination.SinglePageBase
32+
}
33+
34+
// IsEmpty checks whether an APIVersionPage struct is empty.
35+
func (r APIVersionPage) IsEmpty() (bool, error) {
36+
is, err := ExtractAPIVersions(r)
37+
return len(is) == 0, err
38+
}
39+
40+
// ExtractAPIVersions takes a collection page, extracts all of the elements,
41+
// and returns them a slice of APIVersion structs. It is effectively a cast.
42+
func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
43+
var s struct {
44+
Versions []APIVersion `json:"versions"`
45+
}
46+
err := (r.(APIVersionPage)).ExtractInto(&s)
47+
return s.Versions, err
48+
}
49+
50+
// GetResult represents the result of a get operation.
51+
type GetResult struct {
52+
gophercloud.Result
53+
}
54+
55+
// Extract is a function that accepts a result and extracts an API version resource.
56+
func (r GetResult) Extract() (*APIVersion, error) {
57+
var s struct {
58+
Versions []APIVersion `json:"versions"`
59+
}
60+
err := r.ExtractInto(&s)
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
switch len(s.Versions) {
66+
case 0:
67+
return nil, ErrVersionNotFound{}
68+
case 1:
69+
return &s.Versions[0], nil
70+
default:
71+
return nil, ErrMultipleVersionsFound{Count: len(s.Versions)}
72+
}
73+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// apiversions_v1
2+
package testing
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package testing
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"testing"
7+
8+
th "github.com/gophercloud/gophercloud/testhelper"
9+
"github.com/gophercloud/gophercloud/testhelper/client"
10+
)
11+
12+
const APIListResponse = `
13+
{
14+
"versions": [
15+
{
16+
"id": "v1.0",
17+
"links": [
18+
{
19+
"href": "http://docs.openstack.org/",
20+
"rel": "describedby",
21+
"type": "text/html"
22+
},
23+
{
24+
"href": "http://localhost:8776/v1/",
25+
"rel": "self"
26+
}
27+
],
28+
"media-types": [
29+
{
30+
"base": "application/json",
31+
"type": "application/vnd.openstack.volume+json;version=1"
32+
}
33+
],
34+
"min_version": "",
35+
"status": "DEPRECATED",
36+
"updated": "2016-05-02T20:25:19Z",
37+
"version": ""
38+
},
39+
{
40+
"id": "v2.0",
41+
"links": [
42+
{
43+
"href": "http://docs.openstack.org/",
44+
"rel": "describedby",
45+
"type": "text/html"
46+
},
47+
{
48+
"href": "http://localhost:8776/v2/",
49+
"rel": "self"
50+
}
51+
],
52+
"media-types": [
53+
{
54+
"base": "application/json",
55+
"type": "application/vnd.openstack.volume+json;version=1"
56+
}
57+
],
58+
"min_version": "",
59+
"status": "SUPPORTED",
60+
"updated": "2014-06-28T12:20:21Z",
61+
"version": ""
62+
},
63+
{
64+
"id": "v3.0",
65+
"links": [
66+
{
67+
"href": "http://docs.openstack.org/",
68+
"rel": "describedby",
69+
"type": "text/html"
70+
},
71+
{
72+
"href": "http://localhost:8776/v3/",
73+
"rel": "self"
74+
}
75+
],
76+
"media-types": [
77+
{
78+
"base": "application/json",
79+
"type": "application/vnd.openstack.volume+json;version=1"
80+
}
81+
],
82+
"min_version": "3.0",
83+
"status": "CURRENT",
84+
"updated": "2016-02-08T12:20:21Z",
85+
"version": "3.27"
86+
}
87+
]
88+
}
89+
`
90+
91+
const APIGetResponse = `
92+
{
93+
"versions": [
94+
{
95+
"id": "v3.0",
96+
"links": [
97+
{
98+
"href": "http://docs.openstack.org/",
99+
"rel": "describedby",
100+
"type": "text/html"
101+
},
102+
{
103+
"href": "http://localhost:8776/v3/",
104+
"rel": "self"
105+
}
106+
],
107+
"media-types": [
108+
{
109+
"base": "application/json",
110+
"type": "application/vnd.openstack.volume+json;version=1"
111+
}
112+
],
113+
"min_version": "3.0",
114+
"status": "CURRENT",
115+
"updated": "2016-02-08T12:20:21Z",
116+
"version": "3.27"
117+
}
118+
]
119+
}
120+
`
121+
122+
func MockListResponse(t *testing.T) {
123+
th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
124+
th.TestMethod(t, r, "GET")
125+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
126+
127+
w.Header().Add("Content-Type", "application/json")
128+
w.WriteHeader(http.StatusOK)
129+
130+
fmt.Fprintf(w, APIListResponse)
131+
})
132+
}
133+
134+
func MockGetResponse(t *testing.T) {
135+
th.Mux.HandleFunc("/v3/", func(w http.ResponseWriter, r *http.Request) {
136+
th.TestMethod(t, r, "GET")
137+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
138+
139+
w.Header().Add("Content-Type", "application/json")
140+
w.WriteHeader(http.StatusOK)
141+
142+
fmt.Fprintf(w, APIGetResponse)
143+
})
144+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package testing
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/gophercloud/gophercloud/openstack/blockstorage/apiversions"
8+
th "github.com/gophercloud/gophercloud/testhelper"
9+
"github.com/gophercloud/gophercloud/testhelper/client"
10+
)
11+
12+
func TestListVersions(t *testing.T) {
13+
th.SetupHTTP()
14+
defer th.TeardownHTTP()
15+
16+
MockListResponse(t)
17+
18+
allVersions, err := apiversions.List(client.ServiceClient()).AllPages()
19+
th.AssertNoErr(t, err)
20+
actual, err := apiversions.ExtractAPIVersions(allVersions)
21+
th.AssertNoErr(t, err)
22+
23+
expected := []apiversions.APIVersion{
24+
{
25+
ID: "v1.0",
26+
Status: "DEPRECATED",
27+
Updated: time.Date(2016, 5, 2, 20, 25, 19, 0, time.UTC),
28+
},
29+
{
30+
ID: "v2.0",
31+
Status: "SUPPORTED",
32+
Updated: time.Date(2014, 6, 28, 12, 20, 21, 0, time.UTC),
33+
},
34+
{
35+
ID: "v3.0",
36+
MinVersion: "3.0",
37+
Status: "CURRENT",
38+
Updated: time.Date(2016, 2, 8, 12, 20, 21, 0, time.UTC),
39+
Version: "3.27",
40+
},
41+
}
42+
43+
th.AssertDeepEquals(t, expected, actual)
44+
}
45+
46+
func TestGetVersion(t *testing.T) {
47+
th.SetupHTTP()
48+
defer th.TeardownHTTP()
49+
50+
MockGetResponse(t)
51+
52+
actual, err := apiversions.Get(client.ServiceClient(), "v3").Extract()
53+
th.AssertNoErr(t, err)
54+
55+
expected := apiversions.APIVersion{
56+
ID: "v3.0",
57+
MinVersion: "3.0",
58+
Status: "CURRENT",
59+
Updated: time.Date(2016, 2, 8, 12, 20, 21, 0, time.UTC),
60+
Version: "3.27",
61+
}
62+
63+
th.AssertEquals(t, actual.ID, expected.ID)
64+
th.AssertEquals(t, actual.Status, expected.Status)
65+
th.AssertEquals(t, actual.Updated, expected.Updated)
66+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package apiversions
2+
3+
import (
4+
"net/url"
5+
"strings"
6+
7+
"github.com/gophercloud/gophercloud"
8+
)
9+
10+
func getURL(c *gophercloud.ServiceClient, version string) string {
11+
return c.ServiceURL(strings.TrimRight(version, "/") + "/")
12+
}
13+
14+
func listURL(c *gophercloud.ServiceClient) string {
15+
u, _ := url.Parse(c.ServiceURL(""))
16+
u.Path = "/"
17+
return u.String()
18+
}

0 commit comments

Comments
 (0)