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

add testing

Signed-off-by: Alex Meijer <ameijer@kubecost.com>
Alex Meijer 3 лет назад
Родитель
Сommit
51c32934ff
3 измененных файлов с 133 добавлено и 24 удалено
  1. 8 12
      pkg/kubecost/allocation.go
  2. 124 12
      pkg/kubecost/allocation_test.go
  3. 1 0
      pkg/kubecost/mock.go

+ 8 - 12
pkg/kubecost/allocation.go

@@ -1136,21 +1136,17 @@ func (as *AllocationSet) AggregateBy(aggregateBy []string, options *AllocationAg
 		}
 	}
 
-	var parcCoefficients map[string]map[string]map[string]float64
-	if parcSet.Length() > 0 {
-		parcCoefficients, allocatedTotalsMap, err = computeIdleCoeffs(options, as, shareSet)
-		if err != nil {
-			log.Warnf("AllocationSet.AggregateBy: compute parc idle coeff: %s", err)
-			return fmt.Errorf("error computing parc coefficients: %s", err)
-		}
-	}
-
-	log.Infof("[PARCS] idleSet.Length(): %d", idleSet.Length())
-	log.Infof("[PARCS] parcCoefficients: nil:%t len:%d", parcCoefficients == nil, len(parcCoefficients))
-
 	// (2b) If proportional asset resource costs are to be included, derive them
 	// from idle coefficients and add them to the allocations.
 	if options.IncludeProportionalAssetResourceCosts {
+		var parcCoefficients map[string]map[string]map[string]float64
+		if parcSet.Length() > 0 {
+			parcCoefficients, allocatedTotalsMap, err = computeIdleCoeffs(options, as, shareSet)
+			if err != nil {
+				log.Warnf("AllocationSet.AggregateBy: compute parc idle coeff: %s", err)
+				return fmt.Errorf("error computing parc coefficients: %s", err)
+			}
+		}
 		if parcCoefficients == nil {
 			return fmt.Errorf("cannot include proportional resource costs because parc coefficients are nil")
 		}

+ 124 - 12
pkg/kubecost/allocation_test.go

@@ -3,6 +3,7 @@ package kubecost
 import (
 	"fmt"
 	"math"
+	"reflect"
 	"testing"
 	"time"
 
@@ -509,6 +510,19 @@ func assertAllocationSetTotals(t *testing.T, as *AllocationSet, msg string, err
 	}
 }
 
+func assertParcResults(t *testing.T, as *AllocationSet, msg string, exps map[string]ProportionalAssetResourceCosts) {
+	for allocKey, a := range as.Allocations {
+		for key, actualParc := range a.ProportionalAssetResourceCosts {
+			expectedParcs := exps[allocKey]
+
+			if !reflect.DeepEqual(expectedParcs[key], actualParc) {
+				t.Fatalf("actual PARC %v did not match expected PARC %v", actualParc, expectedParcs[key])
+			}
+		}
+
+	}
+}
+
 func assertAllocationTotals(t *testing.T, as *AllocationSet, msg string, exps map[string]float64) {
 	for _, a := range as.Allocations {
 		if exp, ok := exps[a.Name]; ok {
@@ -690,15 +704,16 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 
 	// Tests:
 	cases := map[string]struct {
-		start       time.Time
-		aggBy       []string
-		aggOpts     *AllocationAggregationOptions
-		numResults  int
-		totalCost   float64
-		results     map[string]float64
-		windowStart time.Time
-		windowEnd   time.Time
-		expMinutes  float64
+		start               time.Time
+		aggBy               []string
+		aggOpts             *AllocationAggregationOptions
+		numResults          int
+		totalCost           float64
+		results             map[string]float64
+		windowStart         time.Time
+		windowEnd           time.Time
+		expMinutes          float64
+		expectedParcResults map[string]ProportionalAssetResourceCosts
 	}{
 		// 1  Single-aggregation
 
@@ -1042,8 +1057,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 			start: start,
 			aggBy: []string{AllocationNamespaceProp},
 			aggOpts: &AllocationAggregationOptions{
-				ShareFuncs: []AllocationMatchFunc{isNamespace3},
-				ShareSplit: ShareWeighted,
+				ShareFuncs:                            []AllocationMatchFunc{isNamespace3},
+				ShareSplit:                            ShareWeighted,
+				IncludeProportionalAssetResourceCosts: true,
 			},
 			numResults: numNamespaces,
 			totalCost:  activeTotalCost + idleTotalCost,
@@ -1055,6 +1071,36 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 			windowStart: startYesterday,
 			windowEnd:   endYesterday,
 			expMinutes:  1440.0,
+			expectedParcResults: map[string]ProportionalAssetResourceCosts{
+				"namespace1": ProportionalAssetResourceCosts{
+					"cluster1": ProportionalAssetResourceCost{
+						Cluster:       "cluster1",
+						Node:          "",
+						ProviderID:    "",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.8125,
+					},
+				},
+				"namespace2": ProportionalAssetResourceCosts{
+					"cluster1": ProportionalAssetResourceCost{
+						Cluster:       "cluster1",
+						Node:          "",
+						ProviderID:    "",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.1875,
+					},
+					"cluster2": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "",
+						ProviderID:    "",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.5,
+					},
+				},
+			},
 		},
 		// 4c Share label ShareEven
 		// namespace1: 17.3333 = 28.00 - 16.00 + 16.00*(1.0/3.0)
@@ -1446,7 +1492,8 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 			start: start,
 			aggBy: []string{AllocationNamespaceProp},
 			aggOpts: &AllocationAggregationOptions{
-				IdleByNode: true,
+				IdleByNode:                            true,
+				IncludeProportionalAssetResourceCosts: true,
 			},
 			numResults: numNamespaces + numIdle,
 			totalCost:  activeTotalCost + idleTotalCost,
@@ -1459,6 +1506,70 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 			windowStart: startYesterday,
 			windowEnd:   endYesterday,
 			expMinutes:  1440.0,
+			expectedParcResults: map[string]ProportionalAssetResourceCosts{
+				"namespace1": {
+					"cluster1,c1nodes": ProportionalAssetResourceCost{
+						Cluster:       "cluster1",
+						Node:          "c1nodes",
+						ProviderID:    "c1nodes",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.8125,
+					},
+					"cluster2,node2": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "node2",
+						ProviderID:    "node2",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.5,
+					},
+				},
+				"namespace2": {
+					"cluster1,c1nodes": ProportionalAssetResourceCost{
+						Cluster:       "cluster1",
+						Node:          "c1nodes",
+						ProviderID:    "c1nodes",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.1875,
+					},
+					"cluster2,node1": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "node1",
+						ProviderID:    "node1",
+						CPUPercentage: 1,
+						GPUPercentage: 1,
+						RAMPercentage: 1,
+					},
+					"cluster2,node2": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "node2",
+						ProviderID:    "node2",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.5,
+					},
+				},
+				"namespace3": {
+					"cluster2,node3": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "node3",
+						ProviderID:    "node3",
+						CPUPercentage: 1,
+						GPUPercentage: 1,
+						RAMPercentage: 1,
+					},
+					"cluster2,node2": ProportionalAssetResourceCost{
+						Cluster:       "cluster2",
+						Node:          "node2",
+						ProviderID:    "node2",
+						CPUPercentage: 0.5,
+						GPUPercentage: 0.5,
+						RAMPercentage: 0.5,
+					},
+				},
+			},
 		},
 		// 6k Split Idle, Idle by Node
 		"6k": {
@@ -1524,6 +1635,7 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 			err = as.AggregateBy(testcase.aggBy, testcase.aggOpts)
 			assertAllocationSetTotals(t, as, name, err, testcase.numResults, testcase.totalCost)
 			assertAllocationTotals(t, as, name, testcase.results)
+			assertParcResults(t, as, name, testcase.expectedParcResults)
 			assertAllocationWindow(t, as, name, testcase.windowStart, testcase.windowEnd, testcase.expMinutes)
 		})
 	}

+ 1 - 0
pkg/kubecost/mock.go

@@ -63,6 +63,7 @@ func NewMockUnitAllocation(name string, start time.Time, resolution time.Duratio
 			CPUCoreUsageMax:  1,
 			RAMBytesUsageMax: 1,
 		},
+		ProportionalAssetResourceCosts: nil,
 	}
 
 	// If idle allocation, remove non-idle costs, but maintain total cost