topology.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package proxy
  14. import (
  15. v1 "k8s.io/api/core/v1"
  16. )
  17. // FilterTopologyEndpoint returns the appropriate endpoints based on the cluster
  18. // topology.
  19. // This uses the current node's labels, which contain topology information, and
  20. // the required topologyKeys to find appropriate endpoints. If both the endpoint's
  21. // topology and the current node have matching values for topologyKeys[0], the
  22. // endpoint will be chosen. If no endpoints are chosen, toplogyKeys[1] will be
  23. // considered, and so on. If either the node or the endpoint do not have values
  24. // for a key, it is considered to not match.
  25. //
  26. // If topologyKeys is specified, but no endpoints are chosen for any key, the
  27. // the service has no viable endpoints for clients on this node, and connections
  28. // should fail.
  29. //
  30. // The special key "*" may be used as the last entry in topologyKeys to indicate
  31. // "any endpoint" is acceptable.
  32. //
  33. // If topologyKeys is not specified or empty, no topology constraints will be
  34. // applied and this will return all endpoints.
  35. func FilterTopologyEndpoint(nodeLabels map[string]string, topologyKeys []string, endpoints []Endpoint) []Endpoint {
  36. // Do not filter endpoints if service has no topology keys.
  37. if len(topologyKeys) == 0 {
  38. return endpoints
  39. }
  40. filteredEndpoint := []Endpoint{}
  41. if len(nodeLabels) == 0 {
  42. if topologyKeys[len(topologyKeys)-1] == v1.TopologyKeyAny {
  43. // edge case: include all endpoints if topology key "Any" specified
  44. // when we cannot determine current node's topology.
  45. return endpoints
  46. }
  47. // edge case: do not include any endpoints if topology key "Any" is
  48. // not specified when we cannot determine current node's topology.
  49. return filteredEndpoint
  50. }
  51. for _, key := range topologyKeys {
  52. if key == v1.TopologyKeyAny {
  53. return endpoints
  54. }
  55. topologyValue, found := nodeLabels[key]
  56. if !found {
  57. continue
  58. }
  59. for _, ep := range endpoints {
  60. topology := ep.GetTopology()
  61. if value, found := topology[key]; found && value == topologyValue {
  62. filteredEndpoint = append(filteredEndpoint, ep)
  63. }
  64. }
  65. if len(filteredEndpoint) > 0 {
  66. return filteredEndpoint
  67. }
  68. }
  69. return filteredEndpoint
  70. }