...

Source file src/github.com/linkerd/linkerd2/test/integration/deep/endpoints/endpoints_test.go

Documentation: github.com/linkerd/linkerd2/test/integration/deep/endpoints

     1  package endpoints
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"regexp"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/linkerd/linkerd2/testutil"
    13  )
    14  
    15  var TestHelper *testutil.TestHelper
    16  
    17  type testCase struct {
    18  	name       string
    19  	authority  string
    20  	expectedRE string
    21  	ns         string
    22  }
    23  
    24  func TestMain(m *testing.M) {
    25  	TestHelper = testutil.NewTestHelper()
    26  	// Block test execution until control plane is running
    27  	TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
    28  	os.Exit(m.Run())
    29  }
    30  
    31  func TestGoodEndpoints(t *testing.T) {
    32  	ctx := context.Background()
    33  	controlNs := TestHelper.GetLinkerdNamespace()
    34  
    35  	TestHelper.WithDataPlaneNamespace(ctx, "endpoints-test", map[string]string{}, t, func(t *testing.T, ns string) {
    36  		out, err := TestHelper.Kubectl("", "apply", "-f", "testdata/nginx.yaml", "-n", ns)
    37  		if err != nil {
    38  			testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out)
    39  		}
    40  
    41  		err = TestHelper.CheckPods(ctx, ns, "nginx", 1)
    42  		if err != nil {
    43  			//nolint:errorlint
    44  			if rce, ok := err.(*testutil.RestartCountError); ok {
    45  				testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
    46  			} else {
    47  				testutil.AnnotatedError(t, "CheckPods timed-out", err)
    48  			}
    49  		}
    50  
    51  		endpointCases := createTestCaseTable(controlNs, ns)
    52  		for _, endpointCase := range endpointCases {
    53  			testName := fmt.Sprintf("expect endpoints created for %s", endpointCase.name)
    54  
    55  			t.Run(testName, func(t *testing.T) {
    56  				err = testutil.RetryFor(5*time.Second, func() error {
    57  					out, err = TestHelper.LinkerdRun("diagnostics", "endpoints", endpointCase.authority, "-ojson")
    58  					if err != nil {
    59  						return fmt.Errorf("failed to get endpoints for %s: %w", endpointCase.authority, err)
    60  					}
    61  
    62  					re := regexp.MustCompile(endpointCase.expectedRE)
    63  					if !re.MatchString(out) {
    64  						return fmt.Errorf("endpoint data does not match pattern\nexpected output:\n%s\nactual:\n%s", endpointCase.expectedRE, out)
    65  					}
    66  
    67  					matches := re.FindStringSubmatch(out)
    68  					if matches == nil || len(matches) < 2 {
    69  						return fmt.Errorf("invalid endpoint data\nexpected: \n%s\nactual: \n%s", endpointCase.expectedRE, out)
    70  					}
    71  
    72  					namespaceMatch := matches[1]
    73  					if namespaceMatch != endpointCase.ns {
    74  						return fmt.Errorf("endpoint namespace does not match\nexpected: %s, actual: %s", endpointCase.ns, namespaceMatch)
    75  					}
    76  
    77  					return nil
    78  				})
    79  				if err != nil {
    80  					testutil.AnnotatedErrorf(t, "unexpected error", "unexpected error: %v", err)
    81  				}
    82  			})
    83  		}
    84  
    85  	})
    86  }
    87  
    88  // TODO: when #3004 gets fixed, add a negative test for mismatched ports
    89  func TestBadEndpoints(t *testing.T) {
    90  	_, stderr, err := TestHelper.PipeToLinkerdRun("", "diagnostics", "endpoints", "foo")
    91  	if err == nil {
    92  		testutil.AnnotatedFatalf(t, "was expecting an error", "was expecting an error: %v", err)
    93  	}
    94  	stderrOut := strings.Split(stderr, "\n")
    95  	if len(stderrOut) == 0 {
    96  		testutil.AnnotatedFatalf(t, "unexpected output", "unexpected output: %s", stderr)
    97  	}
    98  	if stderrOut[0] != "Destination API error: Invalid authority: foo" {
    99  		testutil.AnnotatedErrorf(t, "unexpected error string", "unexpected error string: %s", stderrOut[0])
   100  	}
   101  }
   102  
   103  func createTestCaseTable(controlNs, endpointNs string) []testCase {
   104  	return []testCase{
   105  		{
   106  			name:      "linkerd-dst",
   107  			authority: fmt.Sprintf("linkerd-dst.%s.svc.cluster.local:8086", controlNs),
   108  			expectedRE: `\[
   109    \{
   110      "namespace": "(\S*)",
   111      "ip": "[a-f0-9.:]+",
   112      "port": 8086,
   113      "pod": "linkerd-destination\-[a-f0-9]+\-[a-z0-9]+",
   114      "service": "linkerd-dst\.\S*",
   115      "weight": \d+,
   116      "http2": \{(?s).*\},
   117      "labels": \{(?s).*\}
   118    \}
   119  \]`,
   120  			ns: controlNs,
   121  		},
   122  		{
   123  			name:      "linkerd-identity",
   124  			authority: fmt.Sprintf("linkerd-identity.%s.svc.cluster.local:8080", controlNs),
   125  			expectedRE: `\[
   126    \{
   127      "namespace": "(\S*)",
   128      "ip": "[a-f0-9.:]+",
   129      "port": 8080,
   130      "pod": "linkerd-identity\-[a-f0-9]+\-[a-z0-9]+",
   131      "service": "linkerd-identity\.\S*",
   132      "weight": \d+,
   133      "http2": \{(?s).*\},
   134      "labels": \{(?s).*\}
   135    \}
   136  \]`,
   137  			ns: controlNs,
   138  		},
   139  		{
   140  			name:      "linkerd-proxy-injector",
   141  			authority: fmt.Sprintf("linkerd-proxy-injector.%s.svc.cluster.local:443", controlNs),
   142  			expectedRE: `\[
   143    \{
   144      "namespace": "(\S*)",
   145      "ip": "[a-f0-9.:]+",
   146      "port": 8443,
   147      "pod": "linkerd-proxy-injector-[a-f0-9]+\-[a-z0-9]+",
   148      "service": "linkerd-proxy-injector\.\S*",
   149      "weight": \d+,
   150      "http2": \{(?s).*\},
   151      "labels": \{(?s).*\}
   152    \}
   153  \]`,
   154  			ns: controlNs,
   155  		},
   156  		{
   157  			name:      "nginx",
   158  			authority: fmt.Sprintf("nginx.%s.svc.cluster.local:8080", endpointNs),
   159  			expectedRE: `\[
   160    \{
   161      "namespace": "(\S*)",
   162      "ip": "[a-f0-9.:]+",
   163      "port": 8080,
   164      "pod": "nginx-[a-f0-9]+\-[a-z0-9]+",
   165      "service": "nginx\.\S*",
   166      "weight": \d+,
   167      "http2": \{(?s).*\},
   168      "labels": \{(?s).*\}
   169    \}
   170  \]`,
   171  			ns: endpointNs,
   172  		},
   173  	}
   174  }
   175  

View as plain text