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  }