Merge pull request #104664 from aojea/apiserver_endpoints_conformance

fix e2e test apiserver endpoint and endpointslices
This commit is contained in:
Kubernetes Prow Robot 2021-09-02 18:43:49 -07:00 committed by GitHub
commit 81e41b7fc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 15 deletions

View File

@ -1271,8 +1271,9 @@
description: The discovery.k8s.io API group MUST exist in the /apis discovery document.
The discovery.k8s.io/v1 API group/version MUST exist in the /apis/discovery.k8s.io
discovery document. The endpointslices resource MUST exist in the /apis/discovery.k8s.io/v1
discovery document. API Server should create self referential Endpoints and EndpointSlices
named "kubernetes" in the default namespace.
discovery document. The cluster MUST have a service named "kubernetes" on the
default namespace referencing the API servers. The "kubernetes.default" service
MUST have Endpoints and EndpointSlices pointing to each API server instance.
release: v1.21
file: test/e2e/network/endpointslice.go
- testname: EndpointSlice API

View File

@ -57,26 +57,33 @@ var _ = common.SIGDescribe("EndpointSlice", func() {
Description: The discovery.k8s.io API group MUST exist in the /apis discovery document.
The discovery.k8s.io/v1 API group/version MUST exist in the /apis/discovery.k8s.io discovery document.
The endpointslices resource MUST exist in the /apis/discovery.k8s.io/v1 discovery document.
API Server should create self referential Endpoints and EndpointSlices named "kubernetes" in the default namespace.
The cluster MUST have a service named "kubernetes" on the default namespace referencing the API servers.
The "kubernetes.default" service MUST have Endpoints and EndpointSlices pointing to each API server instance.
*/
framework.ConformanceIt("should have Endpoints and EndpointSlices pointing to API Server", func() {
namespace := "default"
name := "kubernetes"
// verify "kubernetes.default" service exist
_, err := cs.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
framework.ExpectNoError(err, "error obtaining API server \"kubernetes\" Service resource on \"default\" namespace")
// verify Endpoints for the API servers exist
endpoints, err := cs.CoreV1().Endpoints(namespace).Get(context.TODO(), name, metav1.GetOptions{})
framework.ExpectNoError(err, "error creating Endpoints resource")
if len(endpoints.Subsets) != 1 {
framework.Failf("Expected 1 subset in endpoints, got %d: %#v", len(endpoints.Subsets), endpoints.Subsets)
framework.ExpectNoError(err, "error obtaining API server \"kubernetes\" Endpoint resource on \"default\" namespace")
if len(endpoints.Subsets) == 0 {
framework.Failf("Expected at least 1 subset in endpoints, got %d: %#v", len(endpoints.Subsets), endpoints.Subsets)
}
// verify EndpointSlices for the API servers exist
endpointSliceList, err := cs.DiscoveryV1().EndpointSlices(namespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: "kubernetes.io/service-name=" + name,
})
framework.ExpectNoError(err, "error obtaining API server \"kubernetes\" EndpointSlice resource on \"default\" namespace")
if len(endpointSliceList.Items) == 0 {
framework.Failf("Expected at least 1 EndpointSlice, got %d: %#v", len(endpoints.Subsets), endpoints.Subsets)
}
endpointSubset := endpoints.Subsets[0]
endpointSlice, err := cs.DiscoveryV1().EndpointSlices(namespace).Get(context.TODO(), name, metav1.GetOptions{})
framework.ExpectNoError(err, "error creating EndpointSlice resource")
if len(endpointSlice.Ports) != len(endpointSubset.Ports) {
framework.Failf("Expected EndpointSlice to have %d ports, got %d: %#v", len(endpointSubset.Ports), len(endpointSlice.Ports), endpointSlice.Ports)
}
numExpectedEndpoints := len(endpointSubset.Addresses) + len(endpointSubset.NotReadyAddresses)
if len(endpointSlice.Endpoints) != numExpectedEndpoints {
framework.Failf("Expected EndpointSlice to have %d endpoints, got %d: %#v", numExpectedEndpoints, len(endpointSlice.Endpoints), endpointSlice.Endpoints)
if !endpointSlicesEqual(endpoints, endpointSliceList) {
framework.Failf("Expected EndpointSlice to have same addresses and port as Endpoints, got %#v: %#v", endpoints, endpointSliceList)
}
})
@ -785,3 +792,57 @@ func createServiceReportErr(cs clientset.Interface, ns string, service *v1.Servi
framework.ExpectNoError(err, "error deleting Service")
return svc
}
// endpointSlicesEqual compare if the Endpoint and the EndpointSliceList contains the same endpoints values
// as in addresses and ports, considering Ready and Unready addresses
func endpointSlicesEqual(endpoints *v1.Endpoints, endpointSliceList *discoveryv1.EndpointSliceList) bool {
// get the apiserver endpoint addresses
epAddresses := sets.NewString()
epPorts := sets.NewInt32()
for _, subset := range endpoints.Subsets {
for _, addr := range subset.Addresses {
epAddresses.Insert(addr.IP)
}
for _, addr := range subset.NotReadyAddresses {
epAddresses.Insert(addr.IP)
}
for _, port := range subset.Ports {
epPorts.Insert(port.Port)
}
}
framework.Logf("Endpoints addresses: %v , ports: %v", epAddresses.List(), epPorts.List())
// Endpoints are single stack, and must match the primary IP family of the Service kubernetes.default
// However, EndpointSlices can be IPv4 or IPv6, we can only compare the Slices that match the same IP family
// framework.TestContext.ClusterIsIPv6() reports the IP family of the kubernetes.default service
var addrType discoveryv1.AddressType
if framework.TestContext.ClusterIsIPv6() {
addrType = discoveryv1.AddressTypeIPv6
} else {
addrType = discoveryv1.AddressTypeIPv4
}
// get the apiserver addresses from the endpoint slice list
sliceAddresses := sets.NewString()
slicePorts := sets.NewInt32()
for _, slice := range endpointSliceList.Items {
if slice.AddressType != addrType {
framework.Logf("Skipping slice %s: wanted %s family, got %s", slice.Name, addrType, slice.AddressType)
continue
}
for _, s := range slice.Endpoints {
sliceAddresses.Insert(s.Addresses...)
}
for _, ports := range slice.Ports {
if ports.Port != nil {
slicePorts.Insert(*ports.Port)
}
}
}
framework.Logf("EndpointSlices addresses: %v , ports: %v", sliceAddresses.List(), slicePorts.List())
if sliceAddresses.Equal(epAddresses) && slicePorts.Equal(epPorts) {
return true
}
return false
}