Skip to content

Commit 6eb6949

Browse files
committed
🧪 test: add e2e test for timeout
1 parent 41b01a5 commit 6eb6949

File tree

4 files changed

+177
-23
lines changed

4 files changed

+177
-23
lines changed

‎go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ require (
4848
)
4949

5050
require (
51+
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c
5152
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
5253
github.com/BurntSushi/toml v1.3.2 // indirect
5354
github.com/beorn7/perks v1.0.1 // indirect

‎go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,8 @@ cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcP
597597
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
598598
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
599599
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
600+
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c h1:uhBf0CHXi7nCFZXxHV7l1cBcYFEEVRK4FYxvm1l9lKg=
601+
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c/go.mod h1:vYWKbnXd2KAZHUECLPzSE0Er3FgiEmOdPtxwSIRihck=
600602
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
601603
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
602604
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=

‎test/e2e/annotations/grpc.go

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import (
2222
"fmt"
2323
"strings"
2424

25+
delaypb "github.com/Anddd7/pb/grpcbin"
2526
pb "github.com/moul/pb/grpcbin/go-grpc"
2627
"github.com/onsi/ginkgo/v2"
2728
"github.com/stretchr/testify/assert"
2829
"google.golang.org/grpc"
2930
"google.golang.org/grpc/credentials"
31+
"google.golang.org/grpc/credentials/insecure"
3032
"google.golang.org/grpc/metadata"
3133
corev1 "k8s.io/api/core/v1"
3234
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -261,47 +263,86 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
261263
assert.Equal(ginkgo.GinkgoT(), metadata["content-type"].Values[0], "application/grpc")
262264
})
263265

264-
ginkgo.It("should set valid grpc timeouts for grpc", func() {
265-
proxyConnectTimeout := "5"
266-
proxySendTimeout := "30"
267-
proxyReadtimeout := "30"
266+
ginkgo.It("should return OK when request not exceed timeout", func() {
267+
f.NewGRPCBinDelayDeployment()
268+
269+
proxyTimeout := "10"
268270

269271
annotations := make(map[string]string)
270272
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPC"
271-
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyConnectTimeout
272-
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxySendTimeout
273-
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyReadtimeout
273+
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyTimeout
274+
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxyTimeout
275+
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyTimeout
276+
277+
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "grpcbin-delay", 50051, annotations)
274278

275-
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
276279
f.EnsureIngress(ing)
277280

278281
f.WaitForNginxServer(host,
279282
func(server string) bool {
280-
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyConnectTimeout)) &&
281-
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxySendTimeout)) &&
282-
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyReadtimeout))
283+
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyTimeout)) &&
284+
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxyTimeout)) &&
285+
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyTimeout))
283286
})
287+
288+
conn, err := grpc.Dial(
289+
f.GetNginxIP()+":80",
290+
grpc.WithTransportCredentials(insecure.NewCredentials()),
291+
grpc.WithAuthority(host),
292+
)
293+
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
294+
defer conn.Close()
295+
296+
client := delaypb.NewGrpcbinServiceClient(conn)
297+
298+
res, err := client.Unary(context.Background(), &delaypb.UnaryRequest{
299+
Data: "hello",
300+
})
301+
assert.Nil(ginkgo.GinkgoT(), err)
302+
303+
metadata := res.GetResponseAttributes().RequestHeaders
304+
assert.Equal(ginkgo.GinkgoT(), metadata["content-type"], "application/grpc")
305+
assert.Equal(ginkgo.GinkgoT(), metadata[":authority"], host)
284306
})
285307

286-
ginkgo.It("should set valid grpc timeouts for grpcs", func() {
287-
proxyConnectTimeout := "5"
288-
proxySendTimeout := "30"
289-
proxyReadtimeout := "30"
308+
ginkgo.It("should return Error when request exceed timeout", func() {
309+
f.NewGRPCBinDelayDeployment()
310+
311+
proxyTimeout := "10"
290312

291313
annotations := make(map[string]string)
292-
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPCS"
293-
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyConnectTimeout
294-
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxySendTimeout
295-
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyReadtimeout
314+
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPC"
315+
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyTimeout
316+
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxyTimeout
317+
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyTimeout
318+
319+
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "grpcbin-delay", 50051, annotations)
296320

297-
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
298321
f.EnsureIngress(ing)
299322

300323
f.WaitForNginxServer(host,
301324
func(server string) bool {
302-
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyConnectTimeout)) &&
303-
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxySendTimeout)) &&
304-
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyReadtimeout))
325+
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyTimeout)) &&
326+
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxyTimeout)) &&
327+
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyTimeout))
305328
})
329+
330+
conn, err := grpc.Dial(
331+
f.GetNginxIP()+":80",
332+
grpc.WithTransportCredentials(insecure.NewCredentials()),
333+
grpc.WithAuthority(host),
334+
)
335+
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
336+
defer conn.Close()
337+
338+
client := delaypb.NewGrpcbinServiceClient(conn)
339+
340+
_, err = client.Unary(context.Background(), &delaypb.UnaryRequest{
341+
Data: "hello",
342+
RequestAttributes: &delaypb.RequestAttributes{
343+
Delay: 15,
344+
},
345+
})
346+
assert.Error(ginkgo.GinkgoT(), err)
306347
})
307348
})

‎test/e2e/framework/grpc_delay.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
//nolint:dupl // Ignore dupl errors for similar test case
18+
package framework
19+
20+
import (
21+
"github.com/onsi/ginkgo/v2"
22+
"github.com/stretchr/testify/assert"
23+
appsv1 "k8s.io/api/apps/v1"
24+
corev1 "k8s.io/api/core/v1"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/fields"
27+
"k8s.io/apimachinery/pkg/util/intstr"
28+
)
29+
30+
// NewGRPCBinDelayDeployment creates a new single replica
31+
// deployment of the grpcbin image in a particular namespace
32+
func (f *Framework) NewGRPCBinDelayDeployment() {
33+
f.NewNewGRPCBinDelayDeploymentWithReplicas(1)
34+
}
35+
36+
// NewNewGRPCBinDelayDeploymentWithReplicas creates a new deployment of the
37+
// grpcbin image in a particular namespace. Number of replicas is configurable
38+
func (f *Framework) NewNewGRPCBinDelayDeploymentWithReplicas(replicas int32) {
39+
name := "grpcbin-delay"
40+
41+
deployment := &appsv1.Deployment{
42+
ObjectMeta: metav1.ObjectMeta{
43+
Name: name,
44+
Namespace: f.Namespace,
45+
},
46+
Spec: appsv1.DeploymentSpec{
47+
Replicas: NewInt32(replicas),
48+
Selector: &metav1.LabelSelector{
49+
MatchLabels: map[string]string{
50+
"app": name,
51+
},
52+
},
53+
Template: corev1.PodTemplateSpec{
54+
ObjectMeta: metav1.ObjectMeta{
55+
Labels: map[string]string{
56+
"app": name,
57+
},
58+
},
59+
Spec: corev1.PodSpec{
60+
TerminationGracePeriodSeconds: NewInt64(0),
61+
Containers: []corev1.Container{
62+
{
63+
Name: name,
64+
Image: "ghcr.io/anddd7/grpcbin:v1.0.5",
65+
Env: []corev1.EnvVar{},
66+
Ports: []corev1.ContainerPort{
67+
{
68+
Name: "grpc",
69+
ContainerPort: 50051,
70+
},
71+
},
72+
},
73+
},
74+
},
75+
},
76+
},
77+
}
78+
79+
d := f.EnsureDeployment(deployment)
80+
81+
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, &metav1.ListOptions{
82+
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
83+
})
84+
assert.Nil(ginkgo.GinkgoT(), err, "failed to wait for to become ready")
85+
86+
service := &corev1.Service{
87+
ObjectMeta: metav1.ObjectMeta{
88+
Name: name,
89+
Namespace: f.Namespace,
90+
},
91+
Spec: corev1.ServiceSpec{
92+
Ports: []corev1.ServicePort{
93+
{
94+
Name: "grpc",
95+
Port: 50051,
96+
TargetPort: intstr.FromInt(50051),
97+
Protocol: "TCP",
98+
},
99+
},
100+
Selector: map[string]string{
101+
"app": name,
102+
},
103+
},
104+
}
105+
106+
f.EnsureService(service)
107+
108+
err = WaitForEndpoints(f.KubeClientSet, DefaultTimeout, name, f.Namespace, int(replicas))
109+
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
110+
}

0 commit comments

Comments
 (0)