serviceconfig.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. // Package serviceconfig contains utility functions to parse service config.
  19. package serviceconfig
  20. import (
  21. "encoding/json"
  22. "fmt"
  23. "google.golang.org/grpc/balancer"
  24. "google.golang.org/grpc/grpclog"
  25. externalserviceconfig "google.golang.org/grpc/serviceconfig"
  26. )
  27. // BalancerConfig is the balancer config part that service config's
  28. // loadBalancingConfig fields can be unmarshalled to. It's a json unmarshaller.
  29. //
  30. // https://github.com/grpc/grpc-proto/blob/54713b1e8bc6ed2d4f25fb4dff527842150b91b2/grpc/service_config/service_config.proto#L247
  31. type BalancerConfig struct {
  32. Name string
  33. Config externalserviceconfig.LoadBalancingConfig
  34. }
  35. type intermediateBalancerConfig []map[string]json.RawMessage
  36. // UnmarshalJSON implements json unmarshaller.
  37. func (bc *BalancerConfig) UnmarshalJSON(b []byte) error {
  38. var ir intermediateBalancerConfig
  39. err := json.Unmarshal(b, &ir)
  40. if err != nil {
  41. return err
  42. }
  43. for i, lbcfg := range ir {
  44. if len(lbcfg) != 1 {
  45. return fmt.Errorf("invalid loadBalancingConfig: entry %v does not contain exactly 1 policy/config pair: %q", i, lbcfg)
  46. }
  47. var (
  48. name string
  49. jsonCfg json.RawMessage
  50. )
  51. // Get the key:value pair from the map.
  52. for name, jsonCfg = range lbcfg {
  53. }
  54. builder := balancer.Get(name)
  55. if builder == nil {
  56. // If the balancer is not registered, move on to the next config.
  57. // This is not an error.
  58. continue
  59. }
  60. bc.Name = name
  61. parser, ok := builder.(balancer.ConfigParser)
  62. if !ok {
  63. if string(jsonCfg) != "{}" {
  64. grpclog.Warningf("non-empty balancer configuration %q, but balancer does not implement ParseConfig", string(jsonCfg))
  65. }
  66. // Stop at this, though the builder doesn't support parsing config.
  67. return nil
  68. }
  69. cfg, err := parser.ParseConfig(jsonCfg)
  70. if err != nil {
  71. return fmt.Errorf("error parsing loadBalancingConfig for policy %q: %v", name, err)
  72. }
  73. bc.Config = cfg
  74. return nil
  75. }
  76. // This is reached when the for loop iterates over all entries, but didn't
  77. // return. This means we had a loadBalancingConfig slice but did not
  78. // encounter a registered policy. The config is considered invalid in this
  79. // case.
  80. return fmt.Errorf("invalid loadBalancingConfig: no supported policies found")
  81. }