@@ -34,6 +34,7 @@ import (
34
34
"k8s.io/apimachinery/pkg/types"
35
35
"k8s.io/apimachinery/pkg/util/dump"
36
36
"k8s.io/apimachinery/pkg/util/sets"
37
+ "k8s.io/utils/ptr"
37
38
38
39
basemetrics "k8s.io/component-base/metrics"
39
40
"k8s.io/kubernetes/pkg/proxy/metrics"
@@ -133,9 +134,9 @@ type hcPayload struct {
133
134
}
134
135
135
136
type healthzPayload struct {
136
- LastUpdated string
137
- CurrentTime string
138
- NodeHealthy bool
137
+ LastUpdated string
138
+ CurrentTime string
139
+ NodeEligible * bool
139
140
}
140
141
141
142
type fakeProxyHealthChecker struct {
@@ -479,23 +480,30 @@ func TestHealthzServer(t *testing.T) {
479
480
tracking503 : 0 ,
480
481
}
481
482
482
- testProxyHealthUpdater (hs , hsTest , fakeClock , t )
483
+ var expectedPayload healthzPayload
484
+ // testProxyHealthUpdater only asserts on proxy health, without considering node eligibility
485
+ // defaulting node health to true for testing.
486
+ testProxyHealthUpdater (hs , hsTest , fakeClock , ptr .To (true ), t )
483
487
484
488
// Should return 200 "OK" if we've synced a node, tainted in any other way
485
489
hs .SyncNode (makeNode (tweakTainted ("other" )))
486
- testHTTPHandler (hsTest , http .StatusOK , t )
490
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : ptr .To (true )}
491
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
487
492
488
493
// Should return 503 "ServiceUnavailable" if we've synced a ToBeDeletedTaint node
489
494
hs .SyncNode (makeNode (tweakTainted (ToBeDeletedTaint )))
490
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
495
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : ptr .To (false )}
496
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
491
497
492
498
// Should return 200 "OK" if we've synced a node, tainted in any other way
493
499
hs .SyncNode (makeNode (tweakTainted ("other" )))
494
- testHTTPHandler (hsTest , http .StatusOK , t )
500
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : ptr .To (true )}
501
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
495
502
496
503
// Should return 503 "ServiceUnavailable" if we've synced a deleted node
497
504
hs .SyncNode (makeNode (tweakDeleted ()))
498
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
505
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : ptr .To (false )}
506
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
499
507
}
500
508
501
509
func TestLivezServer (t * testing.T ) {
@@ -514,23 +522,30 @@ func TestLivezServer(t *testing.T) {
514
522
tracking503 : 0 ,
515
523
}
516
524
517
- testProxyHealthUpdater (hs , hsTest , fakeClock , t )
525
+ var expectedPayload healthzPayload
526
+ // /livez doesn't have a concept of "nodeEligible", keeping the value
527
+ // for node eligibility nil.
528
+ testProxyHealthUpdater (hs , hsTest , fakeClock , nil , t )
518
529
519
530
// Should return 200 "OK" irrespective of node syncs
520
531
hs .SyncNode (makeNode (tweakTainted ("other" )))
521
- testHTTPHandler (hsTest , http .StatusOK , t )
532
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String ()}
533
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
522
534
523
535
// Should return 200 "OK" irrespective of node syncs
524
536
hs .SyncNode (makeNode (tweakTainted (ToBeDeletedTaint )))
525
- testHTTPHandler (hsTest , http .StatusOK , t )
537
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String ()}
538
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
526
539
527
540
// Should return 200 "OK" irrespective of node syncs
528
541
hs .SyncNode (makeNode (tweakTainted ("other" )))
529
- testHTTPHandler (hsTest , http .StatusOK , t )
542
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String ()}
543
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
530
544
531
545
// Should return 200 "OK" irrespective of node syncs
532
546
hs .SyncNode (makeNode (tweakDeleted ()))
533
- testHTTPHandler (hsTest , http .StatusOK , t )
547
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String ()}
548
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
534
549
}
535
550
536
551
type url string
@@ -540,78 +555,121 @@ var (
540
555
livezURL url = "/livez"
541
556
)
542
557
543
- func testProxyHealthUpdater (hs * ProxyHealthServer , hsTest * serverTest , fakeClock * testingclock.FakeClock , t * testing.T ) {
558
+ func testProxyHealthUpdater (hs * ProxyHealthServer , hsTest * serverTest , fakeClock * testingclock.FakeClock , nodeEligible * bool , t * testing.T ) {
559
+ var expectedPayload healthzPayload
560
+ // lastUpdated is used to track the time whenever any of the proxier update is simulated,
561
+ // is used in assertion of the http response.
562
+ var lastUpdated time.Time
563
+
544
564
// Should return 200 "OK" by default.
545
- testHTTPHandler (hsTest , http .StatusOK , t )
565
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
566
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
546
567
547
568
// Should return 200 "OK" after first update for both IPv4 and IPv6 proxiers.
548
569
hs .Updated (v1 .IPv4Protocol )
549
570
hs .Updated (v1 .IPv6Protocol )
550
- testHTTPHandler (hsTest , http .StatusOK , t )
571
+ lastUpdated = fakeClock .Now ()
572
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
573
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
574
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
575
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
551
576
552
577
// Should continue to return 200 "OK" as long as no further updates are queued for any proxier.
553
578
fakeClock .Step (25 * time .Second )
554
- testHTTPHandler (hsTest , http .StatusOK , t )
579
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
580
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
581
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
582
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
555
583
556
584
// Should return 503 "ServiceUnavailable" if IPv4 proxier exceed max update-processing time.
557
585
hs .QueuedUpdate (v1 .IPv4Protocol )
558
586
fakeClock .Step (25 * time .Second )
559
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
587
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
588
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
560
589
561
590
// Should return 200 "OK" after processing update for both IPv4 and IPv6 proxiers.
562
591
hs .Updated (v1 .IPv4Protocol )
563
592
hs .Updated (v1 .IPv6Protocol )
593
+ lastUpdated = fakeClock .Now ()
564
594
fakeClock .Step (5 * time .Second )
565
- testHTTPHandler (hsTest , http .StatusOK , t )
595
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
596
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
597
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
598
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
566
599
567
600
// Should return 503 "ServiceUnavailable" if IPv6 proxier exceed max update-processing time.
568
601
hs .QueuedUpdate (v1 .IPv6Protocol )
569
602
fakeClock .Step (25 * time .Second )
570
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
603
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
604
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
571
605
572
606
// Should return 200 "OK" after processing update for both IPv4 and IPv6 proxiers.
573
607
hs .Updated (v1 .IPv4Protocol )
574
608
hs .Updated (v1 .IPv6Protocol )
609
+ lastUpdated = fakeClock .Now ()
575
610
fakeClock .Step (5 * time .Second )
576
- testHTTPHandler (hsTest , http .StatusOK , t )
611
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
612
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
613
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
614
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
577
615
578
616
// Should return 503 "ServiceUnavailable" if both IPv4 and IPv6 proxiers exceed max update-processing time.
579
617
hs .QueuedUpdate (v1 .IPv4Protocol )
580
618
hs .QueuedUpdate (v1 .IPv6Protocol )
581
619
fakeClock .Step (25 * time .Second )
582
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
620
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
621
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
583
622
584
623
// Should return 200 "OK" after processing update for both IPv4 and IPv6 proxiers.
585
624
hs .Updated (v1 .IPv4Protocol )
586
625
hs .Updated (v1 .IPv6Protocol )
626
+ lastUpdated = fakeClock .Now ()
587
627
fakeClock .Step (5 * time .Second )
588
- testHTTPHandler (hsTest , http .StatusOK , t )
628
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
629
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
630
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
631
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
589
632
590
633
// If IPv6 proxier is late for an update but IPv4 proxier is not then updating IPv4 proxier should have no effect.
591
634
hs .QueuedUpdate (v1 .IPv6Protocol )
592
635
fakeClock .Step (25 * time .Second )
593
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
636
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
637
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
594
638
595
639
hs .Updated (v1 .IPv4Protocol )
596
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
640
+ lastUpdated = fakeClock .Now ()
641
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
642
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
597
643
598
644
hs .Updated (v1 .IPv6Protocol )
599
- testHTTPHandler (hsTest , http .StatusOK , t )
645
+ lastUpdated = fakeClock .Now ()
646
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
647
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
648
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
649
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
600
650
601
651
// If both IPv4 and IPv6 proxiers are late for an update, we shouldn't report 200 "OK" until after both of them update.
602
652
hs .QueuedUpdate (v1 .IPv4Protocol )
603
653
hs .QueuedUpdate (v1 .IPv6Protocol )
604
654
fakeClock .Step (25 * time .Second )
605
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
655
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
656
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
606
657
607
658
hs .Updated (v1 .IPv4Protocol )
608
- testHTTPHandler (hsTest , http .StatusServiceUnavailable , t )
659
+ lastUpdated = fakeClock .Now ()
660
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : lastUpdated .String (), NodeEligible : nodeEligible }
661
+ testHTTPHandler (hsTest , http .StatusServiceUnavailable , expectedPayload , t )
609
662
610
663
hs .Updated (v1 .IPv6Protocol )
611
- testHTTPHandler (hsTest , http .StatusOK , t )
664
+ lastUpdated = fakeClock .Now ()
665
+ // for backward-compatibility returned last_updated is current_time when proxy is healthy,
666
+ // using fakeClock.Now().String() instead of lastUpdated.String() here.
667
+ expectedPayload = healthzPayload {CurrentTime : fakeClock .Now ().String (), LastUpdated : fakeClock .Now ().String (), NodeEligible : nodeEligible }
668
+ testHTTPHandler (hsTest , http .StatusOK , expectedPayload , t )
612
669
}
613
670
614
- func testHTTPHandler (hsTest * serverTest , status int , t * testing.T ) {
671
+ func testHTTPHandler (hsTest * serverTest , status int , expectedPayload healthzPayload , t * testing.T ) {
672
+ t .Helper ()
615
673
handler := hsTest .server .(* fakeHTTPServer ).handler
616
674
req , err := http .NewRequest ("GET" , string (hsTest .url ), nil )
617
675
if err != nil {
@@ -629,17 +687,31 @@ func testHTTPHandler(hsTest *serverTest, status int, t *testing.T) {
629
687
t .Fatal (err )
630
688
}
631
689
690
+ // assert on payload
691
+ if payload .LastUpdated != expectedPayload .LastUpdated {
692
+ t .Errorf ("expected last updated: %s; got: %s" , expectedPayload .LastUpdated , payload .LastUpdated )
693
+ }
694
+ if payload .CurrentTime != expectedPayload .CurrentTime {
695
+ t .Errorf ("expected current time: %s; got: %s" , expectedPayload .CurrentTime , payload .CurrentTime )
696
+ }
697
+
632
698
if status == http .StatusOK {
633
699
hsTest .tracking200 ++
634
700
}
635
701
if status == http .StatusServiceUnavailable {
636
702
hsTest .tracking503 ++
637
703
}
638
704
if hsTest .url == healthzURL {
705
+ if * payload .NodeEligible != * expectedPayload .NodeEligible {
706
+ t .Errorf ("expected node eligible: %v; got: %v" , * payload .NodeEligible , * expectedPayload .NodeEligible )
707
+ }
639
708
testMetricEquals (metrics .ProxyHealthzTotal .WithLabelValues ("200" ), float64 (hsTest .tracking200 ), t )
640
709
testMetricEquals (metrics .ProxyHealthzTotal .WithLabelValues ("503" ), float64 (hsTest .tracking503 ), t )
641
710
}
642
711
if hsTest .url == livezURL {
712
+ if payload .NodeEligible != nil {
713
+ t .Errorf ("expected node eligible nil for %s response" , livezURL )
714
+ }
643
715
testMetricEquals (metrics .ProxyLivezTotal .WithLabelValues ("200" ), float64 (hsTest .tracking200 ), t )
644
716
testMetricEquals (metrics .ProxyLivezTotal .WithLabelValues ("503" ), float64 (hsTest .tracking503 ), t )
645
717
}
0 commit comments