1 package norelay
2
3 import (
4 "context"
5 "fmt"
6 "net"
7 "os"
8 "strings"
9 "testing"
10
11 "github.com/linkerd/linkerd2/testutil"
12 )
13
14 var TestHelper *testutil.TestHelper
15
16 func TestMain(m *testing.M) {
17 TestHelper = testutil.NewTestHelper()
18
19 TestHelper.WaitUntilDeployReady(testutil.LinkerdDeployReplicasEdge)
20 os.Exit(m.Run())
21 }
22
23
24
25
26 func TestNoRelay(t *testing.T) {
27 ctx := context.Background()
28 deployments := getDeployments(t)
29 TestHelper.WithDataPlaneNamespace(ctx, "norelay-test", map[string]string{}, t, func(t *testing.T, ns string) {
30 for name, res := range deployments {
31 out, err := TestHelper.KubectlApply(res, ns)
32 if err != nil {
33 testutil.AnnotatedFatalf(t, "unexpected error",
34 "unexpected error with deployment %s: %v output:\n%s",
35 name, err, out,
36 )
37 }
38 }
39
40 for name := range deployments {
41 err := TestHelper.CheckPods(ctx, ns, name, 1)
42 if err != nil {
43
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
52 relayIPPort := getPodIPPort(t, ns, "app=server-relay", 4140)
53 o, err := TestHelper.Kubectl(
54 "", "-n", ns, "exec", "deploy/client",
55 "--", "curl", "-f", "-H", "l5d-dst-override: server-hello."+ns+".svc.cluster.local:8080", "http://"+relayIPPort,
56 )
57 if err == nil || err.Error() != "exit status 22" {
58 testutil.AnnotatedFatalf(t, "no error or unexpected error returned",
59 "no error or unexpected error returned: %s\n%s", o, err)
60 }
61 })
62 }
63
64
65
66
67
68
69
70
71
72
73 func TestRelay(t *testing.T) {
74 ctx := context.Background()
75 deployments := getDeployments(t)
76
77
78 deployments["server-relay"] = strings.ReplaceAll(
79 deployments["server-relay"],
80 "127.0.0.1:4140,[::1]:4140",
81 "'[::]:4140'",
82 )
83 deployments["server-relay"] = strings.ReplaceAll(
84 deployments["server-relay"],
85 "127.0.0.1:4140",
86 "0.0.0.0:4140",
87 )
88
89 TestHelper.WithDataPlaneNamespace(ctx, "relay-test", map[string]string{}, t, func(t *testing.T, ns string) {
90 for name, res := range deployments {
91 out, err := TestHelper.KubectlApply(res, ns)
92 if err != nil {
93 testutil.AnnotatedFatalf(t, "unexpected error",
94 "unexpected error with deployment %s: %v output:\n%s",
95 name, err, out,
96 )
97 }
98 }
99 waitForPods(t, ctx, ns, deployments)
100 relayIPPort := getPodIPPort(t, ns, "app=server-relay", 4140)
101
102
103 o, err := TestHelper.Kubectl(
104 "", "-n", ns, "exec", "deploy/client",
105 "--", "curl", "-fsv", "-H", "l5d-dst-override: server-hello."+ns+".svc.cluster.local:8080", "http://"+relayIPPort,
106 )
107 if err != nil {
108 log, err := TestHelper.Kubectl(
109 "", "logs",
110 "-n", ns,
111 "-l", "app=server-relay",
112 "-c", "linkerd-proxy",
113 "--tail=1000",
114 )
115 if err != nil {
116 log = fmt.Sprintf("failed to retrieve server-relay logs: %s", err)
117 }
118 testutil.AnnotatedFatalf(t, "unexpected error returned",
119 "unexpected error returned: %s\n%s\n---\n%s", o, err, log)
120 }
121 if !strings.Contains(o, "HELLO-FROM-SERVER") {
122 testutil.AnnotatedFatalf(t, "unexpected response returned",
123 "unexpected response returned: %s", o)
124 }
125 })
126 }
127
128 func getDeployments(t *testing.T) map[string]string {
129 deploys := make(map[string]string)
130 var err error
131
132
133 deploys["server-hello"], err = TestHelper.LinkerdRun("inject", "testdata/server-hello.yml")
134 if err != nil {
135 testutil.AnnotatedFatal(t, "unexpected error", err)
136 }
137
138
139 deploys["server-relay"], err = TestHelper.LinkerdRun(
140 "inject", "--manual", "--ingress",
141 "--proxy-log-level=linkerd=debug,info",
142 "testdata/server-relay.yml")
143 if err != nil {
144 testutil.AnnotatedFatal(t, "unexpected error", err)
145 }
146
147
148 deploys["client"], err = testutil.ReadFile("testdata/client.yml")
149 if err != nil {
150 testutil.AnnotatedFatalf(t, "failed to read 'client.yml'",
151 "failed to read 'client.yml': %s", err)
152 }
153
154 return deploys
155 }
156
157 func getPodIPPort(t *testing.T, ns, selector string, port int) string {
158 t.Helper()
159 ip, err := TestHelper.Kubectl(
160 "", "-n", ns, "get", "po", "-l", selector,
161 "-o", "jsonpath='{range .items[*]}{@.status.podIP}{end}'",
162 )
163 if err != nil {
164 testutil.AnnotatedFatalf(t, "failed to retrieve pod IP",
165 "failed to retrieve pod IP: %s", err)
166 }
167 ip = strings.Trim(ip, "'")
168 parsedIP := net.ParseIP(ip)
169 if parsedIP == nil {
170 testutil.AnnotatedFatalf(t, "invalid pod IP",
171 "invalid pod IP: %s", err)
172 }
173 if parsedIP.To4() != nil {
174 return fmt.Sprintf("%s:%d", ip, port)
175 }
176 return fmt.Sprintf("[%s]:%d", ip, port)
177 }
178
179 func waitForPods(t *testing.T, ctx context.Context, ns string, deployments map[string]string) {
180 t.Helper()
181 for name := range deployments {
182 err := TestHelper.CheckPods(ctx, ns, name, 1)
183 if err != nil {
184
185 if rce, ok := err.(*testutil.RestartCountError); ok {
186 testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
187 } else {
188 testutil.AnnotatedError(t, "CheckPods timed-out", err)
189 }
190 }
191 }
192 }
193
View as plain text