forked from gophercloud/utils
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Gnocchi: implement resource types List method (gophercloud#55)
* Gnocchi: implement resource types List method Add new resourcetypes package with List method. Add tests and a documentation example. * Gnocchi: change resource type attributes Rename resource type attributes to Attributes struct, use cutom field "Extra" with map[string]interface{} type instead of different fields. Those fields will be different for different attribute types. * Gnocchi: change resource type attributes struct Migrate from list to map representation for the attribute details to make it more similar to the actual Gnocchi response JSON.
- Loading branch information
1 parent
18450e9
commit d7844b1
Showing
8 changed files
with
324 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// +build acceptance metric resourcetypes | ||
|
||
package v1 | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/gophercloud/gophercloud/acceptance/tools" | ||
"github.com/gophercloud/utils/acceptance/clients" | ||
"github.com/gophercloud/utils/gnocchi/metric/v1/resourcetypes" | ||
) | ||
|
||
func TestResourceTypesList(t *testing.T) { | ||
client, err := clients.NewGnocchiV1Client() | ||
if err != nil { | ||
t.Fatalf("Unable to create a Gnocchi client: %v", err) | ||
} | ||
|
||
allPages, err := resourcetypes.List(client).AllPages() | ||
if err != nil { | ||
t.Fatalf("Unable to list resource types: %v", err) | ||
} | ||
|
||
allResourceTypes, err := resourcetypes.ExtractResourceTypes(allPages) | ||
if err != nil { | ||
t.Fatalf("Unable to extract resource types: %v", err) | ||
} | ||
|
||
for _, resourceType := range allResourceTypes { | ||
tools.PrintResource(t, resourceType) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
Package resourcetypes provides ability to manage resource types through the Gnocchi API. | ||
Example of Listing resource types | ||
allPages, err := resourcetypes.List(client).AllPages() | ||
if err != nil { | ||
panic(err) | ||
} | ||
allResourceTypes, err := resourcetypes.ExtractResourceTypes(allPages) | ||
if err != nil { | ||
panic(err) | ||
} | ||
for _, resourceType := range allResourceTypes { | ||
fmt.Printf("%+v\n", resourceType) | ||
} | ||
*/ | ||
package resourcetypes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package resourcetypes | ||
|
||
import ( | ||
"github.com/gophercloud/gophercloud" | ||
"github.com/gophercloud/gophercloud/pagination" | ||
) | ||
|
||
// List makes a request against the Gnocchi API to list resource types. | ||
func List(client *gophercloud.ServiceClient) pagination.Pager { | ||
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page { | ||
return ResourceTypePage{pagination.SinglePageBase(r)} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package resourcetypes | ||
|
||
import ( | ||
"encoding/json" | ||
|
||
"github.com/gophercloud/gophercloud" | ||
"github.com/gophercloud/gophercloud/pagination" | ||
) | ||
|
||
type commonResult struct { | ||
gophercloud.Result | ||
} | ||
|
||
// Extract is a function that accepts a result and extracts a Gnocchi resource type. | ||
func (r commonResult) Extract() (*ResourceType, error) { | ||
var s *ResourceType | ||
err := r.ExtractInto(&s) | ||
return s, err | ||
} | ||
|
||
// GetResult represents the result of a get operation. Call its Extract | ||
// method to interpret it as a Gnocchi resource type. | ||
type GetResult struct { | ||
commonResult | ||
} | ||
|
||
// ResourceType represents custom Gnocchi resource type. | ||
type ResourceType struct { | ||
// Attributes is a collection of keys and values of different resource types. | ||
Attributes map[string]Attribute `json:"-"` | ||
|
||
// Name is a human-readable resource type identifier. | ||
Name string `json:"name"` | ||
|
||
// State represents current status of a resource type. | ||
State string `json:"state"` | ||
} | ||
|
||
// Attribute represents single attribute of a Gnocchi resource type. | ||
type Attribute struct { | ||
// Type is an attribute type. | ||
Type string `json:"type"` | ||
|
||
// Details represents different attribute fields. | ||
Details map[string]interface{} | ||
} | ||
|
||
// UnmarshalJSON helps to unmarshal ResourceType fields into needed values. | ||
func (r *ResourceType) UnmarshalJSON(b []byte) error { | ||
type tmp ResourceType | ||
var s struct { | ||
tmp | ||
Attributes map[string]interface{} `json:"attributes"` | ||
} | ||
err := json.Unmarshal(b, &s) | ||
if err != nil { | ||
return err | ||
} | ||
*r = ResourceType(s.tmp) | ||
|
||
if s.Attributes == nil { | ||
return nil | ||
} | ||
|
||
// Populate attributes from the JSON map structure. | ||
attributes := make(map[string]Attribute) | ||
for attributeName, attributeValues := range s.Attributes { | ||
attribute := new(Attribute) | ||
attribute.Details = make(map[string]interface{}) | ||
|
||
attributeValuesMap, ok := attributeValues.(map[string]interface{}) | ||
if !ok { | ||
// Got some strange resource type attribute representation, skip it. | ||
continue | ||
} | ||
|
||
// Populate extra and type attribute values. | ||
for k, v := range attributeValuesMap { | ||
if k == "type" { | ||
if attributeType, ok := v.(string); ok { | ||
attribute.Type = attributeType | ||
} | ||
} else { | ||
attribute.Details[k] = v | ||
} | ||
} | ||
attributes[attributeName] = *attribute | ||
} | ||
|
||
r.Attributes = attributes | ||
|
||
return err | ||
} | ||
|
||
// ResourceTypePage abstracts the raw results of making a List() request against | ||
// the Gnocchi API. | ||
// | ||
// As Gnocchi API may freely alter the response bodies of structures | ||
// returned to the client, you may only safely access the data provided through | ||
// the ExtractResources call. | ||
type ResourceTypePage struct { | ||
pagination.SinglePageBase | ||
} | ||
|
||
// IsEmpty checks whether a ResourceTypePage struct is empty. | ||
func (r ResourceTypePage) IsEmpty() (bool, error) { | ||
is, err := ExtractResourceTypes(r) | ||
return len(is) == 0, err | ||
} | ||
|
||
// ExtractResourceTypes interprets the results of a single page from a List() call, | ||
// producing a slice of ResourceType structs. | ||
func ExtractResourceTypes(r pagination.Page) ([]ResourceType, error) { | ||
var s []ResourceType | ||
err := (r.(ResourceTypePage)).ExtractInto(&s) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return s, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// resource types unit tests | ||
package testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package testing | ||
|
||
import "github.com/gophercloud/utils/gnocchi/metric/v1/resourcetypes" | ||
|
||
// ResourceTypeListResult represents raw server response from a server to a list call. | ||
const ResourceTypeListResult = `[ | ||
{ | ||
"attributes": {}, | ||
"name": "generic", | ||
"state": "active" | ||
}, | ||
{ | ||
"attributes": { | ||
"parent_id": { | ||
"required": false, | ||
"type": "uuid" | ||
} | ||
}, | ||
"name": "identity_project", | ||
"state": "active" | ||
}, | ||
{ | ||
"attributes": { | ||
"host": { | ||
"max_length": 128, | ||
"min_length": 0, | ||
"required": true, | ||
"type": "string" | ||
} | ||
}, | ||
"name": "compute_instance", | ||
"state": "active" | ||
} | ||
]` | ||
|
||
// ResourceType1 is an expected representation of a first resource from the ResourceTypeListResult. | ||
var ResourceType1 = resourcetypes.ResourceType{ | ||
Name: "generic", | ||
State: "active", | ||
Attributes: map[string]resourcetypes.Attribute{}, | ||
} | ||
|
||
// ResourceType2 is an expected representation of a first resource from the ResourceTypeListResult. | ||
var ResourceType2 = resourcetypes.ResourceType{ | ||
Name: "identity_project", | ||
State: "active", | ||
Attributes: map[string]resourcetypes.Attribute{ | ||
"parent_id": resourcetypes.Attribute{ | ||
Type: "uuid", | ||
Details: map[string]interface{}{ | ||
"required": false, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
// ResourceType3 is an expected representation of a first resource from the ResourceTypeListResult. | ||
var ResourceType3 = resourcetypes.ResourceType{ | ||
Name: "compute_instance", | ||
State: "active", | ||
Attributes: map[string]resourcetypes.Attribute{ | ||
"host": resourcetypes.Attribute{ | ||
Type: "string", | ||
Details: map[string]interface{}{ | ||
"max_length": float64(128), | ||
"min_length": float64(0), | ||
"required": true, | ||
}, | ||
}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package testing | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/gophercloud/gophercloud/pagination" | ||
th "github.com/gophercloud/gophercloud/testhelper" | ||
"github.com/gophercloud/utils/gnocchi/metric/v1/resourcetypes" | ||
fake "github.com/gophercloud/utils/gnocchi/testhelper/client" | ||
) | ||
|
||
func TestList(t *testing.T) { | ||
th.SetupHTTP() | ||
defer th.TeardownHTTP() | ||
|
||
th.Mux.HandleFunc("/v1/resource_type", func(w http.ResponseWriter, r *http.Request) { | ||
th.TestMethod(t, r, "GET") | ||
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) | ||
|
||
w.Header().Add("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
|
||
fmt.Fprintf(w, ResourceTypeListResult) | ||
}) | ||
|
||
count := 0 | ||
|
||
resourcetypes.List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) { | ||
count++ | ||
actual, err := resourcetypes.ExtractResourceTypes(page) | ||
if err != nil { | ||
t.Errorf("Failed to extract resource types: %v", err) | ||
return false, nil | ||
} | ||
|
||
expected := []resourcetypes.ResourceType{ | ||
ResourceType1, | ||
ResourceType2, | ||
ResourceType3, | ||
} | ||
|
||
th.CheckDeepEquals(t, expected, actual) | ||
|
||
return true, nil | ||
}) | ||
|
||
if count != 1 { | ||
t.Errorf("Expected 1 page, got %d", count) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package resourcetypes | ||
|
||
import "github.com/gophercloud/gophercloud" | ||
|
||
const resourcePath = "resource_type" | ||
|
||
func rootURL(c *gophercloud.ServiceClient) string { | ||
return c.ServiceURL(resourcePath) | ||
} | ||
|
||
func listURL(c *gophercloud.ServiceClient) string { | ||
return rootURL(c) | ||
} |