Skip to content

Commit

Permalink
feat(k8s): Switch from CoreV1 Endpoints to DiscoveryV1 EndpointSlice
Browse files Browse the repository at this point in the history
  • Loading branch information
programmer04 committed May 10, 2023
1 parent c7c77f1 commit 88b9530
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 25 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v0.31.0

- Convert dumpDiag to use kind export logs
[#591](https://github.com/Kong/kubernetes-testing-framework/pull/591)
- Switch from `CoreV1 Endpoints` to `DiscoveryV1 EndpointSlice`
[#643](https://github.com/Kong/kubernetes-testing-framework/pull/643)

## v0.30.1

- Upgrade `metallb` addon to `v0.13.9`
Expand Down
60 changes: 35 additions & 25 deletions pkg/utils/kubernetes/networking/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
Expand All @@ -17,7 +18,7 @@ import (
// address. This function will throw an error if the service gets provisioned
// more than a single address, that is not supported. The context provided
// should have a timeout associated with it or you're going to have a bad time.
func WaitForServiceLoadBalancerAddress(ctx context.Context, c *kubernetes.Clientset, namespace, name string) (string, bool, error) {
func WaitForServiceLoadBalancerAddress(ctx context.Context, c kubernetes.Interface, namespace, name string) (string, bool, error) {
for {
select {
case <-ctx.Done():
Expand Down Expand Up @@ -54,57 +55,66 @@ func WaitForServiceLoadBalancerAddress(ctx context.Context, c *kubernetes.Client
// to a service (provided by namespace/name). This will temporarily create a LoadBalancer
// type Service to allow connections to the Service and port from outside the cluster while
// the connection attempts are made using the LoadBalancer public address.
func WaitForConnectionOnServicePort(ctx context.Context, c *kubernetes.Clientset, namespace, name string, port int, dialTimeout time.Duration) error {
func WaitForConnectionOnServicePort(ctx context.Context, c kubernetes.Interface, namespace, name string, port int, dialTimeout time.Duration) error {
service, err := c.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return err
}

const correspondingSvcNameLabel = "corresponding-service"
lbServiceName := "templb-" + name
tempLoadBalancer := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: lbServiceName,
Labels: map[string]string{
"corresponding-service": name,
correspondingSvcNameLabel: name,
},
},
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer,
// copy the selector and ports of the service to check.
// Copy the selector and ports of the service to check.
Selector: service.Spec.Selector,
Ports: service.Spec.Ports,
},
}

// empty selector, we should create the endpoints separately.
// if the target service does not have a selector, it usually means that
// Empty selector, we should create the endpoints separately.
// If the target service does not have a selector, it usually means that
// the endpoints of the target server is manually created, but not chosen from pods by labels in selector.
// so we need to manually create the same endpoints as the target service has here.
if service.Spec.Selector == nil || len(service.Spec.Selector) == 0 {
endpoints, err := c.CoreV1().Endpoints(namespace).Get(ctx, name, metav1.GetOptions{})
if len(service.Spec.Selector) == 0 {
endpointSlices, err := c.DiscoveryV1().EndpointSlices(namespace).List(
ctx, metav1.ListOptions{LabelSelector: discoveryv1.LabelServiceName + "=" + name},
)
if err != nil {
return err
}
// copy the endpoints for the lb service, and set metadata.
tempEndpoints := endpoints.DeepCopy()
tempEndpoints.ObjectMeta = metav1.ObjectMeta{
Namespace: namespace,
Name: lbServiceName,
Labels: map[string]string{
"corresponding-service": name,
},
}
_, err = c.CoreV1().Endpoints(namespace).Create(ctx, tempEndpoints, metav1.CreateOptions{})
if err != nil {
return err

// Recreate EndpointSlices for the lb service with proper metadata.
tempEndpointSlices := endpointSlices.DeepCopy().Items
for i := range tempEndpointSlices {
tempEndpointSlices[i].ObjectMeta = metav1.ObjectMeta{
Namespace: namespace,
Name: fmt.Sprintf("%s-%d", lbServiceName, i),
Labels: map[string]string{
discoveryv1.LabelServiceName: lbServiceName, // Maps EndpointSlice to Service.
correspondingSvcNameLabel: name,
},
}
_, err = c.DiscoveryV1().EndpointSlices(namespace).Create(ctx, &tempEndpointSlices[i], metav1.CreateOptions{})
if err != nil {
return err
}
}

defer func() {
err := c.CoreV1().Endpoints(namespace).Delete(ctx, lbServiceName, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
fmt.Printf("failed to delete endpoints %s/%s after testing, error %v\n",
namespace, lbServiceName, err)
for _, eps := range tempEndpointSlices {
err := c.DiscoveryV1().EndpointSlices(namespace).Delete(ctx, eps.Name, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
fmt.Printf("failed to delete endpoints %s/%s after testing, error %v\n",
namespace, eps.Name, err,
)
}
}
}()
}
Expand Down

0 comments on commit 88b9530

Please sign in to comment.