in tools/instance_mapper/instance_mapper.go [293:428]
func (im *InstanceMapper) LoadGCPInstanceTypes(ctx context.Context, projectId string, priceList *GcpPriceList, debug bool) error {
im.InstanceData.GcpInstances = make(map[string]map[string]InstanceType, 0)
im.InstanceData.GcpInstances["all"] = make(map[string]InstanceType, 0)
httpClient, err := im.getHttpClient(ctx, debug)
if err != nil {
return err
}
c, err := compute.NewMachineTypesRESTClient(ctx, option.WithHTTPClient(httpClient))
if err != nil {
return err
}
defer c.Close()
req := &computepb.AggregatedListMachineTypesRequest{
Project: projectId,
}
var pricingHoursPerMonth float64 = 730.0
var allRegions []string
var allInstanceTypes []string
it := c.AggregatedList(ctx, req)
for {
resp, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
region := strings.TrimPrefix(resp.Key[0:len(resp.Key)-2], "zones/")
if _, found := im.InstanceData.GcpInstances[region]; !found {
im.InstanceData.GcpInstances[region] = make(map[string]InstanceType, 0)
}
if !im.stringInSlice(region, allRegions) {
allRegions = append(allRegions, region)
}
for _, mt := range resp.Value.MachineTypes {
gpus := 0
gpuType := ""
if len(mt.GetAccelerators()) > 0 {
for _, accl := range mt.GetAccelerators() {
gpus = gpus + int(*accl.GuestAcceleratorCount)
if gpuType == "" {
gpuType = *accl.GuestAcceleratorType
}
}
}
family := strings.SplitN(mt.GetName(), "-", 2)
it := InstanceType{
InstanceTypeId: mt.GetName(),
InstanceFamily: family[0],
Region: region,
Description: mt.GetDescription(),
BareMetal: false,
SharedTenancy: strings.HasPrefix(mt.GetName(), "e2-"), // to be un-hardcoded
GPUs: gpus,
GPUMemory: 0,
GPUType: gpuType,
Memory: int(mt.GetMemoryMb()),
VCPUs: int(mt.GetGuestCpus()),
GHz: 3.0,
Bandwidth: 0,
}
if !im.stringInSlice(it.InstanceTypeId, allInstanceTypes) {
allInstanceTypes = append(allInstanceTypes, it.InstanceTypeId)
}
if priceList != nil {
instancePricePerHour, err := it.GetHourlyPrice(priceList)
if err == nil {
if _sustainedUseTiers, ok := priceList.PriceList["sustained_use_tiers_new"]; ok {
sustainedUseTiers := _sustainedUseTiers.(map[string]interface{})
if sustainedUseTier, ok := sustainedUseTiers[strings.ToLower(it.InstanceFamily)]; ok {
price := make(map[string]float64, 1)
// Total 730 hours per month, calculate per sustained use tier
price[region] = 0.0
var pricingHoursPerTier float64 = pricingHoursPerMonth / float64(len(sustainedUseTier.(map[string]interface{})))
for _, tierMultiplier := range sustainedUseTier.(map[string]interface{}) {
var multiplier float64
if k := reflect.TypeOf(tierMultiplier).Kind(); k == reflect.Float64 {
multiplier = tierMultiplier.(float64)
} else if k == reflect.Float32 {
multiplier = float64(tierMultiplier.(float32))
} else if k == reflect.Int {
multiplier = float64(tierMultiplier.(int))
} else {
panic("unknown data type in tiers")
}
price[region] += instancePricePerHour * multiplier * pricingHoursPerTier
}
it.PricingPerRegion = &price
} else {
price := make(map[string]float64, 1)
// Total 730 hours per month, no SUDs
price[region] += instancePricePerHour * 730.0
it.PricingPerRegion = &price
}
} else {
log.Warningf("Could not find sustained use tiers configuration in price list")
}
} else {
log.Warningf("Could not find pricing in region %s for: %s", it.Region, it.InstanceTypeId)
}
}
im.InstanceData.GcpInstances[it.Region][it.InstanceTypeId] = it
log.Infof("GCP instance type (region: %s): %s\n", it.Region, it.String())
}
}
for _, instanceType := range allInstanceTypes {
var instance *InstanceType
for _, region := range allRegions {
if regionInstance, ok := im.InstanceData.GcpInstances[region][instanceType]; ok {
if instance == nil {
instance = ®ionInstance
}
if regionInstance.PricingPerRegion != nil {
var ppr *map[string]float64 = instance.PricingPerRegion
for r, price := range *regionInstance.PricingPerRegion {
(*ppr)[r] = price
}
}
}
}
if instance != nil {
im.InstanceData.GcpInstances["all"][instance.InstanceTypeId] = *instance
}
}
return nil
}