Merge pull request #446 from jrperritt/flavor-extra-specs
Rackspace Flavor extra_specs field
diff --git a/rackspace/compute/v2/flavors/delegate.go b/rackspace/compute/v2/flavors/delegate.go
index 6bfc20c..081ea47 100644
--- a/rackspace/compute/v2/flavors/delegate.go
+++ b/rackspace/compute/v2/flavors/delegate.go
@@ -36,11 +36,8 @@
}
// Get returns details about a single flavor, identity by ID.
-func Get(client *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(client, id)
-}
-
-// ExtractFlavors interprets a page of List results as Flavors.
-func ExtractFlavors(page pagination.Page) ([]os.Flavor, error) {
- return os.ExtractFlavors(page)
+func Get(client *gophercloud.ServiceClient, id string) GetResult {
+ var res GetResult
+ _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
+ return res
}
diff --git a/rackspace/compute/v2/flavors/fixtures.go b/rackspace/compute/v2/flavors/fixtures.go
index 894f916..957dccf 100644
--- a/rackspace/compute/v2/flavors/fixtures.go
+++ b/rackspace/compute/v2/flavors/fixtures.go
@@ -2,10 +2,6 @@
package flavors
-import (
- os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
-)
-
// ListOutput is a sample response of a flavor List request.
const ListOutput = `
{
@@ -103,7 +99,7 @@
// Performance1Flavor is the expected result of parsing GetOutput, or the first element of
// ListOutput.
-var Performance1Flavor = os.Flavor{
+var Performance1Flavor = Flavor{
ID: "performance1-1",
Disk: 20,
RAM: 1024,
@@ -111,10 +107,16 @@
RxTxFactor: 200.0,
Swap: 0,
VCPUs: 1,
+ ExtraSpecs: ExtraSpecs{
+ NumDataDisks: 0,
+ Class: "performance1",
+ DiskIOIndex: 0,
+ PolicyClass: "performance_flavor",
+ },
}
// Performance2Flavor is the second result expected from parsing ListOutput.
-var Performance2Flavor = os.Flavor{
+var Performance2Flavor = Flavor{
ID: "performance1-2",
Disk: 40,
RAM: 2048,
@@ -122,8 +124,14 @@
RxTxFactor: 400.0,
Swap: 0,
VCPUs: 2,
+ ExtraSpecs: ExtraSpecs{
+ NumDataDisks: 0,
+ Class: "performance1",
+ DiskIOIndex: 0,
+ PolicyClass: "performance_flavor",
+ },
}
// ExpectedFlavorSlice is the slice of Flavor structs that are expected to be parsed from
// ListOutput.
-var ExpectedFlavorSlice = []os.Flavor{Performance1Flavor, Performance2Flavor}
+var ExpectedFlavorSlice = []Flavor{Performance1Flavor, Performance2Flavor}
diff --git a/rackspace/compute/v2/flavors/results.go b/rackspace/compute/v2/flavors/results.go
new file mode 100644
index 0000000..e9efcdc
--- /dev/null
+++ b/rackspace/compute/v2/flavors/results.go
@@ -0,0 +1,104 @@
+package flavors
+
+import (
+ "reflect"
+
+ "github.com/jrperritt/gophercloud"
+ "github.com/mitchellh/mapstructure"
+ os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
+ "github.com/rackspace/gophercloud/pagination"
+)
+
+// ExtraSpecs provide additional information about the flavor.
+type ExtraSpecs struct {
+ // The number of data disks
+ NumDataDisks int `mapstructure:"number_of_data_disks"`
+ // The flavor class
+ Class string `mapstructure:"class"`
+ // Relative measure of disk I/O performance from 0-99, where higher is faster
+ DiskIOIndex int `mapstructure:"disk_io_index"`
+ PolicyClass string `mapstructure:"policy_class"`
+}
+
+// Flavor records represent (virtual) hardware configurations for server resources in a region.
+type Flavor struct {
+ // The Id field contains the flavor's unique identifier.
+ // For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance.
+ ID string `mapstructure:"id"`
+
+ // The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
+ Disk int `mapstructure:"disk"`
+ RAM int `mapstructure:"ram"`
+
+ // The Name field provides a human-readable moniker for the flavor.
+ Name string `mapstructure:"name"`
+
+ RxTxFactor float64 `mapstructure:"rxtx_factor"`
+
+ // Swap indicates how much space is reserved for swap.
+ // If not provided, this field will be set to 0.
+ Swap int `mapstructure:"swap"`
+
+ // VCPUs indicates how many (virtual) CPUs are available for this flavor.
+ VCPUs int `mapstructure:"vcpus"`
+
+ // ExtraSpecs provides extra information about the flavor
+ ExtraSpecs ExtraSpecs `mapstructure:"OS-FLV-WITH-EXT-SPECS:extra_specs"`
+}
+
+// GetResult temporarily holds the response from a Get call.
+type GetResult struct {
+ gophercloud.Result
+}
+
+// Extract provides access to the individual Flavor returned by the Get function.
+func (gr GetResult) Extract() (*Flavor, error) {
+ if gr.Err != nil {
+ return nil, gr.Err
+ }
+
+ var result struct {
+ Flavor Flavor `mapstructure:"flavor"`
+ }
+
+ cfg := &mapstructure.DecoderConfig{
+ DecodeHook: defaulter,
+ Result: &result,
+ }
+ decoder, err := mapstructure.NewDecoder(cfg)
+ if err != nil {
+ return nil, err
+ }
+ err = decoder.Decode(gr.Body)
+ return &result.Flavor, err
+}
+
+func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) {
+ if (from == reflect.String) && (to == reflect.Int) {
+ return 0, nil
+ }
+ return v, nil
+}
+
+// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
+func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
+ casted := page.(os.FlavorPage).Body
+ var container struct {
+ Flavors []Flavor `mapstructure:"flavors"`
+ }
+
+ cfg := &mapstructure.DecoderConfig{
+ DecodeHook: defaulter,
+ Result: &container,
+ }
+ decoder, err := mapstructure.NewDecoder(cfg)
+ if err != nil {
+ return container.Flavors, err
+ }
+ err = decoder.Decode(casted)
+ if err != nil {
+ return container.Flavors, err
+ }
+
+ return container.Flavors, nil
+}
diff --git a/rackspace/compute/v2/flavors/urls.go b/rackspace/compute/v2/flavors/urls.go
new file mode 100644
index 0000000..f4e2c3d
--- /dev/null
+++ b/rackspace/compute/v2/flavors/urls.go
@@ -0,0 +1,9 @@
+package flavors
+
+import (
+ "github.com/rackspace/gophercloud"
+)
+
+func getURL(client *gophercloud.ServiceClient, id string) string {
+ return client.ServiceURL("flavors", id)
+}