...

Source file src/github.com/linkerd/linkerd2/test/integration/multicluster/multicluster-traffic/pod_to_pod_test.go

Documentation: github.com/linkerd/linkerd2/test/integration/multicluster/multicluster-traffic

     1  package multiclustertraffic
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/linkerd/linkerd2/pkg/k8s"
    11  	"github.com/linkerd/linkerd2/testutil"
    12  	kerrors "k8s.io/apimachinery/pkg/api/errors"
    13  )
    14  
    15  // TestPodToPodTraffic inspects the target cluster's web-svc pod to see if the
    16  // source cluster's vote-bot has been able to hit it with requests. If it has
    17  // successfully issued requests, then we'll see log messages indicating that the
    18  // web-svc can't reach the voting-svc (because it's not running).
    19  //
    20  // We verify that the service has been mirrored in remote discovery mode by
    21  // checking that it had no endpoints in the source cluster.
    22  func TestPodToPodTraffic(t *testing.T) {
    23  	if err := TestHelper.SwitchContext(contexts[testutil.TargetContextKey]); err != nil {
    24  		testutil.AnnotatedFatalf(t,
    25  			"failed to rebuild helper clientset with new context",
    26  			"failed to rebuild helper clientset with new context [%s]: %v",
    27  			contexts[testutil.TargetContextKey], err)
    28  	}
    29  
    30  	ctx := context.Background()
    31  	// Create emojivoto in target cluster, to be deleted at the end of the test.
    32  	annotations := map[string]string{
    33  		// "config.linkerd.io/proxy-log-level": "linkerd=debug,info",
    34  	}
    35  	TestHelper.WithDataPlaneNamespace(ctx, "emojivoto-p2p", annotations, t, func(t *testing.T, ns string) {
    36  		t.Run("Deploy resources in source and target clusters", func(t *testing.T) {
    37  			// Deploy vote-bot client in source-cluster
    38  			o, err := TestHelper.KubectlWithContext("", contexts[testutil.SourceContextKey], "create", "ns", ns)
    39  			if err != nil {
    40  				testutil.AnnotatedFatalf(t, "failed to create ns", "failed to create ns: %s\n%s", err, o)
    41  			}
    42  			o, err = TestHelper.KubectlApplyWithContext("", contexts[testutil.SourceContextKey], "--namespace", ns, "-f", "testdata/vote-bot.yml")
    43  			if err != nil {
    44  				testutil.AnnotatedFatalf(t, "failed to install vote-bot", "failed to install vote-bot: %s\n%s", err, o)
    45  			}
    46  
    47  			out, err := TestHelper.KubectlApplyWithContext("", contexts[testutil.TargetContextKey], "--namespace", ns, "-f", "testdata/emojivoto-no-bot.yml")
    48  			if err != nil {
    49  				testutil.AnnotatedFatalf(t, "failed to install emojivoto", "failed to install emojivoto: %s\n%s", err, out)
    50  			}
    51  
    52  			timeout := time.Minute
    53  			err = testutil.RetryFor(timeout, func() error {
    54  				out, err = TestHelper.KubectlWithContext("", contexts[testutil.TargetContextKey], "--namespace", ns, "label", "service/web-svc", "mirror.linkerd.io/exported=remote-discovery")
    55  				return err
    56  			})
    57  			if err != nil {
    58  				testutil.AnnotatedFatalf(t, "failed to label web-svc", "%s\n%s", err, out)
    59  			}
    60  		})
    61  
    62  		t.Run("Wait until target workloads are ready", func(t *testing.T) {
    63  			// Wait until client is up and running in source cluster
    64  			voteBotDeployReplica := map[string]testutil.DeploySpec{"vote-bot": {Namespace: ns, Replicas: 1}}
    65  			TestHelper.WaitRolloutWithContext(t, voteBotDeployReplica, contexts[testutil.SourceContextKey])
    66  
    67  			// Wait until "target" services and replicas are up and running.
    68  			emojiDeployReplicas := map[string]testutil.DeploySpec{
    69  				"web":    {Namespace: ns, Replicas: 1},
    70  				"emoji":  {Namespace: ns, Replicas: 1},
    71  				"voting": {Namespace: ns, Replicas: 1},
    72  			}
    73  			TestHelper.WaitRolloutWithContext(t, emojiDeployReplicas, targetCtx)
    74  		})
    75  
    76  		timeout := time.Minute
    77  		t.Run("Ensure mirror service exists and has no endpoints", func(t *testing.T) {
    78  			err := TestHelper.SwitchContext(contexts[testutil.SourceContextKey])
    79  			if err != nil {
    80  				testutil.AnnotatedFatal(t, "failed to switch contexts", err)
    81  			}
    82  			err = testutil.RetryFor(timeout, func() error {
    83  				svc, err := TestHelper.GetService(ctx, ns, "web-svc-target")
    84  				if err != nil {
    85  					return err
    86  				}
    87  				remoteDiscovery, found := svc.Labels[k8s.RemoteDiscoveryLabel]
    88  				if !found {
    89  					testutil.AnnotatedFatal(t, "mirror service missing label", "mirror service missing label: "+k8s.RemoteDiscoveryLabel)
    90  				}
    91  				if remoteDiscovery != "target" {
    92  					testutil.AnnotatedFatal(t, "mirror service has incorrect remote discovery", fmt.Sprintf("mirror service remote discovery was %s, expected %s", remoteDiscovery, "target"))
    93  				}
    94  				remoteService, found := svc.Labels[k8s.RemoteServiceLabel]
    95  				if !found {
    96  					testutil.AnnotatedFatal(t, "mirror service missing label", "mirror service missing label: "+k8s.RemoteServiceLabel)
    97  				}
    98  				if remoteService != "web-svc" {
    99  					testutil.AnnotatedFatal(t, "mirror service has incorrect remote service", fmt.Sprintf("mirror service remote service was %s, expected %s", remoteService, "web-svc"))
   100  				}
   101  				_, err = TestHelper.GetEndpoints(ctx, ns, "web-svc-target")
   102  				if err == nil {
   103  					testutil.AnnotatedFatal(t, "mirror service should not have endpoints", "mirror service should not have endpoints")
   104  				}
   105  				if !kerrors.IsNotFound(err) {
   106  					testutil.AnnotatedFatalf(t, "failed to retrieve mirror service endpoints", err.Error())
   107  				}
   108  				return nil
   109  			})
   110  			if err != nil {
   111  				testutil.AnnotatedFatal(t, "timed-out verifying mirror service", err)
   112  			}
   113  		})
   114  
   115  		err := testutil.RetryFor(timeout, func() error {
   116  			out, err := TestHelper.KubectlWithContext("",
   117  				targetCtx,
   118  				"--namespace", ns,
   119  				"logs",
   120  				"--selector", "app=web-svc",
   121  				"--container", "web-svc",
   122  			)
   123  			if err != nil {
   124  				return fmt.Errorf("%w\n%s", err, out)
   125  			}
   126  			// Check for expected error messages
   127  			for _, row := range strings.Split(out, "\n") {
   128  				if strings.Contains(row, " /api/vote?choice=:doughnut: ") {
   129  					return nil
   130  				}
   131  			}
   132  			return fmt.Errorf("web-svc logs in target cluster do not include voting errors\n%s", out)
   133  		})
   134  		if err != nil {
   135  			testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out waiting for traffic (%s)", timeout), err)
   136  		}
   137  	})
   138  }
   139  

View as plain text