@@ -40,12 +40,17 @@ import (
40
40
41
41
"golang.org/x/net/websocket"
42
42
43
+ "go.opentelemetry.io/otel/propagation"
44
+ sdktrace "go.opentelemetry.io/otel/sdk/trace"
45
+ "go.opentelemetry.io/otel/sdk/trace/tracetest"
46
+ "go.opentelemetry.io/otel/trace"
43
47
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
44
48
"k8s.io/apimachinery/pkg/types"
45
49
utilnet "k8s.io/apimachinery/pkg/util/net"
46
50
"k8s.io/apimachinery/pkg/util/proxy"
47
51
"k8s.io/apimachinery/pkg/util/sets"
48
52
"k8s.io/apiserver/pkg/authentication/user"
53
+ "k8s.io/apiserver/pkg/endpoints/filters"
49
54
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
50
55
"k8s.io/apiserver/pkg/server/egressselector"
51
56
utilflowcontrol "k8s.io/apiserver/pkg/util/flowcontrol"
@@ -54,6 +59,7 @@ import (
54
59
"k8s.io/component-base/metrics/legacyregistry"
55
60
apiregistration "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
56
61
"k8s.io/utils/pointer"
62
+ "k8s.io/utils/ptr"
57
63
)
58
64
59
65
type targetHTTPHandler struct {
@@ -774,6 +780,116 @@ func TestGetContextForNewRequest(t *testing.T) {
774
780
775
781
}
776
782
783
+ func TestTracerProvider (t * testing.T ) {
784
+ fakeRecorder := tracetest .NewSpanRecorder ()
785
+ otelTracer := sdktrace .NewTracerProvider (sdktrace .WithSpanProcessor (fakeRecorder ))
786
+ target := & targetHTTPHandler {}
787
+ user := & user.DefaultInfo {
788
+ Name : "username" ,
789
+ Groups : []string {"one" , "two" },
790
+ }
791
+ path := "/request/path"
792
+ apiService := & apiregistration.APIService {
793
+ ObjectMeta : metav1.ObjectMeta {Name : "v1.foo" },
794
+ Spec : apiregistration.APIServiceSpec {
795
+ Service : & apiregistration.ServiceReference {Name : "test-service" , Namespace : "test-ns" , Port : ptr .To (int32 (443 ))},
796
+ Group : "foo" ,
797
+ Version : "v1" ,
798
+ CABundle : testCACrt ,
799
+ },
800
+ Status : apiregistration.APIServiceStatus {
801
+ Conditions : []apiregistration.APIServiceCondition {
802
+ {Type : apiregistration .Available , Status : apiregistration .ConditionTrue },
803
+ },
804
+ },
805
+ }
806
+ targetServer := httptest .NewUnstartedServer (target )
807
+ serviceCert := svcCrt
808
+ if cert , err := tls .X509KeyPair (serviceCert , svcKey ); err != nil {
809
+ t .Fatalf ("TestTracerProvider: failed to parse key pair: %v" , err )
810
+ } else {
811
+ targetServer .TLS = & tls.Config {Certificates : []tls.Certificate {cert }}
812
+ }
813
+ targetServer .StartTLS ()
814
+ defer targetServer .Close ()
815
+
816
+ serviceResolver := & mockedRouter {destinationHost : targetServer .Listener .Addr ().String ()}
817
+ handler := & proxyHandler {
818
+ localDelegate : http .NewServeMux (),
819
+ serviceResolver : serviceResolver ,
820
+ proxyCurrentCertKeyContent : func () ([]byte , []byte ) { return emptyCert (), emptyCert () },
821
+ tracerProvider : otelTracer ,
822
+ }
823
+
824
+ server := httptest .NewServer (contextHandler (filters .WithTracing (handler , otelTracer ), user ))
825
+ defer server .Close ()
826
+
827
+ handler .updateAPIService (apiService )
828
+ curr := handler .handlingInfo .Load ().(proxyHandlingInfo )
829
+ handler .handlingInfo .Store (curr )
830
+ var propagator propagation.TraceContext
831
+ req , err := http .NewRequest (http .MethodGet , server .URL + path , nil )
832
+ if err != nil {
833
+ t .Errorf ("expected new request: %v" , err )
834
+ return
835
+ }
836
+
837
+ t .Logf ("Sending request: %v" , req )
838
+ _ , err = http .DefaultClient .Do (req )
839
+ if err != nil {
840
+ t .Errorf ("http request failed: %v" , err )
841
+ return
842
+ }
843
+
844
+ t .Log ("Ensure the target server received the traceparent header" )
845
+ id , ok := target .headers ["Traceparent" ]
846
+ if ! ok {
847
+ t .Error ("expected traceparent header" )
848
+ return
849
+ }
850
+
851
+ t .Log ("Get the span context from the traceparent header" )
852
+ h := http.Header {
853
+ "Traceparent" : id ,
854
+ }
855
+ ctx := propagator .Extract (context .Background (), propagation .HeaderCarrier (h ))
856
+ span := trace .SpanFromContext (ctx )
857
+
858
+ t .Log ("Ensure that the span context is valid and remote" )
859
+ if ! span .SpanContext ().IsValid () {
860
+ t .Error ("expected valid span context" )
861
+ return
862
+ }
863
+
864
+ if ! span .SpanContext ().IsRemote () {
865
+ t .Error ("expected remote span context" )
866
+ return
867
+ }
868
+
869
+ t .Log ("Ensure that the span ID and trace ID match the expected values" )
870
+ expectedSpanCtx := fakeRecorder .Ended ()[0 ].SpanContext ()
871
+ if expectedSpanCtx .TraceID () != span .SpanContext ().TraceID () {
872
+ t .Errorf ("expected trace id to match. expected: %v, but got %v" , expectedSpanCtx .TraceID (), span .SpanContext ().TraceID ())
873
+ return
874
+ }
875
+
876
+ if expectedSpanCtx .SpanID () != span .SpanContext ().SpanID () {
877
+ t .Errorf ("expected span id to match. expected: %v, but got: %v" , expectedSpanCtx .SpanID (), span .SpanContext ().SpanID ())
878
+ return
879
+ }
880
+
881
+ t .Log ("Ensure that the expected spans were recorded when sending a request through the proxy" )
882
+ expectedSpanNames := []string {"HTTP GET" , "GET" }
883
+ spanNames := []string {}
884
+ for _ , span := range fakeRecorder .Ended () {
885
+ spanNames = append (spanNames , span .Name ())
886
+ }
887
+ if e , a := expectedSpanNames , spanNames ; ! reflect .DeepEqual (e , a ) {
888
+ t .Errorf ("expected span names %v, got %v" , e , a )
889
+ return
890
+ }
891
+ }
892
+
777
893
func TestNewRequestForProxyWithAuditID (t * testing.T ) {
778
894
tests := []struct {
779
895
name string
0 commit comments