github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/evictionmanager/podkiller/killer_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package podkiller
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/client-go/tools/events"
    30  	critesting "k8s.io/cri-api/pkg/apis/testing"
    31  
    32  	katalyst_base "github.com/kubewharf/katalyst-core/cmd/base"
    33  	"github.com/kubewharf/katalyst-core/pkg/consts"
    34  	"github.com/kubewharf/katalyst-core/pkg/metrics"
    35  )
    36  
    37  func TestEvictionQueue(t *testing.T) {
    38  	t.Parallel()
    39  
    40  	pods := []*v1.Pod{
    41  		{
    42  			ObjectMeta: metav1.ObjectMeta{Name: "pod-1"},
    43  		},
    44  		{
    45  			ObjectMeta: metav1.ObjectMeta{Name: "pod-2"},
    46  		},
    47  		{
    48  			ObjectMeta: metav1.ObjectMeta{Name: "pod-3"},
    49  		},
    50  	}
    51  
    52  	ctx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{pods[0], pods[1]})
    53  	require.NoError(t, err)
    54  
    55  	deleteKiller, BuildErr := NewDeletionAPIKiller(nil, ctx.Client.KubeClient, &events.FakeRecorder{}, metrics.DummyMetrics{})
    56  	require.NoError(t, BuildErr)
    57  
    58  	err = deleteKiller.Evict(context.Background(), pods[0], 0, "test-api", "test")
    59  	require.NoError(t, err)
    60  
    61  	err = deleteKiller.Evict(context.Background(), pods[0], 0, "test-api", "test")
    62  	require.NoError(t, err)
    63  
    64  	err = deleteKiller.Evict(context.Background(), pods[1], 0, "test-api", "test")
    65  	require.NoError(t, err)
    66  
    67  	err = evict(ctx.Client.KubeClient, &events.FakeRecorder{}, metrics.DummyMetrics{}, pods[2],
    68  		0, "test-api", "test", func(_ *v1.Pod, gracePeriod int64) error {
    69  			return fmt.Errorf("test")
    70  		})
    71  	require.ErrorContains(t, err, "test")
    72  }
    73  
    74  func TestContainerKiller_Evict(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	fakeRuntimeService := critesting.NewFakeRuntimeService()
    78  	containerKiller := &ContainerKiller{
    79  		containerManager: fakeRuntimeService,
    80  		recorder:         events.NewFakeRecorder(5),
    81  		emitter:          metrics.DummyMetrics{},
    82  	}
    83  	containerKiller.containerManager = fakeRuntimeService
    84  	assert.Equal(t, consts.KillerNameContainerKiller, containerKiller.Name())
    85  
    86  	fakeRuntimeService.Containers["container-01"] = &critesting.FakeContainer{}
    87  	fakeRuntimeService.Containers["container-02"] = &critesting.FakeContainer{}
    88  
    89  	tests := []struct {
    90  		name                   string
    91  		pod                    *v1.Pod
    92  		wantKillContainerCount int
    93  		wantStopFailed         bool
    94  	}{
    95  		{
    96  			name: "1 container",
    97  			pod: &v1.Pod{
    98  				Spec: v1.PodSpec{
    99  					Containers: []v1.Container{
   100  						{
   101  							Name: "container-01",
   102  						},
   103  					},
   104  				},
   105  				Status: v1.PodStatus{
   106  					ContainerStatuses: []v1.ContainerStatus{
   107  						{
   108  							Name:        "container-01",
   109  							ContainerID: "containerd://container-01",
   110  						},
   111  					},
   112  				},
   113  			},
   114  			wantKillContainerCount: 1,
   115  			wantStopFailed:         false,
   116  		},
   117  		{
   118  			name: "2 containers",
   119  			pod: &v1.Pod{
   120  				Spec: v1.PodSpec{
   121  					Containers: []v1.Container{
   122  						{
   123  							Name: "container-01",
   124  						},
   125  						{
   126  							Name: "container-02",
   127  						},
   128  					},
   129  				},
   130  				Status: v1.PodStatus{
   131  					ContainerStatuses: []v1.ContainerStatus{
   132  						{
   133  							Name:        "container-01",
   134  							ContainerID: "containerd://container-01",
   135  						},
   136  						{
   137  							Name:        "container-02",
   138  							ContainerID: "containerd://container-02",
   139  						},
   140  					},
   141  				},
   142  			},
   143  			wantKillContainerCount: 2,
   144  			wantStopFailed:         false,
   145  		},
   146  		{
   147  			name: "1 container but has error",
   148  			pod: &v1.Pod{
   149  				Spec: v1.PodSpec{
   150  					Containers: []v1.Container{
   151  						{
   152  							Name: "container-03",
   153  						},
   154  					},
   155  				},
   156  				Status: v1.PodStatus{
   157  					ContainerStatuses: []v1.ContainerStatus{
   158  						{
   159  							Name:        "container-03",
   160  							ContainerID: "containerd://container-03",
   161  						},
   162  					},
   163  				},
   164  			},
   165  			wantStopFailed: true,
   166  		},
   167  	}
   168  	for _, tt := range tests {
   169  		fakeRuntimeService.Called = make([]string, 0)
   170  		evictErr := containerKiller.Evict(context.TODO(), tt.pod, 0, "test", "test")
   171  		if tt.wantStopFailed {
   172  			require.Error(t, evictErr)
   173  		} else {
   174  			require.NoError(t, evictErr)
   175  			require.Equal(t, tt.wantKillContainerCount, len(fakeRuntimeService.GetCalls()))
   176  		}
   177  	}
   178  }