github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/overcommit/node/node_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 node
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strconv"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/client-go/tools/cache"
    30  	cliflag "k8s.io/component-base/cli/flag"
    31  
    32  	nodev1alpha1 "github.com/kubewharf/katalyst-api/pkg/apis/node/v1alpha1"
    33  	v1alpha12 "github.com/kubewharf/katalyst-api/pkg/apis/node/v1alpha1"
    34  	"github.com/kubewharf/katalyst-api/pkg/apis/overcommit/v1alpha1"
    35  	"github.com/kubewharf/katalyst-api/pkg/consts"
    36  	katalyst_base "github.com/kubewharf/katalyst-core/cmd/base"
    37  	"github.com/kubewharf/katalyst-core/cmd/katalyst-controller/app/options"
    38  	"github.com/kubewharf/katalyst-core/pkg/config/controller"
    39  	"github.com/kubewharf/katalyst-core/pkg/config/generic"
    40  )
    41  
    42  func makeNoc(name string, cpuOvercommitRatio, memoryOvercommitRatio string) *v1alpha1.NodeOvercommitConfig {
    43  	return &v1alpha1.NodeOvercommitConfig{
    44  		ObjectMeta: metav1.ObjectMeta{
    45  			Name:              name,
    46  			CreationTimestamp: metav1.NewTime(time.Now()),
    47  		},
    48  		Spec: v1alpha1.NodeOvercommitConfigSpec{
    49  			ResourceOvercommitRatio: map[corev1.ResourceName]string{
    50  				corev1.ResourceCPU:    cpuOvercommitRatio,
    51  				corev1.ResourceMemory: memoryOvercommitRatio,
    52  			},
    53  		},
    54  	}
    55  }
    56  
    57  func makeSelectorNoc(name string, cpuOvercommitRatio, memoryOvercommitRatio string, value string) *v1alpha1.NodeOvercommitConfig {
    58  	c := makeNoc(name, cpuOvercommitRatio, memoryOvercommitRatio)
    59  	c.Spec.NodeOvercommitSelectorVal = value
    60  	return c
    61  }
    62  
    63  func makeNode(name string, labels map[string]string) *corev1.Node {
    64  	return &corev1.Node{
    65  		ObjectMeta: metav1.ObjectMeta{
    66  			Name:   name,
    67  			Labels: labels,
    68  			Annotations: map[string]string{
    69  				"katalyst.kubewharf.io/overcommit_allocatable_cpu": "8",
    70  			},
    71  		},
    72  	}
    73  }
    74  
    75  type testCase struct {
    76  	name          string
    77  	initNodes     []*corev1.Node
    78  	initConfigs   []*v1alpha1.NodeOvercommitConfig
    79  	initCNR       []*nodev1alpha1.CustomNodeResource
    80  	updateNodes   []*corev1.Node
    81  	updateConfigs []*v1alpha1.NodeOvercommitConfig
    82  	updateCNR     []*nodev1alpha1.CustomNodeResource
    83  	addNodes      []*corev1.Node
    84  	addConfigs    []*v1alpha1.NodeOvercommitConfig
    85  	addCNR        []*nodev1alpha1.CustomNodeResource
    86  	deleteNodes   []string
    87  	deleteConfigs []string
    88  	result        map[string]map[string]string
    89  }
    90  
    91  var defaultInitNodes = func() []*corev1.Node {
    92  	return []*corev1.Node{
    93  		makeNode("node1", map[string]string{consts.NodeOvercommitSelectorKey: "pool1"}),
    94  		makeNode("node2", map[string]string{consts.NodeOvercommitSelectorKey: "pool2"}),
    95  		makeNode("node3", map[string]string{consts.NodeOvercommitSelectorKey: "pool1"}),
    96  		makeNode("node4", map[string]string{consts.NodeOvercommitSelectorKey: "pool3"}),
    97  	}
    98  }()
    99  
   100  var defaultInitCNR = func() []*nodev1alpha1.CustomNodeResource {
   101  	return []*nodev1alpha1.CustomNodeResource{
   102  		{ObjectMeta: metav1.ObjectMeta{Name: "node1", Annotations: map[string]string{
   103  			consts.NodeAnnotationCPUOvercommitRatioKey:    "1",
   104  			consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   105  		}}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Annotations: map[string]string{
   106  			consts.NodeAnnotationCPUOvercommitRatioKey:    "1",
   107  			consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   108  		}}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Annotations: map[string]string{
   109  			consts.NodeAnnotationCPUOvercommitRatioKey:    "3",
   110  			consts.NodeAnnotationMemoryOvercommitRatioKey: "3",
   111  		}}}, {ObjectMeta: metav1.ObjectMeta{Name: "node4", Annotations: map[string]string{
   112  			consts.NodeAnnotationCPUOvercommitRatioKey:    "2",
   113  			consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   114  		}}},
   115  	}
   116  }()
   117  
   118  var testCases = []testCase{
   119  	{
   120  		name:      "init: null config, add: config without selector",
   121  		initNodes: defaultInitNodes,
   122  		addConfigs: []*v1alpha1.NodeOvercommitConfig{
   123  			makeNoc("config", "1", "1"),
   124  		},
   125  		result: map[string]map[string]string{},
   126  	},
   127  	{
   128  		name:      "init: null config, add: selector config",
   129  		initNodes: defaultInitNodes,
   130  		addConfigs: []*v1alpha1.NodeOvercommitConfig{
   131  			makeSelectorNoc("config-selector", "2", "1", "pool1"),
   132  		},
   133  		result: map[string]map[string]string{
   134  			"node1": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   135  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   136  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   137  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   138  		},
   139  	},
   140  	{
   141  		name:      "update selector / nodelist config",
   142  		initNodes: defaultInitNodes,
   143  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   144  			makeSelectorNoc("config-selector", "2", "1", "pool1"),
   145  		},
   146  		updateConfigs: []*v1alpha1.NodeOvercommitConfig{
   147  			makeSelectorNoc("config-selector", "2", "1", "pool2"),
   148  		},
   149  		result: map[string]map[string]string{
   150  			"node1": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   151  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   152  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   153  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   154  		},
   155  	},
   156  	{
   157  		name:      "only update config resource",
   158  		initNodes: defaultInitNodes,
   159  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   160  			makeSelectorNoc("config-selector", "2", "1", "pool1"),
   161  		},
   162  		updateConfigs: []*v1alpha1.NodeOvercommitConfig{
   163  			makeSelectorNoc("config-selector", "3", "1", "pool1"),
   164  		},
   165  		result: map[string]map[string]string{
   166  			"node1": {consts.NodeAnnotationCPUOvercommitRatioKey: "3", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   167  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   168  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "3", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   169  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   170  		},
   171  	},
   172  	{
   173  		name:      "update node label",
   174  		initNodes: defaultInitNodes,
   175  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   176  			makeSelectorNoc("config-selector", "2", "1", "pool1"),
   177  		},
   178  		updateNodes: []*corev1.Node{
   179  			makeNode("node3", map[string]string{consts.NodeOvercommitSelectorKey: "pool2"}),
   180  			makeNode("node4", map[string]string{consts.NodeOvercommitSelectorKey: "pool1"}),
   181  		},
   182  		result: map[string]map[string]string{
   183  			"node1": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   184  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   185  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   186  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   187  		},
   188  	},
   189  	{
   190  		name:      "delete config",
   191  		initNodes: defaultInitNodes,
   192  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   193  			makeSelectorNoc("config-selector", "2", "1", "pool1"),
   194  		},
   195  		deleteConfigs: []string{"config-selector"},
   196  		result: map[string]map[string]string{
   197  			"node1": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   198  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   199  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   200  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   201  		},
   202  	},
   203  	{
   204  		name:      "delete node",
   205  		initNodes: defaultInitNodes,
   206  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   207  			makeSelectorNoc("config2-selector", "2", "1", "pool1"),
   208  		},
   209  		deleteNodes: []string{"node1"},
   210  		result: map[string]map[string]string{
   211  			"node2": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   212  			"node3": {consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   213  			"node4": {consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1"},
   214  		},
   215  	},
   216  	{
   217  		name:      "init: node and cnr, add config",
   218  		initNodes: defaultInitNodes,
   219  		initCNR:   defaultInitCNR,
   220  		addConfigs: []*v1alpha1.NodeOvercommitConfig{
   221  			makeSelectorNoc("config-selector", "2", "2", "pool1"),
   222  		},
   223  		result: map[string]map[string]string{
   224  			"node1": {
   225  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   226  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1",
   227  			},
   228  			"node2": {
   229  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   230  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1",
   231  			},
   232  			"node3": {
   233  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   234  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "3", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "3",
   235  			},
   236  			"node4": {
   237  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   238  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "2", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "2",
   239  			},
   240  		},
   241  	},
   242  	{
   243  		name:      "add CNR",
   244  		initNodes: defaultInitNodes,
   245  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   246  			makeSelectorNoc("config-selector", "2", "2", "pool1"),
   247  		},
   248  		addCNR: defaultInitCNR,
   249  		result: map[string]map[string]string{
   250  			"node1": {
   251  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   252  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1",
   253  			},
   254  			"node2": {
   255  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   256  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1",
   257  			},
   258  			"node3": {
   259  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   260  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "3", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "3",
   261  			},
   262  			"node4": {
   263  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   264  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "2", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "2",
   265  			},
   266  		},
   267  	},
   268  	{
   269  		name:      "update CNR",
   270  		initNodes: defaultInitNodes,
   271  		initCNR:   defaultInitCNR,
   272  		initConfigs: []*v1alpha1.NodeOvercommitConfig{
   273  			makeSelectorNoc("config-selector", "2", "2", "pool1"),
   274  		},
   275  		updateCNR: []*nodev1alpha1.CustomNodeResource{
   276  			{ObjectMeta: metav1.ObjectMeta{Name: "node3", Annotations: map[string]string{
   277  				consts.NodeAnnotationCPUOvercommitRatioKey:    "1.5",
   278  				consts.NodeAnnotationMemoryOvercommitRatioKey: "1.5",
   279  			}}},
   280  			{ObjectMeta: metav1.ObjectMeta{Name: "node1", Annotations: map[string]string{
   281  				consts.NodeAnnotationCPUOvercommitRatioKey:    "3",
   282  				consts.NodeAnnotationMemoryOvercommitRatioKey: "3",
   283  			}}},
   284  		},
   285  		result: map[string]map[string]string{
   286  			"node1": {
   287  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   288  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "3", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "3",
   289  			},
   290  			"node2": {
   291  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   292  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1",
   293  			},
   294  			"node3": {
   295  				consts.NodeAnnotationCPUOvercommitRatioKey: "2", consts.NodeAnnotationMemoryOvercommitRatioKey: "2",
   296  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "1.5", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "1.5",
   297  			},
   298  			"node4": {
   299  				consts.NodeAnnotationCPUOvercommitRatioKey: "1", consts.NodeAnnotationMemoryOvercommitRatioKey: "1",
   300  				consts.NodeAnnotationRealtimeCPUOvercommitRatioKey: "2", consts.NodeAnnotationRealtimeMemoryOvercommitRatioKey: "2",
   301  			},
   302  		},
   303  	},
   304  }
   305  
   306  func TestReconcile(t *testing.T) {
   307  	// test noc and node add/update/delete by reconcile
   308  	t.Parallel()
   309  
   310  	for _, tc := range testCases {
   311  		tc := tc
   312  		t.Run(tc.name, func(t *testing.T) {
   313  			t.Parallel()
   314  
   315  			fss := &cliflag.NamedFlagSets{}
   316  			nocOptions := options.NewOvercommitOptions()
   317  			nocOptions.AddFlags(fss)
   318  			nocOptions.ConfigReconcilePeriod = 5 * time.Second
   319  			nocConf := controller.NewOvercommitConfig()
   320  			_ = nocOptions.ApplyTo(nocConf)
   321  
   322  			genericConf := &generic.GenericConfiguration{}
   323  
   324  			controlCtx, err := katalyst_base.GenerateFakeGenericContext()
   325  			assert.NoError(t, err)
   326  
   327  			ctx, cancel := context.WithCancel(context.Background())
   328  			defer cancel()
   329  			nocController, err := NewNodeOvercommitController(ctx, controlCtx, genericConf, nocConf)
   330  			assert.NoError(t, err)
   331  
   332  			for _, node := range tc.initNodes {
   333  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{})
   334  				assert.NoError(t, err)
   335  			}
   336  			for _, cnr := range tc.initCNR {
   337  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Create(ctx, cnr, metav1.CreateOptions{})
   338  				assert.NoError(t, err)
   339  			}
   340  			for _, config := range tc.initConfigs {
   341  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Create(ctx, config, metav1.CreateOptions{})
   342  				assert.NoError(t, err)
   343  			}
   344  
   345  			controlCtx.StartInformer(nocController.ctx)
   346  			syncd := cache.WaitForCacheSync(nocController.ctx.Done(), nocController.syncedFunc...)
   347  			assert.True(t, syncd)
   348  			assert.Equal(t, 5*time.Second, nocController.reconcilePeriod)
   349  			err = nocController.matcher.Reconcile()
   350  			assert.NoError(t, err)
   351  
   352  			nocController.reconcile()
   353  
   354  			for _, node := range tc.addNodes {
   355  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{})
   356  				assert.NoError(t, err)
   357  			}
   358  			for _, cnr := range tc.addCNR {
   359  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Create(ctx, cnr, metav1.CreateOptions{})
   360  				assert.NoError(t, err)
   361  			}
   362  			for _, config := range tc.addConfigs {
   363  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Create(ctx, config, metav1.CreateOptions{})
   364  				assert.NoError(t, err)
   365  			}
   366  			for _, node := range tc.updateNodes {
   367  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
   368  				assert.NoError(t, err)
   369  			}
   370  			for _, config := range tc.updateConfigs {
   371  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Update(ctx, config, metav1.UpdateOptions{})
   372  				assert.NoError(t, err)
   373  			}
   374  			for _, cnr := range tc.updateCNR {
   375  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Update(ctx, cnr, metav1.UpdateOptions{})
   376  				assert.NoError(t, err)
   377  			}
   378  			for _, node := range tc.deleteNodes {
   379  				err = controlCtx.Client.KubeClient.CoreV1().Nodes().Delete(ctx, node, metav1.DeleteOptions{})
   380  				assert.NoError(t, err)
   381  			}
   382  			for _, config := range tc.deleteConfigs {
   383  				err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Delete(ctx, config, metav1.DeleteOptions{})
   384  				assert.NoError(t, err)
   385  			}
   386  			time.Sleep(6 * time.Second)
   387  
   388  			for nodeName, annotations := range tc.result {
   389  				for k, v := range annotations {
   390  					node, err := nocController.nodeLister.Get(nodeName)
   391  					assert.NoError(t, err)
   392  					assert.Equal(t, v, node.Annotations[k], fmt.Sprintf("node: %v, k: %v, v: %v, actual: %v", nodeName, k, v, node.Annotations[k]))
   393  				}
   394  			}
   395  		})
   396  	}
   397  }
   398  
   399  func TestRun(t *testing.T) {
   400  	t.Parallel()
   401  
   402  	for _, tc := range testCases {
   403  		tc := tc
   404  		t.Run(tc.name, func(t *testing.T) {
   405  			t.Parallel()
   406  
   407  			fss := &cliflag.NamedFlagSets{}
   408  			nocOptions := options.NewOvercommitOptions()
   409  			nocOptions.AddFlags(fss)
   410  			nocConf := controller.NewOvercommitConfig()
   411  			_ = nocOptions.ApplyTo(nocConf)
   412  
   413  			genericConf := &generic.GenericConfiguration{}
   414  
   415  			controlCtx, err := katalyst_base.GenerateFakeGenericContext()
   416  			assert.NoError(t, err)
   417  
   418  			ctx, cancel := context.WithCancel(context.Background())
   419  			defer cancel()
   420  			nocController, err := NewNodeOvercommitController(ctx, controlCtx, genericConf, nocConf)
   421  			assert.NoError(t, err)
   422  
   423  			for _, node := range tc.initNodes {
   424  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{})
   425  				assert.NoError(t, err)
   426  			}
   427  			for _, cnr := range tc.initCNR {
   428  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Create(ctx, cnr, metav1.CreateOptions{})
   429  				assert.NoError(t, err)
   430  			}
   431  			for _, config := range tc.initConfigs {
   432  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Create(ctx, config, metav1.CreateOptions{})
   433  				assert.NoError(t, err)
   434  			}
   435  
   436  			controlCtx.StartInformer(nocController.ctx)
   437  
   438  			go nocController.Run()
   439  			time.Sleep(1 * time.Second)
   440  
   441  			ret, err := nocController.nodeLister.Get("node1")
   442  			assert.NoError(t, err)
   443  			fmt.Println(ret)
   444  
   445  			for _, node := range tc.addNodes {
   446  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Create(ctx, node, metav1.CreateOptions{})
   447  				assert.NoError(t, err)
   448  			}
   449  			for _, config := range tc.addConfigs {
   450  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Create(ctx, config, metav1.CreateOptions{})
   451  				assert.NoError(t, err)
   452  			}
   453  			for _, cnr := range tc.addCNR {
   454  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Create(ctx, cnr, metav1.CreateOptions{})
   455  				assert.NoError(t, err)
   456  			}
   457  			for _, node := range tc.updateNodes {
   458  				_, err = controlCtx.Client.KubeClient.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
   459  				assert.NoError(t, err)
   460  			}
   461  			for _, config := range tc.updateConfigs {
   462  				_, err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Update(ctx, config, metav1.UpdateOptions{})
   463  				assert.NoError(t, err)
   464  			}
   465  			for _, cnr := range tc.updateCNR {
   466  				_, err = controlCtx.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Update(ctx, cnr, metav1.UpdateOptions{})
   467  				assert.NoError(t, err)
   468  			}
   469  			for _, node := range tc.deleteNodes {
   470  				err = controlCtx.Client.KubeClient.CoreV1().Nodes().Delete(ctx, node, metav1.DeleteOptions{})
   471  				assert.NoError(t, err)
   472  			}
   473  			for _, config := range tc.deleteConfigs {
   474  				err = controlCtx.Client.InternalClient.OvercommitV1alpha1().NodeOvercommitConfigs().Delete(ctx, config, metav1.DeleteOptions{})
   475  				assert.NoError(t, err)
   476  			}
   477  
   478  			time.Sleep(2 * time.Second)
   479  			for nodeName, annotations := range tc.result {
   480  				for k, v := range annotations {
   481  					node, err := nocController.nodeLister.Get(nodeName)
   482  					assert.NoError(t, err)
   483  					if v == "1" {
   484  						if _, ok := node.Annotations[k]; ok {
   485  							assert.Equal(t, v, node.Annotations[k])
   486  						}
   487  					}
   488  					assert.Equal(t, v, node.Annotations[k], fmt.Sprintf("node: %v, k: %v, v: %v, actual: %v", nodeName, k, v, node.Annotations[k]))
   489  				}
   490  			}
   491  		})
   492  	}
   493  }
   494  
   495  func TestNodeOvercommitResource(t *testing.T) {
   496  	t.Parallel()
   497  	testCases := []struct {
   498  		name          string
   499  		cpuOvercommit string
   500  		memOvercommit string
   501  		kcnr          *v1alpha12.CustomNodeResource
   502  		node          *corev1.Node
   503  		expectRes     string
   504  		expectMemRes  string
   505  	}{
   506  		{
   507  			name:          "cpu overcommit less than 1",
   508  			cpuOvercommit: "1",
   509  			memOvercommit: "1",
   510  			kcnr: &v1alpha12.CustomNodeResource{
   511  				ObjectMeta: metav1.ObjectMeta{
   512  					Name: "testNode1",
   513  					Annotations: map[string]string{
   514  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "none",
   515  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   516  						"katalyst.kubewharf.io/guaranteed_cpus":           "4",
   517  					},
   518  				},
   519  			},
   520  			node: &corev1.Node{
   521  				ObjectMeta: metav1.ObjectMeta{
   522  					Name: "testNode1",
   523  					Annotations: map[string]string{
   524  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   525  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   526  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   527  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   528  					},
   529  				},
   530  			},
   531  			expectRes:    "15600m",
   532  			expectMemRes: "29258114498560m",
   533  		},
   534  		{
   535  			name:          "kcnr without annotation",
   536  			cpuOvercommit: "1",
   537  			memOvercommit: "1",
   538  			kcnr: &v1alpha12.CustomNodeResource{
   539  				ObjectMeta: metav1.ObjectMeta{
   540  					Name: "testNode1",
   541  				},
   542  			},
   543  			node: &corev1.Node{
   544  				ObjectMeta: metav1.ObjectMeta{
   545  					Name: "testNode1",
   546  					Annotations: map[string]string{
   547  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   548  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   549  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   550  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   551  					},
   552  				},
   553  			},
   554  			expectRes:    "15600m",
   555  			expectMemRes: "29258114498560m",
   556  		},
   557  		{
   558  			name:          "wrong overcommit",
   559  			cpuOvercommit: "xx",
   560  			memOvercommit: "xx",
   561  			kcnr: &v1alpha12.CustomNodeResource{
   562  				ObjectMeta: metav1.ObjectMeta{
   563  					Name: "testNode1",
   564  					Annotations: map[string]string{
   565  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "none",
   566  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   567  						"katalyst.kubewharf.io/guaranteed_cpus":           "4",
   568  					},
   569  				},
   570  			},
   571  			node: &corev1.Node{
   572  				ObjectMeta: metav1.ObjectMeta{
   573  					Name: "testNode1",
   574  					Annotations: map[string]string{
   575  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   576  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   577  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   578  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   579  					},
   580  				},
   581  			},
   582  			expectRes:    "15600m",
   583  			expectMemRes: "29258114498560m",
   584  		},
   585  		{
   586  			name:          "cpu manager off",
   587  			cpuOvercommit: "1.2",
   588  			memOvercommit: "1.2",
   589  			kcnr: &v1alpha12.CustomNodeResource{
   590  				ObjectMeta: metav1.ObjectMeta{
   591  					Name: "testNode1",
   592  					Annotations: map[string]string{
   593  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "none",
   594  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   595  						"katalyst.kubewharf.io/guaranteed_cpus":           "4",
   596  					},
   597  				},
   598  			},
   599  			node: &corev1.Node{
   600  				ObjectMeta: metav1.ObjectMeta{
   601  					Name: "testNode1",
   602  					Annotations: map[string]string{
   603  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   604  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   605  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   606  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   607  					},
   608  				},
   609  			},
   610  			expectRes:    "18720m",
   611  			expectMemRes: "35109737398",
   612  		},
   613  		{
   614  			name:          "guaranteed cpu none",
   615  			cpuOvercommit: "1.2",
   616  			memOvercommit: "1.2",
   617  			kcnr: &v1alpha12.CustomNodeResource{
   618  				ObjectMeta: metav1.ObjectMeta{
   619  					Name: "testNode1",
   620  					Annotations: map[string]string{
   621  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "static",
   622  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   623  					},
   624  				},
   625  			},
   626  			node: &corev1.Node{
   627  				ObjectMeta: metav1.ObjectMeta{
   628  					Name: "testNode1",
   629  					Annotations: map[string]string{
   630  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   631  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   632  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   633  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   634  					},
   635  				},
   636  			},
   637  			expectRes:    "18720m",
   638  			expectMemRes: "35109737398",
   639  		},
   640  		{
   641  			name:          "wrong guaranteed cpu",
   642  			cpuOvercommit: "1.2",
   643  			memOvercommit: "1",
   644  			kcnr: &v1alpha12.CustomNodeResource{
   645  				ObjectMeta: metav1.ObjectMeta{
   646  					Name: "testNode1",
   647  					Annotations: map[string]string{
   648  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "static",
   649  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   650  						"katalyst.kubewharf.io/guaranteed_cpus":           "xx",
   651  					},
   652  				},
   653  			},
   654  			node: &corev1.Node{
   655  				ObjectMeta: metav1.ObjectMeta{
   656  					Name: "testNode1",
   657  					Annotations: map[string]string{
   658  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   659  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   660  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   661  						"katalyst.kubewharf.io/original_capacity_memory":    "32612508Ki",
   662  					},
   663  				},
   664  			},
   665  			expectRes:    "18720m",
   666  			expectMemRes: "29258114498560m",
   667  		},
   668  		{
   669  			name:          "origin allocatable missing",
   670  			cpuOvercommit: "1.2",
   671  			kcnr: &v1alpha12.CustomNodeResource{
   672  				ObjectMeta: metav1.ObjectMeta{
   673  					Name: "testNode1",
   674  					Annotations: map[string]string{
   675  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "static",
   676  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   677  						"katalyst.kubewharf.io/guaranteed_cpus":           "4",
   678  					},
   679  				},
   680  			},
   681  			node: &corev1.Node{
   682  				ObjectMeta: metav1.ObjectMeta{
   683  					Name: "testNode1",
   684  					Annotations: map[string]string{
   685  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   686  						"katalyst.kubewharf.io/original_allocatable_memory": "29258114498560m",
   687  					},
   688  				},
   689  			},
   690  			expectRes:    "",
   691  			expectMemRes: "",
   692  		},
   693  		{
   694  			name:          "origin capacity missing",
   695  			cpuOvercommit: "1.2",
   696  			kcnr: &v1alpha12.CustomNodeResource{
   697  				ObjectMeta: metav1.ObjectMeta{
   698  					Name: "testNode1",
   699  					Annotations: map[string]string{
   700  						"katalyst.kubewharf.io/overcommit_cpu_manager":    "static",
   701  						"katalyst.kubewharf.io/overcommit_memory_manager": "None",
   702  						"katalyst.kubewharf.io/guaranteed_cpus":           "4",
   703  					},
   704  				},
   705  			},
   706  			node: &corev1.Node{
   707  				ObjectMeta: metav1.ObjectMeta{
   708  					Name: "testNode1",
   709  					Annotations: map[string]string{
   710  						"katalyst.kubewharf.io/original_allocatable_cpu": "15600m",
   711  					},
   712  				},
   713  			},
   714  			expectRes:    "",
   715  			expectMemRes: "",
   716  		},
   717  		{
   718  			name:          "large memory allocatable",
   719  			cpuOvercommit: "1.2",
   720  			memOvercommit: "2",
   721  			kcnr: &v1alpha12.CustomNodeResource{
   722  				ObjectMeta: metav1.ObjectMeta{
   723  					Name:        "testNode1",
   724  					Annotations: map[string]string{},
   725  				},
   726  			},
   727  			node: &corev1.Node{
   728  				ObjectMeta: metav1.ObjectMeta{
   729  					Name: "testNode1",
   730  					Annotations: map[string]string{
   731  						"katalyst.kubewharf.io/original_allocatable_cpu":    "15600m",
   732  						"katalyst.kubewharf.io/original_capacity_cpu":       "16000m",
   733  						"katalyst.kubewharf.io/original_allocatable_memory": "1Ei",
   734  						"katalyst.kubewharf.io/original_capacity_memory":    "1Ei",
   735  					},
   736  				},
   737  			},
   738  			expectRes:    "18720m",
   739  			expectMemRes: "2Ei",
   740  		},
   741  	}
   742  
   743  	for _, tc := range testCases {
   744  		tc := tc
   745  		t.Run(tc.name, func(t *testing.T) {
   746  			t.Parallel()
   747  			gc, err := katalyst_base.GenerateFakeGenericContext()
   748  			assert.NoError(t, err)
   749  			_, err = gc.Client.InternalClient.NodeV1alpha1().CustomNodeResources().Create(context.TODO(), tc.kcnr, metav1.CreateOptions{})
   750  			assert.NoError(t, err)
   751  
   752  			fss := &cliflag.NamedFlagSets{}
   753  			nocOptions := options.NewOvercommitOptions()
   754  			nocOptions.AddFlags(fss)
   755  			nocConf := controller.NewOvercommitConfig()
   756  			_ = nocOptions.ApplyTo(nocConf)
   757  
   758  			genericConf := &generic.GenericConfiguration{}
   759  
   760  			ctx, cancel := context.WithCancel(context.Background())
   761  			defer cancel()
   762  			nocController, err := NewNodeOvercommitController(ctx, gc, genericConf, nocConf)
   763  			assert.NoError(t, err)
   764  			gc.StartInformer(nocController.ctx)
   765  
   766  			go nocController.Run()
   767  			time.Sleep(500 * time.Millisecond)
   768  
   769  			cpuOvercommitValue, _ := strconv.ParseFloat(tc.cpuOvercommit, 64)
   770  			allocatable, _ := nocController.nodeOvercommitResource(tc.node, cpuOvercommitValue, corev1.ResourceCPU, consts.NodeAnnotationOriginalAllocatableCPUKey, consts.NodeAnnotationOriginalCapacityCPUKey)
   771  			assert.Equal(t, tc.expectRes, allocatable)
   772  
   773  			memOvercommitValue, _ := strconv.ParseFloat(tc.memOvercommit, 64)
   774  			allocatable, _ = nocController.nodeOvercommitResource(tc.node, memOvercommitValue, corev1.ResourceMemory, consts.NodeAnnotationOriginalAllocatableMemoryKey, consts.NodeAnnotationOriginalCapacityMemoryKey)
   775  			assert.Equal(t, tc.expectMemRes, allocatable)
   776  		})
   777  	}
   778  }