endpointslice: reduce visibility of vars/funcs

Reduce the visibility of various public identifiers that are only used
within the scope of a package.

This was originally motivated by KEP-3685 in order to reduce the public
API surface and improve supportability.
This commit is contained in:
Akhil Velagapudi 2023-04-16 12:47:45 -07:00
parent f3cf92b79b
commit 69eccd41b8
9 changed files with 129 additions and 120 deletions

View File

@ -522,7 +522,7 @@ func (c *Controller) updateNode(old, cur interface{}) {
// LabelTopologyZone may be added by cloud provider asynchronously after the Node is created. // LabelTopologyZone may be added by cloud provider asynchronously after the Node is created.
// The topology cache should be updated in this case. // The topology cache should be updated in this case.
if topologycache.NodeReady(oldNode.Status) != topologycache.NodeReady(curNode.Status) || if isNodeReady(oldNode) != isNodeReady(curNode) ||
oldNode.Labels[v1.LabelTopologyZone] != curNode.Labels[v1.LabelTopologyZone] { oldNode.Labels[v1.LabelTopologyZone] != curNode.Labels[v1.LabelTopologyZone] {
c.checkNodeTopologyDistribution() c.checkNodeTopologyDistribution()
} }

View File

@ -58,8 +58,8 @@ type reconciler struct {
// endpointMeta includes the attributes we group slices on, this type helps with // endpointMeta includes the attributes we group slices on, this type helps with
// that logic in reconciler // that logic in reconciler
type endpointMeta struct { type endpointMeta struct {
Ports []discovery.EndpointPort `json:"ports" protobuf:"bytes,2,rep,name=ports"` ports []discovery.EndpointPort
AddressType discovery.AddressType `json:"addressType" protobuf:"bytes,3,rep,name=addressType"` addressType discovery.AddressType
} }
// reconcile takes a set of pods currently matching a service selector and // reconcile takes a set of pods currently matching a service selector and
@ -166,8 +166,8 @@ func (r *reconciler) reconcileByAddressType(service *corev1.Service, pods []*cor
if _, ok := desiredMetaByPortMap[epHash]; !ok { if _, ok := desiredMetaByPortMap[epHash]; !ok {
desiredMetaByPortMap[epHash] = &endpointMeta{ desiredMetaByPortMap[epHash] = &endpointMeta{
AddressType: addressType, addressType: addressType,
Ports: endpointPorts, ports: endpointPorts,
} }
} }
@ -231,7 +231,7 @@ func (r *reconciler) reconcileByAddressType(service *corev1.Service, pods []*cor
// When no endpoint slices would usually exist, we need to add a placeholder. // When no endpoint slices would usually exist, we need to add a placeholder.
if len(existingSlices) == len(slicesToDelete) && len(slicesToCreate) < 1 { if len(existingSlices) == len(slicesToDelete) && len(slicesToCreate) < 1 {
// Check for existing placeholder slice outside of the core control flow // Check for existing placeholder slice outside of the core control flow
placeholderSlice := newEndpointSlice(service, &endpointMeta{Ports: []discovery.EndpointPort{}, AddressType: addressType}) placeholderSlice := newEndpointSlice(service, &endpointMeta{ports: []discovery.EndpointPort{}, addressType: addressType})
if len(slicesToDelete) == 1 && placeholderSliceCompare.DeepEqual(slicesToDelete[0], placeholderSlice) { if len(slicesToDelete) == 1 && placeholderSliceCompare.DeepEqual(slicesToDelete[0], placeholderSlice) {
// We are about to unnecessarily delete/recreate the placeholder, remove it now. // We are about to unnecessarily delete/recreate the placeholder, remove it now.
slicesToDelete = slicesToDelete[:0] slicesToDelete = slicesToDelete[:0]

View File

@ -495,7 +495,7 @@ func TestReconcile1EndpointSlice(t *testing.T) {
}, },
{ {
desc: "Existing placeholder that's the same", desc: "Existing placeholder that's the same",
existing: newEndpointSlice(&svc, &endpointMeta{Ports: []discovery.EndpointPort{}, AddressType: discovery.AddressTypeIPv4}), existing: newEndpointSlice(&svc, &endpointMeta{ports: []discovery.EndpointPort{}, addressType: discovery.AddressTypeIPv4}),
wantMetrics: expectedMetrics{desiredSlices: 1, actualSlices: 1, desiredEndpoints: 0, addedPerSync: 0, removedPerSync: 0, numCreated: 0, numUpdated: 0, numDeleted: 0, slicesChangedPerSync: 0}, wantMetrics: expectedMetrics{desiredSlices: 1, actualSlices: 1, desiredEndpoints: 0, addedPerSync: 0, removedPerSync: 0, numCreated: 0, numUpdated: 0, numDeleted: 0, slicesChangedPerSync: 0},
}, },
{ {
@ -1022,7 +1022,7 @@ func TestReconcileEndpointSlicesReplaceDeprecated(t *testing.T) {
svc, endpointMeta := newServiceAndEndpointMeta("foo", namespace) svc, endpointMeta := newServiceAndEndpointMeta("foo", namespace)
// "IP" is a deprecated address type, ensuring that it is handled properly. // "IP" is a deprecated address type, ensuring that it is handled properly.
endpointMeta.AddressType = discovery.AddressType("IP") endpointMeta.addressType = discovery.AddressType("IP")
existingSlices := []*discovery.EndpointSlice{} existingSlices := []*discovery.EndpointSlice{}
pods := []*corev1.Pod{} pods := []*corev1.Pod{}
@ -1367,8 +1367,8 @@ func TestReconcilerFinalizeSvcDeletionTimestamp(t *testing.T) {
Name: "to-create", Name: "to-create",
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
}, },
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
} }
// Add EndpointSlice that can be updated. // Add EndpointSlice that can be updated.
@ -1377,8 +1377,8 @@ func TestReconcilerFinalizeSvcDeletionTimestamp(t *testing.T) {
Name: "to-update", Name: "to-update",
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
}, },
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
}, metav1.CreateOptions{}) }, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("Expected no error creating EndpointSlice during test setup, got %v", err) t.Fatalf("Expected no error creating EndpointSlice during test setup, got %v", err)
@ -1393,8 +1393,8 @@ func TestReconcilerFinalizeSvcDeletionTimestamp(t *testing.T) {
Name: "to-delete", Name: "to-delete",
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
}, },
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
}, metav1.CreateOptions{}) }, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("Expected no error creating EndpointSlice during test setup, got %v", err) t.Fatalf("Expected no error creating EndpointSlice during test setup, got %v", err)
@ -1687,7 +1687,7 @@ func TestReconcileTopology(t *testing.T) {
for name, pods := range slicePods { for name, pods := range slicePods {
endpoints := []discovery.Endpoint{} endpoints := []discovery.Endpoint{}
for _, pod := range pods { for _, pod := range pods {
endpoints = append(endpoints, podToEndpoint(pod, nodesByName[pod.Spec.NodeName], &svc, endpointMeta.AddressType)) endpoints = append(endpoints, podToEndpoint(pod, nodesByName[pod.Spec.NodeName], &svc, endpointMeta.addressType))
} }
slicesByName[name] = &discovery.EndpointSlice{ slicesByName[name] = &discovery.EndpointSlice{
@ -1699,8 +1699,8 @@ func TestReconcileTopology(t *testing.T) {
discovery.LabelServiceName: svc.Name, discovery.LabelServiceName: svc.Name,
}, },
}, },
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
Endpoints: endpoints, Endpoints: endpoints,
} }
} }

View File

@ -52,7 +52,7 @@ func (si *SliceInfo) getTotalReadyEndpoints() int {
// - It has endpoint hints that would make the minimum allocations necessary // - It has endpoint hints that would make the minimum allocations necessary
// impossible with changes to slices that are already being updated or // impossible with changes to slices that are already being updated or
// created. // created.
func (si *SliceInfo) getAllocatedHintsByZone(allocations map[string]Allocation) EndpointZoneInfo { func (si *SliceInfo) getAllocatedHintsByZone(allocations map[string]allocation) EndpointZoneInfo {
allocatedHintsByZone := EndpointZoneInfo{} allocatedHintsByZone := EndpointZoneInfo{}
// Using filtering in place to remove any endpoints that are no longer // Using filtering in place to remove any endpoints that are no longer

View File

@ -30,9 +30,9 @@ import (
) )
const ( const (
// OverloadThreshold represents the maximum overload any individual endpoint // overloadThreshold represents the maximum overload any individual endpoint
// should be exposed to. // should be exposed to.
OverloadThreshold float64 = 0.2 overloadThreshold float64 = 0.2
) )
// TopologyCache tracks the distribution of Nodes and endpoints across zones. // TopologyCache tracks the distribution of Nodes and endpoints across zones.
@ -49,12 +49,12 @@ type TopologyCache struct {
// Service. // Service.
type EndpointZoneInfo map[string]int type EndpointZoneInfo map[string]int
// Allocation describes the number of endpoints that should be allocated for a // allocation describes the number of endpoints that should be allocated for a
// zone. // zone.
type Allocation struct { type allocation struct {
Minimum int minimum int
Maximum int maximum int
Desired float64 desired float64
} }
// NewTopologyCache initializes a new TopologyCache. // NewTopologyCache initializes a new TopologyCache.
@ -212,7 +212,7 @@ func (t *TopologyCache) SetNodes(nodes []*v1.Node) {
klog.V(2).Infof("Ignoring node %s because it has an excluded label", node.Name) klog.V(2).Infof("Ignoring node %s because it has an excluded label", node.Name)
continue continue
} }
if !NodeReady(node.Status) { if !isNodeReady(node) {
klog.V(2).Infof("Ignoring node %s because it is not ready: %v", node.Name, node.Status.Conditions) klog.V(2).Infof("Ignoring node %s because it is not ready: %v", node.Name, node.Status.Conditions)
continue continue
} }
@ -269,7 +269,7 @@ func (t *TopologyCache) HasPopulatedHints(serviceKey string) bool {
// getAllocations returns a set of minimum and maximum allocations per zone. If // getAllocations returns a set of minimum and maximum allocations per zone. If
// it is not possible to provide allocations that are below the overload // it is not possible to provide allocations that are below the overload
// threshold, a nil value will be returned. // threshold, a nil value will be returned.
func (t *TopologyCache) getAllocations(numEndpoints int) (map[string]Allocation, *EventBuilder) { func (t *TopologyCache) getAllocations(numEndpoints int) (map[string]allocation, *EventBuilder) {
t.lock.Lock() t.lock.Lock()
defer t.lock.Unlock() defer t.lock.Unlock()
@ -298,14 +298,14 @@ func (t *TopologyCache) getAllocations(numEndpoints int) (map[string]Allocation,
remainingMinEndpoints := numEndpoints remainingMinEndpoints := numEndpoints
minTotal := 0 minTotal := 0
allocations := map[string]Allocation{} allocations := map[string]allocation{}
for zone, ratio := range t.cpuRatiosByZone { for zone, ratio := range t.cpuRatiosByZone {
desired := ratio * float64(numEndpoints) desired := ratio * float64(numEndpoints)
minimum := int(math.Ceil(desired * (1 / (1 + OverloadThreshold)))) minimum := int(math.Ceil(desired * (1 / (1 + overloadThreshold))))
allocations[zone] = Allocation{ allocations[zone] = allocation{
Minimum: minimum, minimum: minimum,
Desired: math.Max(desired, float64(minimum)), desired: math.Max(desired, float64(minimum)),
} }
minTotal += minimum minTotal += minimum
remainingMinEndpoints -= minimum remainingMinEndpoints -= minimum
@ -319,7 +319,7 @@ func (t *TopologyCache) getAllocations(numEndpoints int) (map[string]Allocation,
} }
for zone, allocation := range allocations { for zone, allocation := range allocations {
allocation.Maximum = allocation.Minimum + numEndpoints - minTotal allocation.maximum = allocation.minimum + numEndpoints - minTotal
allocations[zone] = allocation allocations[zone] = allocation
} }

View File

@ -128,7 +128,7 @@ func redistributeHints(slices []*discovery.EndpointSlice, givingZones, receiving
// give to other zones along with the number of endpoints each zone should // give to other zones along with the number of endpoints each zone should
// receive from other zones. This is calculated with the provided allocations // receive from other zones. This is calculated with the provided allocations
// (desired state) and allocatedHintsByZone (current state). // (desired state) and allocatedHintsByZone (current state).
func getGivingAndReceivingZones(allocations map[string]Allocation, allocatedHintsByZone map[string]int) (map[string]int, map[string]int) { func getGivingAndReceivingZones(allocations map[string]allocation, allocatedHintsByZone map[string]int) (map[string]int, map[string]int) {
// 1. Determine the precise number of additional endpoints each zone has // 1. Determine the precise number of additional endpoints each zone has
// (giving) or needs (receiving). // (giving) or needs (receiving).
givingZonesDesired := map[string]float64{} givingZonesDesired := map[string]float64{}
@ -136,7 +136,7 @@ func getGivingAndReceivingZones(allocations map[string]Allocation, allocatedHint
for zone, allocation := range allocations { for zone, allocation := range allocations {
allocatedHints, _ := allocatedHintsByZone[zone] allocatedHints, _ := allocatedHintsByZone[zone]
target := allocation.Desired target := allocation.desired
if float64(allocatedHints) > target { if float64(allocatedHints) > target {
givingZonesDesired[zone] = float64(allocatedHints) - target givingZonesDesired[zone] = float64(allocatedHints) - target
} else if float64(allocatedHints) < target { } else if float64(allocatedHints) < target {
@ -193,7 +193,7 @@ func getMost(zones map[string]float64) (string, float64) {
// - A hint for a zone that no longer requires any allocations. // - A hint for a zone that no longer requires any allocations.
// - An endpoint with no hints. // - An endpoint with no hints.
// - Hints that would make minimum allocations impossible. // - Hints that would make minimum allocations impossible.
func getHintsByZone(slice *discovery.EndpointSlice, allocatedHintsByZone EndpointZoneInfo, allocations map[string]Allocation) map[string]int { func getHintsByZone(slice *discovery.EndpointSlice, allocatedHintsByZone EndpointZoneInfo, allocations map[string]allocation) map[string]int {
hintsByZone := map[string]int{} hintsByZone := map[string]int{}
for _, endpoint := range slice.Endpoints { for _, endpoint := range slice.Endpoints {
if !endpointsliceutil.EndpointReady(endpoint) { if !endpointsliceutil.EndpointReady(endpoint) {
@ -215,7 +215,7 @@ func getHintsByZone(slice *discovery.EndpointSlice, allocatedHintsByZone Endpoin
for zone, numHints := range hintsByZone { for zone, numHints := range hintsByZone {
alreadyAllocated, _ := allocatedHintsByZone[zone] alreadyAllocated, _ := allocatedHintsByZone[zone]
allocation, ok := allocations[zone] allocation, ok := allocations[zone]
if !ok || (numHints+alreadyAllocated) > allocation.Maximum { if !ok || (numHints+alreadyAllocated) > allocation.maximum {
return nil return nil
} }
} }
@ -243,7 +243,7 @@ func serviceOverloaded(ezi EndpointZoneInfo, zoneRatios map[string]float64) bool
if !ok { if !ok {
return true return true
} }
minEndpoints := math.Ceil(totalEndpoints * ratio * (1 / (1 + OverloadThreshold))) minEndpoints := math.Ceil(totalEndpoints * ratio * (1 / (1 + overloadThreshold)))
if svcEndpoints < int(minEndpoints) { if svcEndpoints < int(minEndpoints) {
return true return true
} }
@ -252,12 +252,11 @@ func serviceOverloaded(ezi EndpointZoneInfo, zoneRatios map[string]float64) bool
return false return false
} }
// NodeReady returns true if the Node has a status condition of type "NodeReady" // isNodeReady returns true if a node is ready; false otherwise.
// with a status of "True". func isNodeReady(node *v1.Node) bool {
func NodeReady(nodeStatus v1.NodeStatus) bool { for _, c := range node.Status.Conditions {
for _, cond := range nodeStatus.Conditions { if c.Type == v1.NodeReady {
if cond.Type == v1.NodeReady { return c.Status == v1.ConditionTrue
return cond.Status == v1.ConditionTrue
} }
} }
return false return false

View File

@ -92,92 +92,92 @@ func Test_redistributeHints(t *testing.T) {
func Test_getGivingAndReceivingZones(t *testing.T) { func Test_getGivingAndReceivingZones(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
allocations map[string]Allocation allocations map[string]allocation
allocatedHintsByZone map[string]int allocatedHintsByZone map[string]int
expectedGivingZones map[string]int expectedGivingZones map[string]int
expectedReceivingZones map[string]int expectedReceivingZones map[string]int
}{{ }{{
name: "empty", name: "empty",
allocations: map[string]Allocation{}, allocations: map[string]allocation{},
allocatedHintsByZone: map[string]int{}, allocatedHintsByZone: map[string]int{},
expectedGivingZones: map[string]int{}, expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{}, expectedReceivingZones: map[string]int{},
}, { }, {
name: "simple allocation with no need for rebalancing", name: "simple allocation with no need for rebalancing",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 1.2}, "zone-a": {desired: 1.2},
"zone-b": {Desired: 1.1}, "zone-b": {desired: 1.1},
"zone-c": {Desired: 1.0}, "zone-c": {desired: 1.0},
}, },
allocatedHintsByZone: map[string]int{"zone-a": 1, "zone-b": 1, "zone-c": 1}, allocatedHintsByZone: map[string]int{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedGivingZones: map[string]int{}, expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{}, expectedReceivingZones: map[string]int{},
}, { }, {
name: "preference for same zone even when giving an extra endpoint would result in slightly better distribution", name: "preference for same zone even when giving an extra endpoint would result in slightly better distribution",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.1}, "zone-a": {desired: 5.1},
"zone-b": {Desired: 5.1}, "zone-b": {desired: 5.1},
"zone-c": {Desired: 5.8}, "zone-c": {desired: 5.8},
}, },
allocatedHintsByZone: map[string]int{"zone-a": 16}, allocatedHintsByZone: map[string]int{"zone-a": 16},
expectedGivingZones: map[string]int{"zone-a": 10}, expectedGivingZones: map[string]int{"zone-a": 10},
expectedReceivingZones: map[string]int{"zone-b": 5, "zone-c": 5}, expectedReceivingZones: map[string]int{"zone-b": 5, "zone-c": 5},
}, { }, {
name: "when 2 zones need < 1 endpoint, give to zone that needs endpoint most", name: "when 2 zones need < 1 endpoint, give to zone that needs endpoint most",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.0}, "zone-a": {desired: 5.0},
"zone-b": {Desired: 5.6}, "zone-b": {desired: 5.6},
"zone-c": {Desired: 5.4}, "zone-c": {desired: 5.4},
}, },
allocatedHintsByZone: map[string]int{"zone-a": 16}, allocatedHintsByZone: map[string]int{"zone-a": 16},
expectedGivingZones: map[string]int{"zone-a": 11}, expectedGivingZones: map[string]int{"zone-a": 11},
expectedReceivingZones: map[string]int{"zone-b": 6, "zone-c": 5}, expectedReceivingZones: map[string]int{"zone-b": 6, "zone-c": 5},
}, { }, {
name: "when 2 zones have extra endpoints, give from zone with most extra", name: "when 2 zones have extra endpoints, give from zone with most extra",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.0}, "zone-a": {desired: 5.0},
"zone-b": {Desired: 5.6}, "zone-b": {desired: 5.6},
"zone-c": {Desired: 5.4}, "zone-c": {desired: 5.4},
}, },
allocatedHintsByZone: map[string]int{"zone-b": 8, "zone-c": 8}, allocatedHintsByZone: map[string]int{"zone-b": 8, "zone-c": 8},
expectedGivingZones: map[string]int{"zone-b": 2, "zone-c": 3}, expectedGivingZones: map[string]int{"zone-b": 2, "zone-c": 3},
expectedReceivingZones: map[string]int{"zone-a": 5}, expectedReceivingZones: map[string]int{"zone-a": 5},
}, { }, {
name: "ensure function can handle unexpected data (more allocated than allocations)", name: "ensure function can handle unexpected data (more allocated than allocations)",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.0}, "zone-a": {desired: 5.0},
"zone-b": {Desired: 5.0}, "zone-b": {desired: 5.0},
"zone-c": {Desired: 5.0}, "zone-c": {desired: 5.0},
}, },
allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6}, allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6},
expectedGivingZones: map[string]int{}, expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{}, expectedReceivingZones: map[string]int{},
}, { }, {
name: "ensure function can handle unexpected data (negative allocations)", name: "ensure function can handle unexpected data (negative allocations)",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: -5.0}, "zone-a": {desired: -5.0},
"zone-b": {Desired: -5.0}, "zone-b": {desired: -5.0},
"zone-c": {Desired: -5.0}, "zone-c": {desired: -5.0},
}, },
allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6}, allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6},
expectedGivingZones: map[string]int{}, expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{}, expectedReceivingZones: map[string]int{},
}, { }, {
name: "ensure function can handle unexpected data (negative allocated)", name: "ensure function can handle unexpected data (negative allocated)",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.0}, "zone-a": {desired: 5.0},
"zone-b": {Desired: 5.0}, "zone-b": {desired: 5.0},
"zone-c": {Desired: 5.0}, "zone-c": {desired: 5.0},
}, },
allocatedHintsByZone: map[string]int{"zone-a": -4, "zone-b": -3, "zone-c": -2}, allocatedHintsByZone: map[string]int{"zone-a": -4, "zone-b": -3, "zone-c": -2},
expectedGivingZones: map[string]int{}, expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{}, expectedReceivingZones: map[string]int{},
}, { }, {
name: "ensure function can handle unexpected data (negative for 1 zone)", name: "ensure function can handle unexpected data (negative for 1 zone)",
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Desired: 5.0}, "zone-a": {desired: 5.0},
"zone-b": {Desired: 5.0}, "zone-b": {desired: 5.0},
"zone-c": {Desired: 5.0}, "zone-c": {desired: 5.0},
}, },
allocatedHintsByZone: map[string]int{"zone-a": -40, "zone-b": 20, "zone-c": 20}, allocatedHintsByZone: map[string]int{"zone-a": -40, "zone-b": 20, "zone-c": 20},
expectedGivingZones: map[string]int{"zone-b": 15, "zone-c": 15}, expectedGivingZones: map[string]int{"zone-b": 15, "zone-c": 15},
@ -203,12 +203,12 @@ func Test_getHintsByZone(t *testing.T) {
name string name string
slice discovery.EndpointSlice slice discovery.EndpointSlice
allocatedHintsByZone EndpointZoneInfo allocatedHintsByZone EndpointZoneInfo
allocations map[string]Allocation allocations map[string]allocation
expectedHintsByZone map[string]int expectedHintsByZone map[string]int
}{{ }{{
name: "empty", name: "empty",
slice: discovery.EndpointSlice{}, slice: discovery.EndpointSlice{},
allocations: map[string]Allocation{}, allocations: map[string]allocation{},
allocatedHintsByZone: EndpointZoneInfo{}, allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: map[string]int{}, expectedHintsByZone: map[string]int{},
}, { }, {
@ -220,8 +220,8 @@ func Test_getHintsByZone(t *testing.T) {
Conditions: discovery.EndpointConditions{Ready: pointer.Bool(true)}, Conditions: discovery.EndpointConditions{Ready: pointer.Bool(true)},
}}, }},
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1}, allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: map[string]int{ expectedHintsByZone: map[string]int{
@ -243,8 +243,8 @@ func Test_getHintsByZone(t *testing.T) {
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}}, Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
}}, }},
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1}, allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: map[string]int{ expectedHintsByZone: map[string]int{
@ -271,10 +271,10 @@ func Test_getHintsByZone(t *testing.T) {
}, },
}, },
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
"zone-b": {Maximum: 3}, "zone-b": {maximum: 3},
"zone-c": {Maximum: 3}, "zone-c": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1}, allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedHintsByZone: map[string]int{ expectedHintsByZone: map[string]int{
@ -292,8 +292,8 @@ func Test_getHintsByZone(t *testing.T) {
}, },
}, },
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1}, allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedHintsByZone: nil, expectedHintsByZone: nil,
@ -308,8 +308,8 @@ func Test_getHintsByZone(t *testing.T) {
}, },
}, },
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{}, allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: nil, expectedHintsByZone: nil,
@ -324,8 +324,8 @@ func Test_getHintsByZone(t *testing.T) {
}, },
}, },
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 3}, "zone-a": {maximum: 3},
}, },
allocatedHintsByZone: EndpointZoneInfo{}, allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: nil, expectedHintsByZone: nil,
@ -345,8 +345,8 @@ func Test_getHintsByZone(t *testing.T) {
}, },
}, },
}, },
allocations: map[string]Allocation{ allocations: map[string]allocation{
"zone-a": {Maximum: 2}, "zone-a": {maximum: 2},
}, },
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1}, allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: nil, expectedHintsByZone: nil,

View File

@ -138,8 +138,8 @@ func newEndpointSlice(service *v1.Service, endpointMeta *endpointMeta) *discover
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
} }
// add parent service labels // add parent service labels
@ -246,7 +246,7 @@ func setEndpointSliceLabels(epSlice *discovery.EndpointSlice, service *v1.Servic
// check if the endpoint slice and the service have the same labels // check if the endpoint slice and the service have the same labels
// clone current slice labels except the reserved labels // clone current slice labels except the reserved labels
for key, value := range epSlice.Labels { for key, value := range epSlice.Labels {
if IsReservedLabelKey(key) { if isReservedLabelKey(key) {
continue continue
} }
// copy endpoint slice labels // copy endpoint slice labels
@ -254,7 +254,7 @@ func setEndpointSliceLabels(epSlice *discovery.EndpointSlice, service *v1.Servic
} }
for key, value := range service.Labels { for key, value := range service.Labels {
if IsReservedLabelKey(key) { if isReservedLabelKey(key) {
klog.Warningf("Service %s/%s using reserved endpoint slices label, skipping label %s: %s", service.Namespace, service.Name, key, value) klog.Warningf("Service %s/%s using reserved endpoint slices label, skipping label %s: %s", service.Namespace, service.Name, key, value)
continue continue
} }
@ -281,8 +281,8 @@ func setEndpointSliceLabels(epSlice *discovery.EndpointSlice, service *v1.Servic
return svcLabels, updated return svcLabels, updated
} }
// IsReservedLabelKey return true if the label is one of the reserved label for slices // isReservedLabelKey return true if the label is one of the reserved label for slices
func IsReservedLabelKey(label string) bool { func isReservedLabelKey(label string) bool {
if label == discovery.LabelServiceName || if label == discovery.LabelServiceName ||
label == discovery.LabelManagedBy || label == discovery.LabelManagedBy ||
label == v1.IsHeadlessService { label == v1.IsHeadlessService {
@ -405,3 +405,13 @@ func managedByController(endpointSlice *discovery.EndpointSlice) bool {
managedBy, _ := endpointSlice.Labels[discovery.LabelManagedBy] managedBy, _ := endpointSlice.Labels[discovery.LabelManagedBy]
return managedBy == controllerName return managedBy == controllerName
} }
// isNodeReady returns true if a node is ready; false otherwise.
func isNodeReady(node *v1.Node) bool {
for _, c := range node.Status.Conditions {
if c.Type == v1.NodeReady {
return c.Status == v1.ConditionTrue
}
}
return false
}

View File

@ -41,8 +41,8 @@ func TestNewEndpointSlice(t *testing.T) {
portName := "foo" portName := "foo"
protocol := v1.ProtocolTCP protocol := v1.ProtocolTCP
endpointMeta := endpointMeta{ endpointMeta := endpointMeta{
Ports: []discovery.EndpointPort{{Name: &portName, Protocol: &protocol}}, ports: []discovery.EndpointPort{{Name: &portName, Protocol: &protocol}},
AddressType: ipAddressType, addressType: ipAddressType,
} }
service := v1.Service{ service := v1.Service{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"}, ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"},
@ -76,8 +76,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -99,8 +99,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -124,8 +124,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -148,8 +148,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -175,8 +175,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -197,8 +197,8 @@ func TestNewEndpointSlice(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
Namespace: service.Namespace, Namespace: service.Namespace,
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
}, },
}, },
@ -981,8 +981,8 @@ func newServiceAndEndpointMeta(name, namespace string) (v1.Service, endpointMeta
addressType := discovery.AddressTypeIPv4 addressType := discovery.AddressTypeIPv4
protocol := v1.ProtocolTCP protocol := v1.ProtocolTCP
endpointMeta := endpointMeta{ endpointMeta := endpointMeta{
AddressType: addressType, addressType: addressType,
Ports: []discovery.EndpointPort{{Name: &name, Port: &portNum, Protocol: &protocol}}, ports: []discovery.EndpointPort{{Name: &name, Port: &portNum, Protocol: &protocol}},
} }
return svc, endpointMeta return svc, endpointMeta
@ -998,8 +998,8 @@ func newEmptyEndpointSlice(n int, namespace string, endpointMeta endpointMeta, s
Namespace: namespace, Namespace: namespace,
OwnerReferences: []metav1.OwnerReference{*ownerRef}, OwnerReferences: []metav1.OwnerReference{*ownerRef},
}, },
Ports: endpointMeta.Ports, Ports: endpointMeta.ports,
AddressType: endpointMeta.AddressType, AddressType: endpointMeta.addressType,
Endpoints: []discovery.Endpoint{}, Endpoints: []discovery.Endpoint{},
} }
} }