Przeglądaj źródła

fix for flat shared costs filter

Ajay Tripathy 5 lat temu
rodzic
commit
aeb1ba9cd6
2 zmienionych plików z 62 dodań i 7 usunięć
  1. 39 4
      pkg/kubecost/allocation.go
  2. 23 3
      pkg/kubecost/allocation_test.go

+ 39 - 4
pkg/kubecost/allocation.go

@@ -436,6 +436,9 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 	shareSet := &AllocationSet{
 	shareSet := &AllocationSet{
 		Window: as.Window.Clone(),
 		Window: as.Window.Clone(),
 	}
 	}
+	flatShareSet := &AllocationSet{
+		Window: as.Window.Clone(),
+	}
 
 
 	// Convert SharedHourlyCosts to Allocations in the shareSet
 	// Convert SharedHourlyCosts to Allocations in the shareSet
 	for name, cost := range options.SharedHourlyCosts {
 	for name, cost := range options.SharedHourlyCosts {
@@ -450,7 +453,7 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 
 
 			totalSharedCost := cost * hours
 			totalSharedCost := cost * hours
 
 
-			shareSet.Insert(&Allocation{
+			flatShareSet.Insert(&Allocation{
 				Name:       fmt.Sprintf("%s/%s", name, SharedSuffix),
 				Name:       fmt.Sprintf("%s/%s", name, SharedSuffix),
 				Start:      as.Start(),
 				Start:      as.Start(),
 				End:        as.End(),
 				End:        as.End(),
@@ -533,6 +536,7 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 
 
 	// shareCoefficients are organized by [allocation][resource]=coeff (no cluster)
 	// shareCoefficients are organized by [allocation][resource]=coeff (no cluster)
 	var shareCoefficients map[string]float64
 	var shareCoefficients map[string]float64
+	var flatShareCoefficients map[string]float64
 
 
 	var err error
 	var err error
 
 
@@ -547,6 +551,13 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 		}
 		}
 	}
 	}
 
 
+	flatShareCoefficients, err = computeShareCoeffs(properties, options, as, false)
+	log.Errorf("%+v", flatShareCoefficients)
+	if err != nil {
+		log.Warningf("AllocationSet.AggregateBy: compute shared coeff: missing cluster ID: %s", err)
+		return err
+	}
+
 	// (2b) If we're not sharing idle and we're filtering, we need to track the
 	// (2b) If we're not sharing idle and we're filtering, we need to track the
 	// amount of each idle allocation to "delete" in order to maintain parity
 	// amount of each idle allocation to "delete" in order to maintain parity
 	// with the idle-allocated results. That is, we want to return only the
 	// with the idle-allocated results. That is, we want to return only the
@@ -700,13 +711,34 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 	}
 	}
 
 
 	// (7) Split shared allocations and distribute among aggregated allocations
 	// (7) Split shared allocations and distribute among aggregated allocations
-	if shareSet.Length() > 0 {
-		shareCoefficients, err = computeShareCoeffs(properties, options, aggSet)
+	if shareSet.Length() > 0 || flatShareSet.Length() > 0 {
+		shareCoefficients, err = computeShareCoeffs(properties, options, aggSet, true)
+		log.Errorf("Share Coefficients %+v", shareCoefficients)
 		if err != nil {
 		if err != nil {
 			log.Warningf("AllocationSet.AggregateBy: compute shared coeff: missing cluster ID: %s", err)
 			log.Warningf("AllocationSet.AggregateBy: compute shared coeff: missing cluster ID: %s", err)
 			return err
 			return err
 		}
 		}
 
 
+		for _, alloc := range aggSet.allocations {
+			if alloc.IsIdle() {
+				// Skip idle allocations (they do not receive shared allocation)
+				continue
+			}
+
+			// Distribute shared allocations by coefficient per-allocation
+			// NOTE: share coefficients do not partition by cluster, like
+			// idle coefficients do.
+			for _, sharedAlloc := range flatShareSet.allocations {
+				if _, ok := flatShareCoefficients[alloc.Name]; !ok {
+					log.Errorf("ETL: flat share allocation: error getting allocation coefficienct for '%s'", alloc.Name)
+					continue
+				}
+
+				alloc.SharedCost += sharedAlloc.TotalCost * flatShareCoefficients[alloc.Name]
+				alloc.TotalCost += sharedAlloc.TotalCost * flatShareCoefficients[alloc.Name]
+			}
+		}
+
 		for _, alloc := range aggSet.allocations {
 		for _, alloc := range aggSet.allocations {
 			if alloc.IsIdle() {
 			if alloc.IsIdle() {
 				// Skip idle allocations (they do not receive shared allocation)
 				// Skip idle allocations (they do not receive shared allocation)
@@ -766,7 +798,7 @@ func (as *AllocationSet) AggregateBy(properties Properties, options *AllocationA
 }
 }
 
 
 // TODO niko/etl deprecate the use of a map of resources here, we only use totals
 // TODO niko/etl deprecate the use of a map of resources here, we only use totals
-func computeShareCoeffs(properties Properties, options *AllocationAggregationOptions, as *AllocationSet) (map[string]float64, error) {
+func computeShareCoeffs(properties Properties, options *AllocationAggregationOptions, as *AllocationSet, aggregated bool) (map[string]float64, error) {
 	// Compute coeffs by totalling per-allocation, then dividing by the total.
 	// Compute coeffs by totalling per-allocation, then dividing by the total.
 	coeffs := map[string]float64{}
 	coeffs := map[string]float64{}
 
 
@@ -783,6 +815,9 @@ func computeShareCoeffs(properties Properties, options *AllocationAggregationOpt
 			// Skip idle allocations in coefficient calculation
 			// Skip idle allocations in coefficient calculation
 			continue
 			continue
 		}
 		}
+		if !aggregated {
+			name, _ = alloc.generateKey(properties)
+		}
 
 
 		if shareType == ShareEven {
 		if shareType == ShareEven {
 			// Not additive - set to 1.0 for even distribution
 			// Not additive - set to 1.0 for even distribution

+ 23 - 3
pkg/kubecost/allocation_test.go

@@ -726,9 +726,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	assertAllocationWindow(t, as, "4c", startYesterday, endYesterday, 1440.0)
 	assertAllocationWindow(t, as, "4c", startYesterday, endYesterday, 1440.0)
 
 
 	// 4d Share overhead ShareWeighted
 	// 4d Share overhead ShareWeighted
-	// namespace1: 37.5000 = 25.00 + (7.0*24.0)*(25.00/70.00)
-	// namespace2: 45.0000 = 30.00 + (7.0*24.0)*(30.00/70.00)
-	// namespace3: 22.5000 = 15.00 + (7.0*24.0)*(15.00/70.00)
+	// namespace1: 85 = 25.00 + (7.0*24.0)*(25.00/70.00)
+	// namespace2: 102 = 30.00 + (7.0*24.0)*(30.00/70.00)
+	// namespace3: 51 = 15.00 + (7.0*24.0)*(15.00/70.00)
 	// idle:       30.0000
 	// idle:       30.0000
 	as = generateAllocationSet(start)
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{
@@ -864,6 +864,26 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	})
 	assertAllocationWindow(t, as, "6b", startYesterday, endYesterday, 1440.0)
 	assertAllocationWindow(t, as, "6b", startYesterday, endYesterday, 1440.0)
 
 
+	// 6d Share resources with filters
+	// namespace1: 85 = 25.00 + (7.0*24.0)*(25.00/70.00)
+	// namespace2: 102 = 30.00 + (7.0*24.0)*(30.00/70.00)
+	// namespace3: 51 = 15.00 + (7.0*24.0)*(15.00/70.00)
+	// idle:       30.0000
+	// Then namespace 2 is filtered.
+
+	as = generateAllocationSet(start)
+	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
+		FilterFuncs:       []AllocationMatchFunc{isNamespace("namespace2")},
+		SharedHourlyCosts: map[string]float64{"total": sharedOverheadHourlyCost},
+		ShareSplit:        ShareWeighted,
+	})
+	//assertAllocationSetTotals(t, as, "4d", err, 2, activeTotalCost+idleTotalCost+(sharedOverheadHourlyCost*24.0))
+	assertAllocationTotals(t, as, "6b", map[string]float64{
+		"namespace2": 102.00,
+		IdleSuffix:   30.00,
+	})
+	assertAllocationWindow(t, as, "6b", startYesterday, endYesterday, 1440.0)
+
 	// 6d Share resources with filters
 	// 6d Share resources with filters
 	// 6e Share idle and share resources
 	// 6e Share idle and share resources