google.golang.org/grpc@v1.72.2/xds/internal/xdsclient/transport/grpctransport/grpctransport.go (about)

     1  /*
     2   *
     3   * Copyright 2024 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  // Package grpctransport provides an implementation of the transport interface
    19  // using gRPC.
    20  package grpctransport
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  	"time"
    26  
    27  	"google.golang.org/grpc"
    28  	"google.golang.org/grpc/keepalive"
    29  	"google.golang.org/grpc/xds/internal/xdsclient/internal"
    30  	"google.golang.org/grpc/xds/internal/xdsclient/transport"
    31  
    32  	v3adsgrpc "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
    33  	v3adspb "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
    34  	v3lrsgrpc "github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v3"
    35  	v3lrspb "github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v3"
    36  )
    37  
    38  func init() {
    39  	internal.GRPCNewClient = grpc.NewClient
    40  	internal.NewADSStream = func(ctx context.Context, cc *grpc.ClientConn) (v3adsgrpc.AggregatedDiscoveryService_StreamAggregatedResourcesClient, error) {
    41  		return v3adsgrpc.NewAggregatedDiscoveryServiceClient(cc).StreamAggregatedResources(ctx)
    42  	}
    43  }
    44  
    45  // Builder provides a way to build a gRPC-based transport to an xDS server.
    46  type Builder struct{}
    47  
    48  // Build creates a new gRPC-based transport to an xDS server using the provided
    49  // options. This involves creating a grpc.ClientConn to the server identified by
    50  // the server URI in the provided options.
    51  func (b *Builder) Build(opts transport.BuildOptions) (transport.Transport, error) {
    52  	if opts.ServerConfig == nil {
    53  		return nil, fmt.Errorf("ServerConfig field in opts cannot be nil")
    54  	}
    55  
    56  	// NOTE: The bootstrap package ensures that the server_uri and credentials
    57  	// inside the server config are always populated. If we end up using a
    58  	// different type in BuildOptions to specify the server configuration, we
    59  	// must ensure that those fields are not empty before proceeding.
    60  
    61  	// Dial the xDS management server with dial options specified by the server
    62  	// configuration and a static keepalive configuration that is common across
    63  	// gRPC language implementations.
    64  	kpCfg := grpc.WithKeepaliveParams(keepalive.ClientParameters{
    65  		Time:    5 * time.Minute,
    66  		Timeout: 20 * time.Second,
    67  	})
    68  	dopts := append(opts.ServerConfig.DialOptions(), kpCfg)
    69  	dialer := internal.GRPCNewClient.(func(string, ...grpc.DialOption) (*grpc.ClientConn, error))
    70  	cc, err := dialer(opts.ServerConfig.ServerURI(), dopts...)
    71  	if err != nil {
    72  		// An error from a non-blocking dial indicates something serious.
    73  		return nil, fmt.Errorf("failed to create a grpc transport to the management server %q: %v", opts.ServerConfig.ServerURI(), err)
    74  	}
    75  	cc.Connect()
    76  
    77  	return &grpcTransport{cc: cc}, nil
    78  }
    79  
    80  type grpcTransport struct {
    81  	cc *grpc.ClientConn
    82  }
    83  
    84  func (g *grpcTransport) CreateStreamingCall(ctx context.Context, method string) (transport.StreamingCall, error) {
    85  	switch method {
    86  	case v3adsgrpc.AggregatedDiscoveryService_StreamAggregatedResources_FullMethodName:
    87  		return g.newADSStreamingCall(ctx)
    88  	case v3lrsgrpc.LoadReportingService_StreamLoadStats_FullMethodName:
    89  		return g.newLRSStreamingCall(ctx)
    90  	default:
    91  		return nil, fmt.Errorf("unsupported method: %v", method)
    92  	}
    93  }
    94  
    95  func (g *grpcTransport) newADSStreamingCall(ctx context.Context) (transport.StreamingCall, error) {
    96  	newStream := internal.NewADSStream.(func(context.Context, *grpc.ClientConn) (v3adsgrpc.AggregatedDiscoveryService_StreamAggregatedResourcesClient, error))
    97  	stream, err := newStream(ctx, g.cc)
    98  	if err != nil {
    99  		return nil, fmt.Errorf("failed to create an ADS stream: %v", err)
   100  	}
   101  	return &adsStream{stream: stream}, nil
   102  }
   103  
   104  func (g *grpcTransport) newLRSStreamingCall(ctx context.Context) (transport.StreamingCall, error) {
   105  	stream, err := v3lrsgrpc.NewLoadReportingServiceClient(g.cc).StreamLoadStats(ctx)
   106  	if err != nil {
   107  		return nil, fmt.Errorf("failed to create an LRS stream: %v", err)
   108  	}
   109  	return &lrsStream{stream: stream}, nil
   110  }
   111  
   112  func (g *grpcTransport) Close() error {
   113  	return g.cc.Close()
   114  }
   115  
   116  type adsStream struct {
   117  	stream v3adsgrpc.AggregatedDiscoveryService_StreamAggregatedResourcesClient
   118  }
   119  
   120  func (a *adsStream) Send(msg any) error {
   121  	return a.stream.Send(msg.(*v3adspb.DiscoveryRequest))
   122  }
   123  
   124  func (a *adsStream) Recv() (any, error) {
   125  	return a.stream.Recv()
   126  }
   127  
   128  type lrsStream struct {
   129  	stream v3lrsgrpc.LoadReportingService_StreamLoadStatsClient
   130  }
   131  
   132  func (l *lrsStream) Send(msg any) error {
   133  	return l.stream.Send(msg.(*v3lrspb.LoadStatsRequest))
   134  }
   135  
   136  func (l *lrsStream) Recv() (any, error) {
   137  	return l.stream.Recv()
   138  }