mirror of https://github.com/linkerd/linkerd2.git
175 lines
4.7 KiB
Go
175 lines
4.7 KiB
Go
package endpoints
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/linkerd/linkerd2/testutil"
|
|
)
|
|
|
|
var TestHelper *testutil.TestHelper
|
|
|
|
type testCase struct {
|
|
name string
|
|
authority string
|
|
expectedRE string
|
|
ns string
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
TestHelper = testutil.NewTestHelper()
|
|
// Block test execution until control plane is running
|
|
TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
func TestGoodEndpoints(t *testing.T) {
|
|
ctx := context.Background()
|
|
controlNs := TestHelper.GetLinkerdNamespace()
|
|
|
|
TestHelper.WithDataPlaneNamespace(ctx, "endpoints-test", map[string]string{}, t, func(t *testing.T, ns string) {
|
|
out, err := TestHelper.Kubectl("", "apply", "-f", "testdata/nginx.yaml", "-n", ns)
|
|
if err != nil {
|
|
testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out)
|
|
}
|
|
|
|
err = TestHelper.CheckPods(ctx, ns, "nginx", 1)
|
|
if err != nil {
|
|
//nolint:errorlint
|
|
if rce, ok := err.(*testutil.RestartCountError); ok {
|
|
testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
|
|
} else {
|
|
testutil.AnnotatedError(t, "CheckPods timed-out", err)
|
|
}
|
|
}
|
|
|
|
endpointCases := createTestCaseTable(controlNs, ns)
|
|
for _, endpointCase := range endpointCases {
|
|
testName := fmt.Sprintf("expect endpoints created for %s", endpointCase.name)
|
|
|
|
t.Run(testName, func(t *testing.T) {
|
|
err = testutil.RetryFor(5*time.Second, func() error {
|
|
out, err = TestHelper.LinkerdRun("diagnostics", "endpoints", endpointCase.authority, "-ojson")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get endpoints for %s: %w", endpointCase.authority, err)
|
|
}
|
|
|
|
re := regexp.MustCompile(endpointCase.expectedRE)
|
|
if !re.MatchString(out) {
|
|
return fmt.Errorf("endpoint data does not match pattern\nexpected output:\n%s\nactual:\n%s", endpointCase.expectedRE, out)
|
|
}
|
|
|
|
matches := re.FindStringSubmatch(out)
|
|
if matches == nil || len(matches) < 2 {
|
|
return fmt.Errorf("invalid endpoint data\nexpected: \n%s\nactual: \n%s", endpointCase.expectedRE, out)
|
|
}
|
|
|
|
namespaceMatch := matches[1]
|
|
if namespaceMatch != endpointCase.ns {
|
|
return fmt.Errorf("endpoint namespace does not match\nexpected: %s, actual: %s", endpointCase.ns, namespaceMatch)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
testutil.AnnotatedErrorf(t, "unexpected error", "unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
// TODO: when #3004 gets fixed, add a negative test for mismatched ports
|
|
func TestBadEndpoints(t *testing.T) {
|
|
_, stderr, err := TestHelper.PipeToLinkerdRun("", "diagnostics", "endpoints", "foo")
|
|
if err == nil {
|
|
testutil.AnnotatedFatalf(t, "was expecting an error", "was expecting an error: %v", err)
|
|
}
|
|
stderrOut := strings.Split(stderr, "\n")
|
|
if len(stderrOut) == 0 {
|
|
testutil.AnnotatedFatalf(t, "unexpected output", "unexpected output: %s", stderr)
|
|
}
|
|
if stderrOut[0] != "Destination API error: Invalid authority: foo" {
|
|
testutil.AnnotatedErrorf(t, "unexpected error string", "unexpected error string: %s", stderrOut[0])
|
|
}
|
|
}
|
|
|
|
func createTestCaseTable(controlNs, endpointNs string) []testCase {
|
|
return []testCase{
|
|
{
|
|
name: "linkerd-dst",
|
|
authority: fmt.Sprintf("linkerd-dst.%s.svc.cluster.local:8086", controlNs),
|
|
expectedRE: `\[
|
|
\{
|
|
"namespace": "(\S*)",
|
|
"ip": "[a-f0-9.:]+",
|
|
"port": 8086,
|
|
"pod": "linkerd-destination\-[a-f0-9]+\-[a-z0-9]+",
|
|
"service": "linkerd-dst\.\S*",
|
|
"weight": \d+,
|
|
"http2": \{(?s).*\},
|
|
"labels": \{(?s).*\}
|
|
\}
|
|
\]`,
|
|
ns: controlNs,
|
|
},
|
|
{
|
|
name: "linkerd-identity",
|
|
authority: fmt.Sprintf("linkerd-identity.%s.svc.cluster.local:8080", controlNs),
|
|
expectedRE: `\[
|
|
\{
|
|
"namespace": "(\S*)",
|
|
"ip": "[a-f0-9.:]+",
|
|
"port": 8080,
|
|
"pod": "linkerd-identity\-[a-f0-9]+\-[a-z0-9]+",
|
|
"service": "linkerd-identity\.\S*",
|
|
"weight": \d+,
|
|
"http2": \{(?s).*\},
|
|
"labels": \{(?s).*\}
|
|
\}
|
|
\]`,
|
|
ns: controlNs,
|
|
},
|
|
{
|
|
name: "linkerd-proxy-injector",
|
|
authority: fmt.Sprintf("linkerd-proxy-injector.%s.svc.cluster.local:443", controlNs),
|
|
expectedRE: `\[
|
|
\{
|
|
"namespace": "(\S*)",
|
|
"ip": "[a-f0-9.:]+",
|
|
"port": 8443,
|
|
"pod": "linkerd-proxy-injector-[a-f0-9]+\-[a-z0-9]+",
|
|
"service": "linkerd-proxy-injector\.\S*",
|
|
"weight": \d+,
|
|
"http2": \{(?s).*\},
|
|
"labels": \{(?s).*\}
|
|
\}
|
|
\]`,
|
|
ns: controlNs,
|
|
},
|
|
{
|
|
name: "nginx",
|
|
authority: fmt.Sprintf("nginx.%s.svc.cluster.local:8080", endpointNs),
|
|
expectedRE: `\[
|
|
\{
|
|
"namespace": "(\S*)",
|
|
"ip": "[a-f0-9.:]+",
|
|
"port": 8080,
|
|
"pod": "nginx-[a-f0-9]+\-[a-z0-9]+",
|
|
"service": "nginx\.\S*",
|
|
"weight": \d+,
|
|
"http2": \{(?s).*\},
|
|
"labels": \{(?s).*\}
|
|
\}
|
|
\]`,
|
|
ns: endpointNs,
|
|
},
|
|
}
|
|
}
|