istio

Форк
0
/
conversion_test.go 
477 строк · 12.7 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package kube
16

17
import (
18
	"fmt"
19
	"reflect"
20
	"strings"
21
	"testing"
22
	"time"
23

24
	corev1 "k8s.io/api/core/v1"
25
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26

27
	"istio.io/api/annotation"
28
	"istio.io/istio/pkg/cluster"
29
	"istio.io/istio/pkg/config/kube"
30
	"istio.io/istio/pkg/config/protocol"
31
	"istio.io/istio/pkg/spiffe"
32
)
33

34
var (
35
	domainSuffix = "company.com"
36
	clusterID    = cluster.ID("test-cluster")
37
)
38

39
func TestConvertProtocol(t *testing.T) {
40
	http := "http"
41
	type protocolCase struct {
42
		port        int32
43
		name        string
44
		appProtocol *string
45
		proto       corev1.Protocol
46
		out         protocol.Instance
47
	}
48
	protocols := []protocolCase{
49
		{8888, "", nil, corev1.ProtocolTCP, protocol.Unsupported},
50
		{25, "", nil, corev1.ProtocolTCP, protocol.TCP},
51
		{53, "", nil, corev1.ProtocolTCP, protocol.TCP},
52
		{3306, "", nil, corev1.ProtocolTCP, protocol.TCP},
53
		{27017, "", nil, corev1.ProtocolTCP, protocol.TCP},
54
		{8888, "http", nil, corev1.ProtocolTCP, protocol.HTTP},
55
		{8888, "http-test", nil, corev1.ProtocolTCP, protocol.HTTP},
56
		{8888, "http", nil, corev1.ProtocolUDP, protocol.UDP},
57
		{8888, "httptest", nil, corev1.ProtocolTCP, protocol.Unsupported},
58
		{25, "httptest", nil, corev1.ProtocolTCP, protocol.TCP},
59
		{53, "httptest", nil, corev1.ProtocolTCP, protocol.TCP},
60
		{3306, "httptest", nil, corev1.ProtocolTCP, protocol.TCP},
61
		{27017, "httptest", nil, corev1.ProtocolTCP, protocol.TCP},
62
		{8888, "https", nil, corev1.ProtocolTCP, protocol.HTTPS},
63
		{8888, "https-test", nil, corev1.ProtocolTCP, protocol.HTTPS},
64
		{8888, "http2", nil, corev1.ProtocolTCP, protocol.HTTP2},
65
		{8888, "http2-test", nil, corev1.ProtocolTCP, protocol.HTTP2},
66
		{8888, "grpc", nil, corev1.ProtocolTCP, protocol.GRPC},
67
		{8888, "grpc-test", nil, corev1.ProtocolTCP, protocol.GRPC},
68
		{8888, "grpc-web", nil, corev1.ProtocolTCP, protocol.GRPCWeb},
69
		{8888, "grpc-web-test", nil, corev1.ProtocolTCP, protocol.GRPCWeb},
70
		{8888, "mongo", nil, corev1.ProtocolTCP, protocol.Mongo},
71
		{8888, "mongo-test", nil, corev1.ProtocolTCP, protocol.Mongo},
72
		{8888, "redis", nil, corev1.ProtocolTCP, protocol.Redis},
73
		{8888, "redis-test", nil, corev1.ProtocolTCP, protocol.Redis},
74
		{8888, "mysql", nil, corev1.ProtocolTCP, protocol.MySQL},
75
		{8888, "mysql-test", nil, corev1.ProtocolTCP, protocol.MySQL},
76
		{8888, "tcp", &http, corev1.ProtocolTCP, protocol.HTTP},
77
	}
78

79
	// Create the list of cases for all of the names in both upper and lowercase.
80
	cases := make([]protocolCase, 0, len(protocols)*2)
81
	for _, p := range protocols {
82
		name := p.name
83

84
		p.name = strings.ToLower(name)
85
		cases = append(cases, p)
86

87
		// Don't bother adding uppercase version for empty string.
88
		if name != "" {
89
			p.name = strings.ToUpper(name)
90
			cases = append(cases, p)
91
		}
92
	}
93

94
	for _, c := range cases {
95
		testName := strings.Replace(fmt.Sprintf("%s_%s_%d", c.name, c.proto, c.port), "-", "_", -1)
96
		t.Run(testName, func(t *testing.T) {
97
			out := kube.ConvertProtocol(c.port, c.name, c.proto, c.appProtocol)
98
			if out != c.out {
99
				t.Fatalf("convertProtocol(%d, %q, %q) => %q, want %q", c.port, c.name, c.proto, out, c.out)
100
			}
101
		})
102
	}
103
}
104

105
func BenchmarkConvertProtocol(b *testing.B) {
106
	cases := []struct {
107
		name  string
108
		proto corev1.Protocol
109
		out   protocol.Instance
110
	}{
111
		{"grpc-web-lowercase", corev1.ProtocolTCP, protocol.GRPCWeb},
112
		{"GRPC-WEB-mixedcase", corev1.ProtocolTCP, protocol.GRPCWeb},
113
		{"https-lowercase", corev1.ProtocolTCP, protocol.HTTPS},
114
		{"HTTPS-mixedcase", corev1.ProtocolTCP, protocol.HTTPS},
115
	}
116

117
	for _, c := range cases {
118
		testName := strings.Replace(c.name, "-", "_", -1)
119
		b.Run(testName, func(b *testing.B) {
120
			for i := 0; i < b.N; i++ {
121
				out := kube.ConvertProtocol(8888, c.name, c.proto, nil)
122
				if out != c.out {
123
					b.Fatalf("convertProtocol(%q, %q) => %q, want %q", c.name, c.proto, out, c.out)
124
				}
125
			}
126
		})
127
	}
128
}
129

130
func TestServiceConversion(t *testing.T) {
131
	serviceName := "service1"
132
	namespace := "default"
133
	saA := "serviceaccountA"
134
	saB := "serviceaccountB"
135
	saC := "spiffe://accounts.google.com/serviceaccountC@cloudservices.gserviceaccount.com"
136
	saD := "spiffe://accounts.google.com/serviceaccountD@developer.gserviceaccount.com"
137

138
	oldTrustDomain := spiffe.GetTrustDomain()
139
	spiffe.SetTrustDomain(domainSuffix)
140
	defer spiffe.SetTrustDomain(oldTrustDomain)
141

142
	ip := "10.0.0.1"
143

144
	tnow := time.Now()
145
	localSvc := corev1.Service{
146
		ObjectMeta: metav1.ObjectMeta{
147
			Name:      serviceName,
148
			Namespace: namespace,
149
			Annotations: map[string]string{
150
				annotation.AlphaKubernetesServiceAccounts.Name: saA + "," + saB,
151
				annotation.AlphaCanonicalServiceAccounts.Name:  saC + "," + saD,
152
				"other/annotation": "test",
153
			},
154
			CreationTimestamp: metav1.Time{Time: tnow},
155
		},
156
		Spec: corev1.ServiceSpec{
157
			ClusterIP: ip,
158
			Selector:  map[string]string{"foo": "bar"},
159
			Ports: []corev1.ServicePort{
160
				{
161
					Name:     "http",
162
					Port:     8080,
163
					Protocol: corev1.ProtocolTCP,
164
				},
165
				{
166
					Name:     "https",
167
					Protocol: corev1.ProtocolTCP,
168
					Port:     443,
169
				},
170
			},
171
		},
172
	}
173

174
	service := ConvertService(localSvc, domainSuffix, clusterID)
175
	if service == nil {
176
		t.Fatalf("could not convert service")
177
	}
178

179
	if service.CreationTime != tnow {
180
		t.Fatalf("incorrect creation time => %v, want %v", service.CreationTime, tnow)
181
	}
182

183
	if len(service.Ports) != len(localSvc.Spec.Ports) {
184
		t.Fatalf("incorrect number of ports => %v, want %v",
185
			len(service.Ports), len(localSvc.Spec.Ports))
186
	}
187

188
	if service.External() {
189
		t.Fatal("service should not be external")
190
	}
191

192
	if service.Hostname != ServiceHostname(serviceName, namespace, domainSuffix) {
193
		t.Fatalf("service hostname incorrect => %q, want %q",
194
			service.Hostname, ServiceHostname(serviceName, namespace, domainSuffix))
195
	}
196

197
	ips := service.ClusterVIPs.GetAddressesFor(clusterID)
198
	if len(ips) != 1 {
199
		t.Fatalf("number of ips incorrect => %q, want 1", len(ips))
200
	}
201

202
	if ips[0] != ip {
203
		t.Fatalf("service IP incorrect => %q, want %q", ips[0], ip)
204
	}
205

206
	actualIPs := service.ClusterVIPs.GetAddressesFor(clusterID)
207
	expectedIPs := []string{ip}
208
	if !reflect.DeepEqual(actualIPs, expectedIPs) {
209
		t.Fatalf("service IPs incorrect => %q, want %q", actualIPs, expectedIPs)
210
	}
211

212
	if !reflect.DeepEqual(service.Attributes.LabelSelectors, localSvc.Spec.Selector) {
213
		t.Fatalf("service label selectors incorrect => %q, want %q", service.Attributes.LabelSelectors,
214
			localSvc.Spec.Selector)
215
	}
216

217
	sa := service.ServiceAccounts
218
	if sa == nil || len(sa) != 4 {
219
		t.Fatalf("number of service accounts is incorrect")
220
	}
221
	expected := []string{
222
		saC, saD,
223
		"spiffe://company.com/ns/default/sa/" + saA,
224
		"spiffe://company.com/ns/default/sa/" + saB,
225
	}
226
	if !reflect.DeepEqual(sa, expected) {
227
		t.Fatalf("Unexpected service accounts %v (expecting %v)", sa, expected)
228
	}
229
}
230

231
func TestServiceConversionWithEmptyServiceAccountsAnnotation(t *testing.T) {
232
	serviceName := "service1"
233
	namespace := "default"
234

235
	ip := "10.0.0.1"
236

237
	localSvc := corev1.Service{
238
		ObjectMeta: metav1.ObjectMeta{
239
			Name:        serviceName,
240
			Namespace:   namespace,
241
			Annotations: map[string]string{},
242
		},
243
		Spec: corev1.ServiceSpec{
244
			ClusterIP: ip,
245
			Ports: []corev1.ServicePort{
246
				{
247
					Name:     "http",
248
					Port:     8080,
249
					Protocol: corev1.ProtocolTCP,
250
				},
251
				{
252
					Name:     "https",
253
					Protocol: corev1.ProtocolTCP,
254
					Port:     443,
255
				},
256
			},
257
		},
258
	}
259

260
	service := ConvertService(localSvc, domainSuffix, clusterID)
261
	if service == nil {
262
		t.Fatalf("could not convert service")
263
	}
264

265
	sa := service.ServiceAccounts
266
	if len(sa) != 0 {
267
		t.Fatalf("number of service accounts is incorrect: %d, expected 0", len(sa))
268
	}
269
}
270

271
func TestExternalServiceConversion(t *testing.T) {
272
	serviceName := "service1"
273
	namespace := "default"
274

275
	extSvc := corev1.Service{
276
		ObjectMeta: metav1.ObjectMeta{
277
			Name:      serviceName,
278
			Namespace: namespace,
279
		},
280
		Spec: corev1.ServiceSpec{
281
			Ports: []corev1.ServicePort{
282
				{
283
					Name:     "http",
284
					Port:     80,
285
					Protocol: corev1.ProtocolTCP,
286
				},
287
			},
288
			Type:         corev1.ServiceTypeExternalName,
289
			ExternalName: "google.com",
290
		},
291
	}
292

293
	service := ConvertService(extSvc, domainSuffix, clusterID)
294
	if service == nil {
295
		t.Fatalf("could not convert external service")
296
	}
297

298
	if len(service.Ports) != len(extSvc.Spec.Ports) {
299
		t.Fatalf("incorrect number of ports => %v, want %v",
300
			len(service.Ports), len(extSvc.Spec.Ports))
301
	}
302

303
	if !service.External() {
304
		t.Fatal("service should be external")
305
	}
306

307
	if service.Hostname != ServiceHostname(serviceName, namespace, domainSuffix) {
308
		t.Fatalf("service hostname incorrect => %q, want %q",
309
			service.Hostname, ServiceHostname(serviceName, namespace, domainSuffix))
310
	}
311

312
	if service.Attributes.Type != string(extSvc.Spec.Type) ||
313
		service.Attributes.ExternalName != extSvc.Spec.ExternalName {
314
		t.Fatalf("service attributes incorrect => %v/%v, want %v/%v",
315
			service.Attributes.Type, service.Attributes.ExternalName, extSvc.Spec.Type, extSvc.Spec.ExternalName)
316
	}
317
}
318

319
func TestExternalClusterLocalServiceConversion(t *testing.T) {
320
	serviceName := "service1"
321
	namespace := "default"
322

323
	extSvc := corev1.Service{
324
		ObjectMeta: metav1.ObjectMeta{
325
			Name:      serviceName,
326
			Namespace: namespace,
327
		},
328
		Spec: corev1.ServiceSpec{
329
			Ports: []corev1.ServicePort{
330
				{
331
					Name:     "http",
332
					Port:     80,
333
					Protocol: corev1.ProtocolTCP,
334
				},
335
			},
336
			Type:         corev1.ServiceTypeExternalName,
337
			ExternalName: "some.test.svc.cluster.local",
338
		},
339
	}
340

341
	domainSuffix := "cluster.local"
342

343
	service := ConvertService(extSvc, domainSuffix, clusterID)
344
	if service == nil {
345
		t.Fatalf("could not convert external service")
346
	}
347

348
	if len(service.Ports) != len(extSvc.Spec.Ports) {
349
		t.Fatalf("incorrect number of ports => %v, want %v",
350
			len(service.Ports), len(extSvc.Spec.Ports))
351
	}
352

353
	if !service.External() {
354
		t.Fatal("ExternalName service (even if .cluster.local) should be external")
355
	}
356

357
	if service.Hostname != ServiceHostname(serviceName, namespace, domainSuffix) {
358
		t.Fatalf("service hostname incorrect => %q, want %q",
359
			service.Hostname, ServiceHostname(serviceName, namespace, domainSuffix))
360
	}
361
}
362

363
func TestLBServiceConversion(t *testing.T) {
364
	serviceName := "service1"
365
	namespace := "default"
366

367
	addresses := []corev1.LoadBalancerIngress{
368
		{
369
			IP: "127.68.32.112",
370
		},
371
		{
372
			IP: "127.68.32.113",
373
		},
374
		{
375
			Hostname: "127.68.32.114",
376
		},
377
		{
378
			Hostname: "127.68.32.115",
379
		},
380
	}
381

382
	extSvc := corev1.Service{
383
		ObjectMeta: metav1.ObjectMeta{
384
			Name:      serviceName,
385
			Namespace: namespace,
386
		},
387
		Spec: corev1.ServiceSpec{
388
			Ports: []corev1.ServicePort{
389
				{
390
					Name:     "http",
391
					Port:     80,
392
					Protocol: corev1.ProtocolTCP,
393
				},
394
			},
395
			Type: corev1.ServiceTypeLoadBalancer,
396
		},
397
		Status: corev1.ServiceStatus{
398
			LoadBalancer: corev1.LoadBalancerStatus{
399
				Ingress: addresses,
400
			},
401
		},
402
	}
403

404
	service := ConvertService(extSvc, domainSuffix, clusterID)
405
	if service == nil {
406
		t.Fatalf("could not convert external service")
407
	}
408

409
	gotAddresses := service.Attributes.ClusterExternalAddresses.GetAddressesFor(clusterID)
410
	if len(gotAddresses) == 0 {
411
		t.Fatalf("no load balancer addresses found")
412
	}
413

414
	for i, addr := range addresses {
415
		var want string
416
		if len(addr.IP) > 0 {
417
			want = addr.IP
418
		} else {
419
			want = addr.Hostname
420
		}
421
		got := gotAddresses[i]
422
		if got != want {
423
			t.Fatalf("Expected address %s but got %s", want, got)
424
		}
425
	}
426
}
427

428
func TestInternalTrafficPolicyServiceConversion(t *testing.T) {
429
	serviceName := "service1"
430
	namespace := "default"
431
	local := corev1.ServiceInternalTrafficPolicyLocal
432

433
	svc := corev1.Service{
434
		ObjectMeta: metav1.ObjectMeta{
435
			Name:      serviceName,
436
			Namespace: namespace,
437
		},
438
		Spec: corev1.ServiceSpec{
439
			Ports: []corev1.ServicePort{
440
				{
441
					Name:     "http",
442
					Port:     80,
443
					Protocol: corev1.ProtocolTCP,
444
				},
445
			},
446
			InternalTrafficPolicy: &local,
447
		},
448
	}
449

450
	service := ConvertService(svc, domainSuffix, clusterID)
451
	if service == nil {
452
		t.Fatalf("could not convert service")
453
	}
454

455
	if !service.Attributes.NodeLocal {
456
		t.Fatal("not node local")
457
	}
458
}
459

460
func TestSecureNamingSAN(t *testing.T) {
461
	pod := &corev1.Pod{}
462

463
	pod.Annotations = make(map[string]string)
464

465
	ns := "anything"
466
	sa := "foo"
467
	pod.Namespace = ns
468
	pod.Spec.ServiceAccountName = sa
469

470
	san := SecureNamingSAN(pod)
471

472
	expectedSAN := fmt.Sprintf("spiffe://%v/ns/%v/sa/%v", spiffe.GetTrustDomain(), ns, sa)
473

474
	if san != expectedSAN {
475
		t.Fatalf("SAN match failed, SAN:%v  expectedSAN:%v", san, expectedSAN)
476
	}
477
}
478

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.