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 }