|
|
@@ -673,7 +673,7 @@ func (gcp *GCP) parsePage(r io.Reader, inputKeys map[string]Key, pvKeys map[stri
|
|
|
usageType := strings.ToLower(product.Category.UsageType)
|
|
|
instanceType := strings.ToLower(product.Category.ResourceGroup)
|
|
|
|
|
|
- if instanceType == "ssd" && !strings.Contains(product.Description, "Regional") { // TODO: support regional
|
|
|
+ if instanceType == "ssd" && strings.Contains(product.Description, "SSD backed") && !strings.Contains(product.Description, "Regional") { // TODO: support regional
|
|
|
lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
|
|
|
var nanos float64
|
|
|
if lastRateIndex > -1 && len(product.PricingInfo) > 0 {
|
|
|
@@ -695,6 +695,28 @@ func (gcp *GCP) parsePage(r io.Reader, inputKeys map[string]Key, pvKeys map[stri
|
|
|
}
|
|
|
}
|
|
|
continue
|
|
|
+ } else if instanceType == "ssd" && strings.Contains(product.Description, "SSD backed") && strings.Contains(product.Description, "Regional") { // TODO: support regional
|
|
|
+ lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
|
|
|
+ var nanos float64
|
|
|
+ if lastRateIndex > -1 && len(product.PricingInfo) > 0 {
|
|
|
+ nanos = product.PricingInfo[0].PricingExpression.TieredRates[lastRateIndex].UnitPrice.Nanos
|
|
|
+ } else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ hourlyPrice := (nanos * math.Pow10(-9)) / 730
|
|
|
+
|
|
|
+ for _, sr := range product.ServiceRegions {
|
|
|
+ region := sr
|
|
|
+ candidateKey := region + "," + "ssd" + "," + "regional"
|
|
|
+ if _, ok := pvKeys[candidateKey]; ok {
|
|
|
+ product.PV = &PV{
|
|
|
+ Cost: strconv.FormatFloat(hourlyPrice, 'f', -1, 64),
|
|
|
+ }
|
|
|
+ gcpPricingList[candidateKey] = product
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ continue
|
|
|
} else if instanceType == "pdstandard" && !strings.Contains(product.Description, "Regional") { // TODO: support regional
|
|
|
lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
|
|
|
var nanos float64
|
|
|
@@ -716,6 +738,27 @@ func (gcp *GCP) parsePage(r io.Reader, inputKeys map[string]Key, pvKeys map[stri
|
|
|
}
|
|
|
}
|
|
|
continue
|
|
|
+ } else if instanceType == "pdstandard" && strings.Contains(product.Description, "Regional") { // TODO: support regional
|
|
|
+ lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
|
|
|
+ var nanos float64
|
|
|
+ if lastRateIndex > -1 && len(product.PricingInfo) > 0 {
|
|
|
+ nanos = product.PricingInfo[0].PricingExpression.TieredRates[lastRateIndex].UnitPrice.Nanos
|
|
|
+ } else {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ hourlyPrice := (nanos * math.Pow10(-9)) / 730
|
|
|
+ for _, sr := range product.ServiceRegions {
|
|
|
+ region := sr
|
|
|
+ candidateKey := region + "," + "pdstandard" + "," + "regional"
|
|
|
+ if _, ok := pvKeys[candidateKey]; ok {
|
|
|
+ product.PV = &PV{
|
|
|
+ Cost: strconv.FormatFloat(hourlyPrice, 'f', -1, 64),
|
|
|
+ }
|
|
|
+ gcpPricingList[candidateKey] = product
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ continue
|
|
|
}
|
|
|
|
|
|
if (instanceType == "ram" || instanceType == "cpu") && strings.Contains(strings.ToUpper(product.Description), "CUSTOM") {
|
|
|
@@ -975,7 +1018,12 @@ func (gcp *GCP) parsePages(inputKeys map[string]Key, pvKeys map[string]PVKey) (m
|
|
|
}
|
|
|
klog.V(1).Infof("ALL PAGES: %+v", returnPages)
|
|
|
for k, v := range returnPages {
|
|
|
- klog.V(1).Infof("Returned Page: %s : %+v", k, v.Node)
|
|
|
+ if v.Node != nil {
|
|
|
+ klog.V(1).Infof("Returned Page: %s : %+v", k, v.Node)
|
|
|
+ }
|
|
|
+ if v.PV != nil {
|
|
|
+ klog.V(1).Infof("Returned Page: %s : %+v", k, v.PV)
|
|
|
+ }
|
|
|
}
|
|
|
return returnPages, err
|
|
|
}
|
|
|
@@ -998,13 +1046,17 @@ func (gcp *GCP) DownloadPricingData() error {
|
|
|
nodeList := gcp.Clientset.GetAllNodes()
|
|
|
inputkeys := make(map[string]Key)
|
|
|
|
|
|
+ defaultRegion := "" // Sometimes, PVs may be missing the region label. In that case assume that they are in the same region as the nodes
|
|
|
for _, n := range nodeList {
|
|
|
labels := n.GetObjectMeta().GetLabels()
|
|
|
if _, ok := labels["cloud.google.com/gke-nodepool"]; ok { // The node is part of a GKE nodepool, so you're paying a cluster management cost
|
|
|
gcp.clusterManagementPrice = 0.10
|
|
|
gcp.clusterProvisioner = "GKE"
|
|
|
}
|
|
|
-
|
|
|
+ r, _ := util.GetRegion(labels)
|
|
|
+ if r != "" {
|
|
|
+ defaultRegion = r
|
|
|
+ }
|
|
|
key := gcp.GetKey(labels, n)
|
|
|
inputkeys[key.Features()] = key
|
|
|
}
|
|
|
@@ -1028,7 +1080,7 @@ func (gcp *GCP) DownloadPricingData() error {
|
|
|
log.DedupedWarningf(5, "Unable to find params for storageClassName %s", pv.Name)
|
|
|
continue
|
|
|
}
|
|
|
- key := gcp.GetPVKey(pv, params, "")
|
|
|
+ key := gcp.GetPVKey(pv, params, defaultRegion)
|
|
|
pvkeys[key.Features()] = key
|
|
|
}
|
|
|
|
|
|
@@ -1057,7 +1109,7 @@ func (gcp *GCP) PVPricing(pvk PVKey) (*PV, error) {
|
|
|
defer gcp.DownloadPricingDataLock.RUnlock()
|
|
|
pricing, ok := gcp.Pricing[pvk.Features()]
|
|
|
if !ok {
|
|
|
- klog.V(4).Infof("Persistent Volume pricing not found for %s: %s", pvk.GetStorageClass(), pvk.Features())
|
|
|
+ klog.V(3).Infof("Persistent Volume pricing not found for %s: %s", pvk.GetStorageClass(), pvk.Features())
|
|
|
return &PV{}, nil
|
|
|
}
|
|
|
return pricing.PV, nil
|
|
|
@@ -1363,8 +1415,17 @@ func (key *pvKey) Features() string {
|
|
|
} else if storageClass == "pd-standard" {
|
|
|
storageClass = "pdstandard"
|
|
|
}
|
|
|
+ replicationType := ""
|
|
|
+ if rt, ok := key.StorageClassParameters["replication-type"]; ok {
|
|
|
+ if rt == "regional-pd" {
|
|
|
+ replicationType = ",regional"
|
|
|
+ }
|
|
|
+ }
|
|
|
region, _ := util.GetRegion(key.Labels)
|
|
|
- return region + "," + storageClass
|
|
|
+ if region == "" {
|
|
|
+ region = key.DefaultRegion
|
|
|
+ }
|
|
|
+ return region + "," + storageClass + replicationType
|
|
|
}
|
|
|
|
|
|
type gcpKey struct {
|