const controllerName … func expectAction(t *testing.T, actions []k8stesting.Action, index int, verb, resource string) { … } type cacheMutationCheck … type cacheObject … // newCacheMutationCheck initializes a cacheMutationCheck with EndpointSlices. func newCacheMutationCheck(endpointSlices []*discovery.EndpointSlice) cacheMutationCheck { … } // Add appends a runtime.Object and a deep copy of that object into the // cacheMutationCheck. func (cmc *cacheMutationCheck) Add(o runtime.Object) { … } // Check verifies that no objects in the cacheMutationCheck have been mutated. func (cmc *cacheMutationCheck) Check(t *testing.T) { … } var defaultMaxEndpointsPerSlice … // Even when there are no pods, we want to have a placeholder slice for each service func TestReconcileEmpty(t *testing.T) { … } // Given a single pod matching a service selector and no existing endpoint slices, // a slice should be created func TestReconcile1Pod(t *testing.T) { … } // given an existing placeholder endpoint slice and no pods matching the service, the existing // slice should not change the placeholder func TestReconcile1EndpointSlice(t *testing.T) { … } func TestPlaceHolderSliceCompare(t *testing.T) { … } // when a Service has PublishNotReadyAddresses set to true, corresponding // Endpoints should be considered ready, even if the backing Pod is not. func TestReconcile1EndpointSlicePublishNotReadyAddresses(t *testing.T) { … } // a simple use case with 250 pods matching a service and no existing slices // reconcile should create 3 slices, completely filling 2 of them func TestReconcileManyPods(t *testing.T) { … } // now with preexisting slices, we have 250 pods matching a service // the first endpoint slice contains 62 endpoints, all desired // the second endpoint slice contains 61 endpoints, all desired // that leaves 127 to add // to minimize writes, our strategy is to create new slices for multiples of 100 // that leaves 27 to drop in an existing slice // dropping them in the first slice will result in the slice being closest to full // this approach requires 1 update + 1 create instead of 2 updates + 1 create func TestReconcileEndpointSlicesSomePreexisting(t *testing.T) { … } // now with preexisting slices, we have 300 pods matching a service // this scenario will show some less ideal allocation // the first endpoint slice contains 74 endpoints, all desired // the second endpoint slice contains 74 endpoints, all desired // that leaves 152 to add // to minimize writes, our strategy is to create new slices for multiples of 100 // that leaves 52 to drop in an existing slice // that capacity could fit if split in the 2 existing slices // to minimize writes though, reconcile create a new slice with those 52 endpoints // this approach requires 2 creates instead of 2 updates + 1 create func TestReconcileEndpointSlicesSomePreexistingWorseAllocation(t *testing.T) { … } // In some cases, such as a service port change, all slices for that service will require a change // This test ensures that we are updating those slices and not calling create + delete for each func TestReconcileEndpointSlicesUpdating(t *testing.T) { … } // In some cases, such as service labels updates, all slices for that service will require a change // This test ensures that we are updating those slices and not calling create + delete for each func TestReconcileEndpointSlicesServicesLabelsUpdating(t *testing.T) { … } // In some cases, such as service labels updates, all slices for that service will require a change // However, this should not happen for reserved labels func TestReconcileEndpointSlicesServicesReservedLabels(t *testing.T) { … } // In this test, we start with 10 slices that only have 30 endpoints each // An initial reconcile makes no changes (as desired to limit writes) // When we change a service port, all slices will need to be updated in some way // reconcile repacks the endpoints into 3 slices, and deletes the extras func TestReconcileEndpointSlicesRecycling(t *testing.T) { … } // In this test, we want to verify that endpoints are added to a slice that will // be closest to full after the operation, even when slices are already marked // for update. func TestReconcileEndpointSlicesUpdatePacking(t *testing.T) { … } // In this test, we want to verify that old EndpointSlices with a deprecated IP // address type will be replaced with a newer IPv4 type. func TestReconcileEndpointSlicesReplaceDeprecated(t *testing.T) { … } // In this test, we want to verify that a Service recreation will result in new // EndpointSlices being created. func TestReconcileEndpointSlicesRecreation(t *testing.T) { … } // Named ports can map to different port numbers on different pods. // This test ensures that EndpointSlices are grouped correctly in that case. func TestReconcileEndpointSlicesNamedPorts(t *testing.T) { … } // This test ensures that maxEndpointsPerSlice configuration results in // appropriate endpoints distribution among slices func TestReconcileMaxEndpointsPerSlice(t *testing.T) { … } func TestReconcileEndpointSlicesMetrics(t *testing.T) { … } // When a Service has a non-nil deletionTimestamp we want to avoid creating any // new EndpointSlices but continue to allow updates and deletes through. This // test uses 3 EndpointSlices, 1 "to-create", 1 "to-update", and 1 "to-delete". // Each test case exercises different combinations of calls to finalize with // those resources. func TestReconcilerFinalizeSvcDeletionTimestamp(t *testing.T) { … } // When a Pod references a Node that is not present in the informer cache the // EndpointSlices will continue to allow create, updates and deletes through. // The Pod with the missing reference will be published or retried depending of // the service.spec.PublishNotReadyAddresses. // The test considers two Pods on different nodes, one of the Nodes is not present. func TestReconcilerPodMissingNode(t *testing.T) { … } func TestReconcileTopology(t *testing.T) { … } // Test reconciliation behaviour for trafficDistribution field. func TestReconcile_TrafficDistribution(t *testing.T) { … } func newReconciler(client *fake.Clientset, nodes []*corev1.Node, maxEndpointsPerSlice int32) *Reconciler { … } // ensures endpoint slices exist with the desired set of lengths func expectUnorderedSlicesWithLengths(t *testing.T, endpointSlices []discovery.EndpointSlice, expectedLengths []int) { … } // ensures endpoint slices exist with the desired set of ports and address types func expectUnorderedSlicesWithTopLevelAttrs(t *testing.T, endpointSlices []discovery.EndpointSlice, expectedSlices []discovery.EndpointSlice) { … } func expectActions(t *testing.T, actions []k8stesting.Action, num int, verb, resource string) { … } func expectTrackedGeneration(t *testing.T, tracker *endpointsliceutil.EndpointSliceTracker, slice *discovery.EndpointSlice, expectedGeneration int64) { … } func portsAndAddressTypeEqual(slice1, slice2 discovery.EndpointSlice) bool { … } func createEndpointSlices(t *testing.T, client *fake.Clientset, namespace string, endpointSlices []*discovery.EndpointSlice) { … } func fetchEndpointSlices(t *testing.T, client *fake.Clientset, namespace string) []discovery.EndpointSlice { … } func reconcileHelper(t *testing.T, r *Reconciler, service *corev1.Service, pods []*corev1.Pod, existingSlices []*discovery.EndpointSlice, triggerTime time.Time) { … } type expectedMetrics … func expectMetrics(t *testing.T, em expectedMetrics) { … } func handleErr(t *testing.T, err error, metricName string) { … } func setupMetrics() { … }