Browse Source

Allocations in AllocationSet have correct Window

Causes AllocationSet.insert() to expand the Window of the
inserted Allocation to the Window of the AllocationSet.
Added unit test that failed before making the logic change.

Also added equivalent test for AssetSet, which passes because
AssetSet.Insert() already exhibits this behavior.

+ bonus unit tests for Window.Expand()
Michael Dresser 4 years ago
parent
commit
4f87967e88

+ 4 - 0
pkg/kubecost/allocation.go

@@ -2128,6 +2128,10 @@ func (as *AllocationSet) insert(that *Allocation) error {
 		as.idleKeys[that.Name] = true
 		as.idleKeys[that.Name] = true
 	}
 	}
 
 
+	// Expand the window, just to be safe. It's possible that the Allocation will
+	// be set into the map without expanding it to the AllocationSet's window.
+	as.allocations[that.Name].Window = as.allocations[that.Name].Window.Expand(as.Window)
+
 	return nil
 	return nil
 }
 }
 
 

+ 40 - 0
pkg/kubecost/allocation_test.go

@@ -1847,6 +1847,46 @@ func TestAllocationSet_ComputeIdleAllocationsPerNode(t *testing.T) {
 // TODO niko/etl
 // TODO niko/etl
 //func TestAllocationSet_Insert(t *testing.T) {}
 //func TestAllocationSet_Insert(t *testing.T) {}
 
 
+// Asserts that all Allocations within an AllocationSet have a Window that
+// matches that of the AllocationSet.
+func TestAllocationSet_insertMatchingWindow(t *testing.T) {
+	setStart := time.Now().Round(time.Hour)
+	setEnd := setStart.Add(1 * time.Hour)
+
+	a1WindowStart := setStart.Add(5 * time.Minute)
+	a1WindowEnd := setStart.Add(50 * time.Minute)
+
+	a2WindowStart := setStart.Add(17 * time.Minute)
+	a2WindowEnd := setStart.Add(34 * time.Minute)
+
+	a1 := &Allocation{
+		Name:   "allocation-1",
+		Window: Window(NewClosedWindow(a1WindowStart, a1WindowEnd)),
+	}
+
+	a2 := &Allocation{
+		Name:   "allocation-2",
+		Window: Window(NewClosedWindow(a2WindowStart, a2WindowEnd)),
+	}
+
+	as := NewAllocationSet(setStart, setEnd)
+	as.insert(a1)
+	as.insert(a2)
+
+	if as.Length() != 2 {
+		t.Errorf("AS length got %d, expected %d", as.Length(), 2)
+	}
+
+	as.Each(func(k string, a *Allocation) {
+		if !(*a.Window.Start()).Equal(setStart) {
+			t.Errorf("Allocation %s window start is %s, expected %s", a.Name, *a.Window.Start(), setStart)
+		}
+		if !(*a.Window.End()).Equal(setEnd) {
+			t.Errorf("Allocation %s window end is %s, expected %s", a.Name, *a.Window.End(), setEnd)
+		}
+	})
+}
+
 // TODO niko/etl
 // TODO niko/etl
 //func TestAllocationSet_IsEmpty(t *testing.T) {}
 //func TestAllocationSet_IsEmpty(t *testing.T) {}
 
 

+ 42 - 0
pkg/kubecost/asset_test.go

@@ -808,6 +808,48 @@ func TestAssetSet_FindMatch(t *testing.T) {
 	}
 	}
 }
 }
 
 
+// Asserts that all Assets within an AssetSet have a Window that
+// matches that of the AssetSet.
+func TestAssetSet_InsertMatchingWindow(t *testing.T) {
+	setStart := time.Now().Round(time.Hour)
+	setEnd := setStart.Add(1 * time.Hour)
+
+	a1WindowStart := setStart.Add(5 * time.Minute)
+	a1WindowEnd := setStart.Add(50 * time.Minute)
+
+	a2WindowStart := setStart.Add(17 * time.Minute)
+	a2WindowEnd := setStart.Add(34 * time.Minute)
+
+	a1 := &Node{}
+	a1.SetProperties(&AssetProperties{
+		Name: "asset-1",
+	})
+	a1.window = NewClosedWindow(a1WindowStart, a1WindowEnd)
+
+	a2 := &Disk{}
+	a2.SetProperties(&AssetProperties{
+		Name: "asset-2",
+	})
+	a2.window = NewClosedWindow(a2WindowStart, a2WindowEnd)
+
+	as := NewAssetSet(setStart, setEnd)
+	as.Insert(a1)
+	as.Insert(a2)
+
+	if as.Length() != 2 {
+		t.Errorf("AS length got %d, expected %d", as.Length(), 2)
+	}
+
+	as.Each(func(k string, a Asset) {
+		if !(*a.Window().Start()).Equal(setStart) {
+			t.Errorf("Asset %s window start is %s, expected %s", a.Properties().Name, *a.Window().Start(), setStart)
+		}
+		if !(*a.Window().End()).Equal(setEnd) {
+			t.Errorf("Asset %s window end is %s, expected %s", a.Properties().Name, *a.Window().End(), setEnd)
+		}
+	})
+}
+
 func TestAssetSetRange_Accumulate(t *testing.T) {
 func TestAssetSetRange_Accumulate(t *testing.T) {
 	endYesterday := time.Now().UTC().Truncate(day)
 	endYesterday := time.Now().UTC().Truncate(day)
 	startYesterday := endYesterday.Add(-day)
 	startYesterday := endYesterday.Add(-day)

+ 65 - 0
pkg/kubecost/window_test.go

@@ -766,6 +766,71 @@ func TestWindow_DurationOffsetForPrometheus(t *testing.T) {
 // TODO
 // TODO
 // func TestWindow_ExpandEnd(t *testing.T) {}
 // func TestWindow_ExpandEnd(t *testing.T) {}
 
 
+func TestWindow_Expand(t *testing.T) {
+
+	t1 := time.Now().Round(time.Hour)
+	t2 := t1.Add(34 * time.Minute)
+	t3 := t1.Add(50 * time.Minute)
+	t4 := t1.Add(84 * time.Minute)
+
+	cases := []struct {
+		windowToExpand Window
+		windowArgument Window
+
+		expected Window
+	}{
+		{
+			windowToExpand: NewClosedWindow(t1, t2),
+			windowArgument: NewClosedWindow(t3, t4),
+
+			expected: NewClosedWindow(t1, t4),
+		},
+		{
+			windowToExpand: NewClosedWindow(t3, t4),
+			windowArgument: NewClosedWindow(t1, t2),
+
+			expected: NewClosedWindow(t1, t4),
+		},
+		{
+			windowToExpand: NewClosedWindow(t1, t3),
+			windowArgument: NewClosedWindow(t2, t4),
+
+			expected: NewClosedWindow(t1, t4),
+		},
+		{
+			windowToExpand: NewClosedWindow(t2, t4),
+			windowArgument: NewClosedWindow(t1, t3),
+
+			expected: NewClosedWindow(t1, t4),
+		},
+		{
+			windowToExpand: Window{},
+			windowArgument: NewClosedWindow(t1, t2),
+
+			expected: NewClosedWindow(t1, t2),
+		},
+		{
+			windowToExpand: NewWindow(nil, &t2),
+			windowArgument: NewWindow(nil, &t3),
+
+			expected: NewWindow(nil, &t3),
+		},
+		{
+			windowToExpand: NewWindow(&t2, nil),
+			windowArgument: NewWindow(&t1, nil),
+
+			expected: NewWindow(&t1, nil),
+		},
+	}
+
+	for _, c := range cases {
+		result := c.windowToExpand.Expand(c.windowArgument)
+		if !result.Equal(c.expected) {
+			t.Errorf("Expand %s with %s, expected %s but got %s", c.windowToExpand, c.windowArgument, c.expected, result)
+		}
+	}
+}
+
 // TODO
 // TODO
 // func TestWindow_Start(t *testing.T) {}
 // func TestWindow_Start(t *testing.T) {}