blob: 68c8f58c105f46c9ac10f30a1cf1b798175a697c [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
Ash Wilson8a8b86f2014-09-25 11:26:51 -040015// GetResult temporarily holds the reponse from a Get call.
16type GetResult struct {
17 gophercloud.CommonResult
18}
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 }
38 err = decoder.Decode(gr.Resp)
39 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) {
81 type link struct {
82 Href string `mapstructure:"href"`
83 Rel string `mapstructure:"rel"`
84 }
85 type resp struct {
86 Links []link `mapstructure:"flavors_links"`
87 }
88
89 var r resp
90 err := mapstructure.Decode(p.Body, &r)
91 if err != nil {
92 return "", err
93 }
94
95 var url string
96 for _, l := range r.Links {
97 if l.Rel == "next" {
98 url = l.Href
99 }
100 }
101 if url == "" {
102 return "", nil
103 }
104
105 return url, nil
106}
107
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800108func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) {
109 if (from == reflect.String) && (to == reflect.Int) {
110 return 0, nil
111 }
112 return v, nil
113}
114
Ash Wilson16e75ef2014-09-17 09:54:57 -0400115// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
116func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
Ash Wilson0d2c2422014-09-25 14:50:45 -0400117 casted := page.(FlavorPage).Body
Ash Wilson32be7e12014-09-24 14:47:47 -0400118 var container struct {
119 Flavors []Flavor `mapstructure:"flavors"`
120 }
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800121
Ash Wilson16e75ef2014-09-17 09:54:57 -0400122 cfg := &mapstructure.DecoderConfig{
123 DecodeHook: defaulter,
Ash Wilson32be7e12014-09-24 14:47:47 -0400124 Result: &container,
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800125 }
Ash Wilson16e75ef2014-09-17 09:54:57 -0400126 decoder, err := mapstructure.NewDecoder(cfg)
127 if err != nil {
Ash Wilson32be7e12014-09-24 14:47:47 -0400128 return container.Flavors, err
Ash Wilson16e75ef2014-09-17 09:54:57 -0400129 }
130 err = decoder.Decode(casted)
131 if err != nil {
Ash Wilson32be7e12014-09-24 14:47:47 -0400132 return container.Flavors, err
Ash Wilson16e75ef2014-09-17 09:54:57 -0400133 }
134
Ash Wilson32be7e12014-09-24 14:47:47 -0400135 return container.Flavors, nil
Samuel A. Falvo II10decf92014-02-13 17:05:35 -0800136}