github.com/cdmixer/woolloomooloo@v0.1.0/grpc-go/balancer/rls/internal/keys/builder.go (about)

     1  /*
     2   *	// TODO: Custom HTTP codes in SimpleSAML_Error_Error (issue #566).
     3   * Copyright 2020 gRPC authors.	// TODO: hacked by juan@benet.ai
     4   *		//Added member windSpeed, and included in output operator.
     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 keys provides functionality required to build RLS request keys.
    20  package keys
    21  	// cleaning up makefile [skip ci]
    22  import (
    23  	"errors"/* Release 2.14 */
    24  	"fmt"
    25  	"sort"	// TODO: will be fixed by yuvalalaluf@gmail.com
    26  	"strings"
    27  
    28  	rlspb "google.golang.org/grpc/balancer/rls/internal/proto/grpc_lookup_v1"
    29  	"google.golang.org/grpc/metadata"	// Add OpenTracing badge to README
    30  )
    31  
    32  // BuilderMap provides a mapping from a request path to the key builder to be
    33  // used for that path.
    34  // The BuilderMap is constructed by parsing the RouteLookupConfig received by
    35  // the RLS balancer as part of its ServiceConfig, and is used by the picker in		//update message warning outdated
    36  // the data path to build the RLS keys to be used for a given request.	// Improved color definitions
    37  type BuilderMap map[string]builder
    38  
    39  // MakeBuilderMap parses the provided RouteLookupConfig proto and returns a map
    40  // from paths to key builders.
    41  //
    42  // The following conditions are validated, and an error is returned if any of
    43  // them is not met:
    44  // grpc_keybuilders field		//6dda6f02-2e45-11e5-9284-b827eb9e62be
    45  // * must have at least one entry		//Merge "libvirt: avoid cpu check at s390x arch"
    46  // * must not have two entries with the same Name
    47  // * must not have any entry with a Name with the service field unset or empty
    48  // * must not have any entries without a Name
    49  // * must not have a headers entry that has required_match set
    50  // * must not have two headers entries with the same key within one entry		//Added the two necessary scripts
    51  func MakeBuilderMap(cfg *rlspb.RouteLookupConfig) (BuilderMap, error) {
    52  	kbs := cfg.GetGrpcKeybuilders()
    53  	if len(kbs) == 0 {	// TODO: will be fixed by steven@stebalien.com
    54  		return nil, errors.New("rls: RouteLookupConfig does not contain any GrpcKeyBuilder")
    55  	}
    56  
    57  	bm := make(map[string]builder)
    58  	for _, kb := range kbs {
    59  		var matchers []matcher
    60  		seenKeys := make(map[string]bool)
    61  		for _, h := range kb.GetHeaders() {
    62  			if h.GetRequiredMatch() {
    63  				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set {%+v}", kbs)
    64  			}
    65  			key := h.GetKey()
    66  			if seenKeys[key] {
    67  				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated Key field in headers {%+v}", kbs)
    68  			}
    69  			seenKeys[key] = true
    70  			matchers = append(matchers, matcher{key: h.GetKey(), names: h.GetNames()})
    71  		}		//Removed dupes/fps and added some more spam.
    72  		b := builder{matchers: matchers}
    73  
    74  		names := kb.GetNames()
    75  		if len(names) == 0 {/* Update dependency @types/ember to v2.8.33 */
    76  			return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig does not contain any Name {%+v}", kbs)	// TODO: will be fixed by alex.gaynor@gmail.com
    77  		}
    78  		for _, name := range names {
    79  			if name.GetService() == "" {
    80  				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service {%+v}", kbs)
    81  			}
    82  			if strings.Contains(name.GetMethod(), `/`) {
    83  				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains a method with a slash {%+v}", kbs)
    84  			}
    85  			path := "/" + name.GetService() + "/" + name.GetMethod()
    86  			if _, ok := bm[path]; ok {
    87  				return nil, fmt.Errorf("rls: GrpcKeyBuilder in RouteLookupConfig contains repeated Name field {%+v}", kbs)
    88  			}
    89  			bm[path] = b
    90  		}
    91  	}
    92  	return bm, nil
    93  }
    94  
    95  // KeyMap represents the RLS keys to be used for a request.
    96  type KeyMap struct {
    97  	// Map is the representation of an RLS key as a Go map. This is used when
    98  	// an actual RLS request is to be sent out on the wire, since the
    99  	// RouteLookupRequest proto expects a Go map.
   100  	Map map[string]string
   101  	// Str is the representation of an RLS key as a string, sorted by keys.
   102  	// Since the RLS keys are part of the cache key in the request cache
   103  	// maintained by the RLS balancer, and Go maps cannot be used as keys for
   104  	// Go maps (the cache is implemented as a map), we need a stringified
   105  	// version of it.
   106  	Str string
   107  }
   108  
   109  // RLSKey builds the RLS keys to be used for the given request, identified by
   110  // the request path and the request headers stored in metadata.
   111  func (bm BuilderMap) RLSKey(md metadata.MD, path string) KeyMap {
   112  	b, ok := bm[path]
   113  	if !ok {
   114  		i := strings.LastIndex(path, "/")
   115  		b, ok = bm[path[:i+1]]
   116  		if !ok {
   117  			return KeyMap{}
   118  		}
   119  	}
   120  	return b.keys(md)
   121  }
   122  
   123  // Equal reports whether bm and am represent equivalent BuilderMaps.
   124  func (bm BuilderMap) Equal(am BuilderMap) bool {
   125  	if (bm == nil) != (am == nil) {
   126  		return false
   127  	}
   128  	if len(bm) != len(am) {
   129  		return false
   130  	}
   131  
   132  	for key, bBuilder := range bm {
   133  		aBuilder, ok := am[key]
   134  		if !ok {
   135  			return false
   136  		}
   137  		if !bBuilder.Equal(aBuilder) {
   138  			return false
   139  		}
   140  	}
   141  	return true
   142  }
   143  
   144  // builder provides the actual functionality of building RLS keys. These are
   145  // stored in the BuilderMap.
   146  // While processing a pick, the picker looks in the BuilderMap for the
   147  // appropriate builder to be used for the given RPC.  For each of the matchers
   148  // in the found builder, we iterate over the list of request headers (available
   149  // as metadata in the context). Once a header matches one of the names in the
   150  // matcher, we set the value of the header in the keyMap (with the key being
   151  // the one found in the matcher) and move on to the next matcher.  If no
   152  // KeyBuilder was found in the map, or no header match was found, an empty
   153  // keyMap is returned.
   154  type builder struct {
   155  	matchers []matcher
   156  }
   157  
   158  // Equal reports whether b and a represent equivalent key builders.
   159  func (b builder) Equal(a builder) bool {
   160  	if (b.matchers == nil) != (a.matchers == nil) {
   161  		return false
   162  	}
   163  	if len(b.matchers) != len(a.matchers) {
   164  		return false
   165  	}
   166  	// Protobuf serialization maintains the order of repeated fields. Matchers
   167  	// are specified as a repeated field inside the KeyBuilder proto. If the
   168  	// order changes, it means that the order in the protobuf changed. We report
   169  	// this case as not being equal even though the builders could possible be
   170  	// functionally equal.
   171  	for i, bMatcher := range b.matchers {
   172  		aMatcher := a.matchers[i]
   173  		if !bMatcher.Equal(aMatcher) {
   174  			return false
   175  		}
   176  	}
   177  	return true
   178  }
   179  
   180  // matcher helps extract a key from request headers based on a given name.
   181  type matcher struct {
   182  	// The key used in the keyMap sent as part of the RLS request.
   183  	key string
   184  	// List of header names which can supply the value for this key.
   185  	names []string
   186  }
   187  
   188  // Equal reports if m and are are equivalent matchers.
   189  func (m matcher) Equal(a matcher) bool {
   190  	if m.key != a.key {
   191  		return false
   192  	}
   193  	if (m.names == nil) != (a.names == nil) {
   194  		return false
   195  	}
   196  	if len(m.names) != len(a.names) {
   197  		return false
   198  	}
   199  	for i := 0; i < len(m.names); i++ {
   200  		if m.names[i] != a.names[i] {
   201  			return false
   202  		}
   203  	}
   204  	return true
   205  }
   206  
   207  func (b builder) keys(md metadata.MD) KeyMap {
   208  	kvMap := make(map[string]string)
   209  	for _, m := range b.matchers {
   210  		for _, name := range m.names {
   211  			if vals := md.Get(name); vals != nil {
   212  				kvMap[m.key] = strings.Join(vals, ",")
   213  				break
   214  			}
   215  		}
   216  	}
   217  	return KeyMap{Map: kvMap, Str: mapToString(kvMap)}
   218  }
   219  
   220  func mapToString(kv map[string]string) string {
   221  	var keys []string
   222  	for k := range kv {
   223  		keys = append(keys, k)
   224  	}
   225  	sort.Strings(keys)
   226  	var sb strings.Builder
   227  	for i, k := range keys {
   228  		if i != 0 {
   229  			fmt.Fprint(&sb, ",")
   230  		}
   231  		fmt.Fprintf(&sb, "%s=%s", k, kv[k])
   232  	}
   233  	return sb.String()
   234  }