1/* 2 * 3 * Copyright 2019 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 18package edsbalancer 19 20import ( 21 "encoding/json" 22 "fmt" 23 24 "google.golang.org/grpc/balancer" 25 "google.golang.org/grpc/serviceconfig" 26) 27 28// EDSConfig represents the loadBalancingConfig section of the service config 29// for EDS balancers. 30type EDSConfig struct { 31 serviceconfig.LoadBalancingConfig 32 // ChildPolicy represents the load balancing config for the child 33 // policy. 34 ChildPolicy *loadBalancingConfig 35 // FallBackPolicy represents the load balancing config for the 36 // fallback. 37 FallBackPolicy *loadBalancingConfig 38 // Name to use in EDS query. If not present, defaults to the server 39 // name from the target URI. 40 EDSServiceName string 41 // MaxConcurrentRequests is the max number of concurrent request allowed for 42 // this service. If unset, default value 1024 is used. 43 // 44 // Note that this is not defined in the service config proto. And the reason 45 // is, we are dropping EDS and moving the features into cluster_impl. But in 46 // the mean time, to keep things working, we need to add this field. And it 47 // should be fine to add this extra field here, because EDS is only used in 48 // CDS today, so we have full control. 49 MaxConcurrentRequests *uint32 50 // LRS server to send load reports to. If not present, load reporting 51 // will be disabled. If set to the empty string, load reporting will 52 // be sent to the same server that we obtained CDS data from. 53 LrsLoadReportingServerName *string 54} 55 56// edsConfigJSON is the intermediate unmarshal result of EDSConfig. ChildPolicy 57// and Fallbackspolicy are post-processed, and for each, the first installed 58// policy is kept. 59type edsConfigJSON struct { 60 ChildPolicy []*loadBalancingConfig 61 FallbackPolicy []*loadBalancingConfig 62 EDSServiceName string 63 MaxConcurrentRequests *uint32 64 LRSLoadReportingServerName *string 65} 66 67// UnmarshalJSON parses the JSON-encoded byte slice in data and stores it in l. 68// When unmarshalling, we iterate through the childPolicy/fallbackPolicy lists 69// and select the first LB policy which has been registered. 70func (l *EDSConfig) UnmarshalJSON(data []byte) error { 71 var configJSON edsConfigJSON 72 if err := json.Unmarshal(data, &configJSON); err != nil { 73 return err 74 } 75 76 l.EDSServiceName = configJSON.EDSServiceName 77 l.MaxConcurrentRequests = configJSON.MaxConcurrentRequests 78 l.LrsLoadReportingServerName = configJSON.LRSLoadReportingServerName 79 80 for _, lbcfg := range configJSON.ChildPolicy { 81 if balancer.Get(lbcfg.Name) != nil { 82 l.ChildPolicy = lbcfg 83 break 84 } 85 } 86 87 for _, lbcfg := range configJSON.FallbackPolicy { 88 if balancer.Get(lbcfg.Name) != nil { 89 l.FallBackPolicy = lbcfg 90 break 91 } 92 } 93 return nil 94} 95 96// MarshalJSON returns a JSON encoding of l. 97func (l *EDSConfig) MarshalJSON() ([]byte, error) { 98 return nil, fmt.Errorf("EDSConfig.MarshalJSON() is unimplemented") 99} 100 101// loadBalancingConfig represents a single load balancing config, 102// stored in JSON format. 103type loadBalancingConfig struct { 104 Name string 105 Config json.RawMessage 106} 107 108// MarshalJSON returns a JSON encoding of l. 109func (l *loadBalancingConfig) MarshalJSON() ([]byte, error) { 110 return nil, fmt.Errorf("loadBalancingConfig.MarshalJSON() is unimplemented") 111} 112 113// UnmarshalJSON parses the JSON-encoded byte slice in data and stores it in l. 114func (l *loadBalancingConfig) UnmarshalJSON(data []byte) error { 115 var cfg map[string]json.RawMessage 116 if err := json.Unmarshal(data, &cfg); err != nil { 117 return err 118 } 119 for name, config := range cfg { 120 l.Name = name 121 l.Config = config 122 } 123 return nil 124} 125