Ver Fonte

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 há 4 anos atrás
pai
commit
4f87967e88

+ 4 - 0
pkg/kubecost/allocation.go

@@ -2128,6 +2128,10 @@ func (as *AllocationSet) insert(that *Allocation) error {
 		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
 }
 

+ 40 - 0
pkg/kubecost/allocation_test.go

@@ -1847,6 +1847,46 @@ func TestAllocationSet_ComputeIdleAllocationsPerNode(t *testing.T) {
 // TODO niko/etl
 //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
 //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) {
 	endYesterday := time.Now().UTC().Truncate(day)
 	startYesterday := endYesterday.Add(-day)

+ 65 - 0
pkg/kubecost/window_test.go

@@ -766,6 +766,71 @@ func TestWindow_DurationOffsetForPrometheus(t *testing.T) {
 // TODO
 // 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
 // func TestWindow_Start(t *testing.T) {}