blob: 8dddd705c93db65819e334fd8bcc15bbdd2d7dff [file] [log] [blame]
Samuel A. Falvo II10decf92014-02-13 17:05:35 -08001package flavors
2
3import (
Ash Wilson16e75ef2014-09-17 09:54:57 -04004 "errors"
Samuel A. Falvo II10decf92014-02-13 17:05:35 -08005 "reflect"
Ash Wilson16e75ef2014-09-17 09:54:57 -04006
7 "github.com/mitchellh/mapstructure"
Ash Wilson8a8b86f2014-09-25 11:26:51 -04008 "github.com/rackspace/gophercloud"
Ash Wilson16e75ef2014-09-17 09:54:57 -04009 "github.com/rackspace/gophercloud/pagination"
Samuel A. Falvo II10decf92014-02-13 17:05:35 -080010)
11
Ash Wilson16e75ef2014-09-17 09:54:57 -040012// ErrCannotInterpret is returned by an Extract call if the response body doesn't have the expected structure.
13var ErrCannotInterpet = errors.New("Unable to interpret a response body.")
14
Alex Gaynora6d5f9f2014-10-27 10:52:32 -070015// GetResult temporarily holds the response from a Get call.
Ash Wilson8a8b86f2014-09-25 11:26:51 -040016type GetResult struct {
Ash Wilsonf548aad2014-10-20 08:35:34 -040017 gophercloud.Result
Ash Wilson8a8b86f2014-09-25 11:26:51 -040018}
19
20// Extract provides access to the individual Flavor returned by the Get function.
21func (gr GetResult) Extract() (*Flavor, error) {
22 if gr.Err != nil {
23 return nil, gr.Err
24 }
25
26 var result struct {
27 Flavor Flavor `mapstructure:"flavor"`
28 }
29
30 cfg := &mapstructure.DecoderConfig{
31 DecodeHook: defaulter,
32 Result: &result,
33 }
34 decoder, err := mapstructure.NewDecoder(cfg)
35 if err != nil {
36 return nil, err
37 }
Ash Wilsond3dc2542014-10-20 10:10:48 -040038 err = decoder.Decode(gr.Body)
Ash Wilson8a8b86f2014-09-25 11:26:51 -040039 return &result.Flavor, err
40}
41
Samuel A. Falvo II10decf92014-02-13 17:05:35 -080042// Flavor records represent (virtual) hardware configurations for server resources in a region.
Samuel A. Falvo II10decf92014-02-13 17:05:35 -080043type Flavor struct {
Ash Wilson16e75ef2014-09-17 09:54:57 -040044 // The Id field contains the flavor's unique identifier.
45 // For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance.
46 ID string `mapstructure:"id"`
47
48 // The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
49 Disk int `mapstructure:"disk"`
50 RAM int `mapstructure:"ram"`
51
52 // The Name field provides a human-readable moniker for the flavor.
53 Name string `mapstructure:"name"`
54
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080055 RxTxFactor float64 `mapstructure:"rxtx_factor"`
Ash Wilson16e75ef2014-09-17 09:54:57 -040056
57 // Swap indicates how much space is reserved for swap.
58 // If not provided, this field will be set to 0.
59 Swap int `mapstructure:"swap"`
60
61 // VCPUs indicates how many (virtual) CPUs are available for this flavor.
62 VCPUs int `mapstructure:"vcpus"`
Samuel A. Falvo II10decf92014-02-13 17:05:35 -080063}
64
Ash Wilson0d2c2422014-09-25 14:50:45 -040065// FlavorPage contains a single page of the response from a List call.
66type FlavorPage struct {
67 pagination.LinkedPageBase
68}
69
70// IsEmpty determines if a page contains any results.
71func (p FlavorPage) IsEmpty() (bool, error) {
72 flavors, err := ExtractFlavors(p)
73 if err != nil {
74 return true, err
75 }
76 return len(flavors) == 0, nil
77}
78
79// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
80func (p FlavorPage) NextPageURL() (string, error) {
Ash Wilson0d2c2422014-09-25 14:50:45 -040081 type resp struct {
Jamie Hannaforda581acd2014-10-08 17:14:13 +020082 Links []gophercloud.Link `mapstructure:"flavors_links"`
Ash Wilson0d2c2422014-09-25 14:50:45 -040083 }
84
85 var r resp
86 err := mapstructure.Decode(p.Body, &r)
87 if err != nil {
88 return "", err
89 }
90
Jamie Hannaforda581acd2014-10-08 17:14:13 +020091 return gophercloud.ExtractNextURL(r.Links)
Ash Wilson0d2c2422014-09-25 14:50:45 -040092}
93
Samuel A. Falvo II10decf92014-02-13 17:05:35 -080094func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) {
95 if (from == reflect.String) && (to == reflect.Int) {
96 return 0, nil
97 }
98 return v, nil
99}
100
Ash Wilson16e75ef2014-09-17 09:54:57 -0400101// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
102func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
Ash Wilson0d2c2422014-09-25 14:50:45 -0400103 casted := page.(FlavorPage).Body
Ash Wilson32be7e12014-09-24 14:47:47 -0400104 var container struct {
105 Flavors []Flavor `mapstructure:"flavors"`
106 }
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800107
Ash Wilson16e75ef2014-09-17 09:54:57 -0400108 cfg := &mapstructure.DecoderConfig{
109 DecodeHook: defaulter,
Ash Wilson32be7e12014-09-24 14:47:47 -0400110 Result: &container,
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800111 }
Ash Wilson16e75ef2014-09-17 09:54:57 -0400112 decoder, err := mapstructure.NewDecoder(cfg)
113 if err != nil {
Ash Wilson32be7e12014-09-24 14:47:47 -0400114 return container.Flavors, err
Ash Wilson16e75ef2014-09-17 09:54:57 -0400115 }
116 err = decoder.Decode(casted)
117 if err != nil {
Ash Wilson32be7e12014-09-24 14:47:47 -0400118 return container.Flavors, err
Ash Wilson16e75ef2014-09-17 09:54:57 -0400119 }
120
Ash Wilson32be7e12014-09-24 14:47:47 -0400121 return container.Flavors, nil
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800122}