...

Source file src/google.golang.org/grpc/xds/internal/xdsclient/xdslbregistry/xdslbregistry.go

Documentation: google.golang.org/grpc/xds/internal/xdsclient/xdslbregistry

     1  /*
     2   *
     3   * Copyright 2023 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 xdslbregistry provides a registry of converters that convert proto
    20  // from load balancing configuration, defined by the xDS API spec, to JSON load
    21  // balancing configuration.
    22  package xdslbregistry
    23  
    24  import (
    25  	"encoding/json"
    26  	"fmt"
    27  
    28  	v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
    29  )
    30  
    31  var (
    32  	// m is a map from proto type to Converter.
    33  	m = make(map[string]Converter)
    34  )
    35  
    36  // Register registers the converter to the map keyed on a proto type. Must be
    37  // called at init time. Not thread safe.
    38  func Register(protoType string, c Converter) {
    39  	m[protoType] = c
    40  }
    41  
    42  // SetRegistry sets the xDS LB registry. Must be called at init time. Not thread
    43  // safe.
    44  func SetRegistry(registry map[string]Converter) {
    45  	m = registry
    46  }
    47  
    48  // Converter converts raw proto bytes into the internal Go JSON representation
    49  // of the proto passed. Returns the json message,  and an error. If both
    50  // returned are nil, it represents continuing to the next proto.
    51  type Converter func([]byte, int) (json.RawMessage, error)
    52  
    53  // ConvertToServiceConfig converts a proto Load Balancing Policy configuration
    54  // into a json string. Returns an error if:
    55  //   - no supported policy found
    56  //   - there is more than 16 layers of recursion in the configuration
    57  //   - a failure occurs when converting the policy
    58  func ConvertToServiceConfig(lbPolicy *v3clusterpb.LoadBalancingPolicy, depth int) (json.RawMessage, error) {
    59  	// "Configurations that require more than 16 levels of recursion are
    60  	// considered invalid and should result in a NACK response." - A51
    61  	if depth > 15 {
    62  		return nil, fmt.Errorf("lb policy %v exceeds max depth supported: 16 layers", lbPolicy)
    63  	}
    64  
    65  	// "This function iterate over the list of policy messages in
    66  	// LoadBalancingPolicy, attempting to convert each one to gRPC form,
    67  	// stopping at the first supported policy." - A52
    68  	for _, policy := range lbPolicy.GetPolicies() {
    69  		converter := m[policy.GetTypedExtensionConfig().GetTypedConfig().GetTypeUrl()]
    70  		// "Any entry not in the above list is unsupported and will be skipped."
    71  		// - A52
    72  		// This includes Least Request as well, since grpc-go does not support
    73  		// the Least Request Load Balancing Policy.
    74  		if converter == nil {
    75  			continue
    76  		}
    77  		json, err := converter(policy.GetTypedExtensionConfig().GetTypedConfig().GetValue(), depth)
    78  		if json == nil && err == nil {
    79  			continue
    80  		}
    81  		return json, err
    82  	}
    83  	return nil, fmt.Errorf("no supported policy found in policy list +%v", lbPolicy)
    84  }
    85  

View as plain text