mirror of https://github.com/status-im/consul.git
Retry and timeout test acceptance test (#18791)
* retry and timeout test * add docker mirrior * checkpoint * add in error * add in delay * up error rate * fix status code
This commit is contained in:
parent
6838441c54
commit
753c8f1774
|
@ -9,5 +9,5 @@ import (
|
|||
|
||||
const (
|
||||
envoyLogLevel = "debug"
|
||||
hashicorpDockerProxy = "docker.mirror.hashicorp.services"
|
||||
HashicorpDockerProxy = "docker.mirror.hashicorp.services"
|
||||
)
|
||||
|
|
|
@ -187,7 +187,7 @@ func NewExampleService(ctx context.Context, name string, httpPort int, grpcPort
|
|||
command = append(command, containerArgs...)
|
||||
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: hashicorpDockerProxy + "/fortio/fortio",
|
||||
Image: HashicorpDockerProxy + "/fortio/fortio",
|
||||
WaitingFor: wait.ForLog("").WithStartupTimeout(60 * time.Second),
|
||||
AutoRemove: false,
|
||||
Name: containerName,
|
||||
|
|
|
@ -227,6 +227,7 @@ type checkOptions struct {
|
|||
responseHeaders map[string]string
|
||||
statusCode int
|
||||
testName string
|
||||
expectedBody string
|
||||
}
|
||||
|
||||
// checkRoute, customized version of libassert.RouteEchos to allow for headers/distinguishing between the server instances
|
||||
|
@ -289,8 +290,13 @@ func checkRoute(t *testing.T, port int, path string, headers map[string]string,
|
|||
return false
|
||||
}
|
||||
}
|
||||
if !strings.Contains(string(body), "hello") {
|
||||
t.Log("body does not contain 'hello'")
|
||||
expectedBody := expected.expectedBody
|
||||
if expectedBody == "" {
|
||||
expectedBody = "hello"
|
||||
}
|
||||
if !strings.Contains(string(body), expectedBody) {
|
||||
t.Log(string(body))
|
||||
t.Log("body does not contain " + expectedBody)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"k8s.io/utils/pointer"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -737,3 +739,233 @@ func TestHTTPRouteParentRefChange(t *testing.T) {
|
|||
"Host": "test.foo",
|
||||
}, "")
|
||||
}
|
||||
|
||||
func TestHTTPRouteRetryAndTimeout(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("too slow for testing.Short")
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
|
||||
// infrastructure set up
|
||||
listenerPort := 6018
|
||||
retryServiceHTTPPort := 6019
|
||||
retryServiceGRPCPort := 6020
|
||||
timeoutServiceHTTPPort := 6021
|
||||
timeoutServiceGRPCPort := 6022
|
||||
|
||||
retryServiceName := randomName("service", 16)
|
||||
gatewayName := randomName("gw", 16)
|
||||
retryRouteName := randomName("route", 16)
|
||||
timeoutServiceName := randomName("service", 16)
|
||||
timeoutRouteName := randomName("route", 16)
|
||||
retryPath := "/retry"
|
||||
timeoutPath := "/timeout"
|
||||
|
||||
clusterConfig := &libtopology.ClusterConfig{
|
||||
NumServers: 1,
|
||||
NumClients: 1,
|
||||
BuildOpts: &libcluster.BuildOptions{
|
||||
Datacenter: "dc1",
|
||||
InjectAutoEncryption: true,
|
||||
InjectGossipEncryption: true,
|
||||
AllowHTTPAnyway: true,
|
||||
},
|
||||
ExposedPorts: []int{
|
||||
listenerPort,
|
||||
retryServiceGRPCPort,
|
||||
retryServiceHTTPPort,
|
||||
timeoutServiceGRPCPort,
|
||||
timeoutServiceHTTPPort,
|
||||
},
|
||||
ApplyDefaultProxySettings: true,
|
||||
}
|
||||
|
||||
cluster, _, _ := libtopology.NewCluster(t, clusterConfig)
|
||||
client := cluster.Agents[0].GetClient()
|
||||
|
||||
namespace := getOrCreateNamespace(t, client)
|
||||
|
||||
_, _, err := libservice.CreateAndRegisterCustomServiceAndSidecar(
|
||||
cluster.Agents[0], &libservice.ServiceOpts{
|
||||
ID: retryServiceName,
|
||||
Name: retryServiceName,
|
||||
Namespace: namespace,
|
||||
HTTPPort: retryServiceHTTPPort,
|
||||
GRPCPort: retryServiceGRPCPort,
|
||||
},
|
||||
testcontainers.ContainerRequest{
|
||||
Image: libservice.HashicorpDockerProxy + "/nicholasjackson/fake-service:v0.26.0",
|
||||
Env: map[string]string{
|
||||
"LISTEN_ADDR": fmt.Sprintf("0.0.0.0:%d", retryServiceHTTPPort),
|
||||
"ERROR_RATE": "0.5",
|
||||
},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = libservice.CreateAndRegisterCustomServiceAndSidecar(
|
||||
cluster.Agents[0], &libservice.ServiceOpts{
|
||||
ID: timeoutServiceName,
|
||||
Name: timeoutServiceName,
|
||||
Namespace: namespace,
|
||||
HTTPPort: timeoutServiceHTTPPort,
|
||||
GRPCPort: timeoutServiceGRPCPort,
|
||||
},
|
||||
testcontainers.ContainerRequest{
|
||||
Image: libservice.HashicorpDockerProxy + "/nicholasjackson/fake-service:v0.26.0",
|
||||
Env: map[string]string{
|
||||
"LISTEN_ADDR": fmt.Sprintf("0.0.0.0:%d", timeoutServiceHTTPPort),
|
||||
"ERROR_RATE": "1.0",
|
||||
"ERROR_DELAY": "1m",
|
||||
},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// write config entries
|
||||
proxyDefaults := &api.ProxyConfigEntry{
|
||||
Kind: api.ProxyDefaults,
|
||||
Name: api.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, cluster.ConfigEntryWrite(proxyDefaults))
|
||||
|
||||
apiGateway := &api.APIGatewayConfigEntry{
|
||||
Kind: "api-gateway",
|
||||
Name: gatewayName,
|
||||
Listeners: []api.APIGatewayListener{
|
||||
{
|
||||
Name: "listener",
|
||||
Port: listenerPort,
|
||||
Protocol: "http",
|
||||
},
|
||||
},
|
||||
Namespace: namespace,
|
||||
}
|
||||
|
||||
retryRoute := &api.HTTPRouteConfigEntry{
|
||||
Kind: api.HTTPRoute,
|
||||
Name: retryRouteName,
|
||||
Namespace: namespace,
|
||||
Parents: []api.ResourceReference{
|
||||
{
|
||||
Kind: api.APIGateway,
|
||||
Name: gatewayName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
},
|
||||
Hostnames: []string{
|
||||
"test.foo",
|
||||
"test.example",
|
||||
},
|
||||
Rules: []api.HTTPRouteRule{
|
||||
{
|
||||
Filters: api.HTTPFilters{
|
||||
RetryFilter: &api.RetryFilter{
|
||||
NumRetries: pointer.Uint32(10),
|
||||
RetryOnStatusCodes: []uint32{500},
|
||||
},
|
||||
},
|
||||
Services: []api.HTTPService{
|
||||
{
|
||||
Name: retryServiceName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
},
|
||||
Matches: []api.HTTPMatch{
|
||||
{
|
||||
Path: api.HTTPPathMatch{
|
||||
Match: api.HTTPPathMatchPrefix,
|
||||
Value: retryPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
timeoutRoute := &api.HTTPRouteConfigEntry{
|
||||
Kind: api.HTTPRoute,
|
||||
Name: timeoutRouteName,
|
||||
Namespace: namespace,
|
||||
Parents: []api.ResourceReference{
|
||||
{
|
||||
Kind: api.APIGateway,
|
||||
Name: gatewayName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
},
|
||||
Hostnames: []string{
|
||||
"test.foo",
|
||||
"test.example",
|
||||
},
|
||||
Rules: []api.HTTPRouteRule{
|
||||
{
|
||||
Filters: api.HTTPFilters{
|
||||
TimeoutFilter: &api.TimeoutFilter{
|
||||
RequestTimeout: 1,
|
||||
IdleTimeout: 1,
|
||||
},
|
||||
},
|
||||
Services: []api.HTTPService{
|
||||
{
|
||||
Name: timeoutServiceName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
},
|
||||
Matches: []api.HTTPMatch{
|
||||
{
|
||||
Path: api.HTTPPathMatch{
|
||||
Match: api.HTTPPathMatchPrefix,
|
||||
Value: timeoutPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, cluster.ConfigEntryWrite(apiGateway))
|
||||
require.NoError(t, cluster.ConfigEntryWrite(timeoutRoute))
|
||||
require.NoError(t, cluster.ConfigEntryWrite(retryRoute))
|
||||
|
||||
// create gateway service
|
||||
gwCfg := libservice.GatewayConfig{
|
||||
Name: gatewayName,
|
||||
Kind: "api",
|
||||
Namespace: namespace,
|
||||
}
|
||||
gatewayService, err := libservice.NewGatewayService(context.Background(), gwCfg, cluster.Agents[0], listenerPort)
|
||||
require.NoError(t, err)
|
||||
libassert.CatalogServiceExists(t, client, gatewayName, &api.QueryOptions{Namespace: namespace})
|
||||
|
||||
// make sure config entries have been properly created
|
||||
checkGatewayConfigEntry(t, client, gatewayName, &api.QueryOptions{Namespace: namespace})
|
||||
t.Log("checking retry route")
|
||||
checkHTTPRouteConfigEntry(t, client, retryRouteName, &api.QueryOptions{Namespace: namespace})
|
||||
|
||||
t.Log("checking timeout route")
|
||||
checkHTTPRouteConfigEntry(t, client, timeoutRouteName, &api.QueryOptions{Namespace: namespace})
|
||||
|
||||
// gateway resolves routes
|
||||
gatewayPort, err := gatewayService.GetPort(listenerPort)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Gateway Port: ", gatewayPort)
|
||||
|
||||
// hit service 1 by hitting root path
|
||||
checkRoute(t, gatewayPort, retryPath, map[string]string{
|
||||
"Host": "test.foo",
|
||||
}, checkOptions{debug: false, statusCode: 200, testName: "retry should succeed cleanly", expectedBody: "Hello World"})
|
||||
|
||||
checkRoute(t, gatewayPort, timeoutPath, map[string]string{
|
||||
"Host": "test.foo",
|
||||
}, checkOptions{debug: false, statusCode: 500, testName: "timeout should timeout", expectedBody: "timeout"})
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue