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 }