github.com/kubewharf/katalyst-core@v0.5.3/pkg/metaserver/spd/manager_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 spd 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/require" 29 v1 "k8s.io/api/core/v1" 30 apiequality "k8s.io/apimachinery/pkg/api/equality" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "k8s.io/apimachinery/pkg/runtime" 33 "k8s.io/utils/pointer" 34 35 "github.com/kubewharf/katalyst-api/pkg/apis/config/v1alpha1" 36 workloadapis "github.com/kubewharf/katalyst-api/pkg/apis/workload/v1alpha1" 37 "github.com/kubewharf/katalyst-api/pkg/consts" 38 katalyst_base "github.com/kubewharf/katalyst-core/cmd/base" 39 pkgconsts "github.com/kubewharf/katalyst-core/pkg/consts" 40 "github.com/kubewharf/katalyst-core/pkg/metaserver/agent/cnc" 41 "github.com/kubewharf/katalyst-core/pkg/metrics" 42 ) 43 44 func Test_serviceProfilingManager_ServiceBusinessPerformanceLevel(t *testing.T) { 45 t.Parallel() 46 47 type fields struct { 48 nodeName string 49 spd *workloadapis.ServiceProfileDescriptor 50 cnc *v1alpha1.CustomNodeConfig 51 } 52 type args struct { 53 pod *v1.Pod 54 } 55 tests := []struct { 56 name string 57 fields fields 58 args args 59 want PerformanceLevel 60 wantErr bool 61 }{ 62 { 63 name: "service performance is good", 64 fields: fields{ 65 nodeName: "node-1", 66 spd: &workloadapis.ServiceProfileDescriptor{ 67 ObjectMeta: metav1.ObjectMeta{ 68 Name: "spd-1", 69 Namespace: "default", 70 Annotations: map[string]string{ 71 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 72 }, 73 }, 74 Spec: workloadapis.ServiceProfileDescriptorSpec{ 75 BusinessIndicator: []workloadapis.ServiceBusinessIndicatorSpec{ 76 { 77 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 78 Indicators: []workloadapis.Indicator{ 79 { 80 IndicatorLevel: workloadapis.IndicatorLevelLowerBound, 81 Value: 10, 82 }, 83 { 84 IndicatorLevel: workloadapis.IndicatorLevelUpperBound, 85 Value: 100, 86 }, 87 }, 88 }, 89 }, 90 }, 91 Status: workloadapis.ServiceProfileDescriptorStatus{ 92 BusinessStatus: []workloadapis.ServiceBusinessIndicatorStatus{ 93 { 94 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 95 Current: pointer.Float32(40), 96 }, 97 }, 98 }, 99 }, 100 cnc: &v1alpha1.CustomNodeConfig{ 101 ObjectMeta: metav1.ObjectMeta{ 102 Name: "node-1", 103 }, 104 Status: v1alpha1.CustomNodeConfigStatus{ 105 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 106 { 107 ConfigName: "spd-1", 108 ConfigNamespace: "default", 109 Hash: "3c7e3ff3f218", 110 }, 111 }, 112 }, 113 }, 114 }, 115 args: args{ 116 pod: &v1.Pod{ 117 ObjectMeta: metav1.ObjectMeta{ 118 Name: "pod-1", 119 Namespace: "default", 120 Annotations: map[string]string{ 121 consts.PodAnnotationSPDNameKey: "spd-1", 122 }, 123 }, 124 }, 125 }, 126 want: PerformanceLevelGood, 127 }, 128 { 129 name: "service performance large than upper bound", 130 fields: fields{ 131 nodeName: "node-1", 132 spd: &workloadapis.ServiceProfileDescriptor{ 133 ObjectMeta: metav1.ObjectMeta{ 134 Name: "spd-1", 135 Namespace: "default", 136 Annotations: map[string]string{ 137 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 138 }, 139 }, 140 Spec: workloadapis.ServiceProfileDescriptorSpec{ 141 BusinessIndicator: []workloadapis.ServiceBusinessIndicatorSpec{ 142 { 143 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 144 Indicators: []workloadapis.Indicator{ 145 { 146 IndicatorLevel: workloadapis.IndicatorLevelUpperBound, 147 Value: 50, 148 }, 149 }, 150 }, 151 }, 152 }, 153 Status: workloadapis.ServiceProfileDescriptorStatus{ 154 BusinessStatus: []workloadapis.ServiceBusinessIndicatorStatus{ 155 { 156 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 157 Current: pointer.Float32(60), 158 }, 159 }, 160 }, 161 }, 162 cnc: &v1alpha1.CustomNodeConfig{ 163 ObjectMeta: metav1.ObjectMeta{ 164 Name: "node-1", 165 }, 166 Status: v1alpha1.CustomNodeConfigStatus{ 167 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 168 { 169 ConfigName: "spd-1", 170 ConfigNamespace: "default", 171 Hash: "3c7e3ff3f218", 172 }, 173 }, 174 }, 175 }, 176 }, 177 args: args{ 178 pod: &v1.Pod{ 179 ObjectMeta: metav1.ObjectMeta{ 180 Name: "pod-1", 181 Namespace: "default", 182 Annotations: map[string]string{ 183 consts.PodAnnotationSPDNameKey: "spd-1", 184 }, 185 }, 186 }, 187 }, 188 want: PerformanceLevelPoor, 189 }, 190 { 191 name: "service performance lower than lower bound", 192 fields: fields{ 193 nodeName: "node-1", 194 spd: &workloadapis.ServiceProfileDescriptor{ 195 ObjectMeta: metav1.ObjectMeta{ 196 Name: "spd-1", 197 Namespace: "default", 198 Annotations: map[string]string{ 199 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 200 }, 201 }, 202 Spec: workloadapis.ServiceProfileDescriptorSpec{ 203 BusinessIndicator: []workloadapis.ServiceBusinessIndicatorSpec{ 204 { 205 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 206 Indicators: []workloadapis.Indicator{ 207 { 208 IndicatorLevel: workloadapis.IndicatorLevelLowerBound, 209 Value: 20, 210 }, 211 }, 212 }, 213 }, 214 }, 215 Status: workloadapis.ServiceProfileDescriptorStatus{ 216 BusinessStatus: []workloadapis.ServiceBusinessIndicatorStatus{ 217 { 218 Name: workloadapis.ServiceBusinessIndicatorNameRPCLatency, 219 Current: pointer.Float32(10), 220 }, 221 }, 222 }, 223 }, 224 cnc: &v1alpha1.CustomNodeConfig{ 225 ObjectMeta: metav1.ObjectMeta{ 226 Name: "node-1", 227 }, 228 Status: v1alpha1.CustomNodeConfigStatus{ 229 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 230 { 231 ConfigName: "spd-1", 232 ConfigNamespace: "default", 233 Hash: "3c7e3ff3f218", 234 }, 235 }, 236 }, 237 }, 238 }, 239 args: args{ 240 pod: &v1.Pod{ 241 ObjectMeta: metav1.ObjectMeta{ 242 Name: "pod-1", 243 Namespace: "default", 244 Annotations: map[string]string{ 245 consts.PodAnnotationSPDNameKey: "spd-1", 246 }, 247 }, 248 }, 249 }, 250 want: PerformanceLevelPerfect, 251 }, 252 } 253 for _, tt := range tests { 254 tt := tt 255 t.Run(tt.name, func(t *testing.T) { 256 t.Parallel() 257 258 dir, err := ioutil.TempDir("", "checkpoint-Test_serviceProfilingManager_ServiceBusinessPerformanceLevel") 259 require.NoError(t, err) 260 defer os.RemoveAll(dir) 261 262 conf := generateTestConfiguration(t, tt.fields.nodeName, dir) 263 genericCtx, err := katalyst_base.GenerateFakeGenericContext(nil, []runtime.Object{ 264 tt.fields.spd, 265 tt.fields.cnc, 266 }) 267 require.NoError(t, err) 268 269 cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration, genericCtx.Client.InternalClient.ConfigV1alpha1().CustomNodeConfigs()) 270 s, err := NewSPDFetcher(genericCtx.Client, metrics.DummyMetrics{}, cncFetcher, conf) 271 require.NoError(t, err) 272 require.NotNil(t, s) 273 274 m := NewServiceProfilingManager(s) 275 require.NoError(t, err) 276 277 // first get spd add spd key to cache 278 _, _ = s.GetSPD(context.Background(), tt.args.pod.ObjectMeta) 279 go m.Run(context.Background()) 280 time.Sleep(1 * time.Second) 281 282 got, err := m.ServiceBusinessPerformanceLevel(context.Background(), tt.args.pod.ObjectMeta) 283 if (err != nil) != tt.wantErr { 284 t.Errorf("ServiceBusinessPerformanceLevel() error = %v, wantErr %v", err, tt.wantErr) 285 return 286 } 287 if got != tt.want { 288 t.Errorf("ServiceBusinessPerformanceLevel() got = %v, want %v", got, tt.want) 289 } 290 }) 291 } 292 } 293 294 func Test_serviceProfilingManager_ServiceSystemPerformanceTarget(t *testing.T) { 295 t.Parallel() 296 297 type fields struct { 298 nodeName string 299 spd *workloadapis.ServiceProfileDescriptor 300 cnc *v1alpha1.CustomNodeConfig 301 } 302 type args struct { 303 pod *v1.Pod 304 } 305 tests := []struct { 306 name string 307 fields fields 308 args args 309 want IndicatorTarget 310 wantErr bool 311 }{ 312 { 313 name: "service performance is good", 314 fields: fields{ 315 nodeName: "node-1", 316 spd: &workloadapis.ServiceProfileDescriptor{ 317 ObjectMeta: metav1.ObjectMeta{ 318 Name: "spd-1", 319 Namespace: "default", 320 Annotations: map[string]string{ 321 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 322 }, 323 }, 324 Spec: workloadapis.ServiceProfileDescriptorSpec{ 325 SystemIndicator: []workloadapis.ServiceSystemIndicatorSpec{ 326 { 327 Name: workloadapis.ServiceSystemIndicatorNameCPUSchedWait, 328 Indicators: []workloadapis.Indicator{ 329 { 330 IndicatorLevel: workloadapis.IndicatorLevelLowerBound, 331 Value: 10, 332 }, 333 { 334 IndicatorLevel: workloadapis.IndicatorLevelUpperBound, 335 Value: 100, 336 }, 337 }, 338 }, 339 { 340 Name: workloadapis.ServiceSystemIndicatorNameCPI, 341 Indicators: []workloadapis.Indicator{ 342 { 343 IndicatorLevel: workloadapis.IndicatorLevelLowerBound, 344 Value: 1.4, 345 }, 346 { 347 IndicatorLevel: workloadapis.IndicatorLevelUpperBound, 348 Value: 2.4, 349 }, 350 }, 351 }, 352 }, 353 }, 354 }, 355 cnc: &v1alpha1.CustomNodeConfig{ 356 ObjectMeta: metav1.ObjectMeta{ 357 Name: "node-1", 358 }, 359 Status: v1alpha1.CustomNodeConfigStatus{ 360 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 361 { 362 ConfigName: "spd-1", 363 ConfigNamespace: "default", 364 Hash: "3c7e3ff3f218", 365 }, 366 }, 367 }, 368 }, 369 }, 370 args: args{ 371 pod: &v1.Pod{ 372 ObjectMeta: metav1.ObjectMeta{ 373 Name: "pod-1", 374 Namespace: "default", 375 Annotations: map[string]string{ 376 consts.PodAnnotationSPDNameKey: "spd-1", 377 }, 378 }, 379 }, 380 }, 381 want: IndicatorTarget{ 382 string(workloadapis.ServiceSystemIndicatorNameCPUSchedWait): { 383 UpperBound: pointer.Float64(100), 384 LowerBound: pointer.Float64(10), 385 }, 386 string(workloadapis.ServiceSystemIndicatorNameCPI): { 387 UpperBound: pointer.Float64(2.4), 388 LowerBound: pointer.Float64(1.4), 389 }, 390 }, 391 }, 392 } 393 for i, tt := range tests { 394 i := i 395 tt := tt 396 t.Run(tt.name, func(t *testing.T) { 397 t.Parallel() 398 399 dir, err := ioutil.TempDir("", fmt.Sprintf("checkpoint-Test_serviceProfilingManager_ServiceSystemPerformanceTarget_%d", i)) 400 require.NoError(t, err) 401 defer os.RemoveAll(dir) 402 403 conf := generateTestConfiguration(t, tt.fields.nodeName, dir) 404 genericCtx, err := katalyst_base.GenerateFakeGenericContext(nil, []runtime.Object{ 405 tt.fields.spd, 406 tt.fields.cnc, 407 }) 408 require.NoError(t, err) 409 410 cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration, genericCtx.Client.InternalClient.ConfigV1alpha1().CustomNodeConfigs()) 411 s, err := NewSPDFetcher(genericCtx.Client, metrics.DummyMetrics{}, cncFetcher, conf) 412 require.NoError(t, err) 413 require.NotNil(t, s) 414 415 m := NewServiceProfilingManager(s) 416 require.NoError(t, err) 417 418 // first get spd add pod spd key to cache 419 _, _ = s.GetSPD(context.Background(), tt.args.pod.ObjectMeta) 420 go m.Run(context.Background()) 421 time.Sleep(1 * time.Second) 422 423 got, err := m.ServiceSystemPerformanceTarget(context.Background(), tt.args.pod.ObjectMeta) 424 if (err != nil) != tt.wantErr { 425 t.Errorf("ServiceSystemPerformanceTarget() error = %v, wantErr %v", err, tt.wantErr) 426 return 427 } 428 if apiequality.Semantic.DeepEqual(tt.want, got) { 429 t.Errorf("ServiceSystemPerformanceTarget() got = %v, want %v", got, tt.want) 430 } 431 }) 432 } 433 } 434 435 func Test_serviceProfilingManager_ServiceExtendedIndicator(t *testing.T) { 436 t.Parallel() 437 438 type fields struct { 439 nodeName string 440 spd *workloadapis.ServiceProfileDescriptor 441 cnc *v1alpha1.CustomNodeConfig 442 } 443 type args struct { 444 pod *v1.Pod 445 } 446 tests := []struct { 447 name string 448 fields fields 449 args args 450 want *workloadapis.TestExtendedIndicators 451 isBaseline bool 452 wantErr bool 453 }{ 454 { 455 name: "without baseline", 456 fields: fields{ 457 nodeName: "node-1", 458 spd: &workloadapis.ServiceProfileDescriptor{ 459 ObjectMeta: metav1.ObjectMeta{ 460 Name: "spd-1", 461 Namespace: "default", 462 Annotations: map[string]string{ 463 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 464 }, 465 }, 466 Spec: workloadapis.ServiceProfileDescriptorSpec{ 467 ExtendedIndicator: []workloadapis.ServiceExtendedIndicatorSpec{ 468 { 469 Name: "TestExtended", 470 Indicators: runtime.RawExtension{ 471 Object: &workloadapis.TestExtendedIndicators{ 472 Indicators: &workloadapis.TestIndicators{}, 473 }, 474 }, 475 }, 476 }, 477 }, 478 }, 479 cnc: &v1alpha1.CustomNodeConfig{ 480 ObjectMeta: metav1.ObjectMeta{ 481 Name: "node-1", 482 }, 483 Status: v1alpha1.CustomNodeConfigStatus{ 484 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 485 { 486 ConfigName: "spd-1", 487 ConfigNamespace: "default", 488 Hash: "3c7e3ff3f218", 489 }, 490 }, 491 }, 492 }, 493 }, 494 args: args{ 495 pod: &v1.Pod{ 496 ObjectMeta: metav1.ObjectMeta{ 497 Name: "pod-1", 498 Namespace: "default", 499 Annotations: map[string]string{ 500 consts.PodAnnotationSPDNameKey: "spd-1", 501 }, 502 }, 503 }, 504 }, 505 want: &workloadapis.TestExtendedIndicators{ 506 Indicators: &workloadapis.TestIndicators{}, 507 }, 508 }, 509 { 510 name: "with baseline", 511 fields: fields{ 512 nodeName: "node-1", 513 spd: &workloadapis.ServiceProfileDescriptor{ 514 ObjectMeta: metav1.ObjectMeta{ 515 Name: "spd-1", 516 Namespace: "default", 517 Annotations: map[string]string{ 518 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 519 consts.SPDAnnotationExtendedBaselineSentinelKey: "{\"TestExtended\":{\"timeStamp\":\"2023-08-01T00:00:01Z\",\"podName\":\"pod1\"}}", 520 }, 521 }, 522 Spec: workloadapis.ServiceProfileDescriptorSpec{ 523 ExtendedIndicator: []workloadapis.ServiceExtendedIndicatorSpec{ 524 { 525 Name: "TestExtended", 526 BaselinePercent: pointer.Int32(10), 527 Indicators: runtime.RawExtension{ 528 Object: &workloadapis.TestExtendedIndicators{ 529 Indicators: &workloadapis.TestIndicators{}, 530 }, 531 }, 532 }, 533 }, 534 }, 535 }, 536 cnc: &v1alpha1.CustomNodeConfig{ 537 ObjectMeta: metav1.ObjectMeta{ 538 Name: "node-1", 539 }, 540 Status: v1alpha1.CustomNodeConfigStatus{ 541 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 542 { 543 ConfigName: "spd-1", 544 ConfigNamespace: "default", 545 Hash: "3c7e3ff3f218", 546 }, 547 }, 548 }, 549 }, 550 }, 551 args: args{ 552 pod: &v1.Pod{ 553 ObjectMeta: metav1.ObjectMeta{ 554 Name: "pod-1", 555 Namespace: "default", 556 Annotations: map[string]string{ 557 consts.PodAnnotationSPDNameKey: "spd-1", 558 }, 559 }, 560 }, 561 }, 562 want: &workloadapis.TestExtendedIndicators{ 563 Indicators: &workloadapis.TestIndicators{}, 564 }, 565 isBaseline: true, 566 }, 567 { 568 name: "use raw data", 569 fields: fields{ 570 nodeName: "node-1", 571 spd: &workloadapis.ServiceProfileDescriptor{ 572 ObjectMeta: metav1.ObjectMeta{ 573 Name: "spd-1", 574 Namespace: "default", 575 Annotations: map[string]string{ 576 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 577 consts.SPDAnnotationExtendedBaselineSentinelKey: "{\"TestExtended\":{\"timeStamp\":\"2023-08-01T00:00:01Z\",\"podName\":\"pod1\"}}", 578 }, 579 }, 580 Spec: workloadapis.ServiceProfileDescriptorSpec{ 581 ExtendedIndicator: []workloadapis.ServiceExtendedIndicatorSpec{ 582 { 583 Name: "TestExtended", 584 BaselinePercent: pointer.Int32(10), 585 Indicators: runtime.RawExtension{ 586 Raw: func(object runtime.Object) []byte { 587 marshal, err := json.Marshal(object) 588 if err != nil { 589 return nil 590 } 591 return marshal 592 }( 593 &workloadapis.TestExtendedIndicators{ 594 Indicators: &workloadapis.TestIndicators{}, 595 }, 596 ), 597 }, 598 }, 599 }, 600 }, 601 }, 602 cnc: &v1alpha1.CustomNodeConfig{ 603 ObjectMeta: metav1.ObjectMeta{ 604 Name: "node-1", 605 }, 606 Status: v1alpha1.CustomNodeConfigStatus{ 607 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 608 { 609 ConfigName: "spd-1", 610 ConfigNamespace: "default", 611 Hash: "3c7e3ff3f218", 612 }, 613 }, 614 }, 615 }, 616 }, 617 args: args{ 618 pod: &v1.Pod{ 619 ObjectMeta: metav1.ObjectMeta{ 620 Name: "pod-1", 621 Namespace: "default", 622 Annotations: map[string]string{ 623 consts.PodAnnotationSPDNameKey: "spd-1", 624 }, 625 }, 626 }, 627 }, 628 want: &workloadapis.TestExtendedIndicators{ 629 Indicators: &workloadapis.TestIndicators{}, 630 }, 631 isBaseline: true, 632 }, 633 } 634 for _, tt := range tests { 635 tt := tt 636 t.Run(tt.name, func(t *testing.T) { 637 t.Parallel() 638 dir, err := ioutil.TempDir("", "checkpoint-Test_serviceProfilingManager_ServiceExtendedIndicator") 639 require.NoError(t, err) 640 defer os.RemoveAll(dir) 641 642 conf := generateTestConfiguration(t, tt.fields.nodeName, dir) 643 genericCtx, err := katalyst_base.GenerateFakeGenericContext(nil, []runtime.Object{ 644 tt.fields.spd, 645 tt.fields.cnc, 646 }) 647 require.NoError(t, err) 648 649 cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration, genericCtx.Client.InternalClient.ConfigV1alpha1().CustomNodeConfigs()) 650 s, err := NewSPDFetcher(genericCtx.Client, metrics.DummyMetrics{}, cncFetcher, conf) 651 require.NoError(t, err) 652 require.NotNil(t, s) 653 654 m := NewServiceProfilingManager(s) 655 require.NoError(t, err) 656 657 // first get spd add pod spd key to cache 658 _, _ = s.GetSPD(context.Background(), tt.args.pod.ObjectMeta) 659 go m.Run(context.Background()) 660 time.Sleep(1 * time.Second) 661 662 got := &workloadapis.TestExtendedIndicators{} 663 isBaseline, err := m.ServiceExtendedIndicator(context.Background(), tt.args.pod.ObjectMeta, got) 664 if (err != nil) != tt.wantErr { 665 t.Errorf("ServiceExtendedIndicator() error = %v, wantErr %v", err, tt.wantErr) 666 return 667 } 668 if !apiequality.Semantic.DeepEqual(got, tt.want) { 669 t.Errorf("ServiceExtendedIndicator() got = %v, want %v", got, tt.want) 670 } 671 if isBaseline != tt.isBaseline { 672 t.Errorf("ServiceExtendedIndicator() isBaseline = %v, want %v", isBaseline, tt.isBaseline) 673 } 674 }) 675 } 676 } 677 678 func Test_serviceProfilingManager_ServiceBaseline(t *testing.T) { 679 t.Parallel() 680 681 type fields struct { 682 nodeName string 683 spd *workloadapis.ServiceProfileDescriptor 684 cnc *v1alpha1.CustomNodeConfig 685 } 686 type args struct { 687 pod *v1.Pod 688 } 689 tests := []struct { 690 name string 691 fields fields 692 args args 693 isBaseline bool 694 wantErr bool 695 }{ 696 { 697 name: "without baseline", 698 fields: fields{ 699 nodeName: "node-1", 700 spd: &workloadapis.ServiceProfileDescriptor{ 701 ObjectMeta: metav1.ObjectMeta{ 702 Name: "spd-1", 703 Namespace: "default", 704 Annotations: map[string]string{ 705 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 706 }, 707 }, 708 Spec: workloadapis.ServiceProfileDescriptorSpec{}, 709 }, 710 cnc: &v1alpha1.CustomNodeConfig{ 711 ObjectMeta: metav1.ObjectMeta{ 712 Name: "node-1", 713 }, 714 Status: v1alpha1.CustomNodeConfigStatus{ 715 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 716 { 717 ConfigName: "spd-1", 718 ConfigNamespace: "default", 719 Hash: "3c7e3ff3f218", 720 }, 721 }, 722 }, 723 }, 724 }, 725 args: args{ 726 pod: &v1.Pod{ 727 ObjectMeta: metav1.ObjectMeta{ 728 Name: "pod-1", 729 Namespace: "default", 730 Annotations: map[string]string{ 731 consts.PodAnnotationSPDNameKey: "spd-1", 732 }, 733 }, 734 }, 735 }, 736 }, 737 { 738 name: "with baseline", 739 fields: fields{ 740 nodeName: "node-1", 741 spd: &workloadapis.ServiceProfileDescriptor{ 742 ObjectMeta: metav1.ObjectMeta{ 743 Name: "spd-1", 744 Namespace: "default", 745 Annotations: map[string]string{ 746 pkgconsts.ServiceProfileDescriptorAnnotationKeyConfigHash: "3c7e3ff3f218", 747 consts.SPDAnnotationBaselineSentinelKey: "{\"timeStamp\":\"2023-08-01T00:00:01Z\",\"podName\":\"pod1\"}", 748 }, 749 }, 750 Spec: workloadapis.ServiceProfileDescriptorSpec{ 751 BaselinePercent: pointer.Int32(10), 752 }, 753 }, 754 cnc: &v1alpha1.CustomNodeConfig{ 755 ObjectMeta: metav1.ObjectMeta{ 756 Name: "node-1", 757 }, 758 Status: v1alpha1.CustomNodeConfigStatus{ 759 ServiceProfileConfigList: []v1alpha1.TargetConfig{ 760 { 761 ConfigName: "spd-1", 762 ConfigNamespace: "default", 763 Hash: "3c7e3ff3f218", 764 }, 765 }, 766 }, 767 }, 768 }, 769 args: args{ 770 pod: &v1.Pod{ 771 ObjectMeta: metav1.ObjectMeta{ 772 Name: "pod-1", 773 Namespace: "default", 774 Annotations: map[string]string{ 775 consts.PodAnnotationSPDNameKey: "spd-1", 776 }, 777 }, 778 }, 779 }, 780 isBaseline: true, 781 }, 782 } 783 for _, tt := range tests { 784 tt := tt 785 t.Run(tt.name, func(t *testing.T) { 786 t.Parallel() 787 788 dir, err := ioutil.TempDir("", "checkpoint-Test_serviceProfilingManager_ServiceBaseline") 789 require.NoError(t, err) 790 defer os.RemoveAll(dir) 791 792 conf := generateTestConfiguration(t, tt.fields.nodeName, dir) 793 genericCtx, err := katalyst_base.GenerateFakeGenericContext(nil, []runtime.Object{ 794 tt.fields.spd, 795 tt.fields.cnc, 796 }) 797 require.NoError(t, err) 798 799 cncFetcher := cnc.NewCachedCNCFetcher(conf.BaseConfiguration, conf.CNCConfiguration, genericCtx.Client.InternalClient.ConfigV1alpha1().CustomNodeConfigs()) 800 s, err := NewSPDFetcher(genericCtx.Client, metrics.DummyMetrics{}, cncFetcher, conf) 801 require.NoError(t, err) 802 require.NotNil(t, s) 803 804 m := NewServiceProfilingManager(s) 805 require.NoError(t, err) 806 807 // first get spd add pod spd key to cache 808 _, _ = s.GetSPD(context.Background(), tt.args.pod.ObjectMeta) 809 go m.Run(context.Background()) 810 time.Sleep(1 * time.Second) 811 812 isBaseline, err := m.ServiceBaseline(context.Background(), tt.args.pod.ObjectMeta) 813 if (err != nil) != tt.wantErr { 814 t.Errorf("ServiceBaseline() error = %v, wantErr %v", err, tt.wantErr) 815 return 816 } 817 if isBaseline != tt.isBaseline { 818 t.Errorf("ServiceBaseline() isBaseline = %v, want %v", isBaseline, tt.isBaseline) 819 } 820 }) 821 } 822 }