From d8a5cd59c083247ecca8042022422f9c429fcdcc Mon Sep 17 00:00:00 2001 From: Peter Hunt Date: Fri, 6 Oct 2023 14:46:44 -0400 Subject: [PATCH] kubelet/images: add unit test for MaxAge Signed-off-by: Peter Hunt --- pkg/kubelet/images/image_gc_manager_test.go | 113 ++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/pkg/kubelet/images/image_gc_manager_test.go b/pkg/kubelet/images/image_gc_manager_test.go index 87abc7c7cab..4507f3c0677 100644 --- a/pkg/kubelet/images/image_gc_manager_test.go +++ b/pkg/kubelet/images/image_gc_manager_test.go @@ -652,6 +652,119 @@ func getImagesAndFreeSpace(ctx context.Context, t *testing.T, assert *assert.Ass assert.Len(fakeRuntime.ImageList, imagesLen) } +func TestGarbageCollectImageTooOld(t *testing.T) { + ctx := context.Background() + policy := ImageGCPolicy{ + HighThresholdPercent: 90, + LowThresholdPercent: 80, + MinAge: 0, + MaxAge: time.Minute * 1, + } + fakeRuntime := &containertest.FakeRuntime{} + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + mockStatsProvider := statstest.NewMockProvider(mockCtrl) + manager := &realImageGCManager{ + runtime: fakeRuntime, + policy: policy, + imageRecords: make(map[string]*imageRecord), + statsProvider: mockStatsProvider, + recorder: &record.FakeRecorder{}, + } + + fakeRuntime.ImageList = []container.Image{ + makeImage(0, 1024), + makeImage(1, 2048), + } + // 1 image is in use, and another one is not old enough + fakeRuntime.AllPodList = []*containertest.FakePod{ + {Pod: &container.Pod{ + Containers: []*container.Container{ + makeContainer(1), + }, + }}, + } + + fakeClock := testingclock.NewFakeClock(time.Now()) + t.Log(fakeClock.Now()) + images, err := manager.imagesInEvictionOrder(ctx, fakeClock.Now()) + require.NoError(t, err) + require.Equal(t, len(images), 1) + // Simulate pod having just used this image, but having been GC'd + images[0].lastUsed = fakeClock.Now() + + // First GC round should not GC remaining image, as it was used too recently. + assert := assert.New(t) + images, err = manager.freeOldImages(ctx, images, fakeClock.Now()) + require.NoError(t, err) + assert.Len(images, 1) + assert.Len(fakeRuntime.ImageList, 2) + + // move clock by a millisecond past maxAge duration, then 1 image will be garbage collected + fakeClock.Step(policy.MaxAge + 1) + images, err = manager.freeOldImages(ctx, images, fakeClock.Now()) + require.NoError(t, err) + assert.Len(images, 0) + assert.Len(fakeRuntime.ImageList, 1) +} + +func TestGarbageCollectImageMaxAgeDisabled(t *testing.T) { + ctx := context.Background() + policy := ImageGCPolicy{ + HighThresholdPercent: 90, + LowThresholdPercent: 80, + MinAge: 0, + MaxAge: 0, + } + fakeRuntime := &containertest.FakeRuntime{} + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + mockStatsProvider := statstest.NewMockProvider(mockCtrl) + manager := &realImageGCManager{ + runtime: fakeRuntime, + policy: policy, + imageRecords: make(map[string]*imageRecord), + statsProvider: mockStatsProvider, + recorder: &record.FakeRecorder{}, + } + + assert := assert.New(t) + fakeRuntime.ImageList = []container.Image{ + makeImage(0, 1024), + makeImage(1, 2048), + } + assert.Len(fakeRuntime.ImageList, 2) + // 1 image is in use, and another one is not old enough + fakeRuntime.AllPodList = []*containertest.FakePod{ + {Pod: &container.Pod{ + Containers: []*container.Container{ + makeContainer(1), + }, + }}, + } + + fakeClock := testingclock.NewFakeClock(time.Now()) + t.Log(fakeClock.Now()) + images, err := manager.imagesInEvictionOrder(ctx, fakeClock.Now()) + require.NoError(t, err) + require.Equal(t, len(images), 1) + assert.Len(fakeRuntime.ImageList, 2) + + // First GC round should not GC remaining image, as it was used too recently. + images, err = manager.freeOldImages(ctx, images, fakeClock.Now()) + require.NoError(t, err) + assert.Len(images, 1) + assert.Len(fakeRuntime.ImageList, 2) + + // Move clock by a lot, and the images should continue to not be garbage colleced + // See https://stackoverflow.com/questions/25065055/what-is-the-maximum-time-time-in-go + fakeClock.SetTime(time.Unix(1<<63-62135596801, 999999999)) + images, err = manager.freeOldImages(ctx, images, fakeClock.Now()) + require.NoError(t, err) + assert.Len(images, 1) + assert.Len(fakeRuntime.ImageList, 2) +} + func TestValidateImageGCPolicy(t *testing.T) { testCases := []struct { name string