...

Source file src/github.com/linkerd/linkerd2/controller/api/destination/server_ipv6_test.go

Documentation: github.com/linkerd/linkerd2/controller/api/destination

     1  package destination
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	pb "github.com/linkerd/linkerd2-proxy-api/go/destination"
     9  	"github.com/linkerd/linkerd2/controller/api/util"
    10  	corev1 "k8s.io/api/core/v1"
    11  	discovery "k8s.io/api/discovery/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/apimachinery/pkg/types"
    14  )
    15  
    16  func TestIPv6(t *testing.T) {
    17  	port := int32(port)
    18  	protocol := corev1.ProtocolTCP
    19  
    20  	server := makeServer(t)
    21  	defer server.clusterStore.UnregisterGauges()
    22  
    23  	stream := &bufferingGetStream{
    24  		updates:          make(chan *pb.Update, 50),
    25  		MockServerStream: util.NewMockServerStream(),
    26  	}
    27  	defer stream.Cancel()
    28  
    29  	t.Run("Return only IPv6 endpoint for dual-stack service", func(t *testing.T) {
    30  		testReturnEndpointsForServer(t, server, stream, fullyQualifiedNameDual, podIPv6Dual, uint32(port))
    31  	})
    32  
    33  	t.Run("Returns only IPv4 endpoint when service becomes single-stack IPv4", func(t *testing.T) {
    34  		patch := []byte(`{"spec":{"clusterIPs": ["172.17.13.0"], "ipFamilies":["IPv4"]}}`)
    35  		_, err := server.k8sAPI.Client.CoreV1().Services("ns").Patch(context.Background(), "name-ds", types.MergePatchType, patch, metav1.PatchOptions{})
    36  		if err != nil {
    37  			t.Fatalf("Failed patching name-ds service: %s", err)
    38  		}
    39  		if err = server.k8sAPI.Client.DiscoveryV1().EndpointSlices("ns").Delete(context.Background(), "name-ds-ipv6", metav1.DeleteOptions{}); err != nil {
    40  			t.Fatalf("Failed deleting name-ds-ipv6 ES: %s", err)
    41  		}
    42  
    43  		update := <-stream.updates
    44  		if updateAddAddress(t, update)[0] != "172.17.0.19:8989" {
    45  			t.Fatalf("Expected %s but got %s", "172.17.0.19:8989", updateAddAddress(t, update)[0])
    46  		}
    47  
    48  		update = <-stream.updates
    49  		if updateRemoveAddress(t, update)[0] != "[2001:db8::94]:8989" {
    50  			t.Fatalf("Expected %s but got %s", "[2001:db8::94]:8989", updateRemoveAddress(t, update)[0])
    51  		}
    52  	})
    53  
    54  	t.Run("Returns only IPv6 endpoint when service becomes dual-stack again", func(t *testing.T) {
    55  		// We patch the service to become dual-stack again and we add the IPv6
    56  		// ES. We should receive the events for the removal of the IPv4 ES and
    57  		// the addition of the IPv6 one.
    58  		patch := []byte(`{"spec":{"clusterIPs": ["172.17.13.0","2001:db8::88"], "ipFamilies":["IPv4","IPv6"]}}`)
    59  		_, err := server.k8sAPI.Client.CoreV1().Services("ns").Patch(context.Background(), "name-ds", types.MergePatchType, patch, metav1.PatchOptions{})
    60  		if err != nil {
    61  			t.Fatalf("Failed patching name-ds service: %s", err)
    62  		}
    63  
    64  		es := &discovery.EndpointSlice{
    65  			TypeMeta: metav1.TypeMeta{
    66  				Kind:       "EndpointSlice",
    67  				APIVersion: "discovery.k8s.io/v1",
    68  			},
    69  			ObjectMeta: metav1.ObjectMeta{
    70  				Name:      "name-ds-ipv6",
    71  				Namespace: "ns",
    72  				Labels: map[string]string{
    73  					"kubernetes.io/service-name": "name-ds",
    74  				},
    75  			},
    76  			AddressType: discovery.AddressTypeIPv6,
    77  			Ports: []discovery.EndpointPort{
    78  				{
    79  					Port:     &port,
    80  					Protocol: &protocol,
    81  				},
    82  			},
    83  			Endpoints: []discovery.Endpoint{
    84  				{
    85  					Addresses: []string{"2001:db8::94"},
    86  					TargetRef: &corev1.ObjectReference{
    87  						Kind:      "Pod",
    88  						Namespace: "ns",
    89  						Name:      "name-ds",
    90  					},
    91  				},
    92  			},
    93  		}
    94  		if _, err := server.k8sAPI.Client.DiscoveryV1().EndpointSlices("ns").Create(context.Background(), es, metav1.CreateOptions{}); err != nil {
    95  			t.Fatalf("Failed creating name-ds-ipv6 ES: %s", err)
    96  		}
    97  
    98  		update := <-stream.updates
    99  		if updateAddAddress(t, update)[0] != "[2001:db8::94]:8989" {
   100  			t.Fatalf("Expected %s but got %s", "[2001:db8::94]:8989", updateAddAddress(t, update)[0])
   101  		}
   102  
   103  		update = <-stream.updates
   104  		if updateRemoveAddress(t, update)[0] != "172.17.0.19:8989" {
   105  			t.Fatalf("Expected %s but got %s", "172.17.0.19:8989", updateRemoveAddress(t, update)[0])
   106  		}
   107  	})
   108  
   109  	t.Run("Doesn't return anything when adding an IPv4 to the dual-stack service", func(t *testing.T) {
   110  		es := &discovery.EndpointSlice{
   111  			TypeMeta: metav1.TypeMeta{
   112  				Kind:       "EndpointSlice",
   113  				APIVersion: "discovery.k8s.io/v1",
   114  			},
   115  			ObjectMeta: metav1.ObjectMeta{
   116  				Name:      "name-ds-ipv4-2",
   117  				Namespace: "ns",
   118  				Labels: map[string]string{
   119  					"kubernetes.io/service-name": "name-ds",
   120  				},
   121  			},
   122  			AddressType: discovery.AddressTypeIPv4,
   123  			Ports: []discovery.EndpointPort{
   124  				{
   125  					Port:     &port,
   126  					Protocol: &protocol,
   127  				},
   128  			},
   129  			Endpoints: []discovery.Endpoint{
   130  				{
   131  					Addresses: []string{"172.17.0.20"},
   132  					TargetRef: &corev1.ObjectReference{
   133  						Kind:      "Pod",
   134  						Namespace: "ns",
   135  						Name:      "name-ds",
   136  					},
   137  				},
   138  			},
   139  		}
   140  		if _, err := server.k8sAPI.Client.DiscoveryV1().EndpointSlices("ns").Create(context.Background(), es, metav1.CreateOptions{}); err != nil {
   141  			t.Fatalf("Failed creating name-ds-ipv4-2 ES: %s", err)
   142  		}
   143  
   144  		time.Sleep(50 * time.Millisecond)
   145  
   146  		if len(stream.updates) != 0 {
   147  			t.Fatalf("Expected no events but got %#v", stream.updates)
   148  		}
   149  	})
   150  
   151  	t.Run("Doesn't return anything when removing an IPv4 ES from the dual-stack service", func(t *testing.T) {
   152  		if err := server.k8sAPI.Client.DiscoveryV1().EndpointSlices("ns").Delete(context.Background(), "name-ds-ipv4-2", metav1.DeleteOptions{}); err != nil {
   153  			t.Fatalf("Failed deleting name-ds-ipv4-2 ES: %s", err)
   154  		}
   155  
   156  		time.Sleep(50 * time.Millisecond)
   157  
   158  		if len(stream.updates) != 0 {
   159  			t.Fatalf("Expected no events but got %#v", stream.updates)
   160  		}
   161  	})
   162  
   163  	t.Run("Doesn't return anything when the service becomes single-stack IPv6", func(t *testing.T) {
   164  		patch := []byte(`{"spec":{"clusterIPs": ["2001:db8::88"], "ipFamilies":["IPv6"]}}`)
   165  		_, err := server.k8sAPI.Client.CoreV1().Services("ns").Patch(context.Background(), "name-ds", types.MergePatchType, patch, metav1.PatchOptions{})
   166  		if err != nil {
   167  			t.Fatalf("Failed patching name-ds service: %s", err)
   168  		}
   169  		if err := server.k8sAPI.Client.DiscoveryV1().EndpointSlices("ns").Delete(context.Background(), "name-ds-ipv4", metav1.DeleteOptions{}); err != nil {
   170  			t.Fatalf("Failed deleting name-ds-ipv4 ES: %s", err)
   171  		}
   172  
   173  		time.Sleep(50 * time.Millisecond)
   174  
   175  		if len(stream.updates) != 0 {
   176  			t.Fatalf("Expected no events but got %#v", stream.updates)
   177  		}
   178  	})
   179  }
   180  

View as plain text