Skip to content

Commit c2cafb4

Browse files
dklylejtopjian
authored andcommitted
Flavor Extra Specs: List / Get (#686)
1 parent 7b1b877 commit c2cafb4

7 files changed

Lines changed: 174 additions & 0 deletions

File tree

acceptance/openstack/compute/v2/flavors_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,23 @@ func TestFlavorAccessCRUD(t *testing.T) {
153153
tools.PrintResource(t, access)
154154
}
155155
}
156+
157+
func TestFlavorExtraSpecs(t *testing.T) {
158+
client, err := clients.NewComputeV2Client()
159+
if err != nil {
160+
t.Fatalf("Unable to create a compute client: %v", err)
161+
}
162+
163+
flavor, err := CreatePrivateFlavor(t, client)
164+
if err != nil {
165+
t.Fatalf("Unable to create flavor: %v", err)
166+
}
167+
defer DeleteFlavor(t, client, flavor)
168+
169+
allExtraSpecs, err := flavors.ListExtraSpecs(client, flavor.ID).Extract()
170+
if err != nil {
171+
t.Fatalf("Unable to get flavor extra_specs: %v", err)
172+
}
173+
174+
tools.PrintResource(t, allExtraSpecs)
175+
}

openstack/compute/v2/flavors/doc.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,15 @@ Example to Grant Access to a Flavor
7272
if err != nil {
7373
panic(err)
7474
}
75+
76+
Example to Get Extra Specs for a Flavor
77+
flavorID := "e91758d6-a54a-4778-ad72-0c73a1cb695b"
78+
79+
extraSpecs, err := flavors.ListExtraSpecs(computeClient, flavorID).Extract()
80+
if err != nil {
81+
panic(err)
82+
}
83+
84+
fmt.Printf("%+v", extraSpecs)
7585
*/
7686
package flavors

openstack/compute/v2/flavors/requests.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,14 @@ func IDFromName(client *gophercloud.ServiceClient, name string) (string, error)
230230
return "", err
231231
}
232232
}
233+
234+
// ExtraSpecs requests all the extra-specs for the given flavor ID.
235+
func ListExtraSpecs(client *gophercloud.ServiceClient, flavorID string) (r ListExtraSpecsResult) {
236+
_, r.Err = client.Get(extraSpecsListURL(client, flavorID), &r.Body, nil)
237+
return
238+
}
239+
240+
func GetExtraSpec(client *gophercloud.ServiceClient, flavorID string, key string) (r GetExtraSpecResult) {
241+
_, r.Err = client.Get(extraSpecsGetURL(client, flavorID, key), &r.Body, nil)
242+
return
243+
}

openstack/compute/v2/flavors/results.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,44 @@ type FlavorAccess struct {
182182
// TenantID is the unique ID of the tenant.
183183
TenantID string `json:"tenant_id"`
184184
}
185+
186+
// Extract interprets any extraSpecsResult as ExtraSpecs, if possible.
187+
func (r extraSpecsResult) Extract() (map[string]string, error) {
188+
var s struct {
189+
ExtraSpecs map[string]string `json:"extra_specs"`
190+
}
191+
err := r.ExtractInto(&s)
192+
return s.ExtraSpecs, err
193+
}
194+
195+
// extraSpecsResult contains the result of a call for (potentially) multiple
196+
// key-value pairs. Call its Extract method to interpret it as a
197+
// map[string]interface.
198+
type extraSpecsResult struct {
199+
gophercloud.Result
200+
}
201+
202+
// ListExtraSpecsResult contains the result of a Get operation. Call its Extract
203+
// method to interpret it as a map[string]interface.
204+
type ListExtraSpecsResult struct {
205+
extraSpecsResult
206+
}
207+
208+
// extraSpecResult contains the result of a call for individual a single
209+
// key-value pair.
210+
type extraSpecResult struct {
211+
gophercloud.Result
212+
}
213+
214+
// GetExtraSpecResult contains the result of a Get operation. Call its Extract
215+
// method to interpret it as a map[string]interface.
216+
type GetExtraSpecResult struct {
217+
extraSpecResult
218+
}
219+
220+
// Extract interprets any extraSpecResult as an ExtraSpec, if possible.
221+
func (r extraSpecResult) Extract() (map[string]string, error) {
222+
var s map[string]string
223+
err := r.ExtractInto(&s)
224+
return s, err
225+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package testing
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"testing"
7+
8+
th "github.com/gophercloud/gophercloud/testhelper"
9+
fake "github.com/gophercloud/gophercloud/testhelper/client"
10+
)
11+
12+
// ExtraSpecsGetBody provides a GET result of the extra_specs for a flavor
13+
const ExtraSpecsGetBody = `
14+
{
15+
"extra_specs" : {
16+
"hw:cpu_policy": "CPU-POLICY",
17+
"hw:cpu_thread_policy": "CPU-THREAD-POLICY"
18+
}
19+
}
20+
`
21+
22+
// ExtraSpecGetBody provides a GET result of a particular extra_spec for a flavor
23+
const GetExtraSpecBody = `
24+
{
25+
"hw:cpu_policy": "CPU-POLICY"
26+
}
27+
`
28+
29+
// ExtraSpecs is the expected extra_specs returned from GET on a flavor's extra_specs
30+
var ExtraSpecs = map[string]string{
31+
"hw:cpu_policy": "CPU-POLICY",
32+
"hw:cpu_thread_policy": "CPU-THREAD-POLICY",
33+
}
34+
35+
// ExtraSpec is the expected extra_spec returned from GET on a flavor's extra_specs
36+
var ExtraSpec = map[string]string{
37+
"hw:cpu_policy": "CPU-POLICY",
38+
}
39+
40+
func HandleExtraSpecsListSuccessfully(t *testing.T) {
41+
th.Mux.HandleFunc("/flavors/1/os-extra_specs", func(w http.ResponseWriter, r *http.Request) {
42+
th.TestMethod(t, r, "GET")
43+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
44+
th.TestHeader(t, r, "Accept", "application/json")
45+
46+
w.Header().Set("Content-Type", "application/json")
47+
w.WriteHeader(http.StatusOK)
48+
fmt.Fprintf(w, ExtraSpecsGetBody)
49+
})
50+
}
51+
52+
func HandleExtraSpecGetSuccessfully(t *testing.T) {
53+
th.Mux.HandleFunc("/flavors/1/os-extra_specs/hw:cpu_policy", func(w http.ResponseWriter, r *http.Request) {
54+
th.TestMethod(t, r, "GET")
55+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
56+
th.TestHeader(t, r, "Accept", "application/json")
57+
58+
w.Header().Set("Content-Type", "application/json")
59+
w.WriteHeader(http.StatusOK)
60+
fmt.Fprintf(w, GetExtraSpecBody)
61+
})
62+
}

openstack/compute/v2/flavors/testing/requests_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,25 @@ func TestFlavorAccessAdd(t *testing.T) {
299299
t.Errorf("Expected %#v, but was %#v", expected, actual)
300300
}
301301
}
302+
303+
func TestFlavorExtraSpecsList(t *testing.T) {
304+
th.SetupHTTP()
305+
defer th.TeardownHTTP()
306+
HandleExtraSpecsListSuccessfully(t)
307+
308+
expected := ExtraSpecs
309+
actual, err := flavors.ListExtraSpecs(fake.ServiceClient(), "1").Extract()
310+
th.AssertNoErr(t, err)
311+
th.CheckDeepEquals(t, expected, actual)
312+
}
313+
314+
func TestFlavorExtraSpecGet(t *testing.T) {
315+
th.SetupHTTP()
316+
defer th.TeardownHTTP()
317+
HandleExtraSpecGetSuccessfully(t)
318+
319+
expected := ExtraSpec
320+
actual, err := flavors.GetExtraSpec(fake.ServiceClient(), "1", "hw:cpu_policy").Extract()
321+
th.AssertNoErr(t, err)
322+
th.CheckDeepEquals(t, expected, actual)
323+
}

openstack/compute/v2/flavors/urls.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,11 @@ func accessURL(client *gophercloud.ServiceClient, id string) string {
2727
func accessActionURL(client *gophercloud.ServiceClient, id string) string {
2828
return client.ServiceURL("flavors", id, "action")
2929
}
30+
31+
func extraSpecsListURL(client *gophercloud.ServiceClient, id string) string {
32+
return client.ServiceURL("flavors", id, "os-extra_specs")
33+
}
34+
35+
func extraSpecsGetURL(client *gophercloud.ServiceClient, id, key string) string {
36+
return client.ServiceURL("flavors", id, "os-extra_specs", key)
37+
}

0 commit comments

Comments
 (0)