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

Add loadbalancerCost to Allocation

Sean Holcomb 5 лет назад
Родитель
Сommit
f37395ca94
3 измененных файлов с 229 добавлено и 200 удалено
  1. 1 1
      pkg/costmodel/allocation.go
  2. 8 1
      pkg/kubecost/allocation.go
  3. 220 198
      pkg/kubecost/allocation_test.go

+ 1 - 1
pkg/costmodel/allocation.go

@@ -1671,7 +1671,7 @@ func applyLoadBalancersToPods(lbMap map[serviceKey]*LB, allocsByService map[serv
 
 		// Distribute cost of service once total hours is calculated
 		for alloc, hours := range allocHours {
-			alloc.NetworkCost += lb.TotalCost * hours / totalHours
+			alloc.LoadBalancerCost += lb.TotalCost * hours / totalHours
 		}
 	}
 }

+ 8 - 1
pkg/kubecost/allocation.go

@@ -62,6 +62,7 @@ type Allocation struct {
 	GPUHours               float64    `json:"gpuHours"`
 	GPUCost                float64    `json:"gpuCost"`
 	NetworkCost            float64    `json:"networkCost"`
+	LoadBalancerCost       float64    `json:"loadBalancerCost"`
 	PVByteHours            float64    `json:"pvByteHours"`
 	PVCost                 float64    `json:"pvCost"`
 	RAMByteHours           float64    `json:"ramByteHours"`
@@ -114,6 +115,7 @@ func (a *Allocation) Clone() *Allocation {
 		GPUHours:               a.GPUHours,
 		GPUCost:                a.GPUCost,
 		NetworkCost:            a.NetworkCost,
+		LoadBalancerCost:       a.LoadBalancerCost,
 		PVByteHours:            a.PVByteHours,
 		PVCost:                 a.PVCost,
 		RAMByteHours:           a.RAMByteHours,
@@ -164,6 +166,9 @@ func (a *Allocation) Equal(that *Allocation) bool {
 	if !util.IsApproximately(a.NetworkCost, that.NetworkCost) {
 		return false
 	}
+	if !util.IsApproximately(a.LoadBalancerCost, that.LoadBalancerCost) {
+		return false
+	}
 	if !util.IsApproximately(a.PVByteHours, that.PVByteHours) {
 		return false
 	}
@@ -188,7 +193,7 @@ func (a *Allocation) Equal(that *Allocation) bool {
 
 // TotalCost is the total cost of the Allocation
 func (a *Allocation) TotalCost() float64 {
-	return a.CPUCost + a.GPUCost + a.RAMCost + a.PVCost + a.NetworkCost + a.SharedCost + a.ExternalCost
+	return a.CPUCost + a.GPUCost + a.RAMCost + a.PVCost + a.NetworkCost + a.SharedCost + a.ExternalCost + a.LoadBalancerCost
 }
 
 // CPUEfficiency is the ratio of usage to request. If there is no request and
@@ -275,6 +280,7 @@ func (a *Allocation) MarshalJSON() ([]byte, error) {
 	jsonEncodeFloat64(buffer, "gpuHours", a.GPUHours, ",")
 	jsonEncodeFloat64(buffer, "gpuCost", a.GPUCost, ",")
 	jsonEncodeFloat64(buffer, "networkCost", a.NetworkCost, ",")
+	jsonEncodeFloat64(buffer, "loadBalancerCost", a.LoadBalancerCost, ",")
 	jsonEncodeFloat64(buffer, "pvBytes", a.PVBytes(), ",")
 	jsonEncodeFloat64(buffer, "pvByteHours", a.PVByteHours, ",")
 	jsonEncodeFloat64(buffer, "pvCost", a.PVCost, ",")
@@ -426,6 +432,7 @@ func (a *Allocation) add(that *Allocation) {
 	a.RAMCost += that.RAMCost
 	a.PVCost += that.PVCost
 	a.NetworkCost += that.NetworkCost
+	a.LoadBalancerCost += that.LoadBalancerCost
 	a.SharedCost += that.SharedCost
 	a.ExternalCost += that.ExternalCost
 }

+ 220 - 198
pkg/kubecost/allocation_test.go

@@ -45,6 +45,7 @@ func NewUnitAllocation(name string, start time.Time, resolution time.Duration, p
 		GPUHours:               1,
 		GPUCost:                1,
 		NetworkCost:            1,
+		LoadBalancerCost:       1,
 		PVByteHours:            1,
 		PVCost:                 1,
 		RAMByteHours:           1,
@@ -58,7 +59,7 @@ func NewUnitAllocation(name string, start time.Time, resolution time.Duration, p
 		alloc.PVByteHours = 0.0
 		alloc.PVCost = 0.0
 		alloc.NetworkCost = 0.0
-
+		alloc.LoadBalancerCost = 0.0
 		alloc.CPUCoreHours += 1.0
 		alloc.CPUCost += 1.0
 		alloc.RAMByteHours += 1.0
@@ -138,6 +139,7 @@ func TestAllocation_Add(t *testing.T) {
 		RAMBytesUsageAverage:   8.0 * gib,
 		RAMCost:                8.0 * hrs2 * ramPrice,
 		NetworkCost:            0.01,
+		LoadBalancerCost:       0.05,
 		SharedCost:             0.00,
 		ExternalCost:           1.00,
 	}
@@ -175,6 +177,9 @@ func TestAllocation_Add(t *testing.T) {
 	if !util.IsApproximately(a1.NetworkCost+a2.NetworkCost, act.NetworkCost) {
 		t.Fatalf("Allocation.Add: expected %f; actual %f", a1.NetworkCost+a2.NetworkCost, act.NetworkCost)
 	}
+	if !util.IsApproximately(a1.LoadBalancerCost+a2.LoadBalancerCost, act.LoadBalancerCost) {
+		t.Fatalf("Allocation.Add: expected %f; actual %f", a1.LoadBalancerCost+a2.LoadBalancerCost, act.LoadBalancerCost)
+	}
 	if !util.IsApproximately(a1.SharedCost+a2.SharedCost, act.SharedCost) {
 		t.Fatalf("Allocation.Add: expected %f; actual %f", a1.SharedCost+a2.SharedCost, act.SharedCost)
 	}
@@ -283,6 +288,7 @@ func TestAllocation_Share(t *testing.T) {
 		RAMBytesUsageAverage:   8.0 * gib,
 		RAMCost:                8.0 * hrs2 * ramPrice,
 		NetworkCost:            0.01,
+		LoadBalancerCost:       0.05,
 		SharedCost:             0.00,
 		ExternalCost:           1.00,
 	}
@@ -325,6 +331,9 @@ func TestAllocation_Share(t *testing.T) {
 	if !util.IsApproximately(a1.NetworkCost, act.NetworkCost) {
 		t.Fatalf("Allocation.Share: expected %f; actual %f", a1.NetworkCost, act.NetworkCost)
 	}
+	if !util.IsApproximately(a1.LoadBalancerCost, act.LoadBalancerCost) {
+		t.Fatalf("Allocation.Share: expected %f; actual %f", a1.LoadBalancerCost, act.LoadBalancerCost)
+	}
 	if !util.IsApproximately(a1.ExternalCost, act.ExternalCost) {
 		t.Fatalf("Allocation.Share: expected %f; actual %f", a1.ExternalCost, act.ExternalCost)
 	}
@@ -405,6 +414,7 @@ func TestAllocation_MarshalJSON(t *testing.T) {
 		GPUHours:               1.0 * hrs,
 		GPUCost:                1.0 * hrs * gpuPrice,
 		NetworkCost:            0.05,
+		LoadBalancerCost:       0.02,
 		PVByteHours:            100.0 * gib * hrs,
 		PVCost:                 100.0 * hrs * pvPrice,
 		RAMByteHours:           8.0 * gib * hrs,
@@ -619,7 +629,7 @@ func assertAllocationTotals(t *testing.T, as *AllocationSet, msg string, exps ma
 	as.Each(func(k string, a *Allocation) {
 		if exp, ok := exps[a.Name]; ok {
 			if math.Round(a.TotalCost()*100) != math.Round(exp*100) {
-				t.Fatalf("AllocationSet.AggregateBy[%s]: expected total cost %.2f, actual %.2f", msg, exp, a.TotalCost())
+				t.Fatalf("AllocationSet.AggregateBy[%s]: expected total cost %f, actual %f", msg, exp, a.TotalCost())
 			}
 		} else {
 			t.Fatalf("AllocationSet.AggregateBy[%s]: unexpected allocation: %s", msg, a.Name)
@@ -652,45 +662,45 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// Test AggregateBy against the following workload topology, which is
 	// generated by generateAllocationSet:
 
-	// | Hierarchy                              | Cost |  CPU |  RAM |  GPU |   PV |  Net |
-	// +----------------------------------------+------+------+------+------+------+------+
+	// | Hierarchy                              | Cost |  CPU |  RAM |  GPU |   PV |  Net |  LB  |
+	// +----------------------------------------+------+------+------+------+------+------+------+
 	//   cluster1:
-	//     idle:                                  20.00   5.00  15.00   0.00   0.00   0.00
+	//     idle:                                  20.00   5.00  15.00   0.00   0.00   0.00   0.00
 	//     namespace1:
 	//       pod1:
-	//         container1: [app=app1, env=env1]   15.00   1.00  11.00   1.00   1.00   1.00
+	//         container1: [app=app1, env=env1]   16.00   1.00  11.00   1.00   1.00   1.00   1.00
 	//       pod-abc: (deployment1)
-	//         container2:                         5.00   1.00   1.00   1.00   1.00   1.00
+	//         container2:                         6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//       pod-def: (deployment1)
-	//         container3:                         5.00   1.00   1.00   1.00   1.00   1.00
+	//         container3:                         6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//     namespace2:
 	//       pod-ghi: (deployment2)
-	//         container4: [app=app2, env=env2]    5.00   1.00   1.00   1.00   1.00   1.00
-	//         container5: [app=app2, env=env2]    5.00   1.00   1.00   1.00   1.00   1.00
+	//         container4: [app=app2, env=env2]    6.00   1.00   1.00   1.00   1.00   1.00   1.00
+	//         container5: [app=app2, env=env2]    6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//       pod-jkl: (daemonset1)
-	//         container6: {service1}              5.00   1.00   1.00   1.00   1.00   1.00
-	// +-----------------------------------------+------+------+------+------+------+------+
-	//   cluster1 subtotal                        60.00  11.00  31.00   6.00   6.00   6.00
-	// +-----------------------------------------+------+------+------+------+------+------+
+	//         container6: {service1}              6.00   1.00   1.00   1.00   1.00   1.00   1.00
+	// +-----------------------------------------+------+------+------+------+------+------+------+
+	//   cluster1 subtotal                        66.00  11.00  31.00   6.00   6.00   6.00   6.00
+	// +-----------------------------------------+------+------+------+------+------+------+------+
 	//   cluster2:
-	//     idle:                                  10.00   5.00   5.00   0.00   0.00   0.00
+	//     idle:                                  10.00   5.00   5.00   0.00   0.00   0.00   0.00
 	//     namespace2:
 	//       pod-mno: (deployment2)
-	//         container4: [app=app2]              5.00   1.00   1.00   1.00   1.00   1.00
-	//         container5: [app=app2]              5.00   1.00   1.00   1.00   1.00   1.00
+	//         container4: [app=app2]              6.00   1.00   1.00   1.00   1.00   1.00   1.00
+	//         container5: [app=app2]              6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//       pod-pqr: (daemonset1)
-	//         container6: {service1}              5.00   1.00   1.00   1.00   1.00   1.00
+	//         container6: {service1}              6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//     namespace3:
 	//       pod-stu: (deployment3)
-	//         container7: an[team=team1]          5.00   1.00   1.00   1.00   1.00   1.00
+	//         container7: an[team=team1]          6.00   1.00   1.00   1.00   1.00   1.00   1.00
 	//       pod-vwx: (statefulset1)
-	//         container8: an[team=team2]          5.00   1.00   1.00   1.00   1.00   1.00
-	//         container9: an[team=team1]          5.00   1.00   1.00   1.00   1.00   1.00
-	// +----------------------------------------+------+------+------+------+------+------+
-	//   cluster2 subtotal                        40.00  11.00  11.00   6.00   6.00   6.00
-	// +----------------------------------------+------+------+------+------+------+------+
-	//   total                                   100.00  22.00  42.00  12.00  12.00  12.00
-	// +----------------------------------------+------+------+------+------+------+------+
+	//         container8: an[team=team2]          6.00   1.00   1.00   1.00   1.00   1.00   1.00
+	//         container9: an[team=team1]          6.00   1.00   1.00   1.00   1.00   1.00   1.00
+	// +----------------------------------------+------+------+------+------+------+------+------+
+	//   cluster2 subtotal                        46.00  11.00  11.00   6.00   6.00   6.00   6.00
+	// +----------------------------------------+------+------+------+------+------+------+------+
+	//   total                                   112.00  22.00  42.00  12.00  12.00  12.00  12.00
+	// +----------------------------------------+------+------+------+------+------+------+------+
 
 	// Scenarios to test:
 
@@ -761,7 +771,7 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// There are two clusters, so each gets an idle entry when they are split
 	numSplitIdle := 2
 
-	activeTotalCost := 70.0
+	activeTotalCost := 82.0
 	idleTotalCost := 30.0
 	sharedOverheadHourlyCost := 7.0
 
@@ -790,8 +800,8 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ClusterProp: ""}, nil)
 	assertAllocationSetTotals(t, as, "1a", err, numClusters+numIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1a", map[string]float64{
-		"cluster1": 40.00,
-		"cluster2": 30.00,
+		"cluster1": 46.00,
+		"cluster2": 36.00,
 		IdleSuffix: 30.00,
 	})
 	assertAllocationWindow(t, as, "1a", startYesterday, endYesterday, 1440.0)
@@ -801,9 +811,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{NamespaceProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1b", err, numNamespaces+numIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1b", map[string]float64{
-		"namespace1": 25.00,
-		"namespace2": 30.00,
-		"namespace3": 15.00,
+		"namespace1": 28.00,
+		"namespace2": 36.00,
+		"namespace3": 18.00,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "1b", startYesterday, endYesterday, 1440.0)
@@ -813,15 +823,15 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{PodProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1c", err, numPods+numIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1c", map[string]float64{
-		"pod-jkl":  5.00,
-		"pod-stu":  5.00,
-		"pod-abc":  5.00,
-		"pod-pqr":  5.00,
-		"pod-def":  5.00,
-		"pod-vwx":  10.00,
-		"pod1":     15.00,
-		"pod-mno":  10.00,
-		"pod-ghi":  10.00,
+		"pod-jkl":  6.00,
+		"pod-stu":  6.00,
+		"pod-abc":  6.00,
+		"pod-pqr":  6.00,
+		"pod-def":  6.00,
+		"pod-vwx":  12.00,
+		"pod1":     16.00,
+		"pod-mno":  12.00,
+		"pod-ghi":  12.00,
 		IdleSuffix: 30.00,
 	})
 	assertAllocationWindow(t, as, "1c", startYesterday, endYesterday, 1440.0)
@@ -831,15 +841,15 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ContainerProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1d", err, numContainers+numIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1d", map[string]float64{
-		"container2": 5.00,
-		"container9": 5.00,
-		"container6": 10.00,
-		"container3": 5.00,
-		"container4": 10.00,
-		"container7": 5.00,
-		"container8": 5.00,
-		"container5": 10.00,
-		"container1": 15.00,
+		"container2": 6.00,
+		"container9": 6.00,
+		"container6": 12.00,
+		"container3": 6.00,
+		"container4": 12.00,
+		"container7": 6.00,
+		"container8": 6.00,
+		"container5": 12.00,
+		"container1": 16.00,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "1d", startYesterday, endYesterday, 1440.0)
@@ -849,11 +859,11 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ControllerKindProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1e", err, numControllerKinds+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1e", map[string]float64{
-		"daemonset":       10.00,
-		"deployment":      35.00,
-		"statefulset":     10.00,
+		"daemonset":       12.00,
+		"deployment":      42.00,
+		"statefulset":     12.00,
 		IdleSuffix:        30.00,
-		UnallocatedSuffix: 15.00,
+		UnallocatedSuffix: 16.00,
 	})
 	assertAllocationWindow(t, as, "1e", startYesterday, endYesterday, 1440.0)
 
@@ -862,13 +872,13 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ControllerProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1f", err, numControllers+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1f", map[string]float64{
-		"deployment/deployment2":   20.00,
-		"daemonset/daemonset1":     10.00,
-		"deployment/deployment3":   5.00,
-		"statefulset/statefulset1": 10.00,
-		"deployment/deployment1":   10.00,
+		"deployment/deployment2":   24.00,
+		"daemonset/daemonset1":     12.00,
+		"deployment/deployment3":   6.00,
+		"statefulset/statefulset1": 12.00,
+		"deployment/deployment1":   12.00,
 		IdleSuffix:                 30.00,
-		UnallocatedSuffix:          15.00,
+		UnallocatedSuffix:          16.00,
 	})
 	assertAllocationWindow(t, as, "1f", startYesterday, endYesterday, 1440.0)
 
@@ -877,9 +887,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ServiceProp: true}, nil)
 	assertAllocationSetTotals(t, as, "1g", err, numServices+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1g", map[string]float64{
-		"service1":        10.00,
+		"service1":        12.00,
 		IdleSuffix:        30.00,
-		UnallocatedSuffix: 60.00,
+		UnallocatedSuffix: 70.00,
 	})
 	assertAllocationWindow(t, as, "1g", startYesterday, endYesterday, 1440.0)
 
@@ -888,10 +898,10 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{LabelProp: map[string]string{"app": ""}}, nil)
 	assertAllocationSetTotals(t, as, "1h", err, numLabelApps+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1h", map[string]float64{
-		"app=app1":        15.00,
-		"app=app2":        20.00,
+		"app=app1":        16.00,
+		"app=app2":        24.00,
 		IdleSuffix:        30.00,
-		UnallocatedSuffix: 35.00,
+		UnallocatedSuffix: 42.00,
 	})
 	assertAllocationWindow(t, as, "1h", startYesterday, endYesterday, 1440.0)
 
@@ -900,9 +910,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ControllerKindProp: "deployment"}, nil)
 	assertAllocationSetTotals(t, as, "1i", err, 1+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1i", map[string]float64{
-		"deployment":      35.00,
+		"deployment":      42.00,
 		IdleSuffix:        30.00,
-		UnallocatedSuffix: 35.00,
+		UnallocatedSuffix: 40.00,
 	})
 	assertAllocationWindow(t, as, "1i", startYesterday, endYesterday, 1440.0)
 
@@ -911,10 +921,10 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{AnnotationProp: map[string]string{"team": ""}}, nil)
 	assertAllocationSetTotals(t, as, "1j", err, 2+numIdle+numUnallocated, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "1j", map[string]float64{
-		"team=team1":      10.00,
-		"team=team2":      5.00,
+		"team=team1":      12.00,
+		"team=team2":      6.00,
 		IdleSuffix:        30.00,
-		UnallocatedSuffix: 55.00,
+		UnallocatedSuffix: 64.00,
 	})
 	assertAllocationWindow(t, as, "1i", startYesterday, endYesterday, 1440.0)
 
@@ -930,11 +940,11 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// sets should be {idle, unallocated, app1/env1, app2/env2, app2/unallocated}
 	assertAllocationSetTotals(t, as, "2d", err, numIdle+numUnallocated+3, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "2d", map[string]float64{
-		"app=app1/env=env1":             15.00,
-		"app=app2/env=env2":             10.00,
-		"app=app2/" + UnallocatedSuffix: 10.00,
+		"app=app1/env=env1":             16.00,
+		"app=app2/env=env2":             12.00,
+		"app=app2/" + UnallocatedSuffix: 12.00,
 		IdleSuffix:                      30.00,
-		UnallocatedSuffix:               35.00,
+		UnallocatedSuffix:               42.00,
 	})
 
 	// 2e AggregationProperties=(Cluster, Label:app, Label:environment)
@@ -942,12 +952,12 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{ClusterProp: "", LabelProp: map[string]string{"app": "", "env": ""}}, nil)
 	assertAllocationSetTotals(t, as, "2e", err, 6, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "2e", map[string]float64{
-		"cluster1/app=app2/env=env2":             10.00,
+		"cluster1/app=app2/env=env2":             12.00,
 		"__idle__":                               30.00,
-		"cluster1/app=app1/env=env1":             15.00,
-		"cluster1/" + UnallocatedSuffix:          15.00,
-		"cluster2/app=app2/" + UnallocatedSuffix: 10.00,
-		"cluster2/" + UnallocatedSuffix:          20.00,
+		"cluster1/app=app1/env=env1":             16.00,
+		"cluster1/" + UnallocatedSuffix:          18.00,
+		"cluster2/app=app2/" + UnallocatedSuffix: 12.00,
+		"cluster2/" + UnallocatedSuffix:          24.00,
 	})
 
 	// 2f AggregationProperties=(annotation:team, pod)
@@ -955,16 +965,16 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{AnnotationProp: map[string]string{"team": ""}, PodProp: ""}, nil)
 	assertAllocationSetTotals(t, as, "2e", err, 11, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "2e", map[string]float64{
-		"pod-jkl/" + UnallocatedSuffix: 5.00,
-		"pod-stu/team=team1":           5.00,
-		"pod-abc/" + UnallocatedSuffix: 5.00,
-		"pod-pqr/" + UnallocatedSuffix: 5.00,
-		"pod-def/" + UnallocatedSuffix: 5.00,
-		"pod-vwx/team=team1":           5.00,
-		"pod-vwx/team=team2":           5.00,
-		"pod1/" + UnallocatedSuffix:    15.00,
-		"pod-mno/" + UnallocatedSuffix: 10.00,
-		"pod-ghi/" + UnallocatedSuffix: 10.00,
+		"pod-jkl/" + UnallocatedSuffix: 6.00,
+		"pod-stu/team=team1":           6.00,
+		"pod-abc/" + UnallocatedSuffix: 6.00,
+		"pod-pqr/" + UnallocatedSuffix: 6.00,
+		"pod-def/" + UnallocatedSuffix: 6.00,
+		"pod-vwx/team=team1":           6.00,
+		"pod-vwx/team=team2":           6.00,
+		"pod1/" + UnallocatedSuffix:    16.00,
+		"pod-mno/" + UnallocatedSuffix: 12.00,
+		"pod-ghi/" + UnallocatedSuffix: 12.00,
 		IdleSuffix:                     30.00,
 	})
 
@@ -973,38 +983,38 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// // 3  Share idle
 
 	// 3a AggregationProperties=(Namespace) ShareIdle=ShareWeighted
-	// namespace1: 39.6875 = 25.00 + 5.00*(3.00/6.00) + 15.0*(13.0/16.0)
-	// namespace2: 40.3125 = 30.00 + 5.0*(3.0/6.0) + 15.0*(3.0/16.0) + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
-	// namespace3: 20.0000 = 15.00 + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
+	// namespace1: 42.6875 = 28.00 + 5.00*(3.00/6.00) + 15.0*(13.0/16.0)
+	// namespace2: 46.3125 = 36.00 + 5.0*(3.0/6.0) + 15.0*(3.0/16.0) + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
+	// namespace3: 23.0000 = 18.00 + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{ShareIdle: ShareWeighted})
 	assertAllocationSetTotals(t, as, "3a", err, numNamespaces, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "3a", map[string]float64{
-		"namespace1": 39.69,
-		"namespace2": 40.31,
-		"namespace3": 20.00,
+		"namespace1": 42.69,
+		"namespace2": 46.31,
+		"namespace3": 23.00,
 	})
 	assertAllocationWindow(t, as, "3a", startYesterday, endYesterday, 1440.0)
 
 	// 3b AggregationProperties=(Namespace) ShareIdle=ShareEven
-	// namespace1: 35.0000 = 25.00 + 5.00*(1.0/2.0) + 15.0*(1.0/2.0)
-	// namespace2: 45.0000 = 30.00 + 5.0*(1.0/2.0) + 15.0*(1.0/2.0) + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
-	// namespace3: 20.0000 = 15.00 + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
+	// namespace1: 38.0000 = 28.00 + 5.00*(1.0/2.0) + 15.0*(1.0/2.0)
+	// namespace2: 51.0000 = 36.00 + 5.0*(1.0/2.0) + 15.0*(1.0/2.0) + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
+	// namespace3: 23.0000 = 18.00 + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{ShareIdle: ShareEven})
 	assertAllocationSetTotals(t, as, "3a", err, numNamespaces, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "3a", map[string]float64{
-		"namespace1": 35.00,
-		"namespace2": 45.00,
-		"namespace3": 20.00,
+		"namespace1": 38.00,
+		"namespace2": 51.00,
+		"namespace3": 23.00,
 	})
 	assertAllocationWindow(t, as, "3b", startYesterday, endYesterday, 1440.0)
 
 	// 4  Share resources
 
 	// 4a Share namespace ShareEven
-	// namespace1: 32.5000 = 25.00 + 15.00*(1.0/2.0)
-	// namespace2: 37.5000 = 30.00 + 15.00*(1.0/2.0)
+	// namespace1: 37.5000 = 28.00 + 18.00*(1.0/2.0)
+	// namespace2: 45.5000 = 36.00 + 18.00*(1.0/2.0)
 	// idle:       30.0000
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{
@@ -1013,8 +1023,8 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	assertAllocationSetTotals(t, as, "4a", err, numNamespaces, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "4a", map[string]float64{
-		"namespace1": 32.50,
-		"namespace2": 37.50,
+		"namespace1": 37.00,
+		"namespace2": 45.00,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "4a", startYesterday, endYesterday, 1440.0)
@@ -1030,16 +1040,16 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	assertAllocationSetTotals(t, as, "4b", err, numNamespaces, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "4b", map[string]float64{
-		"namespace1": 31.82,
-		"namespace2": 38.18,
+		"namespace1": 35.88,
+		"namespace2": 46.125,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "4b", startYesterday, endYesterday, 1440.0)
 
 	// 4c Share label ShareEven
-	// namespace1: 15.0000 = 25.00 - 15.00 + 15.00*(1.0/3.0)
-	// namespace2: 35.0000 = 30.00 + 15.00*(1.0/3.0)
-	// namespace3: 20.0000 = 15.00 + 15.00*(1.0/3.0)
+	// namespace1: 17.3333 = 28.00 - 16.00 + 16.00*(1.0/3.0)
+	// namespace2: 41.3333 = 36.00 + 16.00*(1.0/3.0)
+	// namespace3: 23.3333 = 18.00 + 16.00*(1.0/3.0)
 	// idle:       30.0000
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{
@@ -1048,17 +1058,17 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	assertAllocationSetTotals(t, as, "4c", err, numNamespaces+numIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "4c", map[string]float64{
-		"namespace1": 15.00,
-		"namespace2": 35.00,
-		"namespace3": 20.00,
+		"namespace1": 17.33,
+		"namespace2": 41.33,
+		"namespace3": 23.33,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "4c", startYesterday, endYesterday, 1440.0)
 
 	// 4d Share overhead ShareWeighted
-	// 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)
+	// namespace1: 85.366 = 28.00 + (7.0*24.0)*(28.00/82.00)
+	// namespace2: 109.756 = 36.00 + (7.0*24.0)*(36.00/82.00)
+	// namespace3: 54.878 = 18.00 + (7.0*24.0)*(18.00/82.00)
 	// idle:       30.0000
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: true}, &AllocationAggregationOptions{
@@ -1067,9 +1077,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	assertAllocationSetTotals(t, as, "4d", err, numNamespaces+numIdle, activeTotalCost+idleTotalCost+(sharedOverheadHourlyCost*24.0))
 	assertAllocationTotals(t, as, "4d", map[string]float64{
-		"namespace1": 85.00,
-		"namespace2": 102.00,
-		"namespace3": 51.00,
+		"namespace1": 85.366,
+		"namespace2": 109.756,
+		"namespace3": 54.878,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "4d", startYesterday, endYesterday, 1440.0)
@@ -1096,9 +1106,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		FilterFuncs: []AllocationMatchFunc{isCluster("cluster1")},
 		ShareIdle:   ShareNone,
 	})
-	assertAllocationSetTotals(t, as, "5a", err, 2, 60.0)
+	assertAllocationSetTotals(t, as, "5a", err, 2, 66.0)
 	assertAllocationTotals(t, as, "5a", map[string]float64{
-		"cluster1": 40.00,
+		"cluster1": 46.00,
 		IdleSuffix: 20.00,
 	})
 	assertAllocationWindow(t, as, "5a", startYesterday, endYesterday, 1440.0)
@@ -1109,9 +1119,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		FilterFuncs: []AllocationMatchFunc{isCluster("cluster1")},
 		ShareIdle:   ShareWeighted,
 	})
-	assertAllocationSetTotals(t, as, "5b", err, 1, 60.0)
+	assertAllocationSetTotals(t, as, "5b", err, 1, 66.0)
 	assertAllocationTotals(t, as, "5b", map[string]float64{
-		"cluster1": 60.00,
+		"cluster1": 66.00,
 	})
 	assertAllocationWindow(t, as, "5b", startYesterday, endYesterday, 1440.0)
 
@@ -1121,10 +1131,10 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		FilterFuncs: []AllocationMatchFunc{isCluster("cluster1")},
 		ShareIdle:   ShareNone,
 	})
-	assertAllocationSetTotals(t, as, "5c", err, 3, 60.0)
+	assertAllocationSetTotals(t, as, "5c", err, 3, 66.0)
 	assertAllocationTotals(t, as, "5c", map[string]float64{
-		"namespace1": 25.00,
-		"namespace2": 15.00,
+		"namespace1": 28.00,
+		"namespace2": 18.00,
 		IdleSuffix:   20.00,
 	})
 	assertAllocationWindow(t, as, "5c", startYesterday, endYesterday, 1440.0)
@@ -1135,10 +1145,10 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		FilterFuncs: []AllocationMatchFunc{isNamespace("namespace2")},
 		ShareIdle:   ShareNone,
 	})
-	assertAllocationSetTotals(t, as, "5d", err, 3, 40.31)
+	assertAllocationSetTotals(t, as, "5d", err, 3, 46.31)
 	assertAllocationTotals(t, as, "5d", map[string]float64{
-		"cluster1": 15.00,
-		"cluster2": 15.00,
+		"cluster1": 18.00,
+		"cluster2": 18.00,
 		IdleSuffix: 10.31,
 	})
 	assertAllocationWindow(t, as, "5d", startYesterday, endYesterday, 1440.0)
@@ -1150,9 +1160,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{SplitIdle: true})
 	assertAllocationSetTotals(t, as, "6a", err, numNamespaces+numSplitIdle, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "6a", map[string]float64{
-		"namespace1":                           25.00,
-		"namespace2":                           30.00,
-		"namespace3":                           15.00,
+		"namespace1":                           28.00,
+		"namespace2":                           36.00,
+		"namespace3":                           18.00,
 		fmt.Sprintf("cluster1/%s", IdleSuffix): 20.00,
 		fmt.Sprintf("cluster2/%s", IdleSuffix): 10.00,
 	})
@@ -1160,36 +1170,36 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 
 	// 6b Share idle weighted with filters
 	// Should match values from unfiltered aggregation (3a)
-	// namespace2: 40.3125 = 30.00 + 5.0*(3.0/6.0) + 15.0*(3.0/16.0) + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
+	// namespace2: 46.3125 = 36.00 + 5.0*(3.0/6.0) + 15.0*(3.0/16.0) + 5.0*(3.0/6.0) + 5.0*(3.0/6.0)
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
 		FilterFuncs: []AllocationMatchFunc{isNamespace("namespace2")},
 		ShareIdle:   ShareWeighted,
 	})
-	assertAllocationSetTotals(t, as, "6b", err, 1, 40.31)
+	assertAllocationSetTotals(t, as, "6b", err, 1, 46.31)
 	assertAllocationTotals(t, as, "6b", map[string]float64{
-		"namespace2": 40.31,
+		"namespace2": 46.31,
 	})
 	assertAllocationWindow(t, as, "6b", startYesterday, endYesterday, 1440.0)
 
 	// 6c Share idle even with filters
 	// Should match values from unfiltered aggregation (3b)
-	// namespace2: 45.0000 = 30.00 + 5.0*(1.0/2.0) + 15.0*(1.0/2.0) + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
+	// namespace2: 51.0000 = 36.00 + 5.0*(1.0/2.0) + 15.0*(1.0/2.0) + 5.0*(1.0/2.0) + 5.0*(1.0/2.0)
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
 		FilterFuncs: []AllocationMatchFunc{isNamespace("namespace2")},
 		ShareIdle:   ShareEven,
 	})
-	assertAllocationSetTotals(t, as, "6b", err, 1, 45.00)
+	assertAllocationSetTotals(t, as, "6b", err, 1, 51.00)
 	assertAllocationTotals(t, as, "6b", map[string]float64{
-		"namespace2": 45.00,
+		"namespace2": 51.00,
 	})
 	assertAllocationWindow(t, as, "6b", startYesterday, endYesterday, 1440.0)
 
 	// 6d Share overhead 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)
+	// namespace1: 85.366 = 28.00 + (7.0*24.0)*(28.00/82.00)
+	// namespace2: 109.756 = 36.00 + (7.0*24.0)*(36.00/82.00)
+	// namespace3: 54.878 = 18.00 + (7.0*24.0)*(18.00/82.00)
 	// idle:       30.0000
 	// Then namespace 2 is filtered.
 	as = generateAllocationSet(start)
@@ -1198,20 +1208,20 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		SharedHourlyCosts: map[string]float64{"total": sharedOverheadHourlyCost},
 		ShareSplit:        ShareWeighted,
 	})
-	assertAllocationSetTotals(t, as, "6d", err, 2, 132.00)
+	assertAllocationSetTotals(t, as, "6d", err, 2, 139.756)
 	assertAllocationTotals(t, as, "6d", map[string]float64{
-		"namespace2": 102.00,
+		"namespace2": 109.756,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "6d", startYesterday, endYesterday, 1440.0)
 
 	// 6e Share resources with filters
 	// --- Shared ---
-	// namespace1: 25.00 (gets shared among namespace2 and namespace3)
+	// namespace1: 28.00 (gets shared among namespace2 and namespace3)
 	// --- Filtered ---
-	// namespace3: 23.33 = 15.00 + (25.00)*(15.00/45.00) (filtered out)
+	// namespace3: 27.33 = 18.00 + (28.00)*(18.00/54.00) (filtered out)
 	// --- Results ---
-	// namespace2: 46.67 = 30.00 + (25.00)*(15.00/45.00)
+	// namespace2: 54.667 = 36.00 + (28.00)*(36.00/54.00)
 	// idle:       30.0000
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
@@ -1219,9 +1229,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		ShareFuncs:  []AllocationMatchFunc{isNamespace("namespace1")},
 		ShareSplit:  ShareWeighted,
 	})
-	assertAllocationSetTotals(t, as, "6e", err, 2, 76.67)
+	assertAllocationSetTotals(t, as, "6e", err, 2, 84.667)
 	assertAllocationTotals(t, as, "6e", map[string]float64{
-		"namespace2": 46.67,
+		"namespace2": 54.667,
 		IdleSuffix:   30.00,
 	})
 	assertAllocationWindow(t, as, "6e", startYesterday, endYesterday, 1440.0)
@@ -1230,20 +1240,20 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	//
 	// First, share idle weighted produces:
 	//
-	// namespace1:      39.6875
-	//   initial cost   25.0000
+	// namespace1:      42.6875
+	//   initial cost   28.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.00/6.00)
 	//   cluster1.ram   12.1875 = 15.00*(13.0/16.0)
 	//
-	// namespace2:      40.3125
-	//   initial cost   30.0000
+	// namespace2:      46.3125
+	//   initial cost   36.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster1.ram    2.8125 = 15.00*(3.0/16.0)
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
-	// namespace3:      20.0000
-	//   initial cost   15.0000
+	// namespace3:      23.0000
+	//   initial cost   18.0000
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
@@ -1251,15 +1261,15 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// computed before allocating idle (so that weighting idle differently
 	// doesn't adversely affect the sharing mechanism):
 	//
-	// namespace2:      66.7708
+	// namespace2:      74.7708
 	//   initial cost   30.0000
 	//   idle cost      10.3125
-	//   shared cost    26.4583 = (39.6875)*(30.0/45.0)
+	//   shared cost    28.4583 = (42.6875)*(36.0/54.0)
 	//
-	// namespace3:      33.2292
-	//   initial cost   15.0000
+	// namespace3:      37.2292
+	//   initial cost   18.0000
 	//   idle cost       5.0000
-	//   shared cost    13.2292 = (39.6875)*(15.0/45.0)
+	//   shared cost    14.2292 = (42.6875)*(18.0/54.0)
 	//
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
@@ -1269,8 +1279,8 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	})
 	assertAllocationSetTotals(t, as, "6f", err, 2, activeTotalCost+idleTotalCost)
 	assertAllocationTotals(t, as, "6f", map[string]float64{
-		"namespace2": 66.77,
-		"namespace3": 33.23,
+		"namespace2": 74.77,
+		"namespace3": 37.23,
 	})
 	assertAllocationWindow(t, as, "6f", startYesterday, endYesterday, 1440.0)
 
@@ -1278,20 +1288,20 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	//
 	// First, share idle weighted produces:
 	//
-	// namespace1:      39.6875
-	//   initial cost   25.0000
+	// namespace1:      42.6875
+	//   initial cost   28.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.00/6.00)
 	//   cluster1.ram   12.1875 = 15.00*(13.0/16.0)
 	//
-	// namespace2:      40.3125
-	//   initial cost   30.0000
+	// namespace2:      46.3125
+	//   initial cost   36.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster1.ram    2.8125 = 15.00*(3.0/16.0)
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
-	// namespace3:      20.0000
-	//   initial cost   15.0000
+	// namespace3:      23.0000
+	//   initial cost   18.0000
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
@@ -1299,17 +1309,17 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	// computed before allocating idle (so that weighting idle differently
 	// doesn't adversely affect the sharing mechanism):
 	//
-	// namespace2:      66.7708
-	//   initial cost   30.0000
+	// namespace2:      74.7708
+	//   initial cost   36.0000
 	//   idle cost      10.3125
-	//   shared cost    26.4583 = (39.6875)*(30.0/45.0)
+	//   shared cost    28.4583 = (42.6875)*(36.0/54.0)
 	//
-	// namespace3:      33.2292
-	//   initial cost   15.0000
+	// namespace3:      37.2292
+	//   initial cost   18.0000
 	//   idle cost       5.0000
-	//   shared cost    13.2292 = (39.6875)*(15.0/45.0)
+	//   shared cost    14.2292 = (42.6875)*(18.0/54.0)
 	//
-	// Then, filter for namespace2: 66.7708
+	// Then, filter for namespace2: 74.7708
 	//
 	as = generateAllocationSet(start)
 	err = as.AggregateBy(Properties{NamespaceProp: ""}, &AllocationAggregationOptions{
@@ -1318,9 +1328,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		ShareSplit:  ShareWeighted,
 		ShareIdle:   ShareWeighted,
 	})
-	assertAllocationSetTotals(t, as, "6g", err, 1, 66.77)
+	assertAllocationSetTotals(t, as, "6g", err, 1, 74.77)
 	assertAllocationTotals(t, as, "6g", map[string]float64{
-		"namespace2": 66.77,
+		"namespace2": 74.77,
 	})
 	assertAllocationWindow(t, as, "6g", startYesterday, endYesterday, 1440.0)
 
@@ -1328,28 +1338,28 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 	//
 	// Share idle weighted:
 	//
-	// namespace1:      39.6875
-	//   initial cost   25.0000
+	// namespace1:      42.6875
+	//   initial cost   28.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.00/6.00)
 	//   cluster1.ram   12.1875 = 15.00*(13.0/16.0)
 	//
-	// namespace2:      40.3125
-	//   initial cost   30.0000
+	// namespace2:      46.3125
+	//   initial cost   36.0000
 	//   cluster1.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster1.ram    2.8125 = 15.00*(3.0/16.0)
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
-	// namespace3:      20.0000
-	//   initial cost   15.0000
+	// namespace3:      23.0000
+	//   initial cost   18.0000
 	//   cluster2.cpu    2.5000 = 5.00*(3.0/6.0)
 	//   cluster2.ram    2.5000 = 5.00*(3.0/6.0)
 	//
 	// Then share overhead:
 	//
-	// namespace1:      99.6875 = 39.6875 + (7.0*24.0)*(25.00/70.00)
-	// namespace2:     112.3125 = 40.3125 + (7.0*24.0)*(30.00/70.00)
-	// namespace3:      56.0000 = 20.0000 + (7.0*24.0)*(15.00/70.00)
+	// namespace1:     100.0533 = 42.6875 + (7.0*24.0)*(28.00/82.00)
+	// namespace2:     120.0686 = 46.3125 + (7.0*24.0)*(36.00/82.00)
+	// namespace3:      59.8780 = 23.0000 + (7.0*24.0)*(18.00/82.00)
 	//
 	// Then namespace 2 is filtered.
 	as = generateAllocationSet(start)
@@ -1359,9 +1369,9 @@ func TestAllocationSet_AggregateBy(t *testing.T) {
 		ShareIdle:         ShareWeighted,
 		SharedHourlyCosts: map[string]float64{"total": sharedOverheadHourlyCost},
 	})
-	assertAllocationSetTotals(t, as, "6h", err, 1, 112.31)
+	assertAllocationSetTotals(t, as, "6h", err, 1, 120.07)
 	assertAllocationTotals(t, as, "6h", map[string]float64{
-		"namespace2": 112.31,
+		"namespace2": 120.07,
 	})
 	assertAllocationWindow(t, as, "6h", startYesterday, endYesterday, 1440.0)
 
@@ -1668,8 +1678,8 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if result == nil {
 		t.Fatalf("accumulating AllocationSetRange: expected AllocationSet; actual %s", result)
 	}
-	if result.TotalCost() != 5.0 {
-		t.Fatalf("accumulating AllocationSetRange: expected total cost 5.0; actual %f", result.TotalCost())
+	if result.TotalCost() != 6.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected total cost 6.0; actual %f", result.TotalCost())
 	}
 
 	result, err = NewAllocationSetRange(todayAS, nil).Accumulate()
@@ -1679,8 +1689,8 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if result == nil {
 		t.Fatalf("accumulating AllocationSetRange: expected AllocationSet; actual %s", result)
 	}
-	if result.TotalCost() != 5.0 {
-		t.Fatalf("accumulating AllocationSetRange: expected total cost 5.0; actual %f", result.TotalCost())
+	if result.TotalCost() != 6.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected total cost 6.0; actual %f", result.TotalCost())
 	}
 
 	result, err = NewAllocationSetRange(nil, todayAS, nil).Accumulate()
@@ -1690,8 +1700,8 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if result == nil {
 		t.Fatalf("accumulating AllocationSetRange: expected AllocationSet; actual %s", result)
 	}
-	if result.TotalCost() != 5.0 {
-		t.Fatalf("accumulating AllocationSetRange: expected total cost 5.0; actual %f", result.TotalCost())
+	if result.TotalCost() != 6.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected total cost 6.0; actual %f", result.TotalCost())
 	}
 
 	// Accumulate two non-nil should result in sum of both with appropriate start, end
@@ -1702,8 +1712,8 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if result == nil {
 		t.Fatalf("accumulating AllocationSetRange: expected AllocationSet; actual %s", result)
 	}
-	if result.TotalCost() != 10.0 {
-		t.Fatalf("accumulating AllocationSetRange: expected total cost 10.0; actual %f", result.TotalCost())
+	if result.TotalCost() != 12.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected total cost 12.0; actual %f", result.TotalCost())
 	}
 	allocMap := result.Map()
 	if len(allocMap) != 1 {
@@ -1731,6 +1741,9 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if alloc.NetworkCost != 2.0 {
 		t.Fatalf("accumulating AllocationSetRange: expected 2.0; actual %f", alloc.NetworkCost)
 	}
+	if alloc.LoadBalancerCost != 2.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected 2.0; actual %f", alloc.LoadBalancerCost)
+	}
 	if alloc.PVByteHours != 2.0 {
 		t.Fatalf("accumulating AllocationSetRange: expected 2.0; actual %f", alloc.PVByteHours)
 	}
@@ -1746,8 +1759,8 @@ func TestAllocationSetRange_Accumulate(t *testing.T) {
 	if alloc.RAMEfficiency() != 1.0 {
 		t.Fatalf("accumulating AllocationSetRange: expected 1.0; actual %f", alloc.RAMEfficiency())
 	}
-	if alloc.TotalCost() != 10.0 {
-		t.Fatalf("accumulating AllocationSetRange: expected 10.0; actual %f", alloc.TotalCost())
+	if alloc.TotalCost() != 12.0 {
+		t.Fatalf("accumulating AllocationSetRange: expected 12.0; actual %f", alloc.TotalCost())
 	}
 	if alloc.TotalEfficiency() != 1.0 {
 		t.Fatalf("accumulating AllocationSetRange: expected 1.0; actual %f", alloc.TotalEfficiency())
@@ -1848,6 +1861,9 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 			if !util.IsApproximately(a.NetworkCost, unit.NetworkCost) {
 				t.Fatalf("allocation %s: expected %f; got %f", k, unit.NetworkCost, a.NetworkCost)
 			}
+			if !util.IsApproximately(a.LoadBalancerCost, unit.LoadBalancerCost) {
+				t.Fatalf("allocation %s: expected %f; got %f", k, unit.LoadBalancerCost, a.LoadBalancerCost)
+			}
 			if !util.IsApproximately(a.TotalCost(), unit.TotalCost()) {
 				t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 			}
@@ -1896,6 +1912,10 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 		if !util.IsApproximately(a.NetworkCost, 2*unit.NetworkCost) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.NetworkCost, a.NetworkCost)
 		}
+		if !util.IsApproximately(a.LoadBalancerCost, 2*unit.LoadBalancerCost) {
+			t.Fatalf("allocation %s: expected %f; got %f", k, unit.LoadBalancerCost, a.LoadBalancerCost)
+		}
+
 		if !util.IsApproximately(a.TotalCost(), 2*unit.TotalCost()) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 		}
@@ -1929,13 +1949,15 @@ func TestAllocationSetRange_InsertRange(t *testing.T) {
 		if !util.IsApproximately(a.NetworkCost, unit.NetworkCost) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.NetworkCost, a.NetworkCost)
 		}
+		if !util.IsApproximately(a.LoadBalancerCost, unit.LoadBalancerCost) {
+			t.Fatalf("allocation %s: expected %f; got %f", k, unit.LoadBalancerCost, a.LoadBalancerCost)
+		}
 		if !util.IsApproximately(a.TotalCost(), unit.TotalCost()) {
 			t.Fatalf("allocation %s: expected %f; got %f", k, unit.TotalCost(), a.TotalCost())
 		}
 	})
 }
 
-
 // TODO niko/etl
 // func TestAllocationSetRange_Length(t *testing.T) {}