gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/xds/internal/xdsclient/controller/version/v3/client.go (about)

     1  /*
     2   *
     3   * Copyright 2020 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  
    19  // Package v3 provides xDS v3 transport protocol specific functionality.
    20  package v3
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  
    26  	grpc "gitee.com/ks-custle/core-gm/grpc"
    27  	"gitee.com/ks-custle/core-gm/grpc/codes"
    28  	"gitee.com/ks-custle/core-gm/grpc/internal/grpclog"
    29  	"gitee.com/ks-custle/core-gm/grpc/internal/pretty"
    30  	controllerversion "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/controller/version"
    31  	"gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource"
    32  	xdsresourceversion "gitee.com/ks-custle/core-gm/grpc/xds/internal/xdsclient/xdsresource/version"
    33  	"github.com/golang/protobuf/proto"
    34  	statuspb "google.golang.org/genproto/googleapis/rpc/status"
    35  	"google.golang.org/protobuf/types/known/anypb"
    36  
    37  	v3corepb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/config/core/v3"
    38  	v3adsgrpc "gitee.com/ks-custle/core-gm/go-control-plane/envoy/service/discovery/v3"
    39  	v3discoverypb "gitee.com/ks-custle/core-gm/go-control-plane/envoy/service/discovery/v3"
    40  )
    41  
    42  func init() {
    43  	controllerversion.RegisterAPIClientBuilder(xdsresourceversion.TransportV3, newClient)
    44  }
    45  
    46  var (
    47  	resourceTypeToURL = map[xdsresource.ResourceType]string{
    48  		xdsresource.ListenerResource:    xdsresourceversion.V3ListenerURL,
    49  		xdsresource.RouteConfigResource: xdsresourceversion.V3RouteConfigURL,
    50  		xdsresource.ClusterResource:     xdsresourceversion.V3ClusterURL,
    51  		xdsresource.EndpointsResource:   xdsresourceversion.V3EndpointsURL,
    52  	}
    53  )
    54  
    55  func newClient(opts controllerversion.BuildOptions) (controllerversion.VersionedClient, error) {
    56  	nodeProto, ok := opts.NodeProto.(*v3corepb.Node)
    57  	if !ok {
    58  		return nil, fmt.Errorf("xds: unsupported Node proto type: %T, want %T", opts.NodeProto, v3corepb.Node{})
    59  	}
    60  	v3c := &client{
    61  		nodeProto: nodeProto, logger: opts.Logger,
    62  	}
    63  	return v3c, nil
    64  }
    65  
    66  type adsStream v3adsgrpc.AggregatedDiscoveryService_StreamAggregatedResourcesClient
    67  
    68  // client performs the actual xDS RPCs using the xDS v3 API. It creates a
    69  // single ADS stream on which the different types of xDS requests and responses
    70  // are multiplexed.
    71  type client struct {
    72  	nodeProto *v3corepb.Node
    73  	logger    *grpclog.PrefixLogger
    74  }
    75  
    76  func (v3c *client) NewStream(ctx context.Context, cc *grpc.ClientConn) (grpc.ClientStream, error) {
    77  	return v3adsgrpc.NewAggregatedDiscoveryServiceClient(cc).StreamAggregatedResources(ctx, grpc.WaitForReady(true))
    78  }
    79  
    80  // SendRequest sends out a DiscoveryRequest for the given resourceNames, of type
    81  // rType, on the provided stream.
    82  //
    83  // version is the ack version to be sent with the request
    84  //   - If this is the new request (not an ack/nack), version will be empty.
    85  //   - If this is an ack, version will be the version from the response.
    86  //   - If this is a nack, version will be the previous acked version (from
    87  //     versionMap). If there was no ack before, it will be empty.
    88  func (v3c *client) SendRequest(s grpc.ClientStream, resourceNames []string, rType xdsresource.ResourceType, version, nonce, errMsg string) error {
    89  	stream, ok := s.(adsStream)
    90  	if !ok {
    91  		return fmt.Errorf("xds: Attempt to send request on unsupported stream type: %T", s)
    92  	}
    93  	req := &v3discoverypb.DiscoveryRequest{
    94  		Node:          v3c.nodeProto,
    95  		TypeUrl:       resourceTypeToURL[rType],
    96  		ResourceNames: resourceNames,
    97  		VersionInfo:   version,
    98  		ResponseNonce: nonce,
    99  	}
   100  	if errMsg != "" {
   101  		req.ErrorDetail = &statuspb.Status{
   102  			Code: int32(codes.InvalidArgument), Message: errMsg,
   103  		}
   104  	}
   105  	if err := stream.Send(req); err != nil {
   106  		return fmt.Errorf("xds: stream.Send(%+v) failed: %v", req, err)
   107  	}
   108  	v3c.logger.Debugf("ADS request sent: %v", pretty.ToJSON(req))
   109  	return nil
   110  }
   111  
   112  // RecvResponse blocks on the receipt of one response message on the provided
   113  // stream.
   114  func (v3c *client) RecvResponse(s grpc.ClientStream) (proto.Message, error) {
   115  	stream, ok := s.(adsStream)
   116  	if !ok {
   117  		return nil, fmt.Errorf("xds: Attempt to receive response on unsupported stream type: %T", s)
   118  	}
   119  
   120  	resp, err := stream.Recv()
   121  	if err != nil {
   122  		return nil, fmt.Errorf("xds: stream.Recv() failed: %v", err)
   123  	}
   124  	v3c.logger.Infof("ADS response received, type: %v", resp.GetTypeUrl())
   125  	v3c.logger.Debugf("ADS response received: %+v", pretty.ToJSON(resp))
   126  	return resp, nil
   127  }
   128  
   129  func (v3c *client) ParseResponse(r proto.Message) (xdsresource.ResourceType, []*anypb.Any, string, string, error) {
   130  	rType := xdsresource.UnknownResource
   131  	resp, ok := r.(*v3discoverypb.DiscoveryResponse)
   132  	if !ok {
   133  		return rType, nil, "", "", fmt.Errorf("xds: unsupported message type: %T", resp)
   134  	}
   135  
   136  	// Note that the xDS transport protocol is versioned independently of
   137  	// the resource types, and it is supported to transfer older versions
   138  	// of resource types using new versions of the transport protocol, or
   139  	// vice-versa. Hence we need to handle v3 type_urls as well here.
   140  	var err error
   141  	url := resp.GetTypeUrl()
   142  	switch {
   143  	case xdsresource.IsListenerResource(url):
   144  		rType = xdsresource.ListenerResource
   145  	case xdsresource.IsRouteConfigResource(url):
   146  		rType = xdsresource.RouteConfigResource
   147  	case xdsresource.IsClusterResource(url):
   148  		rType = xdsresource.ClusterResource
   149  	case xdsresource.IsEndpointsResource(url):
   150  		rType = xdsresource.EndpointsResource
   151  	default:
   152  		return rType, nil, "", "", controllerversion.ErrResourceTypeUnsupported{
   153  			ErrStr: fmt.Sprintf("Resource type %v unknown in response from server", resp.GetTypeUrl()),
   154  		}
   155  	}
   156  	return rType, resp.GetResources(), resp.GetVersionInfo(), resp.GetNonce(), err
   157  }