🧪 test: add e2e test for timeout

This commit is contained in:
Anddd7 2024-04-25 11:12:25 +08:00
parent 41b01a569f
commit 6eb6949c73
No known key found for this signature in database
GPG key ID: 10EB2713E5FEFB99
4 changed files with 177 additions and 23 deletions

1
go.mod
View file

@ -48,6 +48,7 @@ require (
)
require (
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect

2
go.sum
View file

@ -597,6 +597,8 @@ cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcP
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c h1:uhBf0CHXi7nCFZXxHV7l1cBcYFEEVRK4FYxvm1l9lKg=
github.com/Anddd7/pb v0.0.0-20240425032658-369b0f6a404c/go.mod h1:vYWKbnXd2KAZHUECLPzSE0Er3FgiEmOdPtxwSIRihck=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=

View file

@ -22,11 +22,13 @@ import (
"fmt"
"strings"
delaypb "github.com/Anddd7/pb/grpcbin"
pb "github.com/moul/pb/grpcbin/go-grpc"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -261,47 +263,86 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
assert.Equal(ginkgo.GinkgoT(), metadata["content-type"].Values[0], "application/grpc")
})
ginkgo.It("should set valid grpc timeouts for grpc", func() {
proxyConnectTimeout := "5"
proxySendTimeout := "30"
proxyReadtimeout := "30"
ginkgo.It("should return OK when request not exceed timeout", func() {
f.NewGRPCBinDelayDeployment()
proxyTimeout := "10"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPC"
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyConnectTimeout
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxySendTimeout
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyReadtimeout
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyTimeout
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxyTimeout
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyTimeout
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "grpcbin-delay", 50051, annotations)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyConnectTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxySendTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyReadtimeout))
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxyTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyTimeout))
})
conn, err := grpc.Dial(
f.GetNginxIP()+":80",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithAuthority(host),
)
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
defer conn.Close()
client := delaypb.NewGrpcbinServiceClient(conn)
res, err := client.Unary(context.Background(), &delaypb.UnaryRequest{
Data: "hello",
})
assert.Nil(ginkgo.GinkgoT(), err)
metadata := res.GetResponseAttributes().RequestHeaders
assert.Equal(ginkgo.GinkgoT(), metadata["content-type"], "application/grpc")
assert.Equal(ginkgo.GinkgoT(), metadata[":authority"], host)
})
ginkgo.It("should set valid grpc timeouts for grpcs", func() {
proxyConnectTimeout := "5"
proxySendTimeout := "30"
proxyReadtimeout := "30"
ginkgo.It("should return Error when request exceed timeout", func() {
f.NewGRPCBinDelayDeployment()
proxyTimeout := "10"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPCS"
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyConnectTimeout
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxySendTimeout
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyReadtimeout
annotations["nginx.ingress.kubernetes.io/backend-protocol"] = "GRPC"
annotations["nginx.ingress.kubernetes.io/proxy-connect-timeout"] = proxyTimeout
annotations["nginx.ingress.kubernetes.io/proxy-send-timeout"] = proxyTimeout
annotations["nginx.ingress.kubernetes.io/proxy-read-timeout"] = proxyTimeout
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "grpcbin-delay", 50051, annotations)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyConnectTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxySendTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyReadtimeout))
return strings.Contains(server, fmt.Sprintf("grpc_connect_timeout %ss;", proxyTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_send_timeout %ss;", proxyTimeout)) &&
strings.Contains(server, fmt.Sprintf("grpc_read_timeout %ss;", proxyTimeout))
})
conn, err := grpc.Dial(
f.GetNginxIP()+":80",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithAuthority(host),
)
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
defer conn.Close()
client := delaypb.NewGrpcbinServiceClient(conn)
_, err = client.Unary(context.Background(), &delaypb.UnaryRequest{
Data: "hello",
RequestAttributes: &delaypb.RequestAttributes{
Delay: 15,
},
})
assert.Error(ginkgo.GinkgoT(), err)
})
})

View file

@ -0,0 +1,110 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
//nolint:dupl // Ignore dupl errors for similar test case
package framework
import (
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/intstr"
)
// NewGRPCBinDelayDeployment creates a new single replica
// deployment of the grpcbin image in a particular namespace
func (f *Framework) NewGRPCBinDelayDeployment() {
f.NewNewGRPCBinDelayDeploymentWithReplicas(1)
}
// NewNewGRPCBinDelayDeploymentWithReplicas creates a new deployment of the
// grpcbin image in a particular namespace. Number of replicas is configurable
func (f *Framework) NewNewGRPCBinDelayDeploymentWithReplicas(replicas int32) {
name := "grpcbin-delay"
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: f.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: NewInt32(replicas),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": name,
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": name,
},
},
Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: NewInt64(0),
Containers: []corev1.Container{
{
Name: name,
Image: "ghcr.io/anddd7/grpcbin:v1.0.5",
Env: []corev1.EnvVar{},
Ports: []corev1.ContainerPort{
{
Name: "grpc",
ContainerPort: 50051,
},
},
},
},
},
},
},
}
d := f.EnsureDeployment(deployment)
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, &metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
assert.Nil(ginkgo.GinkgoT(), err, "failed to wait for to become ready")
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: f.Namespace,
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Name: "grpc",
Port: 50051,
TargetPort: intstr.FromInt(50051),
Protocol: "TCP",
},
},
Selector: map[string]string{
"app": name,
},
},
}
f.EnsureService(service)
err = WaitForEndpoints(f.KubeClientSet, DefaultTimeout, name, f.Namespace, int(replicas))
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
}