github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/openstack/css/v1/flavors/results.go (about) 1 package flavors 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "math" 7 "strconv" 8 "strings" 9 ) 10 11 type Flavor struct { 12 // RAM - memory size of an instance. 13 // Unit: GB 14 RAM int `json:"ram"` 15 // CPU - number of vCPUs of an instance. 16 CPU int `json:"cpu"` 17 // Name - flavor name. 18 Name string `json:"name"` 19 Region string `json:"region"` 20 // DiskMin - minimal disk capacity of an instance. 21 DiskMin int `json:"-"` 22 // DiskMax - maximum disk capacity of an instance. 23 DiskMax int `json:"-"` 24 // FlavorID - ID of a flavor. 25 FlavorID string `json:"flavor_id"` 26 } 27 28 func (f *Flavor) UnmarshalJSON(b []byte) error { 29 type tmp Flavor 30 var flavor struct { 31 tmp 32 DiskRange string `json:"diskrange"` 33 } 34 if err := json.Unmarshal(b, &flavor); err != nil { 35 return err 36 } 37 *f = Flavor(flavor.tmp) 38 dRange := strings.Split(flavor.DiskRange, ",") 39 if len(dRange) != 2 { 40 return fmt.Errorf("disk range format is invalid: %s", flavor.DiskRange) 41 } 42 min, errMin := strconv.Atoi(dRange[0]) 43 max, errMax := strconv.Atoi(dRange[1]) 44 if errMin != nil || errMax != nil { 45 return fmt.Errorf("failed to convert disk range format: %s, %s", errMin, errMax) 46 } 47 f.DiskMin = min 48 f.DiskMax = max 49 return nil 50 } 51 52 type Version struct { 53 // Version - engine version 54 Version string `json:"version"` 55 // Type - instance type. 56 // The options are `ess`, `ess-cold`, `ess-master`, and `ess-client`. 57 Type string `json:"type"` 58 // Flavors - list of flavors 59 Flavors []Flavor `json:"flavors"` 60 } 61 62 type Limit struct { 63 Min int 64 Max int 65 } 66 67 func (r Limit) Matches(value int) bool { 68 if r.Max == 0 { 69 r.Max = math.MaxInt32 70 } 71 return value >= r.Min && value <= r.Max 72 } 73 74 // FilterOpts to filter version list by 75 type FilterOpts struct { 76 Version string 77 // One of ess, ess-master, ess-client, ess-cloud 78 Type string 79 // Name of the searched flavor 80 FlavorName string 81 DiskMin *Limit 82 DiskMax *Limit 83 // Region - region the flavor is available for 84 Region string 85 CPU *Limit 86 // RAM - memory size, GB 87 RAM *Limit 88 } 89 90 func matches(value int, limits *Limit) bool { 91 if limits == nil { 92 return true 93 } 94 return (*limits).Matches(value) 95 } 96 97 func filterFlavors(flavors []Flavor, opts FilterOpts) []Flavor { 98 var resFlavors []Flavor 99 for _, flv := range flavors { 100 if opts.FlavorName != "" && flv.Name != opts.FlavorName { 101 continue 102 } 103 if opts.Region != "" && flv.Region != opts.Region { 104 continue 105 } 106 107 if !matches(flv.CPU, opts.CPU) { 108 continue 109 } 110 if !matches(flv.RAM, opts.RAM) { 111 continue 112 } 113 if !matches(flv.DiskMin, opts.DiskMin) { 114 continue 115 } 116 if !matches(flv.DiskMax, opts.DiskMax) { 117 continue 118 } 119 120 resFlavors = append(resFlavors, flv) 121 } 122 return resFlavors 123 } 124 125 func findSingleFlavor(flavors []Flavor, opts FilterOpts) *Flavor { 126 for _, flv := range flavors { 127 if (opts.FlavorName == "" || flv.Name == opts.FlavorName) && 128 (opts.Region == "" || flv.Region == opts.Region) && 129 matches(flv.CPU, opts.CPU) && 130 matches(flv.RAM, opts.RAM) && 131 matches(flv.DiskMin, opts.DiskMin) && 132 matches(flv.DiskMax, opts.DiskMax) { 133 return &flv 134 } 135 } 136 return nil 137 } 138 139 // FilterVersions - filters flavors in version list by given options (with AND operator) 140 func FilterVersions(versions []Version, opts FilterOpts) []Version { 141 var resVersions []Version 142 for _, version := range versions { 143 144 if opts.Version != "" && version.Version != opts.Version { 145 continue 146 } 147 if opts.Type != "" && version.Type != opts.Type { 148 continue 149 } 150 version.Flavors = filterFlavors(version.Flavors, opts) 151 resVersions = append(resVersions, version) 152 } 153 return resVersions 154 } 155 156 // FindFlavor - finds first flavor matching options 157 func FindFlavor(versions []Version, opts FilterOpts) *Flavor { 158 for _, version := range versions { 159 if opts.Version != "" && version.Version != opts.Version { 160 continue 161 } 162 if opts.Type != "" && version.Type != opts.Type { 163 continue 164 } 165 flavor := findSingleFlavor(version.Flavors, opts) 166 if flavor != nil { 167 return flavor 168 } 169 } 170 return nil 171 }