2
0
Эх сурвалжийг харах

add unit test for bad config

Ajay Tripathy 5 жил өмнө
parent
commit
04383db9d0

+ 3 - 0
go.sum

@@ -447,6 +447,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -567,6 +568,8 @@ k8s.io/client-go v0.0.0-20190404172613-2e1a3ed22ac5 h1:BwY2C//EoWktJi74O6R2REBon
 k8s.io/client-go v0.0.0-20190404172613-2e1a3ed22ac5/go.mod h1:bIEHXHbykaOlj+pgLllzLJ2RPGdzkjtqdk0Il07KPEM=
 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab h1:E8Fecph0qbNsAbijJJQryKu4Oi9QTp5cVpjTE+nqg6g=
 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
+k8s.io/client-go v1.5.1 h1:XaX/lo2/u3/pmFau8HN+sB5C/b4dc4Dmm2eXjBH4p1E=
+k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.0.0-20190306015804-8e90cee79f82 h1:SHucoAy7lRb+w5oC/hbXyZg+zX+Wftn6hD4tGzHCVqA=

+ 5 - 26
pkg/cloud/awsprovider.go

@@ -977,40 +977,19 @@ func (aws *AWS) savingsPlanPricing(instanceID string) (*SavingsPlanData, bool) {
 }
 
 func (aws *AWS) createNode(terms *AWSProductTerms, usageType string, k Key) (*Node, error) {
-	key := k.Features()
+	//key := k.Features()
 
-	if spotInfo, ok := aws.spotPricing(k.ID()); ok {
-		var spotcost string
-		log.DedupedInfof(5, "Looking up spot data from feed for node %s", k.ID())
-		arr := strings.Split(spotInfo.Charge, " ")
-		if len(arr) == 2 {
-			spotcost = arr[0]
-		} else {
-			klog.V(2).Infof("Spot data for node %s is missing", k.ID())
-		}
-		return &Node{
-			Cost:         spotcost,
-			VCPU:         terms.VCpu,
-			RAM:          terms.Memory,
-			GPU:          terms.GPU,
-			Storage:      terms.Storage,
-			BaseCPUPrice: aws.BaseCPUPrice,
-			BaseRAMPrice: aws.BaseRAMPrice,
-			BaseGPUPrice: aws.BaseGPUPrice,
-			UsageType:    PreemptibleType,
-		}, nil
-	} else if aws.isPreemptible(key) { // Preemptible but we don't have any data in the pricing report.
+	if true { // Preemptible but we don't have any data in the pricing report.
 		log.DedupedWarningf(5, "Node %s marked preemptible but we have no data in spot feed", k.ID())
 		return &Node{
 			VCPU:         terms.VCpu,
 			VCPUCost:     aws.BaseSpotCPUPrice,
 			RAM:          terms.Memory,
 			GPU:          terms.GPU,
-			RAMCost:      aws.BaseSpotRAMPrice,
 			Storage:      terms.Storage,
-			BaseCPUPrice: aws.BaseCPUPrice,
-			BaseRAMPrice: aws.BaseRAMPrice,
-			BaseGPUPrice: aws.BaseGPUPrice,
+			BaseCPUPrice: aws.BaseSpotCPUPrice,
+			BaseRAMPrice: aws.BaseSpotRAMPrice,
+			BaseGPUPrice: aws.BaseSpotGPUPrice,
 			UsageType:    PreemptibleType,
 		}, nil
 	} else if sp, ok := aws.savingsPlanPricing(k.ID()); ok {

+ 55 - 1
test/cloud_test.go

@@ -1,10 +1,16 @@
-package test
+package costmodel_test
 
 import (
+	"os"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/kubecost/cost-model/pkg/cloud"
+	"github.com/kubecost/cost-model/pkg/clustercache"
+	"github.com/kubecost/cost-model/pkg/costmodel"
+	"github.com/kubecost/cost-model/pkg/costmodel/clusters"
+
 	v1 "k8s.io/api/core/v1"
 )
 
@@ -229,6 +235,54 @@ func TestNodePriceFromCSVWithRegion(t *testing.T) {
 	}
 }
 
+type FakeCache struct {
+	nodes []*v1.Node
+	clustercache.ClusterCache
+}
+
+func (f FakeCache) GetAllNodes() []*v1.Node {
+	return f.nodes
+}
+
+func NewFakeNodeCache(nodes []*v1.Node) FakeCache {
+	return FakeCache{
+		nodes: nodes,
+	}
+}
+
+type FakeClusterMap struct {
+	clusters.ClusterMap
+}
+
+func TestNodePriceFromCSVWithBadConfig(t *testing.T) {
+	os.Setenv("CONFIG_PATH", "../config")
+	c := &cloud.CSVProvider{
+		CSVLocation: "../configs/pricing_schema_case.csv",
+		CustomProvider: &cloud.CustomProvider{
+			Config: cloud.NewProviderConfig("invalid.json"),
+		},
+	}
+	c.DownloadPricingData()
+
+	n := &v1.Node{}
+	n.Spec.ProviderID = "fake"
+	n.Name = "nameWant"
+	n.Labels = make(map[string]string)
+	n.Labels["foo"] = "labelFooWant"
+	n.Labels[v1.LabelZoneRegion] = "regionone"
+
+	fc := NewFakeNodeCache([]*v1.Node{n})
+	fm := FakeClusterMap{}
+	d, _ := time.ParseDuration("1m")
+
+	model := costmodel.NewCostModel(fc, fm, d)
+
+	_, err := model.GetNodeCost(c)
+	if err != nil {
+		t.Errorf("Error in node pricing: %s", err)
+	}
+}
+
 func TestNodePriceFromCSVWithCase(t *testing.T) {
 	n := &v1.Node{}
 	n.Spec.ProviderID = "azure:///subscriptions/123a7sd-asd-1234-578a9-123abcdef/resourceGroups/case_12_STaGe_TeSt7/providers/Microsoft.Compute/virtualMachineScaleSets/vmss-agent-worker0-12stagetest7-ezggnore/virtualMachines/7"

+ 0 - 194
test/cluster_test.go

@@ -1,194 +0,0 @@
-package costmodel_test
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-
-	//	"math"
-	//	"net"
-	"net/http"
-	"strconv"
-
-	//	"testing"
-	//	"time"
-
-	//	"gotest.tools/assert"
-
-	prometheusClient "github.com/prometheus/client_golang/api"
-
-	//	v1 "k8s.io/api/core/v1"
-	//	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	_ "k8s.io/client-go/plugin/pkg/client/auth"
-
-	"log"
-)
-
-const apiPrefix = "/api/v1"
-
-const epQuery = apiPrefix + "/query"
-
-// The integration test assumes a GKE cluster in us-central-1 or an AWS cluster in us-east-2, with the following instance types
-// and storage classes.
-var prices = map[string]float64{
-	"n1standardRAM":   0.004237,
-	"n1standardCPU":   0.031611,
-	"t2.medium":       0.0464,
-	"t2.small":        0.023,
-	"t2.micro":        0.0116,
-	"c4.large":        0.1,
-	"gp2":             0.000137,
-	"ssd":             0.170,
-	"Standard_DS2_v2": 0.252,
-	"g1smallCPU":      0.025643,
-	"g1smallRAM":      0.000034,
-	"n1-highmem-2":    0.1171,
-}
-
-func parseQuery(qr interface{}) (float64, error) {
-	data, ok := qr.(map[string]interface{})["data"]
-	if !ok {
-		return 0, fmt.Errorf("Improperly formatted response from prometheus, response %+v has no data field", data)
-	}
-	r, ok := data.(map[string]interface{})["result"]
-	if !ok {
-		return 0, fmt.Errorf("Improperly formatted data from prometheus, data has no result field")
-	}
-	results, ok := r.([]interface{})
-	if !ok {
-		return 0, fmt.Errorf("Improperly formatted results from prometheus, result field is not a slice")
-	}
-	val, ok := results[0].(map[string]interface{})["value"]
-	if !ok {
-		return 0, fmt.Errorf("Improperly formatted results from prometheus, value is not a field in the vector")
-	}
-	dataPoint, ok := val.([]interface{})
-	if !ok || len(dataPoint) != 2 {
-		return 0, fmt.Errorf("Improperly formatted datapoint from Prometheus")
-	}
-
-	return strconv.ParseFloat(dataPoint[1].(string), 64)
-
-}
-
-func query(cli prometheusClient.Client, query string) (interface{}, error) {
-	u := cli.URL(epQuery, nil)
-	q := u.Query()
-	q.Set("query", query)
-	u.RawQuery = q.Encode()
-
-	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
-	if err != nil {
-		return nil, err
-	}
-
-	_, body, _, err := cli.Do(context.Background(), req)
-	if err != nil {
-		return nil, err
-	}
-	var toReturn interface{}
-	err = json.Unmarshal(body, &toReturn)
-	if err != nil {
-		log.Printf("ERROR" + err.Error())
-	}
-	return toReturn, err
-}
-
-/*
-func TestKubernetesPVCosts(t *testing.T) {
-	cli, err := getKubernetesClient()
-	if err != nil {
-		panic(err)
-	}
-	var LongTimeoutRoundTripper http.RoundTripper = &http.Transport{ // may be necessary for long prometheus queries. TODO: make this configurable
-		Proxy: http.ProxyFromEnvironment,
-		DialContext: (&net.Dialer{
-			Timeout:   120 * time.Second,
-			KeepAlive: 120 * time.Second,
-		}).DialContext,
-		TLSHandshakeTimeout: 10 * time.Second,
-	}
-
-	pc := prometheusClient.Config{
-		Address:      address,
-		RoundTripper: LongTimeoutRoundTripper,
-	}
-	promCli, err := prometheusClient.NewClient(pc)
-	if err != nil {
-		panic(err)
-	}
-
-	pvs, err := cli.CoreV1().PersistentVolumes().List(metav1.ListOptions{})
-	if err != nil {
-		panic(err)
-	}
-	for _, pv := range pvs.Items {
-		name := pv.Name
-		class := pv.Spec.StorageClassName
-
-		q := fmt.Sprintf(`pv_hourly_cost{persistentvolume="%s"}`, name)
-		qt, err := query(promCli, q)
-		total, err := parseQuery(qt)
-		if err != nil {
-			log.Printf(err.Error())
-		}
-		if price, ok := prices[class]; ok {
-			assert.Equal(t, math.Round(total*1000000)/1000000, price)
-		}
-
-	}
-
-}
-
-func TestKubernetesClusterCosts(t *testing.T) {
-	prices["n1-standard-1"] = math.Round((prices["n1standardCPU"]+3.61219*prices["n1standardRAM"])*10000) / 10000
-	prices["g1-small"] = math.Round(((prices["g1smallCPU"] + 0.216998*prices["g1smallRAM"]) * 10000)) / 10000
-	cli, err := getKubernetesClient()
-	if err != nil {
-		panic(err)
-	}
-	var LongTimeoutRoundTripper http.RoundTripper = &http.Transport{ // may be necessary for long prometheus queries. TODO: make this configurable
-		Proxy: http.ProxyFromEnvironment,
-		DialContext: (&net.Dialer{
-			Timeout:   120 * time.Second,
-			KeepAlive: 120 * time.Second,
-		}).DialContext,
-		TLSHandshakeTimeout: 10 * time.Second,
-	}
-
-	pc := prometheusClient.Config{
-		Address:      address,
-		RoundTripper: LongTimeoutRoundTripper,
-	}
-	promCli, err := prometheusClient.NewClient(pc)
-	if err != nil {
-		panic(err)
-	}
-
-	nodes, err := cli.CoreV1().Nodes().List(metav1.ListOptions{})
-	if err != nil {
-		panic(err)
-	}
-	for _, n := range nodes.Items {
-		name := n.GetObjectMeta().GetName()
-		q := fmt.Sprintf(`node_total_hourly_cost{instance="%s"}`, name)
-		labels := n.GetObjectMeta().GetLabels()
-		instanceType := labels[v1.LabelInstanceType]
-
-		qt, err := query(promCli, q)
-		if err != nil {
-			panic(err)
-		}
-		total, err := parseQuery(qt)
-		if err != nil {
-			panic(err)
-		}
-
-		if price, ok := prices[instanceType]; ok {
-			assert.Equal(t, math.Round(total*10000)/10000, price)
-		}
-
-	}
-}
-*/

+ 1 - 1
test/clusterinfo_test.go

@@ -1,4 +1,4 @@
-package test
+package costmodel_test
 
 import (
 	"encoding/json"

+ 1 - 1
test/util_test.go

@@ -1,4 +1,4 @@
-package test
+package costmodel_test
 
 import (
 	"net/http"