AjayTripathy 6 lat temu
rodzic
commit
7a4d2e98a6

+ 8 - 2
cloud/awsprovider.go

@@ -8,7 +8,6 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"math"
 	"net/http"
 	"net/url"
 	"os"
@@ -205,6 +204,10 @@ var regionToBillingRegionCode = map[string]string{
 	"us-gov-west-1":  "UGW1",
 }
 
+func (aws *AWS) GetLocalStorageCost() (float64, error) {
+	return 0, nil
+}
+
 // KubeAttrConversion maps the k8s labels for region to an aws region
 func (aws *AWS) KubeAttrConversion(location, instanceType, operatingSystem string) string {
 	operatingSystem = strings.ToLower(operatingSystem)
@@ -254,6 +257,9 @@ func (aws *AWS) GetManagementPlatform() (string, error) {
 
 func (aws *AWS) GetConfig() (*CustomPricing, error) {
 	c, err := GetDefaultPricingData("aws.json")
+	if c.Discount == "" {
+		c.Discount = "0%"
+	}
 	if err != nil {
 		return nil, err
 	}
@@ -609,7 +615,7 @@ func (aws *AWS) DownloadPricingData() error {
 								// If volume, we need to get hourly cost and add it to the PV object
 								cost := offerTerm.PriceDimensions[sku.(string)+OnDemandRateCode+HourlyRateCode].PricePerUnit.USD
 								costFloat, _ := strconv.ParseFloat(cost, 64)
-								hourlyPrice := (costFloat * math.Pow10(-9)) / 730
+								hourlyPrice := costFloat / 730
 
 								aws.Pricing[key].PV.Cost = strconv.FormatFloat(hourlyPrice, 'f', -1, 64)
 							}

+ 4 - 0
cloud/azureprovider.go

@@ -512,3 +512,7 @@ func (az *Azure) ExternalAllocations(string, string, string) ([]*OutOfClusterAll
 func (az *Azure) PVPricing(PVKey) (*PV, error) {
 	return nil, nil
 }
+
+func (az *Azure) GetLocalStorageCost() (float64, error) {
+	return 0.04, nil
+}

+ 10 - 2
cloud/gcpprovider.go

@@ -79,8 +79,15 @@ func gcpAllocationToOutOfClusterAllocation(gcpAlloc gcpAllocation) *OutOfCluster
 	}
 }
 
+func (gcp *GCP) GetLocalStorageCost() (float64, error) {
+	return 0.04, nil
+}
+
 func (gcp *GCP) GetConfig() (*CustomPricing, error) {
 	c, err := GetDefaultPricingData("gcp.json")
+	if c.Discount == "" {
+		c.Discount = "30%"
+	}
 	if err != nil {
 		return nil, err
 	}
@@ -356,7 +363,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" {
+				if instanceType == "ssd" && !strings.Contains(product.Description, "Regional") { // TODO: support regional
 					lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
 					var nanos float64
 					if len(product.PricingInfo) > 0 {
@@ -378,7 +385,7 @@ func (gcp *GCP) parsePage(r io.Reader, inputKeys map[string]Key, pvKeys map[stri
 						}
 					}
 					continue
-				} else if instanceType == "pdstandard" {
+				} else if instanceType == "pdstandard" && !strings.Contains(product.Description, "Regional") { // TODO: support regional
 					lastRateIndex := len(product.PricingInfo[0].PricingExpression.TieredRates) - 1
 					var nanos float64
 					if len(product.PricingInfo) > 0 {
@@ -702,6 +709,7 @@ func (gcp *GCP) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string)
 }
 
 func (key *pvKey) Features() string {
+	// TODO: regional cluster pricing.
 	storageClass := key.StorageClassParameters["type"]
 	if storageClass == "pd-ssd" {
 		storageClass = "ssd"

+ 5 - 0
cloud/provider.go

@@ -87,6 +87,7 @@ type Provider interface {
 	UpdateConfig(r io.Reader, updateType string) (*CustomPricing, error)
 	GetConfig() (*CustomPricing, error)
 	GetManagementPlatform() (string, error)
+	GetLocalStorageCost() (float64, error)
 
 	ExternalAllocations(string, string, string) ([]*OutOfClusterAllocation, error)
 }
@@ -209,6 +210,10 @@ type CustomProvider struct {
 	DownloadPricingDataLock sync.RWMutex
 }
 
+func (*CustomProvider) GetLocalStorageCost() (float64, error) {
+	return 0.04, nil
+}
+
 func (*CustomProvider) GetConfig() (*CustomPricing, error) {
 	return GetDefaultPricingData("default.json")
 }

+ 20 - 8
costmodel/cluster.go

@@ -5,7 +5,9 @@ import (
 	"log"
 	"time"
 
+	costAnalyzerCloud "github.com/kubecost/cost-model/cloud"
 	prometheusClient "github.com/prometheus/client_golang/api"
+
 	"k8s.io/klog"
 )
 
@@ -23,14 +25,14 @@ const (
 		avg(avg_over_time(pv_hourly_cost[%s] %s)) by (persistentvolume) * 730 
 		* avg(avg_over_time(kube_persistentvolume_capacity_bytes[%s] %s)) by (persistentvolume) / 1024 / 1024 / 1024
 	  ) +
-	  sum(avg(container_fs_limit_bytes{device!="tmpfs", id="/"} %s) by (instance) / 1024 / 1024 / 1024) * 0.04`
+	  (sum(container_fs_limit_bytes{device!="tmpfs", id="/"}) by (instance) / 1024 / 1024 / 1024) * %f`
 
 	queryTotal = `sum(avg(node_total_hourly_cost) by (node)) * 730 +
 	  sum(
 		avg(avg_over_time(pv_hourly_cost[1h])) by (persistentvolume) * 730 
 		* avg(avg_over_time(kube_persistentvolume_capacity_bytes[1h])) by (persistentvolume) / 1024 / 1024 / 1024
 	  ) +
-	  sum(avg(container_fs_limit_bytes{device!="tmpfs", id="/"}) by (instance) / 1024 / 1024 / 1024) * 0.04`
+	  (sum(container_fs_limit_bytes{device!="tmpfs", id="/"}) by (instance) / 1024 / 1024 / 1024) * %f`
 )
 
 type Totals struct {
@@ -110,12 +112,17 @@ func resultToTotal(qr interface{}) ([][]string, error) {
 }
 
 // ClusterCostsOverTime gives the current full cluster costs averaged over a window of time.
-func ClusterCosts(cli prometheusClient.Client, windowString, offset string) (*Totals, error) {
+func ClusterCosts(cli prometheusClient.Client, cloud costAnalyzerCloud.Provider, windowString, offset string) (*Totals, error) {
+
+	localStorageCost, err := cloud.GetLocalStorageCost()
+	if err != nil {
+		return nil, err
+	}
 
 	qCores := fmt.Sprintf(queryClusterCores, offset, offset, offset)
 	qRAM := fmt.Sprintf(queryClusterRAM, offset, offset)
-	qStorage := fmt.Sprintf(queryStorage, windowString, offset, windowString, offset, offset)
-	qTotal := fmt.Sprintf(queryTotal)
+	qStorage := fmt.Sprintf(queryStorage, windowString, offset, windowString, offset, offset, localStorageCost)
+	qTotal := fmt.Sprintf(queryTotal, localStorageCost)
 	log.Printf("%s", qTotal)
 
 	resultClusterCores, err := query(cli, qCores)
@@ -167,7 +174,12 @@ func ClusterCosts(cli prometheusClient.Client, windowString, offset string) (*To
 }
 
 // ClusterCostsOverTime gives the full cluster costs over time
-func ClusterCostsOverTime(cli prometheusClient.Client, startString, endString, windowString, offset string) (*Totals, error) {
+func ClusterCostsOverTime(cli prometheusClient.Client, cloud costAnalyzerCloud.Provider, startString, endString, windowString, offset string) (*Totals, error) {
+
+	localStorageCost, err := cloud.GetLocalStorageCost()
+	if err != nil {
+		return nil, err
+	}
 
 	layout := "2006-01-02T15:04:05.000Z"
 
@@ -189,8 +201,8 @@ func ClusterCostsOverTime(cli prometheusClient.Client, startString, endString, w
 
 	qCores := fmt.Sprintf(queryClusterCores, offset, offset, offset)
 	qRAM := fmt.Sprintf(queryClusterRAM, offset, offset)
-	qStorage := fmt.Sprintf(queryStorage, windowString, offset, windowString, offset, offset)
-	qTotal := fmt.Sprintf(queryTotal)
+	qStorage := fmt.Sprintf(queryStorage, windowString, offset, windowString, offset, offset, localStorageCost)
+	qTotal := fmt.Sprintf(queryTotal, localStorageCost)
 	log.Printf("%s", qTotal)
 
 	resultClusterCores, err := queryRange(cli, qCores, start, end, window)

+ 2 - 2
main.go

@@ -153,7 +153,7 @@ func (a *Accesses) ClusterCosts(w http.ResponseWriter, r *http.Request, ps httpr
 		offset = "offset " + offset
 	}
 
-	data, err := costModel.ClusterCosts(a.PrometheusClient, window, offset)
+	data, err := costModel.ClusterCosts(a.PrometheusClient, a.Cloud, window, offset)
 	w.Write(wrapData(data, err))
 }
 
@@ -170,7 +170,7 @@ func (a *Accesses) ClusterCostsOverTime(w http.ResponseWriter, r *http.Request,
 		offset = "offset " + offset
 	}
 
-	data, err := costModel.ClusterCostsOverTime(a.PrometheusClient, start, end, window, offset)
+	data, err := costModel.ClusterCostsOverTime(a.PrometheusClient, a.Cloud, start, end, window, offset)
 	w.Write(wrapData(data, err))
 }
 

+ 2 - 9
test/costmodel_test.go

@@ -1,14 +1,6 @@
 package costmodel_test
 
-import (
-	"net/url"
-	"testing"
-
-	"github.com/golang/mock/gomock"
-	costModel "github.com/kubecost/cost-model/costmodel"
-	"github.com/kubecost/test/mocks"
-)
-
+/*
 func TestCostModel(t *testing.T) {
 	ctrl := gomock.NewController(t)
 
@@ -24,3 +16,4 @@ func TestCostModel(t *testing.T) {
 
 	costModel.ComputeCostData(cli, clientset, provider, "1d", "")
 }
+*/