github.com/kubewharf/katalyst-core@v0.5.3/pkg/custom-metric/provider/provider_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 provider 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "net/http/httptest" 24 "strconv" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/stretchr/testify/assert" 30 v1 "k8s.io/api/core/v1" 31 "k8s.io/apimachinery/pkg/api/resource" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/labels" 34 "k8s.io/apimachinery/pkg/runtime" 35 "k8s.io/apimachinery/pkg/runtime/schema" 36 "k8s.io/apimachinery/pkg/types" 37 "k8s.io/metrics/pkg/apis/custom_metrics" 38 "k8s.io/metrics/pkg/apis/external_metrics" 39 "sigs.k8s.io/custom-metrics-apiserver/pkg/provider" 40 41 katalystbase "github.com/kubewharf/katalyst-core/cmd/base" 42 "github.com/kubewharf/katalyst-core/pkg/config/generic" 43 metricconf "github.com/kubewharf/katalyst-core/pkg/config/metric" 44 "github.com/kubewharf/katalyst-core/pkg/custom-metric/store" 45 "github.com/kubewharf/katalyst-core/pkg/custom-metric/store/data" 46 "github.com/kubewharf/katalyst-core/pkg/custom-metric/store/local" 47 "github.com/kubewharf/katalyst-core/pkg/custom-metric/store/remote" 48 "github.com/kubewharf/katalyst-core/pkg/util/native" 49 ) 50 51 func generateStorePodMeta(namespace, name, nameLabel string, port int32) *metav1.PartialObjectMetadata { 52 return &metav1.PartialObjectMetadata{ 53 TypeMeta: metav1.TypeMeta{ 54 APIVersion: "v1", 55 Kind: "Pod", 56 }, 57 ObjectMeta: metav1.ObjectMeta{ 58 Namespace: namespace, 59 Name: name, 60 Labels: map[string]string{ 61 "test": "local-store", 62 "name": nameLabel, 63 }, 64 }, 65 } 66 } 67 68 func generateStoreNodeMeta(name, nameLabel string) *metav1.PartialObjectMetadata { 69 return &metav1.PartialObjectMetadata{ 70 TypeMeta: metav1.TypeMeta{ 71 APIVersion: "v1", 72 Kind: "Node", 73 }, 74 ObjectMeta: metav1.ObjectMeta{ 75 Name: name, 76 Labels: map[string]string{ 77 "name": nameLabel, 78 }, 79 }, 80 } 81 } 82 83 func generateStorePod(namespace, name, nameLabel string, port int32) *v1.Pod { 84 return &v1.Pod{ 85 ObjectMeta: metav1.ObjectMeta{ 86 Namespace: namespace, 87 Name: name, 88 Labels: map[string]string{ 89 "test": "local-store", 90 "name": nameLabel, 91 }, 92 }, 93 Spec: v1.PodSpec{ 94 Containers: []v1.Container{ 95 { 96 Name: "pod-container", 97 Ports: []v1.ContainerPort{ 98 { 99 Name: native.ContainerMetricStorePortName, 100 HostPort: port, 101 }, 102 }, 103 }, 104 }, 105 }, 106 Status: v1.PodStatus{ 107 HostIP: "127.0.0.1", 108 ContainerStatuses: []v1.ContainerStatus{ 109 { 110 Ready: true, 111 }, 112 }, 113 }, 114 } 115 } 116 117 func TestWithLocalStore(t *testing.T) { 118 t.Parallel() 119 120 ctx := context.Background() 121 122 p1 := generateStorePodMeta("ns-1", "pod-1", "full_metric_with_conflict_time", 11) 123 p2 := generateStorePodMeta("ns-2", "pod-2", "full_metric_with_multiple_data", 11) 124 p3 := generateStorePodMeta("ns-3", "pod-3", "full_metric_with_multiple_label", 33) 125 n1 := generateStoreNodeMeta("node-1", "full_metric_with_node") 126 127 baseCtx, err := katalystbase.GenerateFakeGenericContext(nil, nil, nil, []runtime.Object{p1, p2, p3, n1}) 128 assert.NoError(t, err) 129 130 genericConf := &metricconf.GenericMetricConfiguration{ 131 OutOfDataPeriod: time.Second * 10, 132 } 133 storeConf := &metricconf.StoreConfiguration{ 134 ServiceDiscoveryConf: &generic.ServiceDiscoveryConf{ 135 PodSinglePortSDConf: &generic.PodSinglePortSDConf{ 136 PortName: native.ContainerMetricStorePortName, 137 PodLister: labels.SelectorFromSet(map[string]string{ 138 "test": "local-store", 139 }), 140 }, 141 }, 142 PurgePeriod: time.Second * 3, 143 GCPeriod: time.Second * 3, 144 IndexLabelKeys: []string{"name"}, 145 } 146 147 s, err := local.NewLocalMemoryMetricStore(ctx, baseCtx, genericConf, storeConf) 148 assert.NoError(t, err) 149 150 baseCtx.StartInformer(ctx) 151 err = s.Start() 152 assert.NoError(t, err) 153 154 p := NewMetricProviderImp(ctx, baseCtx, s) 155 testProvider(t, p, s, ctx, baseCtx, genericConf, storeConf) 156 } 157 158 func TestWithRemoteStoreOne(t *testing.T) { 159 t.Parallel() 160 161 testWithRemoteStoreWithIndex(t, []int{1}) 162 } 163 164 func TestWithRemoteStoreTwo(t *testing.T) { 165 t.Parallel() 166 167 testWithRemoteStoreWithIndex(t, []int{1, 2}) 168 } 169 170 func TestWithRemoteStoreThree(t *testing.T) { 171 t.Parallel() 172 173 testWithRemoteStoreWithIndex(t, []int{1, 2, 3}) 174 } 175 176 func testWithRemoteStoreWithIndex(t *testing.T, index []int) { 177 ctx := context.Background() 178 179 genericConf := &metricconf.GenericMetricConfiguration{ 180 OutOfDataPeriod: time.Second * 10, 181 } 182 storeConf := &metricconf.StoreConfiguration{ 183 ServiceDiscoveryConf: &generic.ServiceDiscoveryConf{ 184 PodSinglePortSDConf: &generic.PodSinglePortSDConf{ 185 PortName: native.ContainerMetricStorePortName, 186 PodLister: labels.SelectorFromSet(map[string]string{ 187 "test": "local-store", 188 }), 189 }, 190 }, 191 StoreServerReplicaTotal: len(index), 192 GCPeriod: time.Second * 3, 193 PurgePeriod: time.Second * 3, 194 IndexLabelKeys: []string{"name"}, 195 } 196 197 lp1 := generateStorePodMeta("ns-1", "pod-1", "full_metric_with_conflict_time", 11) 198 lp2 := generateStorePodMeta("ns-2", "pod-2", "full_metric_with_multiple_data", 22) 199 lp3 := generateStorePodMeta("ns-3", "pod-3", "full_metric_with_multiple_label", 33) 200 ln1 := generateStoreNodeMeta("node-1", "full_metric_with_node") 201 202 var podList []runtime.Object 203 for i := range index { 204 mux := http.NewServeMux() 205 206 server := httptest.NewServer(mux) 207 t.Logf("server url %v\n", server.URL) 208 209 urlList := strings.Split(server.URL, ":") 210 assert.Equal(t, len(urlList), 3) 211 port, err := strconv.Atoi(strings.TrimSpace(urlList[2])) 212 assert.NoError(t, err) 213 214 baseCtx, err := katalystbase.GenerateFakeGenericContext(nil, nil, nil, []runtime.Object{lp1, lp2, lp3, ln1}) 215 assert.NoError(t, err) 216 baseCtx.Handler = mux 217 218 l, err := local.NewLocalMemoryMetricStore(ctx, baseCtx, genericConf, storeConf) 219 assert.NoError(t, err) 220 baseCtx.StartInformer(ctx) 221 222 err = l.Start() 223 assert.NoError(t, err) 224 l.(*local.LocalMemoryMetricStore).Serve(baseCtx.Handler.(*http.ServeMux)) 225 226 p := generateStorePod("ns-fake", fmt.Sprintf("pod-r-%v", i), fmt.Sprintf("pod-r-%v", i), int32(port)) 227 podList = append(podList, p) 228 } 229 230 baseCtx, err := katalystbase.GenerateFakeGenericContext(podList, nil, nil) 231 assert.NoError(t, err) 232 233 r, err := remote.NewRemoteMemoryMetricStore(ctx, baseCtx, genericConf, storeConf) 234 assert.NoError(t, err) 235 baseCtx.StartInformer(ctx) 236 237 err = r.Start() 238 assert.NoError(t, err) 239 240 p := NewMetricProviderImp(ctx, baseCtx, r) 241 testProvider(t, p, r, ctx, baseCtx, genericConf, storeConf) 242 } 243 244 func testProvider(t *testing.T, p MetricProvider, s store.MetricStore, ctx context.Context, baseCtx *katalystbase.GenericContext, 245 genericConf *metricconf.GenericMetricConfiguration, storeConf *metricconf.StoreConfiguration, 246 ) { 247 var err error 248 249 podGR := schema.GroupVersionResource{Version: "v1", Resource: "pods"}.GroupResource() 250 nodeGR := schema.GroupVersionResource{Version: "v1", Resource: "nodes"}.GroupResource() 251 252 now := time.Now().Add(time.Second * 10) 253 err = s.InsertMetric([]*data.MetricSeries{ 254 { 255 Name: "none_namespace_metric", 256 Labels: map[string]string{ 257 "labels-1": "key-1", 258 "selector_name": "none_namespace_metric", 259 }, 260 Series: []*data.MetricData{ 261 { 262 Data: 1, 263 Timestamp: now.UnixMilli(), 264 }, 265 { 266 Data: 2, 267 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() + time.Second.Milliseconds()*5, 268 }, 269 }, 270 }, 271 { 272 Name: "none_namespace_metric_all_timeout", 273 Labels: map[string]string{ 274 "labels-2": "key-2", 275 "selector_name": "none_namespace_metric_all_timeout", 276 }, 277 Series: []*data.MetricData{ 278 { 279 Data: 2, 280 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() + time.Second.Milliseconds()*5, 281 }, 282 }, 283 }, 284 { 285 Name: "none_object_metric", 286 Labels: map[string]string{ 287 "selector_name": "none_object_metric", 288 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-1", 289 }, 290 Series: []*data.MetricData{ 291 { 292 Data: 19, 293 Timestamp: now.UnixMilli(), 294 }, 295 { 296 Data: 23, 297 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds(), 298 }, 299 }, 300 }, 301 { 302 Name: "invalid_object_metric", 303 Labels: map[string]string{ 304 "selector_name": "invalid_object_metric", 305 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-1", 306 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 307 }, 308 Series: []*data.MetricData{ 309 { 310 Data: 19, 311 Timestamp: now.UnixMilli(), 312 }, 313 }, 314 }, 315 { 316 Name: "object_metric_with_unsupported_obj", 317 Labels: map[string]string{ 318 "selector_name": "object_metric_with_unsupported_obj", 319 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-1", 320 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "deployment", 321 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "dp-1", 322 }, 323 Series: []*data.MetricData{ 324 { 325 Data: 31, 326 Timestamp: now.UnixMilli(), 327 }, 328 }, 329 }, 330 { 331 Name: "full_metric_with_conflict_time", 332 Labels: map[string]string{ 333 "selector_name": "full_metric_with_conflict_time", 334 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-1", 335 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 336 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-1", 337 }, 338 Series: []*data.MetricData{ 339 { 340 Data: 31, 341 Timestamp: now.UnixMilli(), 342 }, 343 { 344 Data: 21, 345 Timestamp: now.UnixMilli(), 346 }, 347 }, 348 }, 349 { 350 Name: "full_metric_with_multiple_data", 351 Labels: map[string]string{ 352 "selector_name": "full_metric_with_multiple_data", 353 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-2", 354 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 355 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-2", 356 }, 357 Series: []*data.MetricData{ 358 { 359 Data: 31, 360 Timestamp: now.UnixMilli(), 361 }, 362 { 363 Data: 44, 364 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*3, 365 }, 366 }, 367 }, 368 { 369 Name: "full_metric_with_multiple_data", 370 Labels: map[string]string{ 371 "selector_name": "full_metric_with_multiple_data", 372 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-2", 373 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 374 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-2", 375 }, 376 Series: []*data.MetricData{ 377 { 378 Data: 34, 379 Timestamp: now.UnixMilli(), 380 }, 381 }, 382 }, 383 { 384 Name: "full_metric_with_multiple_data", 385 Labels: map[string]string{ 386 "selector_name": "full_metric_with_multiple_data", 387 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-2", 388 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 389 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-2", 390 }, 391 Series: []*data.MetricData{ 392 { 393 Data: 86, 394 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2, 395 }, 396 }, 397 }, 398 { 399 Name: "full_metric_with_multiple_label", 400 Labels: map[string]string{ 401 "selector_container": "container1", 402 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-3", 403 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 404 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-3", 405 }, 406 Series: []*data.MetricData{ 407 { 408 Data: 0, 409 Timestamp: now.UnixMilli(), 410 }, 411 { 412 Data: 50, 413 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2, 414 }, 415 { 416 Data: 100, 417 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*4, 418 }, 419 }, 420 }, 421 { 422 Name: "full_metric_with_multiple_label", 423 Labels: map[string]string{ 424 "selector_container": "container2", 425 fmt.Sprintf("%v", data.CustomMetricLabelKeyNamespace): "ns-3", 426 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "pods", 427 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "pod-3", 428 }, 429 Series: []*data.MetricData{ 430 { 431 Data: 100, 432 Timestamp: now.UnixMilli(), 433 }, 434 { 435 Data: 150, 436 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2, 437 }, 438 { 439 Data: 200, 440 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*4, 441 }, 442 }, 443 }, 444 { 445 Name: "full_metric_with_node", 446 Labels: map[string]string{ 447 "selector_name": "full_metric_with_node", 448 fmt.Sprintf("%v", data.CustomMetricLabelKeyObject): "nodes", 449 fmt.Sprintf("%v", data.CustomMetricLabelKeyObjectName): "node-1", 450 }, 451 Series: []*data.MetricData{ 452 { 453 Data: 73, 454 Timestamp: now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2, 455 }, 456 }, 457 }, 458 }) 459 assert.NoError(t, err) 460 461 var ( 462 oneMetric *custom_metrics.MetricValue 463 batchMetric *custom_metrics.MetricValueList 464 metricInfo []provider.CustomMetricInfo 465 466 batchExternal *external_metrics.ExternalMetricValueList 467 externalInfo []provider.ExternalMetricInfo 468 ) 469 470 t.Log("#### 1.1: ListAllMetrics") 471 472 metricInfo = p.ListAllMetrics() 473 assert.Equal(t, 4, len(metricInfo)) 474 assert.ElementsMatch(t, []provider.CustomMetricInfo{ 475 { 476 GroupResource: podGR, 477 Namespaced: true, 478 Metric: "full_metric_with_conflict_time", 479 }, 480 { 481 GroupResource: podGR, 482 Namespaced: true, 483 Metric: "full_metric_with_multiple_data", 484 }, 485 { 486 GroupResource: podGR, 487 Namespaced: true, 488 Metric: "full_metric_with_multiple_label", 489 }, 490 { 491 GroupResource: nodeGR, 492 Namespaced: false, 493 Metric: "full_metric_with_node", 494 }, 495 }, metricInfo) 496 497 t.Log("#### 1.2.1: GetMetricByName for node") 498 499 oneMetric, err = p.GetMetricByName(ctx, types.NamespacedName{ 500 Name: "node-1", 501 }, provider.CustomMetricInfo{ 502 GroupResource: nodeGR, 503 Namespaced: false, 504 Metric: "full_metric_with_node", 505 }, labels.Everything()) 506 assert.NoError(t, err) 507 assert.Equal(t, &custom_metrics.MetricValue{ 508 DescribedObject: custom_metrics.ObjectReference{ 509 Name: "node-1", 510 Kind: "nodes", 511 }, 512 Metric: custom_metrics.MetricIdentifier{ 513 Name: "full_metric_with_node", 514 Selector: &metav1.LabelSelector{ 515 MatchLabels: map[string]string{ 516 "name": "full_metric_with_node", 517 }, 518 }, 519 }, 520 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2)), 521 Value: resource.MustParse("73"), 522 }, oneMetric) 523 524 t.Log("#### 1.2.2: GetMetricByName for pod") 525 526 oneMetric, err = p.GetMetricByName(ctx, types.NamespacedName{ 527 Namespace: "ns-1", 528 Name: "pod-1", 529 }, provider.CustomMetricInfo{ 530 GroupResource: podGR, 531 Namespaced: false, 532 Metric: "full_metric_with_conflict_time", 533 }, labels.SelectorFromSet(labels.Set(map[string]string{ 534 "name": "full_metric_with_conflict_time", 535 }))) 536 assert.NoError(t, err) 537 assert.Equal(t, &custom_metrics.MetricValue{ 538 DescribedObject: custom_metrics.ObjectReference{ 539 Namespace: "ns-1", 540 Name: "pod-1", 541 Kind: "pods", 542 }, 543 Metric: custom_metrics.MetricIdentifier{ 544 Name: "full_metric_with_conflict_time", 545 Selector: &metav1.LabelSelector{ 546 MatchLabels: map[string]string{ 547 "name": "full_metric_with_conflict_time", 548 }, 549 }, 550 }, 551 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 552 Value: resource.MustParse("31"), 553 }, oneMetric) 554 555 t.Log("#### 1.3.1: GetMetricBySelector empty ns") 556 557 batchMetric, err = p.GetMetricBySelector(ctx, "", labels.Everything(), provider.CustomMetricInfo{GroupResource: nodeGR}, labels.Everything()) 558 assert.NoError(t, err) 559 assert.Equal(t, 1, len(batchMetric.Items)) 560 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 561 { 562 DescribedObject: custom_metrics.ObjectReference{ 563 Name: "node-1", 564 Kind: "nodes", 565 }, 566 Metric: custom_metrics.MetricIdentifier{ 567 Name: "full_metric_with_node", 568 Selector: &metav1.LabelSelector{ 569 MatchLabels: map[string]string{ 570 "name": "full_metric_with_node", 571 }, 572 }, 573 }, 574 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2)), 575 Value: resource.MustParse("73"), 576 }, 577 }, batchMetric.Items) 578 579 t.Log("#### 1.3.2: GetMetricBySelector byLabel") 580 batchMetric, err = p.GetMetricBySelector(ctx, "ns-2", 581 labels.SelectorFromSet(labels.Set{"name": "full_metric_with_multiple_data"}), 582 provider.CustomMetricInfo{Metric: "full_metric_with_multiple_data", GroupResource: podGR}, labels.Everything()) 583 assert.NoError(t, err) 584 assert.Equal(t, 3, len(batchMetric.Items)) 585 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 586 { 587 DescribedObject: custom_metrics.ObjectReference{ 588 Namespace: "ns-2", 589 Name: "pod-2", 590 Kind: "pods", 591 }, 592 Metric: custom_metrics.MetricIdentifier{ 593 Name: "full_metric_with_multiple_data", 594 Selector: &metav1.LabelSelector{ 595 MatchLabels: map[string]string{ 596 "name": "full_metric_with_multiple_data", 597 }, 598 }, 599 }, 600 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 601 Value: resource.MustParse("31"), 602 }, 603 { 604 DescribedObject: custom_metrics.ObjectReference{ 605 Namespace: "ns-2", 606 Name: "pod-2", 607 Kind: "pods", 608 }, 609 Metric: custom_metrics.MetricIdentifier{ 610 Name: "full_metric_with_multiple_data", 611 Selector: &metav1.LabelSelector{ 612 MatchLabels: map[string]string{ 613 "name": "full_metric_with_multiple_data", 614 }, 615 }, 616 }, 617 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*3)), 618 Value: resource.MustParse("44"), 619 }, 620 { 621 DescribedObject: custom_metrics.ObjectReference{ 622 Namespace: "ns-2", 623 Name: "pod-2", 624 Kind: "pods", 625 }, 626 Metric: custom_metrics.MetricIdentifier{ 627 Name: "full_metric_with_multiple_data", 628 Selector: &metav1.LabelSelector{ 629 MatchLabels: map[string]string{ 630 "name": "full_metric_with_multiple_data", 631 }, 632 }, 633 }, 634 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2)), 635 Value: resource.MustParse("86"), 636 }, 637 }, batchMetric.Items) 638 639 t.Log("#### 1.3.3: GetMetricBySelector ns-1") 640 641 batchMetric, err = p.GetMetricBySelector(ctx, "ns-1", labels.Everything(), provider.CustomMetricInfo{GroupResource: podGR}, labels.Everything()) 642 assert.NoError(t, err) 643 assert.Equal(t, 1, len(batchMetric.Items)) 644 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 645 { 646 DescribedObject: custom_metrics.ObjectReference{ 647 Namespace: "ns-1", 648 Name: "pod-1", 649 Kind: "pods", 650 }, 651 Metric: custom_metrics.MetricIdentifier{ 652 Name: "full_metric_with_conflict_time", 653 Selector: &metav1.LabelSelector{ 654 MatchLabels: map[string]string{ 655 "name": "full_metric_with_conflict_time", 656 }, 657 }, 658 }, 659 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 660 Value: resource.MustParse("31"), 661 }, 662 }, batchMetric.Items) 663 664 t.Log("#### 1.3.4: GetMetricBySelector ns-2") 665 666 batchMetric, err = p.GetMetricBySelector(ctx, "ns-2", labels.Everything(), provider.CustomMetricInfo{GroupResource: podGR}, labels.Everything()) 667 assert.NoError(t, err) 668 assert.Equal(t, 3, len(batchMetric.Items)) 669 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 670 { 671 DescribedObject: custom_metrics.ObjectReference{ 672 Namespace: "ns-2", 673 Name: "pod-2", 674 Kind: "pods", 675 }, 676 Metric: custom_metrics.MetricIdentifier{ 677 Name: "full_metric_with_multiple_data", 678 Selector: &metav1.LabelSelector{ 679 MatchLabels: map[string]string{ 680 "name": "full_metric_with_multiple_data", 681 }, 682 }, 683 }, 684 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 685 Value: resource.MustParse("31"), 686 }, 687 { 688 DescribedObject: custom_metrics.ObjectReference{ 689 Namespace: "ns-2", 690 Name: "pod-2", 691 Kind: "pods", 692 }, 693 Metric: custom_metrics.MetricIdentifier{ 694 Name: "full_metric_with_multiple_data", 695 Selector: &metav1.LabelSelector{ 696 MatchLabels: map[string]string{ 697 "name": "full_metric_with_multiple_data", 698 }, 699 }, 700 }, 701 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*3)), 702 Value: resource.MustParse("44"), 703 }, 704 { 705 DescribedObject: custom_metrics.ObjectReference{ 706 Namespace: "ns-2", 707 Name: "pod-2", 708 Kind: "pods", 709 }, 710 Metric: custom_metrics.MetricIdentifier{ 711 Name: "full_metric_with_multiple_data", 712 Selector: &metav1.LabelSelector{ 713 MatchLabels: map[string]string{ 714 "name": "full_metric_with_multiple_data", 715 }, 716 }, 717 }, 718 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() - time.Second.Milliseconds()*2)), 719 Value: resource.MustParse("86"), 720 }, 721 }, batchMetric.Items) 722 723 t.Log("#### 1.4: ListAllExternalMetrics") 724 725 externalInfo = p.ListAllExternalMetrics() 726 assert.Equal(t, 3, len(externalInfo)) 727 assert.ElementsMatch(t, []provider.ExternalMetricInfo{ 728 { 729 Metric: "none_namespace_metric", 730 }, 731 { 732 Metric: "none_namespace_metric_all_timeout", 733 }, 734 { 735 Metric: "none_object_metric", 736 }, 737 }, externalInfo) 738 739 t.Log("#### 1.5.1: GetExternalMetric empty ns") 740 741 batchExternal, err = p.GetExternalMetric(ctx, "", labels.Everything(), provider.ExternalMetricInfo{}) 742 assert.NoError(t, err) 743 assert.Equal(t, 3, len(batchExternal.Items)) 744 assert.ElementsMatch(t, []external_metrics.ExternalMetricValue{ 745 { 746 MetricName: "none_namespace_metric", 747 MetricLabels: map[string]string{ 748 "name": "none_namespace_metric", 749 }, 750 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 751 Value: resource.MustParse("1"), 752 }, 753 { 754 MetricName: "none_namespace_metric", 755 MetricLabels: map[string]string{ 756 "name": "none_namespace_metric", 757 }, 758 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() + time.Second.Milliseconds()*5)), 759 Value: resource.MustParse("2"), 760 }, 761 { 762 MetricName: "none_namespace_metric_all_timeout", 763 MetricLabels: map[string]string{ 764 "name": "none_namespace_metric_all_timeout", 765 }, 766 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds() + time.Second.Milliseconds()*5)), 767 Value: resource.MustParse("2"), 768 }, 769 }, batchExternal.Items) 770 771 t.Log("#### 1.5.2: GetExternalMetric ns-1") 772 773 batchExternal, err = p.GetExternalMetric(ctx, "ns-1", labels.Everything(), provider.ExternalMetricInfo{}) 774 assert.NoError(t, err) 775 assert.Equal(t, 2, len(batchExternal.Items)) 776 assert.ElementsMatch(t, []external_metrics.ExternalMetricValue{ 777 { 778 MetricName: "none_object_metric", 779 MetricLabels: map[string]string{ 780 "name": "none_object_metric", 781 }, 782 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 783 Value: resource.MustParse("19"), 784 }, 785 { 786 MetricName: "none_object_metric", 787 MetricLabels: map[string]string{ 788 "name": "none_object_metric", 789 }, 790 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli() - genericConf.OutOfDataPeriod.Milliseconds())), 791 Value: resource.MustParse("23"), 792 }, 793 }, batchExternal.Items) 794 795 t.Log("#### 1.6.1 GetAggregatedMetric pod-3") 796 metric, err := p.GetMetricBySelector(ctx, "ns-3", labels.Everything(), 797 provider.CustomMetricInfo{GroupResource: podGR, Metric: "full_metric_with_multiple_label_agg_avg"}, 798 labels.Everything()) 799 assert.NoError(t, err) 800 assert.Equal(t, 1, len(metric.Items)) 801 windowSeconds := int64(14) 802 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 803 { 804 DescribedObject: custom_metrics.ObjectReference{ 805 Namespace: "ns-3", 806 Name: "pod-3", 807 Kind: "pods", 808 }, 809 Metric: custom_metrics.MetricIdentifier{ 810 Name: "full_metric_with_multiple_label_agg_avg", 811 Selector: &metav1.LabelSelector{}, 812 }, 813 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 814 Value: resource.MustParse("100"), 815 WindowSeconds: &windowSeconds, 816 }, 817 }, metric.Items) 818 819 t.Log("#### 1.6.2 GetGroupedAggregatedMetric pod-3") 820 metric, err = p.GetMetricBySelector(ctx, "ns-3", labels.Everything(), 821 provider.CustomMetricInfo{GroupResource: podGR, Metric: "full_metric_with_multiple_label_agg_avg"}, 822 labels.SelectorFromSet(labels.Set{"groupBy": "container"})) 823 assert.NoError(t, err) 824 assert.Equal(t, 2, len(metric.Items)) 825 windowSeconds = int64(14) 826 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 827 { 828 DescribedObject: custom_metrics.ObjectReference{ 829 Namespace: "ns-3", 830 Name: "pod-3", 831 Kind: "pods", 832 }, 833 Metric: custom_metrics.MetricIdentifier{ 834 Name: "full_metric_with_multiple_label_agg_avg", 835 Selector: &metav1.LabelSelector{ 836 MatchLabels: map[string]string{ 837 "container": "container1", 838 }, 839 }, 840 }, 841 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 842 Value: resource.MustParse("50"), 843 WindowSeconds: &windowSeconds, 844 }, 845 { 846 DescribedObject: custom_metrics.ObjectReference{ 847 Namespace: "ns-3", 848 Name: "pod-3", 849 Kind: "pods", 850 }, 851 Metric: custom_metrics.MetricIdentifier{ 852 Name: "full_metric_with_multiple_label_agg_avg", 853 Selector: &metav1.LabelSelector{ 854 MatchLabels: map[string]string{ 855 "container": "container2", 856 }, 857 }, 858 }, 859 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 860 Value: resource.MustParse("150"), 861 WindowSeconds: &windowSeconds, 862 }, 863 }, metric.Items) 864 865 // sleep a while to trigger gc 866 time.Sleep(time.Second * 20) 867 868 t.Log("#### 2.1: ListAllMetrics") 869 870 metricInfo = p.ListAllMetrics() 871 assert.Equal(t, 4, len(metricInfo)) 872 assert.ElementsMatch(t, []provider.CustomMetricInfo{ 873 { 874 GroupResource: podGR, 875 Namespaced: true, 876 Metric: "full_metric_with_conflict_time", 877 }, 878 { 879 GroupResource: podGR, 880 Namespaced: true, 881 Metric: "full_metric_with_multiple_data", 882 }, 883 { 884 GroupResource: podGR, 885 Namespaced: true, 886 Metric: "full_metric_with_multiple_label", 887 }, 888 { 889 GroupResource: nodeGR, 890 Namespaced: false, 891 Metric: "full_metric_with_node", 892 }, 893 }, metricInfo) 894 895 t.Log("#### 2.3.1: GetMetricBySelector empty ns") 896 897 batchMetric, err = p.GetMetricBySelector(ctx, "", labels.Everything(), provider.CustomMetricInfo{GroupResource: podGR}, labels.Everything()) 898 assert.NoError(t, err) 899 assert.Equal(t, 0, len(batchMetric.Items)) 900 901 t.Log("#### 2.3.2: GetMetricBySelector ns-1") 902 903 batchMetric, err = p.GetMetricBySelector(ctx, "ns-1", labels.Everything(), provider.CustomMetricInfo{GroupResource: podGR}, labels.Everything()) 904 assert.NoError(t, err) 905 assert.Equal(t, 1, len(batchMetric.Items)) 906 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 907 { 908 DescribedObject: custom_metrics.ObjectReference{ 909 Namespace: "ns-1", 910 Name: "pod-1", 911 Kind: "pods", 912 }, 913 Metric: custom_metrics.MetricIdentifier{ 914 Name: "full_metric_with_conflict_time", 915 Selector: &metav1.LabelSelector{ 916 MatchLabels: map[string]string{ 917 "name": "full_metric_with_conflict_time", 918 }, 919 }, 920 }, 921 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 922 Value: resource.MustParse("31"), 923 }, 924 }, batchMetric.Items) 925 926 t.Log("#### 2.3.3: GetMetricBySelector ns-2") 927 928 batchMetric, err = p.GetMetricBySelector(ctx, "ns-2", labels.Everything(), provider.CustomMetricInfo{GroupResource: podGR}, labels.Everything()) 929 assert.NoError(t, err) 930 assert.Equal(t, 1, len(batchMetric.Items)) 931 assert.ElementsMatch(t, []custom_metrics.MetricValue{ 932 { 933 DescribedObject: custom_metrics.ObjectReference{ 934 Namespace: "ns-2", 935 Name: "pod-2", 936 Kind: "pods", 937 }, 938 Metric: custom_metrics.MetricIdentifier{ 939 Name: "full_metric_with_multiple_data", 940 Selector: &metav1.LabelSelector{ 941 MatchLabels: map[string]string{ 942 "name": "full_metric_with_multiple_data", 943 }, 944 }, 945 }, 946 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 947 Value: resource.MustParse("31"), 948 }, 949 }, batchMetric.Items) 950 951 t.Log("#### 2.4: ListAllExternalMetrics") 952 953 externalInfo = p.ListAllExternalMetrics() 954 assert.Equal(t, 3, len(externalInfo)) 955 assert.ElementsMatch(t, []provider.ExternalMetricInfo{ 956 { 957 Metric: "none_namespace_metric", 958 }, 959 { 960 Metric: "none_object_metric", 961 }, 962 { 963 Metric: "none_namespace_metric_all_timeout", 964 }, 965 }, externalInfo) 966 967 t.Log("#### 2.5.1: GetExternalMetric empty ns") 968 969 batchExternal, err = p.GetExternalMetric(ctx, "", labels.Everything(), provider.ExternalMetricInfo{}) 970 assert.NoError(t, err) 971 assert.Equal(t, 1, len(batchExternal.Items)) 972 assert.ElementsMatch(t, []external_metrics.ExternalMetricValue{ 973 { 974 MetricName: "none_namespace_metric", 975 MetricLabels: map[string]string{ 976 "name": "none_namespace_metric", 977 }, 978 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 979 Value: resource.MustParse("1"), 980 }, 981 }, batchExternal.Items) 982 983 t.Log("#### 2.5.2: GetExternalMetric ns-1") 984 985 batchExternal, err = p.GetExternalMetric(ctx, "ns-1", labels.Everything(), provider.ExternalMetricInfo{}) 986 assert.NoError(t, err) 987 assert.Equal(t, 1, len(batchExternal.Items)) 988 assert.ElementsMatch(t, []external_metrics.ExternalMetricValue{ 989 { 990 MetricName: "none_object_metric", 991 MetricLabels: map[string]string{ 992 "name": "none_object_metric", 993 }, 994 Timestamp: metav1.NewTime(time.UnixMilli(now.UnixMilli())), 995 Value: resource.MustParse("19"), 996 }, 997 }, batchExternal.Items) 998 999 _ = s.Stop() 1000 }