Просмотр исходного кода

Factor CustomProvider into its own file within cloud to match structure of Azure, GCP, and AWS; implement ClusterName for Provider interface; use ClusterName instead of Cluster ID for cost data model and aggregate data; clean up and make some cod emore idiomatic.

Niko Kovacevic 6 лет назад
Родитель
Сommit
aa8e6ebbb4
6 измененных файлов с 328 добавлено и 301 удалено
  1. 3 3
      cloud/awsprovider.go
  2. 2 2
      cloud/azureprovider.go
  3. 250 0
      cloud/customprovider.go
  4. 2 2
      cloud/gcpprovider.go
  5. 57 282
      cloud/provider.go
  6. 14 12
      costmodel/costmodel.go

+ 3 - 3
cloud/awsprovider.go

@@ -328,7 +328,7 @@ func (aws *AWS) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, er
 	path += "aws.json"
 	remoteEnabled := os.Getenv(remoteEnabled)
 	if remoteEnabled == "true" {
-		err = UpdateClusterMeta(os.Getenv(KC_CLUSTER_ID), c.ClusterName)
+		err = UpdateClusterMeta(os.Getenv(clusterIDKey), c.ClusterName)
 		if err != nil {
 			return nil, err
 		}
@@ -825,7 +825,7 @@ func (awsProvider *AWS) ClusterInfo() (map[string]string, error) {
 		m := make(map[string]string)
 		m["name"] = c.ClusterName
 		m["provider"] = "AWS"
-		m["id"] = os.Getenv(KC_CLUSTER_ID)
+		m["id"] = os.Getenv(clusterIDKey)
 		m["remoteReadEnabled"] = strconv.FormatBool(remoteEnabled)
 		return m, nil
 	}
@@ -834,7 +834,7 @@ func (awsProvider *AWS) ClusterInfo() (map[string]string, error) {
 		m := make(map[string]string)
 		m["name"] = clusterName
 		m["provider"] = "AWS"
-		m["id"] = os.Getenv(KC_CLUSTER_ID)
+		m["id"] = os.Getenv(clusterIDKey)
 		m["remoteReadEnabled"] = strconv.FormatBool(remoteEnabled)
 		return m, nil
 	}

+ 2 - 2
cloud/azureprovider.go

@@ -506,7 +506,7 @@ func (az *Azure) ClusterInfo() (map[string]string, error) {
 	}
 	m["provider"] = "azure"
 	m["remoteReadEnabled"] = strconv.FormatBool(remoteEnabled)
-	m["id"] = os.Getenv(KC_CLUSTER_ID)
+	m["id"] = os.Getenv(clusterIDKey)
 	return m, nil
 
 }
@@ -543,7 +543,7 @@ func (az *Azure) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, e
 	}
 	remoteEnabled := os.Getenv(remoteEnabled)
 	if remoteEnabled == "true" {
-		err = UpdateClusterMeta(os.Getenv(KC_CLUSTER_ID), c.ClusterName)
+		err = UpdateClusterMeta(os.Getenv(clusterIDKey), c.ClusterName)
 		if err != nil {
 			return nil, err
 		}

+ 250 - 0
cloud/customprovider.go

@@ -0,0 +1,250 @@
+package cloud
+
+import (
+	"encoding/json"
+	"io"
+	"io/ioutil"
+	"net/url"
+	"os"
+	"strconv"
+	"strings"
+	"sync"
+
+	v1 "k8s.io/api/core/v1"
+	"k8s.io/client-go/kubernetes"
+)
+
+type NodePrice struct {
+	CPU string
+	RAM string
+	GPU string
+}
+
+type CustomProvider struct {
+	Clientset               *kubernetes.Clientset
+	Pricing                 map[string]*NodePrice
+	SpotLabel               string
+	SpotLabelValue          string
+	GPULabel                string
+	GPULabelValue           string
+	DownloadPricingDataLock sync.RWMutex
+}
+
+type customProviderKey struct {
+	SpotLabel      string
+	SpotLabelValue string
+	GPULabel       string
+	GPULabelValue  string
+	Labels         map[string]string
+}
+
+func (*CustomProvider) GetLocalStorageQuery() (string, error) {
+	return "", nil
+}
+
+func (*CustomProvider) GetConfig() (*CustomPricing, error) {
+	return GetDefaultPricingData("default.json")
+}
+
+func (*CustomProvider) GetManagementPlatform() (string, error) {
+	return "", nil
+}
+
+func (cp *CustomProvider) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, error) {
+	c, err := GetDefaultPricingData("default.json")
+	if err != nil {
+		return nil, err
+	}
+	path := os.Getenv("CONFIG_PATH")
+	if path == "" {
+		path = "/models/"
+	}
+	a := make(map[string]string)
+	err = json.NewDecoder(r).Decode(&a)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range a {
+		kUpper := strings.Title(k) // Just so we consistently supply / receive the same values, uppercase the first letter.
+		err := SetCustomPricingField(c, kUpper, v)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	cj, err := json.Marshal(c)
+	if err != nil {
+		return nil, err
+	}
+
+	configPath := path + "default.json"
+	err = ioutil.WriteFile(configPath, cj, 0644)
+	if err != nil {
+		return nil, err
+	}
+	defer cp.DownloadPricingData()
+	return c, nil
+
+}
+
+func (cp *CustomProvider) ClusterInfo() (map[string]string, error) {
+	conf, err := cp.GetConfig()
+	if err != nil {
+		return nil, err
+	}
+	m := make(map[string]string)
+	if conf.ClusterName != "" {
+		m["name"] = conf.ClusterName
+	}
+	m["provider"] = "custom"
+	return m, nil
+}
+
+func (*CustomProvider) AddServiceKey(url.Values) error {
+	return nil
+}
+
+func (*CustomProvider) GetDisks() ([]byte, error) {
+	return nil, nil
+}
+
+func (cp *CustomProvider) AllNodePricing() (interface{}, error) {
+	cp.DownloadPricingDataLock.RLock()
+	defer cp.DownloadPricingDataLock.RUnlock()
+
+	return cp.Pricing, nil
+}
+
+func (cp *CustomProvider) NodePricing(key Key) (*Node, error) {
+	cp.DownloadPricingDataLock.RLock()
+	defer cp.DownloadPricingDataLock.RUnlock()
+
+	k := key.Features()
+	var gpuCount string
+	if _, ok := cp.Pricing[k]; !ok {
+		k = "default"
+	}
+	if key.GPUType() != "" {
+		k += ",gpu"    // TODO: support multiple custom gpu types.
+		gpuCount = "1" // TODO: support more than one gpu.
+	}
+	return &Node{
+		VCPUCost: cp.Pricing[k].CPU,
+		RAMCost:  cp.Pricing[k].RAM,
+		GPUCost:  cp.Pricing[k].GPU,
+		GPU:      gpuCount,
+	}, nil
+}
+
+func (cp *CustomProvider) DownloadPricingData() error {
+	cp.DownloadPricingDataLock.Lock()
+	defer cp.DownloadPricingDataLock.Unlock()
+
+	if cp.Pricing == nil {
+		m := make(map[string]*NodePrice)
+		cp.Pricing = m
+	}
+	p, err := GetDefaultPricingData("default.json")
+	if err != nil {
+		return err
+	}
+	cp.SpotLabel = p.SpotLabel
+	cp.SpotLabelValue = p.SpotLabelValue
+	cp.GPULabel = p.GpuLabel
+	cp.GPULabelValue = p.GpuLabelValue
+	cp.Pricing["default"] = &NodePrice{
+		CPU: p.CPU,
+		RAM: p.RAM,
+	}
+	cp.Pricing["default,spot"] = &NodePrice{
+		CPU: p.SpotCPU,
+		RAM: p.SpotRAM,
+	}
+	cp.Pricing["default,gpu"] = &NodePrice{
+		CPU: p.CPU,
+		RAM: p.RAM,
+		GPU: p.GPU,
+	}
+	return nil
+}
+
+func (cp *CustomProvider) GetKey(labels map[string]string) Key {
+	return &customProviderKey{
+		SpotLabel:      cp.SpotLabel,
+		SpotLabelValue: cp.SpotLabelValue,
+		GPULabel:       cp.GPULabel,
+		GPULabelValue:  cp.GPULabelValue,
+		Labels:         labels,
+	}
+}
+
+// ExternalAllocations represents tagged assets outside the scope of kubernetes.
+// "start" and "end" are dates of the format YYYY-MM-DD
+// "aggregator" is the tag used to determine how to allocate those assets, ie namespace, pod, etc.
+func (*CustomProvider) ExternalAllocations(start string, end string, aggregator string) ([]*OutOfClusterAllocation, error) {
+	return nil, nil // TODO: transform the QuerySQL lines into the new OutOfClusterAllocation Struct
+}
+
+func (*CustomProvider) QuerySQL(query string) ([]byte, error) {
+	return nil, nil
+}
+
+func (*CustomProvider) PVPricing(pvk PVKey) (*PV, error) {
+	cpricing, err := GetDefaultPricingData("default")
+	if err != nil {
+		return nil, err
+	}
+	return &PV{
+		Cost: cpricing.Storage,
+	}, nil
+}
+
+func (*CustomProvider) NetworkPricing() (*Network, error) {
+	cpricing, err := GetDefaultPricingData("default")
+	if err != nil {
+		return nil, err
+	}
+	znec, err := strconv.ParseFloat(cpricing.ZoneNetworkEgress, 64)
+	if err != nil {
+		return nil, err
+	}
+	rnec, err := strconv.ParseFloat(cpricing.RegionNetworkEgress, 64)
+	if err != nil {
+		return nil, err
+	}
+	inec, err := strconv.ParseFloat(cpricing.InternetNetworkEgress, 64)
+	if err != nil {
+		return nil, err
+	}
+
+	return &Network{
+		ZoneNetworkEgressCost:     znec,
+		RegionNetworkEgressCost:   rnec,
+		InternetNetworkEgressCost: inec,
+	}, nil
+}
+
+func (*CustomProvider) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string) PVKey {
+	return &awsPVKey{
+		Labels:           pv.Labels,
+		StorageClassName: pv.Spec.StorageClassName,
+	}
+}
+
+func (cpk *customProviderKey) GPUType() string {
+	if t, ok := cpk.Labels[cpk.GPULabel]; ok {
+		return t
+	}
+	return ""
+}
+
+func (cpk *customProviderKey) ID() string {
+	return ""
+}
+
+func (cpk *customProviderKey) Features() string {
+	if cpk.Labels[cpk.SpotLabel] != "" && cpk.Labels[cpk.SpotLabel] == cpk.SpotLabelValue {
+		return "default,spot"
+	}
+	return "default" // TODO: multiple custom pricing support.
+}

+ 2 - 2
cloud/gcpprovider.go

@@ -165,7 +165,7 @@ func (gcp *GCP) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, er
 	}
 	remoteEnabled := os.Getenv(remoteEnabled)
 	if remoteEnabled == "true" {
-		err = UpdateClusterMeta(os.Getenv(KC_CLUSTER_ID), c.ClusterName)
+		err = UpdateClusterMeta(os.Getenv(clusterIDKey), c.ClusterName)
 		if err != nil {
 			return nil, err
 		}
@@ -268,7 +268,7 @@ func (gcp *GCP) ClusterInfo() (map[string]string, error) {
 	m := make(map[string]string)
 	m["name"] = attribute
 	m["provider"] = "GCP"
-	m["id"] = os.Getenv(KC_CLUSTER_ID)
+	m["id"] = os.Getenv(clusterIDKey)
 	m["remoteReadEnabled"] = strconv.FormatBool(remoteEnabled)
 	return m, nil
 }

+ 57 - 282
cloud/provider.go

@@ -10,9 +10,7 @@ import (
 	"net/url"
 	"os"
 	"reflect"
-	"strconv"
 	"strings"
-	"sync"
 
 	"k8s.io/klog"
 
@@ -23,10 +21,10 @@ import (
 	"k8s.io/client-go/kubernetes"
 )
 
-const KC_CLUSTER_ID = "CLUSTER_ID"
+const clusterIDKey = "CLUSTER_ID"
+const remoteEnabled = "REMOTE_WRITE_ENABLED"
 const remotePW = "REMOTE_WRITE_PASSWORD"
 const sqlAddress = "SQL_ADDRESS"
-const remoteEnabled = "REMOTE_WRITE_ENABLED"
 
 var createTableStatements = []string{
 	`CREATE TABLE IF NOT EXISTS names (
@@ -97,6 +95,45 @@ type OutOfClusterAllocation struct {
 	Cluster     string  `json:"cluster"`
 }
 
+type CustomPricing struct {
+	Provider              string `json:"provider"`
+	Description           string `json:"description"`
+	CPU                   string `json:"CPU"`
+	SpotCPU               string `json:"spotCPU"`
+	RAM                   string `json:"RAM"`
+	SpotRAM               string `json:"spotRAM"`
+	GPU                   string `json:"GPU"`
+	SpotGPU               string `json:"spotGPU"`
+	Storage               string `json:"storage"`
+	ZoneNetworkEgress     string `json:"zoneNetworkEgress"`
+	RegionNetworkEgress   string `json:"regionNetworkEgress"`
+	InternetNetworkEgress string `json:"internetNetworkEgress"`
+	SpotLabel             string `json:"spotLabel,omitempty"`
+	SpotLabelValue        string `json:"spotLabelValue,omitempty"`
+	GpuLabel              string `json:"gpuLabel,omitempty"`
+	GpuLabelValue         string `json:"gpuLabelValue,omitempty"`
+	ServiceKeyName        string `json:"awsServiceKeyName,omitempty"`
+	ServiceKeySecret      string `json:"awsServiceKeySecret,omitempty"`
+	SpotDataRegion        string `json:"awsSpotDataRegion,omitempty"`
+	SpotDataBucket        string `json:"awsSpotDataBucket,omitempty"`
+	SpotDataPrefix        string `json:"awsSpotDataPrefix,omitempty"`
+	ProjectID             string `json:"projectID,omitempty"`
+	AthenaBucketName      string `json:"athenaBucketName"`
+	AthenaRegion          string `json:"athenaRegion"`
+	AthenaDatabase        string `json:"athenaDatabase"`
+	AthenaTable           string `json:"athenaTable"`
+	BillingDataDataset    string `json:"billingDataDataset,omitempty"`
+	CustomPricesEnabled   string `json:"customPricesEnabled"`
+	AzureSubscriptionID   string `json:"azureSubscriptionID"`
+	AzureClientID         string `json:"azureClientID"`
+	AzureClientSecret     string `json:"azureClientSecret"`
+	AzureTenantID         string `json:"azureTenantID"`
+	AzureBillingRegion    string `json:"azureBillingRegion"`
+	CurrencyCode          string `json:"currencyCode"`
+	Discount              string `json:"discount"`
+	ClusterName           string `json:"clusterName"`
+}
+
 // Provider represents a k8s provider.
 type Provider interface {
 	ClusterInfo() (map[string]string, error)
@@ -113,10 +150,25 @@ type Provider interface {
 	GetConfig() (*CustomPricing, error)
 	GetManagementPlatform() (string, error)
 	GetLocalStorageQuery() (string, error)
-
 	ExternalAllocations(string, string, string) ([]*OutOfClusterAllocation, error)
 }
 
+// ClusterName returns the name defined in cluster info, defaulting to the
+// CLUSTER_ID environment variable
+func ClusterName(p Provider) string {
+	info, err := p.ClusterInfo()
+	if err != nil {
+		return os.Getenv(clusterIDKey)
+	}
+
+	name, ok := info["name"]
+	if !ok {
+		return os.Getenv(clusterIDKey)
+	}
+
+	return name
+}
+
 // GetDefaultPricingData will search for a json file representing pricing data in /models/ and use it for base pricing info.
 func GetDefaultPricingData(fname string) (*CustomPricing, error) {
 	path := os.Getenv("CONFIG_PATH")
@@ -170,47 +222,6 @@ func GetDefaultPricingData(fname string) (*CustomPricing, error) {
 	}
 }
 
-const KeyUpdateType = "athenainfo"
-
-type CustomPricing struct {
-	Provider              string `json:"provider"`
-	Description           string `json:"description"`
-	CPU                   string `json:"CPU"`
-	SpotCPU               string `json:"spotCPU"`
-	RAM                   string `json:"RAM"`
-	SpotRAM               string `json:"spotRAM"`
-	GPU                   string `json:"GPU"`
-	SpotGPU               string `json:"spotGPU"`
-	Storage               string `json:"storage"`
-	ZoneNetworkEgress     string `json:"zoneNetworkEgress"`
-	RegionNetworkEgress   string `json:"regionNetworkEgress"`
-	InternetNetworkEgress string `json:"internetNetworkEgress"`
-	SpotLabel             string `json:"spotLabel,omitempty"`
-	SpotLabelValue        string `json:"spotLabelValue,omitempty"`
-	GpuLabel              string `json:"gpuLabel,omitempty"`
-	GpuLabelValue         string `json:"gpuLabelValue,omitempty"`
-	ServiceKeyName        string `json:"awsServiceKeyName,omitempty"`
-	ServiceKeySecret      string `json:"awsServiceKeySecret,omitempty"`
-	SpotDataRegion        string `json:"awsSpotDataRegion,omitempty"`
-	SpotDataBucket        string `json:"awsSpotDataBucket,omitempty"`
-	SpotDataPrefix        string `json:"awsSpotDataPrefix,omitempty"`
-	ProjectID             string `json:"projectID,omitempty"`
-	AthenaBucketName      string `json:"athenaBucketName"`
-	AthenaRegion          string `json:"athenaRegion"`
-	AthenaDatabase        string `json:"athenaDatabase"`
-	AthenaTable           string `json:"athenaTable"`
-	BillingDataDataset    string `json:"billingDataDataset,omitempty"`
-	CustomPricesEnabled   string `json:"customPricesEnabled"`
-	AzureSubscriptionID   string `json:"azureSubscriptionID"`
-	AzureClientID         string `json:"azureClientID"`
-	AzureClientSecret     string `json:"azureClientSecret"`
-	AzureTenantID         string `json:"azureTenantID"`
-	AzureBillingRegion    string `json:"azureBillingRegion"`
-	CurrencyCode          string `json:"currencyCode"`
-	Discount              string `json:"discount"`
-	ClusterName           string `json:"clusterName"`
-}
-
 func SetCustomPricingField(obj *CustomPricing, name string, value string) error {
 	structValue := reflect.ValueOf(obj).Elem()
 	structFieldValue := structValue.FieldByName(name)
@@ -233,241 +244,6 @@ func SetCustomPricingField(obj *CustomPricing, name string, value string) error
 	return nil
 }
 
-type NodePrice struct {
-	CPU string
-	RAM string
-	GPU string
-}
-
-type CustomProvider struct {
-	Clientset               *kubernetes.Clientset
-	Pricing                 map[string]*NodePrice
-	SpotLabel               string
-	SpotLabelValue          string
-	GPULabel                string
-	GPULabelValue           string
-	DownloadPricingDataLock sync.RWMutex
-}
-
-func (*CustomProvider) GetLocalStorageQuery() (string, error) {
-	return "", nil
-}
-
-func (*CustomProvider) GetConfig() (*CustomPricing, error) {
-	return GetDefaultPricingData("default.json")
-}
-
-func (*CustomProvider) GetManagementPlatform() (string, error) {
-	return "", nil
-}
-
-func (cprov *CustomProvider) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, error) {
-	c, err := GetDefaultPricingData("default.json")
-	if err != nil {
-		return nil, err
-	}
-	path := os.Getenv("CONFIG_PATH")
-	if path == "" {
-		path = "/models/"
-	}
-	a := make(map[string]string)
-	err = json.NewDecoder(r).Decode(&a)
-	if err != nil {
-		return nil, err
-	}
-	for k, v := range a {
-		kUpper := strings.Title(k) // Just so we consistently supply / receive the same values, uppercase the first letter.
-		err := SetCustomPricingField(c, kUpper, v)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	cj, err := json.Marshal(c)
-	if err != nil {
-		return nil, err
-	}
-
-	configPath := path + "default.json"
-	err = ioutil.WriteFile(configPath, cj, 0644)
-	if err != nil {
-		return nil, err
-	}
-	defer cprov.DownloadPricingData()
-	return c, nil
-
-}
-
-func (c *CustomProvider) ClusterInfo() (map[string]string, error) {
-	conf, err := c.GetConfig()
-	if err != nil {
-		return nil, err
-	}
-	m := make(map[string]string)
-	if conf.ClusterName != "" {
-		m["name"] = conf.ClusterName
-	}
-	m["provider"] = "custom"
-	return m, nil
-}
-
-func (*CustomProvider) AddServiceKey(url.Values) error {
-	return nil
-}
-
-func (*CustomProvider) GetDisks() ([]byte, error) {
-	return nil, nil
-}
-
-func (c *CustomProvider) AllNodePricing() (interface{}, error) {
-	c.DownloadPricingDataLock.RLock()
-	defer c.DownloadPricingDataLock.RUnlock()
-
-	return c.Pricing, nil
-}
-
-func (c *CustomProvider) NodePricing(key Key) (*Node, error) {
-	c.DownloadPricingDataLock.RLock()
-	defer c.DownloadPricingDataLock.RUnlock()
-
-	k := key.Features()
-	var gpuCount string
-	if _, ok := c.Pricing[k]; !ok {
-		k = "default"
-	}
-	if key.GPUType() != "" {
-		k += ",gpu"    // TODO: support multiple custom gpu types.
-		gpuCount = "1" // TODO: support more than one gpu.
-	}
-	return &Node{
-		VCPUCost: c.Pricing[k].CPU,
-		RAMCost:  c.Pricing[k].RAM,
-		GPUCost:  c.Pricing[k].GPU,
-		GPU:      gpuCount,
-	}, nil
-}
-
-func (c *CustomProvider) DownloadPricingData() error {
-	c.DownloadPricingDataLock.Lock()
-	defer c.DownloadPricingDataLock.Unlock()
-
-	if c.Pricing == nil {
-		m := make(map[string]*NodePrice)
-		c.Pricing = m
-	}
-	p, err := GetDefaultPricingData("default.json")
-	if err != nil {
-		return err
-	}
-	c.SpotLabel = p.SpotLabel
-	c.SpotLabelValue = p.SpotLabelValue
-	c.GPULabel = p.GpuLabel
-	c.GPULabelValue = p.GpuLabelValue
-	c.Pricing["default"] = &NodePrice{
-		CPU: p.CPU,
-		RAM: p.RAM,
-	}
-	c.Pricing["default,spot"] = &NodePrice{
-		CPU: p.SpotCPU,
-		RAM: p.SpotRAM,
-	}
-	c.Pricing["default,gpu"] = &NodePrice{
-		CPU: p.CPU,
-		RAM: p.RAM,
-		GPU: p.GPU,
-	}
-	return nil
-}
-
-type customProviderKey struct {
-	SpotLabel      string
-	SpotLabelValue string
-	GPULabel       string
-	GPULabelValue  string
-	Labels         map[string]string
-}
-
-func (c *customProviderKey) GPUType() string {
-	if t, ok := c.Labels[c.GPULabel]; ok {
-		return t
-	}
-	return ""
-}
-
-func (c *customProviderKey) ID() string {
-	return ""
-}
-
-func (c *customProviderKey) Features() string {
-	if c.Labels[c.SpotLabel] != "" && c.Labels[c.SpotLabel] == c.SpotLabelValue {
-		return "default,spot"
-	}
-	return "default" // TODO: multiple custom pricing support.
-}
-
-func (c *CustomProvider) GetKey(labels map[string]string) Key {
-	return &customProviderKey{
-		SpotLabel:      c.SpotLabel,
-		SpotLabelValue: c.SpotLabelValue,
-		GPULabel:       c.GPULabel,
-		GPULabelValue:  c.GPULabelValue,
-		Labels:         labels,
-	}
-}
-
-// ExternalAllocations represents tagged assets outside the scope of kubernetes.
-// "start" and "end" are dates of the format YYYY-MM-DD
-// "aggregator" is the tag used to determine how to allocate those assets, ie namespace, pod, etc.
-func (*CustomProvider) ExternalAllocations(start string, end string, aggregator string) ([]*OutOfClusterAllocation, error) {
-	return nil, nil // TODO: transform the QuerySQL lines into the new OutOfClusterAllocation Struct
-}
-
-func (*CustomProvider) QuerySQL(query string) ([]byte, error) {
-	return nil, nil
-}
-
-func (c *CustomProvider) PVPricing(pvk PVKey) (*PV, error) {
-	cpricing, err := GetDefaultPricingData("default")
-	if err != nil {
-		return nil, err
-	}
-	return &PV{
-		Cost: cpricing.Storage,
-	}, nil
-}
-
-func (c *CustomProvider) NetworkPricing() (*Network, error) {
-	cpricing, err := GetDefaultPricingData("default")
-	if err != nil {
-		return nil, err
-	}
-	znec, err := strconv.ParseFloat(cpricing.ZoneNetworkEgress, 64)
-	if err != nil {
-		return nil, err
-	}
-	rnec, err := strconv.ParseFloat(cpricing.RegionNetworkEgress, 64)
-	if err != nil {
-		return nil, err
-	}
-	inec, err := strconv.ParseFloat(cpricing.InternetNetworkEgress, 64)
-	if err != nil {
-		return nil, err
-	}
-
-	return &Network{
-		ZoneNetworkEgressCost:     znec,
-		RegionNetworkEgressCost:   rnec,
-		InternetNetworkEgressCost: inec,
-	}, nil
-}
-
-func (*CustomProvider) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string) PVKey {
-	return &awsPVKey{
-		Labels:           pv.Labels,
-		StorageClassName: pv.Spec.StorageClassName,
-	}
-}
-
 // NewProvider looks at the nodespec or provider metadata server to decide which provider to instantiate.
 func NewProvider(clientset *kubernetes.Clientset, apiKey string) (Provider, error) {
 	if metadata.OnGCE() {
@@ -587,5 +363,4 @@ func GetOrCreateClusterMeta(cluster_id, cluster_name string) (string, string, er
 	}
 
 	return id, name, nil
-
 }

+ 14 - 12
costmodel/costmodel.go

@@ -13,6 +13,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/kubecost/cost-model/cloud"
 	costAnalyzerCloud "github.com/kubecost/cost-model/cloud"
 	prometheusClient "github.com/prometheus/client_golang/api"
 	v1 "k8s.io/api/core/v1"
@@ -25,8 +26,7 @@ import (
 const (
 	statusAPIError = 422
 
-	apiPrefix = "/api/v1"
-
+	apiPrefix         = "/api/v1"
 	epAlertManagers   = apiPrefix + "/alertmanagers"
 	epQuery           = apiPrefix + "/query"
 	epQueryRange      = apiPrefix + "/query_range"
@@ -38,8 +38,9 @@ const (
 	epCleanTombstones = apiPrefix + "/admin/tsdb/clean_tombstones"
 	epConfig          = apiPrefix + "/status/config"
 	epFlags           = apiPrefix + "/status/flags"
-	remoteEnabled     = "REMOTE_WRITE_ENABLED"
-	CLUSTER_ID        = "CLUSTER_ID"
+
+	clusterIDKey  = "CLUSTER_ID"
+	remoteEnabled = "REMOTE_WRITE_ENABLED"
 )
 
 type CostModel struct {
@@ -253,7 +254,7 @@ func ComputeUptimes(cli prometheusClient.Client) (map[string]float64, error) {
 	return results, nil
 }
 
-func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kubernetes.Interface, cloud costAnalyzerCloud.Provider, window string, offset string, filterNamespace string) (map[string]*CostData, error) {
+func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kubernetes.Interface, cp costAnalyzerCloud.Provider, window string, offset string, filterNamespace string) (map[string]*CostData, error) {
 	queryRAMRequests := fmt.Sprintf(queryRAMRequestsStr, window, offset, window, offset)
 	queryRAMUsage := fmt.Sprintf(queryRAMUsageStr, window, offset, window, offset)
 	queryCPURequests := fmt.Sprintf(queryCPURequestsStr, window, offset, window, offset)
@@ -265,7 +266,8 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 	queryNetInternetRequests := fmt.Sprintf(queryInternetNetworkUsage, window, "")
 	normalization := fmt.Sprintf(normalizationStr, window, offset)
 
-	clustID := os.Getenv(CLUSTER_ID)
+	// Retrieve cluster ID from cloud provider's cluster info
+	clusterName := cloud.ClusterName(cp)
 
 	var wg sync.WaitGroup
 	wg.Add(11)
@@ -360,7 +362,7 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 		return nil, fmt.Errorf("Error parsing normalization values: " + err.Error())
 	}
 
-	nodes, err := getNodeCost(cm.Cache, cloud)
+	nodes, err := getNodeCost(cm.Cache, cp)
 	if err != nil {
 		klog.V(1).Infof("Warning, no Node cost model available: " + err.Error())
 		return nil, err
@@ -371,7 +373,7 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 		klog.Infof("Unable to get PV Data: %s", err.Error())
 	}
 	if pvClaimMapping != nil {
-		err = addPVData(cm.Cache, pvClaimMapping, cloud)
+		err = addPVData(cm.Cache, pvClaimMapping, cp)
 		if err != nil {
 			return nil, err
 		}
@@ -485,7 +487,7 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 
 			var podNetCosts []*Vector
 			if usage, ok := networkUsageMap[ns+","+podName]; ok {
-				netCosts, err := GetNetworkCost(usage, cloud)
+				netCosts, err := GetNetworkCost(usage, cp)
 				if err != nil {
 					klog.V(3).Infof("Error pulling network costs: %s", err.Error())
 				} else {
@@ -561,7 +563,7 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 					NetworkData:     netReq,
 					Labels:          podLabels,
 					NamespaceLabels: nsLabels,
-					ClusterID:       clustID,
+					ClusterID:       clusterName,
 				}
 				costs.CPUAllocation = getContainerAllocation(costs.CPUReq, costs.CPUUsed)
 				costs.RAMAllocation = getContainerAllocation(costs.RAMReq, costs.RAMUsed)
@@ -630,7 +632,7 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
 				CPUUsed:         CPUUsedV,
 				GPUReq:          GPUReqV,
 				NamespaceLabels: namespacelabels,
-				ClusterID:       clustID,
+				ClusterID:       clusterName,
 			}
 			costs.CPUAllocation = getContainerAllocation(costs.CPUReq, costs.CPUUsed)
 			costs.RAMAllocation = getContainerAllocation(costs.RAMReq, costs.RAMUsed)
@@ -1140,7 +1142,7 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
 		klog.V(1).Infof("Error parsing time " + windowString + ". Error: " + err.Error())
 		return nil, err
 	}
-	clustID := os.Getenv(CLUSTER_ID)
+	clustID := os.Getenv(clusterIDKey)
 	if remoteEnabled == true {
 		remoteLayout := "2006-01-02T15:04:05Z"
 		remoteStartStr := start.Format(remoteLayout)