endpointslice_tracker.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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 endpointslice
  14. import (
  15. "sync"
  16. discovery "k8s.io/api/discovery/v1beta1"
  17. "k8s.io/apimachinery/pkg/types"
  18. )
  19. // endpointSliceResourceVersions tracks expected EndpointSlice resource versions
  20. // by EndpointSlice name.
  21. type endpointSliceResourceVersions map[string]string
  22. // endpointSliceTracker tracks EndpointSlices and their associated resource
  23. // versions to help determine if a change to an EndpointSlice has been processed
  24. // by the EndpointSlice controller.
  25. type endpointSliceTracker struct {
  26. // lock protects resourceVersionsByService.
  27. lock sync.Mutex
  28. // resourceVersionsByService tracks the list of EndpointSlices and
  29. // associated resource versions expected for a given Service.
  30. resourceVersionsByService map[types.NamespacedName]endpointSliceResourceVersions
  31. }
  32. // newEndpointSliceTracker creates and initializes a new endpointSliceTracker.
  33. func newEndpointSliceTracker() *endpointSliceTracker {
  34. return &endpointSliceTracker{
  35. resourceVersionsByService: map[types.NamespacedName]endpointSliceResourceVersions{},
  36. }
  37. }
  38. // Has returns true if the endpointSliceTracker has a resource version for the
  39. // provided EndpointSlice.
  40. func (est *endpointSliceTracker) Has(endpointSlice *discovery.EndpointSlice) bool {
  41. est.lock.Lock()
  42. defer est.lock.Unlock()
  43. rrv := est.relatedResourceVersions(endpointSlice)
  44. _, ok := rrv[endpointSlice.Name]
  45. return ok
  46. }
  47. // Stale returns true if this endpointSliceTracker does not have a resource
  48. // version for the provided EndpointSlice or it does not match the resource
  49. // version of the provided EndpointSlice.
  50. func (est *endpointSliceTracker) Stale(endpointSlice *discovery.EndpointSlice) bool {
  51. est.lock.Lock()
  52. defer est.lock.Unlock()
  53. rrv := est.relatedResourceVersions(endpointSlice)
  54. return rrv[endpointSlice.Name] != endpointSlice.ResourceVersion
  55. }
  56. // Update adds or updates the resource version in this endpointSliceTracker for
  57. // the provided EndpointSlice.
  58. func (est *endpointSliceTracker) Update(endpointSlice *discovery.EndpointSlice) {
  59. est.lock.Lock()
  60. defer est.lock.Unlock()
  61. rrv := est.relatedResourceVersions(endpointSlice)
  62. rrv[endpointSlice.Name] = endpointSlice.ResourceVersion
  63. }
  64. // Delete removes the resource version in this endpointSliceTracker for the
  65. // provided EndpointSlice.
  66. func (est *endpointSliceTracker) Delete(endpointSlice *discovery.EndpointSlice) {
  67. est.lock.Lock()
  68. defer est.lock.Unlock()
  69. rrv := est.relatedResourceVersions(endpointSlice)
  70. delete(rrv, endpointSlice.Name)
  71. }
  72. // relatedResourceVersions returns the set of resource versions tracked for the
  73. // Service corresponding to the provided EndpointSlice. If no resource versions
  74. // are currently tracked for this service, an empty set is initialized.
  75. func (est *endpointSliceTracker) relatedResourceVersions(endpointSlice *discovery.EndpointSlice) endpointSliceResourceVersions {
  76. serviceNN := getServiceNN(endpointSlice)
  77. vers, ok := est.resourceVersionsByService[serviceNN]
  78. if !ok {
  79. vers = endpointSliceResourceVersions{}
  80. est.resourceVersionsByService[serviceNN] = vers
  81. }
  82. return vers
  83. }
  84. // getServiceNN returns a namespaced name for the Service corresponding to the
  85. // provided EndpointSlice.
  86. func getServiceNN(endpointSlice *discovery.EndpointSlice) types.NamespacedName {
  87. serviceName, _ := endpointSlice.Labels[discovery.LabelServiceName]
  88. return types.NamespacedName{Name: serviceName, Namespace: endpointSlice.Namespace}
  89. }
  90. // managedByChanged returns true if one of the provided EndpointSlices is
  91. // managed by the EndpointSlice controller while the other is not.
  92. func managedByChanged(endpointSlice1, endpointSlice2 *discovery.EndpointSlice) bool {
  93. return managedByController(endpointSlice1) != managedByController(endpointSlice2)
  94. }
  95. // managedByController returns true if the controller of the provided
  96. // EndpointSlices is the EndpointSlice controller.
  97. func managedByController(endpointSlice *discovery.EndpointSlice) bool {
  98. managedBy, _ := endpointSlice.Labels[discovery.LabelManagedBy]
  99. return managedBy == controllerName
  100. }