github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/lifecycle/agent-healthz/healthz_controller_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 agent_healthz
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  	"github.com/stretchr/testify/require"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/labels"
    30  	"k8s.io/apimachinery/pkg/runtime"
    31  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    32  	"k8s.io/client-go/informers"
    33  	"k8s.io/client-go/kubernetes/fake"
    34  	"k8s.io/client-go/tools/cache"
    35  	"k8s.io/klog/v2"
    36  
    37  	apis "github.com/kubewharf/katalyst-api/pkg/apis/node/v1alpha1"
    38  	internalfake "github.com/kubewharf/katalyst-api/pkg/client/clientset/versioned/fake"
    39  	"github.com/kubewharf/katalyst-api/pkg/client/informers/externalversions"
    40  	"github.com/kubewharf/katalyst-core/cmd/katalyst-controller/app/options"
    41  	"github.com/kubewharf/katalyst-core/pkg/client"
    42  	pkgconfig "github.com/kubewharf/katalyst-core/pkg/config"
    43  )
    44  
    45  func generateTestKubeClientSet(objects []runtime.Object, internalObjects []runtime.Object) *client.GenericClientSet {
    46  	return &client.GenericClientSet{
    47  		KubeClient:     fake.NewSimpleClientset(objects...),
    48  		InternalClient: internalfake.NewSimpleClientset(internalObjects...),
    49  	}
    50  }
    51  
    52  func generateTestConfiguration(t *testing.T) *pkgconfig.Configuration {
    53  	seletor, _ := labels.Parse("app=katalyst-agent")
    54  
    55  	testConfiguration, err := options.NewOptions().Config()
    56  	require.NoError(t, err)
    57  	require.NotNil(t, testConfiguration)
    58  	testConfiguration.ControllersConfiguration.LifeCycleConfig.HandlePeriod = time.Second
    59  	testConfiguration.ControllersConfiguration.LifeCycleConfig.UnhealthyPeriods = 5 * time.Second
    60  	testConfiguration.ControllersConfiguration.LifeCycleConfig.AgentSelector = map[string]labels.Selector{
    61  		"katalyst-agent": seletor,
    62  	}
    63  
    64  	return testConfiguration
    65  }
    66  
    67  func NewFakeHealthzController(t *testing.T) (*HealthzController, error) {
    68  	stopCh := make(chan struct{})
    69  	defer close(stopCh)
    70  
    71  	label := make(map[string]string)
    72  	label["app"] = "katalyst-agent"
    73  
    74  	pod := &corev1.Pod{
    75  		ObjectMeta: metav1.ObjectMeta{
    76  			Name:   "pod1",
    77  			Labels: label,
    78  		},
    79  		Spec: corev1.PodSpec{
    80  			NodeName: "node1",
    81  			Containers: []corev1.Container{
    82  				{
    83  					Name: "katalyst-agent",
    84  				},
    85  			},
    86  		},
    87  		Status: corev1.PodStatus{
    88  			ContainerStatuses: []corev1.ContainerStatus{
    89  				{Ready: true},
    90  			},
    91  		},
    92  	}
    93  
    94  	node := &corev1.Node{
    95  		ObjectMeta: metav1.ObjectMeta{
    96  			Name: "node1",
    97  			UID:  "1",
    98  		},
    99  		Spec: corev1.NodeSpec{},
   100  	}
   101  
   102  	cnr := &apis.CustomNodeResource{
   103  		ObjectMeta: metav1.ObjectMeta{
   104  			Name: "node1",
   105  		},
   106  		Spec: apis.CustomNodeResourceSpec{
   107  			Taints: []*apis.Taint{},
   108  		},
   109  		Status: apis.CustomNodeResourceStatus{},
   110  	}
   111  
   112  	clientSet := generateTestKubeClientSet([]runtime.Object{pod, node}, []runtime.Object{cnr})
   113  	kubeInformerFactory := informers.NewSharedInformerFactoryWithOptions(clientSet.KubeClient, time.Hour*24)
   114  	nodeInformer := kubeInformerFactory.Core().V1().Nodes()
   115  	podInformer := kubeInformerFactory.Core().V1().Pods()
   116  
   117  	internalInformerFactory := externalversions.NewSharedInformerFactoryWithOptions(clientSet.InternalClient, time.Hour*24)
   118  	cnrInformer := internalInformerFactory.Node().V1alpha1().CustomNodeResources()
   119  
   120  	conf := generateTestConfiguration(t)
   121  	ec, err := NewHealthzController(context.Background(), conf.GenericConfiguration, conf.GenericControllerConfiguration,
   122  		conf.ControllersConfiguration.LifeCycleConfig, clientSet, nodeInformer, podInformer, cnrInformer, nil)
   123  	if err != nil {
   124  		t.Errorf("new eviction controller error")
   125  	}
   126  
   127  	kubeInformerFactory.Start(stopCh)
   128  	internalInformerFactory.Start(stopCh)
   129  
   130  	if !cache.WaitForCacheSync(ec.ctx.Done(), ec.nodeListerSynced, ec.cnrListerSynced, ec.podListerSynced) {
   131  		utilruntime.HandleError(fmt.Errorf("unable to sync caches for evcition controller"))
   132  	}
   133  	return ec, nil
   134  }
   135  
   136  func TestHealthzController(t *testing.T) {
   137  	t.Parallel()
   138  
   139  	ec, err := NewFakeHealthzController(t)
   140  	if err != nil {
   141  		klog.Errorf("get new fake cnr lifecycle err %v", err)
   142  	}
   143  
   144  	go ec.Run()
   145  
   146  	healthy := ec.healthzHelper.CheckAllAgentReady("node1")
   147  	assert.Equal(t, true, healthy)
   148  }
   149  
   150  func Test_podTransformerFunc(t *testing.T) {
   151  	t.Parallel()
   152  
   153  	type args struct {
   154  		src  *corev1.Pod
   155  		dest *corev1.Pod
   156  	}
   157  	tests := []struct {
   158  		name string
   159  		args args
   160  		want *corev1.Pod
   161  	}{
   162  		{
   163  			name: "normal",
   164  			args: args{
   165  				src: &corev1.Pod{
   166  					Spec: corev1.PodSpec{
   167  						Containers: []corev1.Container{
   168  							{
   169  								Name: "container-1",
   170  							},
   171  						},
   172  						NodeName: "node-1",
   173  						HostPID:  true,
   174  					},
   175  					Status: corev1.PodStatus{
   176  						ContainerStatuses: []corev1.ContainerStatus{
   177  							{
   178  								Name:  "container-1",
   179  								Ready: true,
   180  							},
   181  						},
   182  					},
   183  				},
   184  				dest: &corev1.Pod{},
   185  			},
   186  			want: &corev1.Pod{
   187  				Spec: corev1.PodSpec{
   188  					Containers: []corev1.Container{
   189  						{
   190  							Name: "container-1",
   191  						},
   192  					},
   193  					NodeName: "node-1",
   194  				},
   195  				Status: corev1.PodStatus{
   196  					ContainerStatuses: []corev1.ContainerStatus{
   197  						{
   198  							Name:  "container-1",
   199  							Ready: true,
   200  						},
   201  					},
   202  				},
   203  			},
   204  		},
   205  	}
   206  	for _, tt := range tests {
   207  		tt := tt
   208  		t.Run(tt.name, func(t *testing.T) {
   209  			t.Parallel()
   210  			podTransformerFunc(tt.args.src, tt.args.dest)
   211  			assert.Equal(t, tt.want, tt.args.dest)
   212  		})
   213  	}
   214  }