1 package inject
2
3 import (
4 "testing"
5
6 "github.com/go-test/deep"
7 l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
8 "github.com/linkerd/linkerd2/pkg/k8s"
9 "github.com/linkerd/linkerd2/pkg/util"
10 "github.com/linkerd/linkerd2/pkg/version"
11 appsv1 "k8s.io/api/apps/v1"
12 corev1 "k8s.io/api/core/v1"
13 k8sResource "k8s.io/apimachinery/pkg/api/resource"
14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15 "sigs.k8s.io/yaml"
16 )
17
18 func TestGetOverriddenValues(t *testing.T) {
19
20
21
22 var (
23 proxyVersionOverride = "proxy-version-override"
24 pullPolicy = "Always"
25 )
26
27 testConfig, err := l5dcharts.NewValues()
28 if err != nil {
29 t.Fatalf("Unexpected error: %v", err)
30 }
31
32 var testCases = []struct {
33 id string
34 nsAnnotations map[string]string
35 spec appsv1.DeploymentSpec
36 expected func() *l5dcharts.Values
37 }{
38 {id: "use overrides",
39 nsAnnotations: make(map[string]string),
40 spec: appsv1.DeploymentSpec{
41 Template: corev1.PodTemplateSpec{
42 ObjectMeta: metav1.ObjectMeta{
43 Annotations: map[string]string{
44 k8s.ProxyImageAnnotation: "cr.l5d.io/linkerd/proxy",
45 k8s.ProxyImagePullPolicyAnnotation: pullPolicy,
46 k8s.ProxyInitImageAnnotation: "cr.l5d.io/linkerd/proxy-init",
47 k8s.ProxyControlPortAnnotation: "4000",
48 k8s.ProxyInboundPortAnnotation: "5000",
49 k8s.ProxyAdminPortAnnotation: "5001",
50 k8s.ProxyOutboundPortAnnotation: "5002",
51 k8s.ProxyPodInboundPortsAnnotation: "1234,5678",
52 k8s.ProxyIgnoreInboundPortsAnnotation: "4222,6222",
53 k8s.ProxyIgnoreOutboundPortsAnnotation: "8079,8080",
54 k8s.ProxyCPURequestAnnotation: "0.15",
55 k8s.ProxyMemoryRequestAnnotation: "120",
56 k8s.ProxyEphemeralStorageRequestAnnotation: "10",
57 k8s.ProxyCPULimitAnnotation: "1.5",
58 k8s.ProxyMemoryLimitAnnotation: "256",
59 k8s.ProxyEphemeralStorageLimitAnnotation: "50",
60 k8s.ProxyUIDAnnotation: "8500",
61 k8s.ProxyGIDAnnotation: "8500",
62 k8s.ProxyLogLevelAnnotation: "debug,linkerd=debug",
63 k8s.ProxyLogFormatAnnotation: "json",
64 k8s.ProxyEnableExternalProfilesAnnotation: "false",
65 k8s.ProxyVersionOverrideAnnotation: proxyVersionOverride,
66 k8s.ProxyWaitBeforeExitSecondsAnnotation: "123",
67 k8s.ProxyRequireIdentityOnInboundPortsAnnotation: "8888,9999",
68 k8s.ProxyOutboundConnectTimeout: "6000ms",
69 k8s.ProxyInboundConnectTimeout: "600ms",
70 k8s.ProxyOpaquePortsAnnotation: "4320-4325,3306",
71 k8s.ProxyAwait: "enabled",
72 k8s.ProxySkipSubnetsAnnotation: "172.17.0.0/16",
73 k8s.ProxyAccessLogAnnotation: "apache",
74 k8s.ProxyShutdownGracePeriodAnnotation: "30s",
75 k8s.ProxyOutboundDiscoveryCacheUnusedTimeout: "50000ms",
76 k8s.ProxyInboundDiscoveryCacheUnusedTimeout: "900s",
77 k8s.ProxyDisableOutboundProtocolDetectTimeout: "true",
78 k8s.ProxyDisableInboundProtocolDetectTimeout: "true",
79 k8s.ProxyEnableNativeSidecarAnnotation: "true",
80 },
81 },
82 Spec: corev1.PodSpec{},
83 },
84 },
85 expected: func() *l5dcharts.Values {
86 values, _ := l5dcharts.NewValues()
87
88 values.Proxy.Cores = 2
89 values.Proxy.Image.Name = "cr.l5d.io/linkerd/proxy"
90 values.Proxy.Image.PullPolicy = pullPolicy
91 values.Proxy.Image.Version = proxyVersionOverride
92 values.Proxy.PodInboundPorts = "1234,5678"
93 values.Proxy.Ports.Control = 4000
94 values.Proxy.Ports.Inbound = 5000
95 values.Proxy.Ports.Admin = 5001
96 values.Proxy.Ports.Outbound = 5002
97 values.Proxy.WaitBeforeExitSeconds = 123
98 values.Proxy.LogLevel = "debug,linkerd=debug"
99 values.Proxy.LogFormat = "json"
100 values.Proxy.Resources = &l5dcharts.Resources{
101 CPU: l5dcharts.Constraints{
102 Limit: "1.5",
103 Request: "0.15",
104 },
105 Memory: l5dcharts.Constraints{
106 Limit: "256",
107 Request: "120",
108 },
109 EphemeralStorage: l5dcharts.Constraints{
110 Limit: "50",
111 Request: "10",
112 },
113 }
114 values.Proxy.UID = 8500
115 values.Proxy.GID = 8500
116 values.ProxyInit.Image.Name = "cr.l5d.io/linkerd/proxy-init"
117 values.ProxyInit.Image.PullPolicy = pullPolicy
118 values.ProxyInit.Image.Version = version.ProxyInitVersion
119 values.ProxyInit.IgnoreInboundPorts = "4222,6222"
120 values.ProxyInit.IgnoreOutboundPorts = "8079,8080"
121 values.ProxyInit.SkipSubnets = "172.17.0.0/16"
122 values.Proxy.RequireIdentityOnInboundPorts = "8888,9999"
123 values.Proxy.OutboundConnectTimeout = "6000ms"
124 values.Proxy.InboundConnectTimeout = "600ms"
125 values.Proxy.OpaquePorts = "4320-4325,3306"
126 values.Proxy.Await = true
127 values.Proxy.AccessLog = "apache"
128 values.Proxy.ShutdownGracePeriod = "30000ms"
129 values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "50s"
130 values.Proxy.InboundDiscoveryCacheUnusedTimeout = "900s"
131 values.Proxy.DisableOutboundProtocolDetectTimeout = true
132 values.Proxy.DisableInboundProtocolDetectTimeout = true
133 values.Proxy.NativeSidecar = true
134 return values
135 },
136 },
137 {id: "use defaults",
138 nsAnnotations: make(map[string]string),
139 spec: appsv1.DeploymentSpec{
140 Template: corev1.PodTemplateSpec{
141 ObjectMeta: metav1.ObjectMeta{},
142 Spec: corev1.PodSpec{},
143 },
144 },
145 expected: func() *l5dcharts.Values {
146 values, _ := l5dcharts.NewValues()
147 return values
148 },
149 },
150 {id: "use namespace overrides",
151 nsAnnotations: map[string]string{
152 k8s.ProxyImageAnnotation: "cr.l5d.io/linkerd/proxy",
153 k8s.ProxyImagePullPolicyAnnotation: pullPolicy,
154 k8s.ProxyInitImageAnnotation: "cr.l5d.io/linkerd/proxy-init",
155 k8s.ProxyControlPortAnnotation: "4000",
156 k8s.ProxyInboundPortAnnotation: "5000",
157 k8s.ProxyAdminPortAnnotation: "5001",
158 k8s.ProxyOutboundPortAnnotation: "5002",
159 k8s.ProxyPodInboundPortsAnnotation: "1234,5678",
160 k8s.ProxyIgnoreInboundPortsAnnotation: "4222,6222",
161 k8s.ProxyIgnoreOutboundPortsAnnotation: "8079,8080",
162 k8s.ProxyCPURequestAnnotation: "0.15",
163 k8s.ProxyMemoryRequestAnnotation: "120",
164 k8s.ProxyCPULimitAnnotation: "1.5",
165 k8s.ProxyMemoryLimitAnnotation: "256",
166 k8s.ProxyUIDAnnotation: "8500",
167 k8s.ProxyGIDAnnotation: "8500",
168 k8s.ProxyLogLevelAnnotation: "debug,linkerd=debug",
169 k8s.ProxyLogFormatAnnotation: "json",
170 k8s.ProxyEnableExternalProfilesAnnotation: "false",
171 k8s.ProxyVersionOverrideAnnotation: proxyVersionOverride,
172 k8s.ProxyWaitBeforeExitSecondsAnnotation: "123",
173 k8s.ProxyOutboundConnectTimeout: "6000ms",
174 k8s.ProxyInboundConnectTimeout: "600ms",
175 k8s.ProxyOpaquePortsAnnotation: "4320-4325,3306",
176 k8s.ProxyAwait: "enabled",
177 k8s.ProxyAccessLogAnnotation: "apache",
178 k8s.ProxyInjectAnnotation: "ingress",
179 k8s.ProxyOutboundDiscoveryCacheUnusedTimeout: "50s",
180 k8s.ProxyInboundDiscoveryCacheUnusedTimeout: "6000ms",
181 k8s.ProxyDisableOutboundProtocolDetectTimeout: "true",
182 k8s.ProxyDisableInboundProtocolDetectTimeout: "false",
183 k8s.ProxyEnableNativeSidecarAnnotation: "true",
184 },
185 spec: appsv1.DeploymentSpec{
186 Template: corev1.PodTemplateSpec{
187 Spec: corev1.PodSpec{},
188 },
189 },
190 expected: func() *l5dcharts.Values {
191 values, _ := l5dcharts.NewValues()
192
193 values.Proxy.Cores = 2
194 values.Proxy.Image.Name = "cr.l5d.io/linkerd/proxy"
195 values.Proxy.Image.PullPolicy = pullPolicy
196 values.Proxy.Image.Version = proxyVersionOverride
197 values.Proxy.PodInboundPorts = "1234,5678"
198 values.Proxy.Ports.Control = 4000
199 values.Proxy.Ports.Inbound = 5000
200 values.Proxy.Ports.Admin = 5001
201 values.Proxy.Ports.Outbound = 5002
202 values.Proxy.WaitBeforeExitSeconds = 123
203 values.Proxy.LogLevel = "debug,linkerd=debug"
204 values.Proxy.LogFormat = "json"
205 values.Proxy.Resources = &l5dcharts.Resources{
206 CPU: l5dcharts.Constraints{
207 Limit: "1.5",
208 Request: "0.15",
209 },
210 Memory: l5dcharts.Constraints{
211 Limit: "256",
212 Request: "120",
213 },
214 }
215 values.Proxy.UID = 8500
216 values.Proxy.GID = 8500
217 values.ProxyInit.Image.Name = "cr.l5d.io/linkerd/proxy-init"
218 values.ProxyInit.Image.PullPolicy = pullPolicy
219 values.ProxyInit.Image.Version = version.ProxyInitVersion
220 values.ProxyInit.IgnoreInboundPorts = "4222,6222"
221 values.ProxyInit.IgnoreOutboundPorts = "8079,8080"
222 values.Proxy.OutboundConnectTimeout = "6000ms"
223 values.Proxy.InboundConnectTimeout = "600ms"
224 values.Proxy.OpaquePorts = "4320-4325,3306"
225 values.Proxy.Await = true
226 values.Proxy.AccessLog = "apache"
227 values.Proxy.IsIngress = true
228 values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "50s"
229 values.Proxy.InboundDiscoveryCacheUnusedTimeout = "6s"
230 values.Proxy.DisableOutboundProtocolDetectTimeout = true
231 values.Proxy.DisableInboundProtocolDetectTimeout = false
232 values.Proxy.NativeSidecar = true
233 return values
234 },
235 },
236 {id: "use invalid duration for proxy timeouts",
237 nsAnnotations: map[string]string{
238 k8s.ProxyOutboundConnectTimeout: "6000",
239 k8s.ProxyInboundConnectTimeout: "600",
240 k8s.ProxyOutboundDiscoveryCacheUnusedTimeout: "50",
241 k8s.ProxyInboundDiscoveryCacheUnusedTimeout: "5000",
242 k8s.ProxyDisableOutboundProtocolDetectTimeout: "9000",
243 k8s.ProxyDisableInboundProtocolDetectTimeout: "9",
244 },
245 spec: appsv1.DeploymentSpec{
246 Template: corev1.PodTemplateSpec{
247 ObjectMeta: metav1.ObjectMeta{},
248 Spec: corev1.PodSpec{},
249 },
250 },
251 expected: func() *l5dcharts.Values {
252 values, _ := l5dcharts.NewValues()
253 return values
254 },
255 },
256 {id: "use valid duration for proxy timeouts",
257 nsAnnotations: map[string]string{
258
259 k8s.ProxyOutboundConnectTimeout: "6s5ms",
260 k8s.ProxyInboundConnectTimeout: "2s5ms",
261 k8s.ProxyOutboundDiscoveryCacheUnusedTimeout: "6s5000ms",
262 k8s.ProxyInboundDiscoveryCacheUnusedTimeout: "6s5000ms",
263 k8s.ProxyDisableOutboundProtocolDetectTimeout: "false",
264 k8s.ProxyDisableInboundProtocolDetectTimeout: "true",
265 },
266 spec: appsv1.DeploymentSpec{
267 Template: corev1.PodTemplateSpec{
268 ObjectMeta: metav1.ObjectMeta{},
269 Spec: corev1.PodSpec{},
270 },
271 },
272 expected: func() *l5dcharts.Values {
273 values, _ := l5dcharts.NewValues()
274 values.Proxy.OutboundConnectTimeout = "6005ms"
275 values.Proxy.InboundConnectTimeout = "2005ms"
276 values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "11s"
277 values.Proxy.InboundDiscoveryCacheUnusedTimeout = "11s"
278 values.Proxy.DisableOutboundProtocolDetectTimeout = false
279 values.Proxy.DisableInboundProtocolDetectTimeout = true
280 return values
281 },
282 },
283 {id: "use named port for opaque ports",
284 nsAnnotations: make(map[string]string),
285 spec: appsv1.DeploymentSpec{
286 Template: corev1.PodTemplateSpec{
287 ObjectMeta: metav1.ObjectMeta{
288 Annotations: map[string]string{
289 k8s.ProxyOpaquePortsAnnotation: "mysql",
290 },
291 },
292 Spec: corev1.PodSpec{
293 Containers: []corev1.Container{
294 {
295 Ports: []corev1.ContainerPort{
296 {
297 Name: "mysql",
298 ContainerPort: 3306,
299 },
300 },
301 },
302 },
303 },
304 },
305 },
306 expected: func() *l5dcharts.Values {
307 values, _ := l5dcharts.NewValues()
308 values.Proxy.OpaquePorts = "3306"
309 return values
310 },
311 },
312 }
313
314 for _, tc := range testCases {
315 testCase := tc
316 t.Run(testCase.id, func(t *testing.T) {
317 data, err := yaml.Marshal(&appsv1.Deployment{Spec: testCase.spec})
318 if err != nil {
319 t.Fatal(err)
320 }
321
322 resourceConfig := NewResourceConfig(testConfig, OriginUnknown, "linkerd").
323 WithKind("Deployment").WithNsAnnotations(testCase.nsAnnotations)
324 if err := resourceConfig.parse(data); err != nil {
325 t.Fatal(err)
326 }
327
328 AppendNamespaceAnnotations(resourceConfig.GetOverrideAnnotations(), resourceConfig.GetNsAnnotations(), resourceConfig.GetWorkloadAnnotations())
329 actual, err := GetOverriddenValues(
330 resourceConfig.values,
331 resourceConfig.getAnnotationOverrides(),
332 util.GetNamedPorts(resourceConfig.pod.spec.Containers),
333 )
334 if err != nil {
335 t.Fatal(err)
336 }
337 expected := testCase.expected()
338 if diff := deep.Equal(actual, expected); diff != nil {
339 t.Errorf("%+v", diff)
340 }
341 })
342 }
343 }
344
345 func TestWholeCPUCores(t *testing.T) {
346 for _, c := range []struct {
347 v string
348 n int
349 }{
350 {v: "1", n: 1},
351 {v: "1m", n: 1},
352 {v: "1000m", n: 1},
353 {v: "1001m", n: 2},
354 } {
355 q, err := k8sResource.ParseQuantity(c.v)
356 if err != nil {
357 t.Fatal(err)
358 }
359 n, err := ToWholeCPUCores(q)
360 if err != nil {
361 t.Fatal(err)
362 }
363 if n != int64(c.n) {
364 t.Fatalf("Unexpected value: %v != %v", n, c.n)
365 }
366 }
367 }
368
View as plain text