mirror of https://github.com/status-im/consul.git
mesh: compute more of the xRoute features into ComputedRoutes (#18980)
Convert more of the xRoutes features that were skipped in an earlier PR into ComputedRoutes and make them work: - DestinationPolicy defaults - more timeouts - load balancer policy - request/response header mutations - urlrewrite - GRPCRoute matches
This commit is contained in:
parent
d3bb5ff21a
commit
9e48607893
|
@ -11,8 +11,6 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
|
|
||||||
|
|
||||||
svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing"
|
svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing"
|
||||||
"github.com/hashicorp/consul/internal/catalog"
|
"github.com/hashicorp/consul/internal/catalog"
|
||||||
"github.com/hashicorp/consul/internal/controller"
|
"github.com/hashicorp/consul/internal/controller"
|
||||||
|
@ -20,6 +18,7 @@ import (
|
||||||
"github.com/hashicorp/consul/internal/resource"
|
"github.com/hashicorp/consul/internal/resource"
|
||||||
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
|
rtest "github.com/hashicorp/consul/internal/resource/resourcetest"
|
||||||
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
||||||
|
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
|
||||||
"github.com/hashicorp/consul/proto-public/pbresource"
|
"github.com/hashicorp/consul/proto-public/pbresource"
|
||||||
"github.com/hashicorp/consul/proto/private/prototest"
|
"github.com/hashicorp/consul/proto/private/prototest"
|
||||||
"github.com/hashicorp/consul/sdk/testutil"
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
|
@ -112,9 +111,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "tcp"): {
|
backendName("api", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -184,9 +184,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "tcp"): {
|
backendName("api", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -211,9 +212,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http"): {
|
backendName("api", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -238,9 +240,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http2"): {
|
backendName("api", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http2", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -260,9 +263,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "grpc"): {
|
backendName("api", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(apiServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -347,9 +351,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "tcp"): {
|
backendName("foo", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -376,9 +381,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -405,9 +411,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "grpc"): {
|
backendName("foo", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -434,9 +441,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http2"): {
|
backendName("foo", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -548,9 +556,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "tcp"): {
|
backendName("foo", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -588,9 +597,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -629,9 +639,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "grpc"): {
|
backendName("foo", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -669,9 +680,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http2"): {
|
backendName("foo", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -786,9 +798,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "tcp"): {
|
backendName("foo", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -815,9 +828,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -844,9 +858,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "grpc"): {
|
backendName("foo", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -873,9 +888,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http2"): {
|
backendName("foo", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -952,9 +968,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "tcp"): {
|
backendName("foo", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -981,9 +998,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1010,9 +1028,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "grpc"): {
|
backendName("foo", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1039,9 +1058,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http2"): {
|
backendName("foo", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1166,9 +1186,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http"): {
|
backendName("api", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1204,9 +1225,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http"): {
|
backendName("api", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1260,9 +1282,10 @@ func (suite *controllerSuite) TestController() {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("bar", "http"): {
|
backendName("bar", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,10 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/internal/catalog"
|
"github.com/hashicorp/consul/internal/catalog"
|
||||||
"github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader"
|
"github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/loader"
|
||||||
|
@ -334,6 +338,72 @@ func compile(
|
||||||
details.DestinationConfig = portDestConfig
|
details.DestinationConfig = portDestConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
details.DestinationConfig = fillInDefaultDestConfig(details.DestinationConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull target information up to the level of the rules.
|
||||||
|
switch x := mc.Config.(type) {
|
||||||
|
case *pbmesh.ComputedPortRoutes_Http:
|
||||||
|
route := x.Http
|
||||||
|
for _, rule := range route.Rules {
|
||||||
|
// If there are multiple legs (split) then choose the first actually set value.
|
||||||
|
var requestTimeoutFallback *durationpb.Duration
|
||||||
|
for _, backendRef := range rule.BackendRefs {
|
||||||
|
if backendRef.BackendTarget == types.NullRouteBackend {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
details, ok := mc.Targets[backendRef.BackendTarget]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if details.DestinationConfig.RequestTimeout != nil {
|
||||||
|
requestTimeoutFallback = details.DestinationConfig.RequestTimeout
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestTimeoutFallback == nil {
|
||||||
|
continue // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
if rule.Timeouts == nil {
|
||||||
|
rule.Timeouts = &pbmesh.HTTPRouteTimeouts{}
|
||||||
|
}
|
||||||
|
if rule.Timeouts.Request == nil {
|
||||||
|
rule.Timeouts.Request = requestTimeoutFallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *pbmesh.ComputedPortRoutes_Grpc:
|
||||||
|
route := x.Grpc
|
||||||
|
for _, rule := range route.Rules {
|
||||||
|
// If there are multiple legs (split) then choose the first actually set value.
|
||||||
|
var requestTimeoutFallback *durationpb.Duration
|
||||||
|
for _, backendRef := range rule.BackendRefs {
|
||||||
|
if backendRef.BackendTarget == types.NullRouteBackend {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
details, ok := mc.Targets[backendRef.BackendTarget]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if details.DestinationConfig.RequestTimeout != nil {
|
||||||
|
requestTimeoutFallback = details.DestinationConfig.RequestTimeout
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestTimeoutFallback == nil {
|
||||||
|
continue // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
if rule.Timeouts == nil {
|
||||||
|
rule.Timeouts = &pbmesh.HTTPRouteTimeouts{}
|
||||||
|
}
|
||||||
|
if rule.Timeouts.Request == nil {
|
||||||
|
rule.Timeouts.Request = requestTimeoutFallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *pbmesh.ComputedPortRoutes_Tcp:
|
||||||
}
|
}
|
||||||
|
|
||||||
computedRoutes.PortedConfigs[port] = mc
|
computedRoutes.PortedConfigs[port] = mc
|
||||||
|
@ -412,6 +482,28 @@ func compileFailoverConfig(
|
||||||
return cfc
|
return cfc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fillInDefaultDestConfig(target *pbmesh.DestinationConfig) *pbmesh.DestinationConfig {
|
||||||
|
base := defaultDestConfig()
|
||||||
|
|
||||||
|
if target == nil {
|
||||||
|
return proto.Clone(base).(*pbmesh.DestinationConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := proto.Clone(target).(*pbmesh.DestinationConfig)
|
||||||
|
|
||||||
|
if out.ConnectTimeout == nil {
|
||||||
|
out.ConnectTimeout = base.GetConnectTimeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultDestConfig() *pbmesh.DestinationConfig {
|
||||||
|
return &pbmesh.DestinationConfig{
|
||||||
|
ConnectTimeout: durationpb.New(5 * time.Second),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func compileHTTPRouteNode(
|
func compileHTTPRouteNode(
|
||||||
port string,
|
port string,
|
||||||
res *pbresource.Resource,
|
res *pbresource.Resource,
|
||||||
|
|
|
@ -222,9 +222,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "tcp"): {
|
backendName("api", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(apiServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -282,9 +283,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", protoName): {
|
backendName("api", protoName): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, protoName, ""),
|
BackendRef: newBackendRef(apiServiceRef, protoName, ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -334,9 +336,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "grpc"): {
|
backendName("api", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(apiServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -443,9 +446,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "tcp"): {
|
backendName("foo", "tcp"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
BackendRef: newBackendRef(fooServiceRef, "tcp", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -472,9 +476,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -501,9 +506,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http2"): {
|
backendName("foo", "http2"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http2", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -530,9 +536,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
Protocol: pbcatalog.Protocol_PROTOCOL_GRPC,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "grpc"): {
|
backendName("foo", "grpc"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
BackendRef: newBackendRef(fooServiceRef, "grpc", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -612,9 +619,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", portName): {
|
backendName("foo", portName): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, portName, ""),
|
BackendRef: newBackendRef(fooServiceRef, portName, ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -721,9 +729,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http"): {
|
backendName("api", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -803,9 +812,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("api", "http"): {
|
backendName("api", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
BackendRef: newBackendRef(apiServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -910,9 +920,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1062,14 +1073,16 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
backendName("bar", "http"): {
|
backendName("bar", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1155,9 +1168,10 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1648,15 +1662,17 @@ func TestGenerateComputedRoutes(t *testing.T) {
|
||||||
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
Protocol: pbcatalog.Protocol_PROTOCOL_HTTP,
|
||||||
Targets: map[string]*pbmesh.BackendTargetDetails{
|
Targets: map[string]*pbmesh.BackendTargetDetails{
|
||||||
backendName("foo", "http"): {
|
backendName("foo", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
BackendRef: newBackendRef(fooServiceRef, "http", ""),
|
||||||
FailoverConfig: portFailoverConfig,
|
FailoverConfig: portFailoverConfig,
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
backendName("bar", "http"): {
|
backendName("bar", "http"): {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_INDIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
BackendRef: newBackendRef(barServiceRef, "http", ""),
|
||||||
|
DestinationConfig: defaultDestConfig(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,19 +5,16 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/internal/protoutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: see protoutil.Clone
|
||||||
func protoClone[T proto.Message](v T) T {
|
func protoClone[T proto.Message](v T) T {
|
||||||
return proto.Clone(v).(T)
|
return protoutil.Clone(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: see protoutil.CloneSlice
|
||||||
func protoSliceClone[T proto.Message](in []T) []T {
|
func protoSliceClone[T proto.Message](in []T) []T {
|
||||||
if in == nil {
|
return protoutil.CloneSlice(in)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := make([]T, 0, len(in))
|
|
||||||
for _, v := range in {
|
|
||||||
out = append(out, protoClone[T](v))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
|
||||||
|
@ -15,6 +14,7 @@ import (
|
||||||
"github.com/hashicorp/consul/envoyextensions/xdscommon"
|
"github.com/hashicorp/consul/envoyextensions/xdscommon"
|
||||||
"github.com/hashicorp/consul/internal/mesh/internal/types"
|
"github.com/hashicorp/consul/internal/mesh/internal/types"
|
||||||
"github.com/hashicorp/consul/internal/mesh/internal/types/intermediate"
|
"github.com/hashicorp/consul/internal/mesh/internal/types/intermediate"
|
||||||
|
"github.com/hashicorp/consul/internal/protoutil"
|
||||||
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
||||||
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
|
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1"
|
||||||
"github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate"
|
"github.com/hashicorp/consul/proto-public/pbmesh/v2beta1/pbproxystate"
|
||||||
|
@ -109,6 +109,8 @@ func (b *Builder) buildDestination(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries)
|
destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries)
|
||||||
|
headerMutations := applyRouteFilters(destConfig, routeRule.Filters)
|
||||||
|
applyLoadBalancerPolicy(destConfig, cpr, routeRule.BackendRefs)
|
||||||
|
|
||||||
dest := b.makeHTTPRouteDestination(
|
dest := b.makeHTTPRouteDestination(
|
||||||
routeRule.BackendRefs,
|
routeRule.BackendRefs,
|
||||||
|
@ -117,17 +119,14 @@ func (b *Builder) buildDestination(
|
||||||
defaultDC,
|
defaultDC,
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(rb/v2): Filters []*HTTPRouteFilter
|
|
||||||
// TODO(rb/v2): BackendRefs []*ComputedHTTPBackendRef
|
|
||||||
|
|
||||||
// Explode out by matches
|
// Explode out by matches
|
||||||
for _, match := range routeRule.Matches {
|
for _, match := range routeRule.Matches {
|
||||||
routeMatch := makeHTTPRouteMatch(match)
|
routeMatch := makeHTTPRouteMatch(match)
|
||||||
|
|
||||||
proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{
|
proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{
|
||||||
Match: routeMatch,
|
Match: routeMatch,
|
||||||
Destination: proto.Clone(dest).(*pbproxystate.RouteDestination),
|
Destination: protoutil.Clone(dest),
|
||||||
// TODO: mutations
|
HeaderMutations: protoutil.CloneSlice(headerMutations),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,6 +152,8 @@ func (b *Builder) buildDestination(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries)
|
destConfig := b.makeDestinationConfiguration(routeRule.Timeouts, routeRule.Retries)
|
||||||
|
headerMutations := applyRouteFilters(destConfig, routeRule.Filters)
|
||||||
|
applyLoadBalancerPolicy(destConfig, cpr, routeRule.BackendRefs)
|
||||||
|
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
dest := b.makeGRPCRouteDestination(
|
dest := b.makeGRPCRouteDestination(
|
||||||
|
@ -162,16 +163,14 @@ func (b *Builder) buildDestination(
|
||||||
defaultDC,
|
defaultDC,
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(rb/v2): Filters []*HTTPRouteFilter
|
|
||||||
|
|
||||||
// Explode out by matches
|
// Explode out by matches
|
||||||
for _, match := range routeRule.Matches {
|
for _, match := range routeRule.Matches {
|
||||||
routeMatch := makeGRPCRouteMatch(match)
|
routeMatch := makeGRPCRouteMatch(match)
|
||||||
|
|
||||||
proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{
|
proxyRouteRules = append(proxyRouteRules, &pbproxystate.RouteRule{
|
||||||
Match: routeMatch,
|
Match: routeMatch,
|
||||||
Destination: proto.Clone(dest).(*pbproxystate.RouteDestination),
|
Destination: protoutil.Clone(dest),
|
||||||
// TODO: mutations
|
HeaderMutations: protoutil.CloneSlice(headerMutations),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +266,8 @@ func (b *Builder) buildDestination(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
connectTimeout := durationpb.New(5 * time.Second)
|
connectTimeout := details.DestinationConfig.ConnectTimeout
|
||||||
|
loadBalancer := details.DestinationConfig.LoadBalancer
|
||||||
|
|
||||||
// NOTE: we collect both DIRECT and INDIRECT target information here.
|
// NOTE: we collect both DIRECT and INDIRECT target information here.
|
||||||
dc := defaultDC(details.BackendRef.Datacenter)
|
dc := defaultDC(details.BackendRef.Datacenter)
|
||||||
|
@ -280,7 +280,7 @@ func (b *Builder) buildDestination(
|
||||||
)
|
)
|
||||||
clusterName := fmt.Sprintf("%s.%s", portName, sni)
|
clusterName := fmt.Sprintf("%s.%s", portName, sni)
|
||||||
|
|
||||||
egBase := b.newClusterEndpointGroup("", sni, portName, details.IdentityRefs, connectTimeout)
|
egBase := b.newClusterEndpointGroup("", sni, portName, details.IdentityRefs, connectTimeout, loadBalancer)
|
||||||
|
|
||||||
var endpointGroups []*pbproxystate.EndpointGroup
|
var endpointGroups []*pbproxystate.EndpointGroup
|
||||||
|
|
||||||
|
@ -301,6 +301,9 @@ func (b *Builder) buildDestination(
|
||||||
continue // not possible
|
continue // not possible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destConnectTimeout := destDetails.DestinationConfig.ConnectTimeout
|
||||||
|
destLoadBalancer := destDetails.DestinationConfig.LoadBalancer
|
||||||
|
|
||||||
destDC := defaultDC(destDetails.BackendRef.Datacenter)
|
destDC := defaultDC(destDetails.BackendRef.Datacenter)
|
||||||
destPortName := destDetails.BackendRef.Port
|
destPortName := destDetails.BackendRef.Port
|
||||||
|
|
||||||
|
@ -311,7 +314,7 @@ func (b *Builder) buildDestination(
|
||||||
)
|
)
|
||||||
destClusterName := fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, i, clusterName)
|
destClusterName := fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, i, clusterName)
|
||||||
|
|
||||||
egDest := b.newClusterEndpointGroup(destClusterName, destSNI, destPortName, destDetails.IdentityRefs, connectTimeout)
|
egDest := b.newClusterEndpointGroup(destClusterName, destSNI, destPortName, destDetails.IdentityRefs, destConnectTimeout, destLoadBalancer)
|
||||||
|
|
||||||
endpointGroups = append(endpointGroups, egDest)
|
endpointGroups = append(endpointGroups, egDest)
|
||||||
b.addEndpointsRef(destClusterName, destDetails.ServiceEndpointsId, destDetails.MeshPort)
|
b.addEndpointsRef(destClusterName, destDetails.ServiceEndpointsId, destDetails.MeshPort)
|
||||||
|
@ -389,7 +392,7 @@ func (b *ListenerBuilder) addL4RouterForSplit(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StatPrefix: statPrefix,
|
StatPrefix: statPrefix,
|
||||||
// TODO: can we use RDS for TCPRoute split?
|
// TODO(rb/v2): can we use RDS for TCPRoute split?
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,24 +568,71 @@ func (b *Builder) newClusterEndpointGroup(
|
||||||
portName string,
|
portName string,
|
||||||
destinationIdentities []*pbresource.Reference,
|
destinationIdentities []*pbresource.Reference,
|
||||||
connectTimeout *durationpb.Duration,
|
connectTimeout *durationpb.Duration,
|
||||||
|
loadBalancer *pbmesh.LoadBalancer,
|
||||||
) *pbproxystate.EndpointGroup {
|
) *pbproxystate.EndpointGroup {
|
||||||
var spiffeIDs []string
|
var spiffeIDs []string
|
||||||
for _, identity := range destinationIdentities {
|
for _, identity := range destinationIdentities {
|
||||||
spiffeIDs = append(spiffeIDs, connect.SpiffeIDFromIdentityRef(b.trustDomain, identity))
|
spiffeIDs = append(spiffeIDs, connect.SpiffeIDFromIdentityRef(b.trustDomain, identity))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(v2): DestinationPolicy: connect timeout, lb policy, cluster discovery type, circuit breakers, outlier detection
|
// TODO(v2): DestinationPolicy: circuit breakers, outlier detection
|
||||||
|
|
||||||
// TODO(v2): if http2/grpc then set http2protocol options
|
// TODO(v2): if http2/grpc then set http2protocol options
|
||||||
|
|
||||||
|
degConfig := &pbproxystate.DynamicEndpointGroupConfig{
|
||||||
|
DisablePanicThreshold: true,
|
||||||
|
ConnectTimeout: connectTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
if loadBalancer != nil {
|
||||||
|
// enumcover:pbmesh.LoadBalancerPolicy
|
||||||
|
switch loadBalancer.Policy {
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RANDOM:
|
||||||
|
degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Random{}
|
||||||
|
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_ROUND_ROBIN:
|
||||||
|
degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_RoundRobin{}
|
||||||
|
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_LEAST_REQUEST:
|
||||||
|
var choiceCount uint32
|
||||||
|
cfg, ok := loadBalancer.Config.(*pbmesh.LoadBalancer_LeastRequestConfig)
|
||||||
|
if ok {
|
||||||
|
choiceCount = cfg.LeastRequestConfig.GetChoiceCount()
|
||||||
|
}
|
||||||
|
degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_LeastRequest{
|
||||||
|
LeastRequest: &pbproxystate.LBPolicyLeastRequest{
|
||||||
|
ChoiceCount: wrapperspb.UInt32(choiceCount),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_MAGLEV:
|
||||||
|
degConfig.LbPolicy = &pbproxystate.DynamicEndpointGroupConfig_Maglev{}
|
||||||
|
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_RING_HASH:
|
||||||
|
policy := &pbproxystate.DynamicEndpointGroupConfig_RingHash{}
|
||||||
|
|
||||||
|
cfg, ok := loadBalancer.Config.(*pbmesh.LoadBalancer_RingHashConfig)
|
||||||
|
if ok {
|
||||||
|
policy.RingHash = &pbproxystate.LBPolicyRingHash{
|
||||||
|
MinimumRingSize: wrapperspb.UInt64(cfg.RingHashConfig.MinimumRingSize),
|
||||||
|
MaximumRingSize: wrapperspb.UInt64(cfg.RingHashConfig.MaximumRingSize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
degConfig.LbPolicy = policy
|
||||||
|
|
||||||
|
case pbmesh.LoadBalancerPolicy_LOAD_BALANCER_POLICY_UNSPECIFIED:
|
||||||
|
// fallthrough to default
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &pbproxystate.EndpointGroup{
|
return &pbproxystate.EndpointGroup{
|
||||||
Name: clusterName,
|
Name: clusterName,
|
||||||
Group: &pbproxystate.EndpointGroup_Dynamic{
|
Group: &pbproxystate.EndpointGroup_Dynamic{
|
||||||
Dynamic: &pbproxystate.DynamicEndpointGroup{
|
Dynamic: &pbproxystate.DynamicEndpointGroup{
|
||||||
Config: &pbproxystate.DynamicEndpointGroupConfig{
|
Config: degConfig,
|
||||||
DisablePanicThreshold: true,
|
|
||||||
ConnectTimeout: connectTimeout,
|
|
||||||
},
|
|
||||||
OutboundTls: &pbproxystate.TransportSocket{
|
OutboundTls: &pbproxystate.TransportSocket{
|
||||||
ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{
|
ConnectionTls: &pbproxystate.TransportSocket_OutboundMesh{
|
||||||
OutboundMesh: &pbproxystate.OutboundMeshMTLS{
|
OutboundMesh: &pbproxystate.OutboundMeshMTLS{
|
||||||
|
|
|
@ -5,8 +5,11 @@ package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/internal/catalog"
|
"github.com/hashicorp/consul/internal/catalog"
|
||||||
"github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest"
|
"github.com/hashicorp/consul/internal/mesh/internal/controllers/routes/routestest"
|
||||||
|
@ -130,6 +133,19 @@ func TestBuildExplicitDestinations(t *testing.T) {
|
||||||
Tenancy: backup1Endpoints.Id.Tenancy,
|
Tenancy: backup1Endpoints.Id.Tenancy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api1DestPolicy := resourcetest.Resource(types.DestinationPolicyType, api1Service.Id.Name).
|
||||||
|
WithTenancy(api1Service.Id.GetTenancy()).
|
||||||
|
WithData(t, &pbmesh.DestinationPolicy{
|
||||||
|
PortConfigs: map[string]*pbmesh.DestinationConfig{
|
||||||
|
"http": {
|
||||||
|
ConnectTimeout: durationpb.New(55 * time.Second),
|
||||||
|
RequestTimeout: durationpb.New(77 * time.Second),
|
||||||
|
// LoadBalancer *LoadBalancer `protobuf:"bytes,3,opt,name=load_balancer,json=loadBalancer,proto3" json:"load_balancer,omitempty"`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).
|
||||||
|
Build()
|
||||||
|
|
||||||
api1HTTPRoute := resourcetest.Resource(types.HTTPRouteType, "api-1-http-route").
|
api1HTTPRoute := resourcetest.Resource(types.HTTPRouteType, "api-1-http-route").
|
||||||
WithTenancy(resource.DefaultNamespacedTenancy()).
|
WithTenancy(resource.DefaultNamespacedTenancy()).
|
||||||
WithData(t, &pbmesh.HTTPRoute{
|
WithData(t, &pbmesh.HTTPRoute{
|
||||||
|
@ -137,28 +153,56 @@ func TestBuildExplicitDestinations(t *testing.T) {
|
||||||
Ref: resource.Reference(api1Service.Id, ""),
|
Ref: resource.Reference(api1Service.Id, ""),
|
||||||
Port: "http",
|
Port: "http",
|
||||||
}},
|
}},
|
||||||
Rules: []*pbmesh.HTTPRouteRule{{
|
Rules: []*pbmesh.HTTPRouteRule{
|
||||||
BackendRefs: []*pbmesh.HTTPBackendRef{
|
{
|
||||||
{
|
Matches: []*pbmesh.HTTPRouteMatch{{
|
||||||
BackendRef: &pbmesh.BackendReference{
|
Path: &pbmesh.HTTPPathMatch{
|
||||||
Ref: resource.Reference(api2Service.Id, ""),
|
Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX,
|
||||||
|
Value: "/split",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
BackendRefs: []*pbmesh.HTTPBackendRef{
|
||||||
|
{
|
||||||
|
BackendRef: &pbmesh.BackendReference{
|
||||||
|
Ref: resource.Reference(api2Service.Id, ""),
|
||||||
|
},
|
||||||
|
Weight: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BackendRef: &pbmesh.BackendReference{
|
||||||
|
Ref: resource.Reference(api1Service.Id, ""),
|
||||||
|
},
|
||||||
|
Weight: 40,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BackendRef: &pbmesh.BackendReference{
|
||||||
|
Ref: resource.Reference(api3Service.Id, ""),
|
||||||
|
},
|
||||||
|
Weight: 10,
|
||||||
},
|
},
|
||||||
Weight: 60,
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
|
{
|
||||||
|
Matches: []*pbmesh.HTTPRouteMatch{{
|
||||||
|
Path: &pbmesh.HTTPPathMatch{
|
||||||
|
Type: pbmesh.PathMatchType_PATH_MATCH_TYPE_PREFIX,
|
||||||
|
Value: "/",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
BackendRefs: []*pbmesh.HTTPBackendRef{{
|
||||||
BackendRef: &pbmesh.BackendReference{
|
BackendRef: &pbmesh.BackendReference{
|
||||||
Ref: resource.Reference(api1Service.Id, ""),
|
Ref: resource.Reference(api1Service.Id, ""),
|
||||||
},
|
},
|
||||||
Weight: 40,
|
}},
|
||||||
|
Timeouts: &pbmesh.HTTPRouteTimeouts{
|
||||||
|
Request: durationpb.New(606 * time.Second), // differnet than the 77s
|
||||||
},
|
},
|
||||||
{
|
Retries: &pbmesh.HTTPRouteRetries{
|
||||||
BackendRef: &pbmesh.BackendReference{
|
Number: wrapperspb.UInt32(4),
|
||||||
Ref: resource.Reference(api3Service.Id, ""),
|
OnConnectFailure: true,
|
||||||
},
|
|
||||||
Weight: 10,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
}).
|
}).
|
||||||
Build()
|
Build()
|
||||||
resourcetest.ValidateAndNormalize(t, registry, api1HTTPRoute)
|
resourcetest.ValidateAndNormalize(t, registry, api1HTTPRoute)
|
||||||
|
@ -249,6 +293,7 @@ func TestBuildExplicitDestinations(t *testing.T) {
|
||||||
resourcetest.MustDecode[*pbcatalog.Service](t, api2Service),
|
resourcetest.MustDecode[*pbcatalog.Service](t, api2Service),
|
||||||
resourcetest.MustDecode[*pbcatalog.Service](t, backup1Service),
|
resourcetest.MustDecode[*pbcatalog.Service](t, backup1Service),
|
||||||
// notably we do NOT include api3Service here so we trigger a null route to be generated
|
// notably we do NOT include api3Service here so we trigger a null route to be generated
|
||||||
|
resourcetest.MustDecode[*pbmesh.DestinationPolicy](t, api1DestPolicy),
|
||||||
resourcetest.MustDecode[*pbmesh.HTTPRoute](t, api1HTTPRoute),
|
resourcetest.MustDecode[*pbmesh.HTTPRoute](t, api1HTTPRoute),
|
||||||
resourcetest.MustDecode[*pbmesh.TCPRoute](t, api1TCPRoute),
|
resourcetest.MustDecode[*pbmesh.TCPRoute](t, api1TCPRoute),
|
||||||
resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, api1FailoverPolicy),
|
resourcetest.MustDecode[*pbcatalog.FailoverPolicy](t, api1FailoverPolicy),
|
||||||
|
|
|
@ -6,7 +6,9 @@ package builder
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/internal/mesh/internal/types"
|
"github.com/hashicorp/consul/internal/mesh/internal/types"
|
||||||
|
@ -131,8 +133,6 @@ func (b *Builder) makeDestinationConfiguration(
|
||||||
timeouts *pbmesh.HTTPRouteTimeouts,
|
timeouts *pbmesh.HTTPRouteTimeouts,
|
||||||
retries *pbmesh.HTTPRouteRetries,
|
retries *pbmesh.HTTPRouteRetries,
|
||||||
) *pbproxystate.DestinationConfiguration {
|
) *pbproxystate.DestinationConfiguration {
|
||||||
// TODO: prefix rewrite, lb config
|
|
||||||
|
|
||||||
cfg := &pbproxystate.DestinationConfiguration{
|
cfg := &pbproxystate.DestinationConfiguration{
|
||||||
TimeoutConfig: translateTimeouts(timeouts),
|
TimeoutConfig: translateTimeouts(timeouts),
|
||||||
RetryPolicy: translateRetries(retries),
|
RetryPolicy: translateRetries(retries),
|
||||||
|
@ -144,8 +144,202 @@ func (b *Builder) makeDestinationConfiguration(
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeGRPCRouteMatch(match *pbmesh.GRPCRouteMatch) *pbproxystate.RouteMatch {
|
func applyRouteFilters[V interface {
|
||||||
panic("TODO")
|
GetRequestHeaderModifier() *pbmesh.HTTPHeaderFilter
|
||||||
|
GetResponseHeaderModifier() *pbmesh.HTTPHeaderFilter
|
||||||
|
GetUrlRewrite() *pbmesh.HTTPURLRewriteFilter
|
||||||
|
}](
|
||||||
|
psDestConfig *pbproxystate.DestinationConfiguration,
|
||||||
|
filters []V,
|
||||||
|
) []*pbproxystate.HeaderMutation {
|
||||||
|
var headerMutations []*pbproxystate.HeaderMutation
|
||||||
|
for _, filter := range filters {
|
||||||
|
switch {
|
||||||
|
case filter.GetRequestHeaderModifier() != nil:
|
||||||
|
mod := filter.GetRequestHeaderModifier()
|
||||||
|
|
||||||
|
for _, hdr := range mod.Set {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{
|
||||||
|
RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{
|
||||||
|
Header: &pbproxystate.Header{
|
||||||
|
Key: hdr.Name,
|
||||||
|
Value: hdr.Value,
|
||||||
|
},
|
||||||
|
AppendAction: pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, hdr := range mod.Add {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_RequestHeaderAdd{
|
||||||
|
RequestHeaderAdd: &pbproxystate.RequestHeaderAdd{
|
||||||
|
Header: &pbproxystate.Header{
|
||||||
|
Key: hdr.Name,
|
||||||
|
Value: hdr.Value,
|
||||||
|
},
|
||||||
|
AppendAction: pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mod.Remove) > 0 {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_RequestHeaderRemove{
|
||||||
|
RequestHeaderRemove: &pbproxystate.RequestHeaderRemove{
|
||||||
|
HeaderKeys: mod.Remove,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
case filter.GetResponseHeaderModifier() != nil:
|
||||||
|
mod := filter.GetResponseHeaderModifier()
|
||||||
|
|
||||||
|
for _, hdr := range mod.Set {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{
|
||||||
|
ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{
|
||||||
|
Header: &pbproxystate.Header{
|
||||||
|
Key: hdr.Name,
|
||||||
|
Value: hdr.Value,
|
||||||
|
},
|
||||||
|
AppendAction: pbproxystate.AppendAction_APPEND_ACTION_OVERWRITE_IF_EXISTS_OR_ADD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, hdr := range mod.Add {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_ResponseHeaderAdd{
|
||||||
|
ResponseHeaderAdd: &pbproxystate.ResponseHeaderAdd{
|
||||||
|
Header: &pbproxystate.Header{
|
||||||
|
Key: hdr.Name,
|
||||||
|
Value: hdr.Value,
|
||||||
|
},
|
||||||
|
AppendAction: pbproxystate.AppendAction_APPEND_ACTION_APPEND_IF_EXISTS_OR_ADD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mod.Remove) > 0 {
|
||||||
|
headerMutations = append(headerMutations, &pbproxystate.HeaderMutation{
|
||||||
|
Action: &pbproxystate.HeaderMutation_ResponseHeaderRemove{
|
||||||
|
ResponseHeaderRemove: &pbproxystate.ResponseHeaderRemove{
|
||||||
|
HeaderKeys: mod.Remove,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
case filter.GetUrlRewrite() != nil:
|
||||||
|
prefix := filter.GetUrlRewrite().PathPrefix
|
||||||
|
if prefix != "" {
|
||||||
|
psDestConfig.PrefixRewrite = prefix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headerMutations
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyLoadBalancerPolicy[V interface {
|
||||||
|
GetBackendTarget() string
|
||||||
|
}](
|
||||||
|
psDestConfig *pbproxystate.DestinationConfiguration,
|
||||||
|
cpr *pbmesh.ComputedPortRoutes,
|
||||||
|
backendRefs []V,
|
||||||
|
) {
|
||||||
|
var lb *pbmesh.LoadBalancer
|
||||||
|
|
||||||
|
// If there are multiple targets, just pick the lb policy from
|
||||||
|
// the first one configured.
|
||||||
|
for _, backendRef := range backendRefs {
|
||||||
|
if backendRef.GetBackendTarget() == types.NullRouteBackend {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
details, ok := cpr.Targets[backendRef.GetBackendTarget()]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
thisLB := details.DestinationConfig.LoadBalancer
|
||||||
|
if thisLB != nil {
|
||||||
|
lb = thisLB
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if lb == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, policy := range lb.HashPolicies {
|
||||||
|
if policy.SourceIp {
|
||||||
|
psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{
|
||||||
|
Policy: &pbproxystate.LoadBalancerHashPolicy_ConnectionProperties{
|
||||||
|
ConnectionProperties: &pbproxystate.ConnectionPropertiesPolicy{
|
||||||
|
SourceIp: true,
|
||||||
|
Terminal: policy.Terminal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// enumcover:pbmesh.HashPolicyField
|
||||||
|
switch policy.Field {
|
||||||
|
case pbmesh.HashPolicyField_HASH_POLICY_FIELD_HEADER:
|
||||||
|
psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{
|
||||||
|
Policy: &pbproxystate.LoadBalancerHashPolicy_Header{
|
||||||
|
Header: &pbproxystate.HeaderPolicy{
|
||||||
|
Name: policy.FieldValue,
|
||||||
|
Terminal: policy.Terminal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
case pbmesh.HashPolicyField_HASH_POLICY_FIELD_COOKIE:
|
||||||
|
cookie := &pbproxystate.CookiePolicy{
|
||||||
|
Name: policy.FieldValue,
|
||||||
|
Terminal: policy.Terminal,
|
||||||
|
}
|
||||||
|
if policy.CookieConfig != nil {
|
||||||
|
cookie.Path = policy.CookieConfig.Path
|
||||||
|
|
||||||
|
if policy.CookieConfig.Ttl != nil {
|
||||||
|
if policy.CookieConfig.Ttl.AsDuration() != 0 {
|
||||||
|
cookie.Ttl = policy.CookieConfig.Ttl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Envoy will generate a session cookie if the ttl is present and zero.
|
||||||
|
if policy.CookieConfig.Session {
|
||||||
|
cookie.Ttl = durationpb.New(0 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{
|
||||||
|
Policy: &pbproxystate.LoadBalancerHashPolicy_Cookie{
|
||||||
|
Cookie: cookie,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
case pbmesh.HashPolicyField_HASH_POLICY_FIELD_QUERY_PARAMETER:
|
||||||
|
psDestConfig.HashPolicies = append(psDestConfig.HashPolicies, &pbproxystate.LoadBalancerHashPolicy{
|
||||||
|
Policy: &pbproxystate.LoadBalancerHashPolicy_QueryParameter{
|
||||||
|
QueryParameter: &pbproxystate.QueryParameterPolicy{
|
||||||
|
Name: policy.FieldValue,
|
||||||
|
Terminal: policy.Terminal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
case pbmesh.HashPolicyField_HASH_POLICY_FIELD_UNSPECIFIED:
|
||||||
|
// fallthrough to default
|
||||||
|
default:
|
||||||
|
// not possible from validation
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch {
|
func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch {
|
||||||
|
@ -185,48 +379,7 @@ func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(match.Headers) > 0 {
|
em.HeaderMatches = translateHeaderMatches(match.Headers, (*pbmesh.HTTPHeaderMatch).GetInvert)
|
||||||
em.HeaderMatches = make([]*pbproxystate.HeaderMatch, 0, len(match.Headers))
|
|
||||||
for _, hdr := range match.Headers {
|
|
||||||
eh := &pbproxystate.HeaderMatch{
|
|
||||||
Name: hdr.Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
// enumcover:pbmesh.HeaderMatchType
|
|
||||||
switch hdr.Type {
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT:
|
|
||||||
eh.Match = &pbproxystate.HeaderMatch_Exact{
|
|
||||||
Exact: hdr.Value,
|
|
||||||
}
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX:
|
|
||||||
eh.Match = &pbproxystate.HeaderMatch_Regex{
|
|
||||||
Regex: hdr.Value,
|
|
||||||
}
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX:
|
|
||||||
eh.Match = &pbproxystate.HeaderMatch_Prefix{
|
|
||||||
Prefix: hdr.Value,
|
|
||||||
}
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX:
|
|
||||||
eh.Match = &pbproxystate.HeaderMatch_Suffix{
|
|
||||||
Suffix: hdr.Value,
|
|
||||||
}
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT:
|
|
||||||
eh.Match = &pbproxystate.HeaderMatch_Present{
|
|
||||||
Present: true,
|
|
||||||
}
|
|
||||||
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED:
|
|
||||||
fallthrough // to default
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unknown header match type: %v", hdr.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
if hdr.Invert {
|
|
||||||
eh.InvertMatch = true
|
|
||||||
}
|
|
||||||
|
|
||||||
em.HeaderMatches = append(em.HeaderMatches, eh)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if match.Method != "" {
|
if match.Method != "" {
|
||||||
em.MethodMatches = []string{match.Method}
|
em.MethodMatches = []string{match.Method}
|
||||||
|
@ -267,6 +420,122 @@ func makeHTTPRouteMatch(match *pbmesh.HTTPRouteMatch) *pbproxystate.RouteMatch {
|
||||||
return em
|
return em
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeGRPCRouteMatch(match *pbmesh.GRPCRouteMatch) *pbproxystate.RouteMatch {
|
||||||
|
em := &pbproxystate.RouteMatch{}
|
||||||
|
|
||||||
|
if match.Method != nil {
|
||||||
|
mm := match.Method
|
||||||
|
switch mm.Type {
|
||||||
|
case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_EXACT:
|
||||||
|
switch {
|
||||||
|
case mm.Method == "":
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Prefix{
|
||||||
|
Prefix: fmt.Sprintf("/%s/", mm.Service),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case mm.Service == "":
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Regex{
|
||||||
|
Regex: fmt.Sprintf("/[^/]+/%s", mm.Method),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Exact{
|
||||||
|
Exact: fmt.Sprintf("/%s/%s", mm.Service, mm.Method),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_REGEX:
|
||||||
|
switch {
|
||||||
|
case mm.Method == "":
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Regex{
|
||||||
|
Regex: fmt.Sprintf("/%s/.+", mm.Service),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case mm.Service == "":
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Regex{
|
||||||
|
Regex: fmt.Sprintf("/[^/]+/%s", mm.Method),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
em.PathMatch = &pbproxystate.PathMatch{
|
||||||
|
PathMatch: &pbproxystate.PathMatch_Regex{
|
||||||
|
Regex: fmt.Sprintf("/%s/%s", mm.Service, mm.Method),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case pbmesh.GRPCMethodMatchType_GRPC_METHOD_MATCH_TYPE_UNSPECIFIED:
|
||||||
|
fallthrough // to default
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown method match type: %v", match.Method.Type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
em.HeaderMatches = translateHeaderMatches(match.Headers, nil)
|
||||||
|
|
||||||
|
return em
|
||||||
|
}
|
||||||
|
|
||||||
|
func translateHeaderMatches[V interface {
|
||||||
|
GetType() pbmesh.HeaderMatchType
|
||||||
|
GetName() string
|
||||||
|
GetValue() string
|
||||||
|
}](
|
||||||
|
headers []V,
|
||||||
|
getInvert func(v V) bool,
|
||||||
|
) []*pbproxystate.HeaderMatch {
|
||||||
|
if len(headers) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var out []*pbproxystate.HeaderMatch
|
||||||
|
out = make([]*pbproxystate.HeaderMatch, 0, len(headers))
|
||||||
|
for _, hdr := range headers {
|
||||||
|
eh := &pbproxystate.HeaderMatch{
|
||||||
|
Name: hdr.GetName(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// enumcover:pbmesh.HeaderMatchType
|
||||||
|
switch hdr.GetType() {
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_EXACT:
|
||||||
|
eh.Match = &pbproxystate.HeaderMatch_Exact{
|
||||||
|
Exact: hdr.GetValue(),
|
||||||
|
}
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_REGEX:
|
||||||
|
eh.Match = &pbproxystate.HeaderMatch_Regex{
|
||||||
|
Regex: hdr.GetValue(),
|
||||||
|
}
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PREFIX:
|
||||||
|
eh.Match = &pbproxystate.HeaderMatch_Prefix{
|
||||||
|
Prefix: hdr.GetValue(),
|
||||||
|
}
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_SUFFIX:
|
||||||
|
eh.Match = &pbproxystate.HeaderMatch_Suffix{
|
||||||
|
Suffix: hdr.GetValue(),
|
||||||
|
}
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_PRESENT:
|
||||||
|
eh.Match = &pbproxystate.HeaderMatch_Present{
|
||||||
|
Present: true,
|
||||||
|
}
|
||||||
|
case pbmesh.HeaderMatchType_HEADER_MATCH_TYPE_UNSPECIFIED:
|
||||||
|
fallthrough // to default
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown header match type: %v", hdr.GetType()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPHeaderMatch only
|
||||||
|
if getInvert != nil && getInvert(hdr) {
|
||||||
|
eh.InvertMatch = true
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, eh)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func translateTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) *pbproxystate.TimeoutConfig {
|
func translateTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) *pbproxystate.TimeoutConfig {
|
||||||
if timeouts == nil || (timeouts.Request == nil && timeouts.Idle == nil) {
|
if timeouts == nil || (timeouts.Request == nil && timeouts.Idle == nil) {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
"altStatName": "http.api-1.default.dc1.internal.foo.consul",
|
"altStatName": "http.api-1.default.dc1.internal.foo.consul",
|
||||||
"failoverGroup": {
|
"failoverGroup": {
|
||||||
"config": {
|
"config": {
|
||||||
"connectTimeout": "5s",
|
"connectTimeout": "55s",
|
||||||
"useAltStatName": true
|
"useAltStatName": true
|
||||||
},
|
},
|
||||||
"endpointGroups": [
|
"endpointGroups": [
|
||||||
{
|
{
|
||||||
"dynamic": {
|
"dynamic": {
|
||||||
"config": {
|
"config": {
|
||||||
"connectTimeout": "5s",
|
"connectTimeout": "55s",
|
||||||
"disablePanicThreshold": true
|
"disablePanicThreshold": true
|
||||||
},
|
},
|
||||||
"outboundTls": {
|
"outboundTls": {
|
||||||
|
@ -235,6 +235,11 @@
|
||||||
"routeRules": [
|
"routeRules": [
|
||||||
{
|
{
|
||||||
"destination": {
|
"destination": {
|
||||||
|
"destinationConfiguration": {
|
||||||
|
"timeoutConfig": {
|
||||||
|
"timeout": "77s"
|
||||||
|
}
|
||||||
|
},
|
||||||
"weightedClusters": {
|
"weightedClusters": {
|
||||||
"clusters": [
|
"clusters": [
|
||||||
{
|
{
|
||||||
|
@ -252,6 +257,27 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"match": {
|
||||||
|
"pathMatch": {
|
||||||
|
"prefix": "/split"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": {
|
||||||
|
"cluster": {
|
||||||
|
"name": "http.api-1.default.dc1.internal.foo.consul"
|
||||||
|
},
|
||||||
|
"destinationConfiguration": {
|
||||||
|
"retryPolicy": {
|
||||||
|
"numRetries": 4,
|
||||||
|
"retryOn": "connect-failure"
|
||||||
|
},
|
||||||
|
"timeoutConfig": {
|
||||||
|
"timeout": "606s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"match": {
|
"match": {
|
||||||
"pathMatch": {
|
"pathMatch": {
|
||||||
"prefix": "/"
|
"prefix": "/"
|
||||||
|
|
|
@ -111,6 +111,36 @@ func ValidateComputedRoutes(res *pbresource.Resource) error {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if target.DestinationConfig == nil {
|
||||||
|
merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{
|
||||||
|
Name: "destination_config",
|
||||||
|
Wrapped: resource.ErrMissing,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
wrapDestConfigErr := func(err error) error {
|
||||||
|
return wrapTargetErr(resource.ErrInvalidField{
|
||||||
|
Name: "destination_config",
|
||||||
|
Wrapped: err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
destConfig := target.DestinationConfig
|
||||||
|
if destConfig.ConnectTimeout == nil {
|
||||||
|
merr = multierror.Append(merr, wrapDestConfigErr(resource.ErrInvalidField{
|
||||||
|
Name: "connect_timeout",
|
||||||
|
Wrapped: resource.ErrMissing,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
connectTimeout := destConfig.ConnectTimeout.AsDuration()
|
||||||
|
if connectTimeout < 0 {
|
||||||
|
merr = multierror.Append(merr, wrapDestConfigErr(resource.ErrInvalidField{
|
||||||
|
Name: "connect_timeout",
|
||||||
|
Wrapped: errTimeoutCannotBeNegative(connectTimeout),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if target.MeshPort == "" {
|
if target.MeshPort == "" {
|
||||||
merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{
|
merr = multierror.Append(merr, wrapTargetErr(resource.ErrInvalidField{
|
||||||
Name: "mesh_port",
|
Name: "mesh_port",
|
||||||
|
|
|
@ -5,8 +5,10 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/internal/resource/resourcetest"
|
"github.com/hashicorp/consul/internal/resource/resourcetest"
|
||||||
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1"
|
||||||
|
@ -197,6 +199,9 @@ func TestValidateComputedRoutes(t *testing.T) {
|
||||||
"foo": {
|
"foo": {
|
||||||
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
Type: pbmesh.BackendTargetDetailsType_BACKEND_TARGET_DETAILS_TYPE_DIRECT,
|
||||||
MeshPort: "mesh",
|
MeshPort: "mesh",
|
||||||
|
DestinationConfig: &pbmesh.DestinationConfig{
|
||||||
|
ConnectTimeout: durationpb.New(5 * time.Second),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -249,6 +249,10 @@ func ValidateHTTPRoute(res *pbresource.Resource) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
hasReqMod bool
|
||||||
|
hasUrlRewrite bool
|
||||||
|
)
|
||||||
for j, filter := range rule.Filters {
|
for j, filter := range rule.Filters {
|
||||||
wrapFilterErr := func(err error) error {
|
wrapFilterErr := func(err error) error {
|
||||||
return wrapRuleErr(resource.ErrInvalidListElement{
|
return wrapRuleErr(resource.ErrInvalidListElement{
|
||||||
|
@ -260,12 +264,14 @@ func ValidateHTTPRoute(res *pbresource.Resource) error {
|
||||||
set := 0
|
set := 0
|
||||||
if filter.RequestHeaderModifier != nil {
|
if filter.RequestHeaderModifier != nil {
|
||||||
set++
|
set++
|
||||||
|
hasReqMod = true
|
||||||
}
|
}
|
||||||
if filter.ResponseHeaderModifier != nil {
|
if filter.ResponseHeaderModifier != nil {
|
||||||
set++
|
set++
|
||||||
}
|
}
|
||||||
if filter.UrlRewrite != nil {
|
if filter.UrlRewrite != nil {
|
||||||
set++
|
set++
|
||||||
|
hasUrlRewrite = true
|
||||||
if filter.UrlRewrite.PathPrefix == "" {
|
if filter.UrlRewrite.PathPrefix == "" {
|
||||||
merr = multierror.Append(merr, wrapFilterErr(
|
merr = multierror.Append(merr, wrapFilterErr(
|
||||||
resource.ErrInvalidField{
|
resource.ErrInvalidField{
|
||||||
|
@ -285,6 +291,12 @@ func ValidateHTTPRoute(res *pbresource.Resource) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hasReqMod && hasUrlRewrite {
|
||||||
|
merr = multierror.Append(merr, wrapRuleErr(
|
||||||
|
errors.New("exactly one of request_header_modifier or url_rewrite can be set at a time"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
if len(rule.BackendRefs) == 0 {
|
if len(rule.BackendRefs) == 0 {
|
||||||
merr = multierror.Append(merr, wrapRuleErr(
|
merr = multierror.Append(merr, wrapRuleErr(
|
||||||
resource.ErrInvalidField{
|
resource.ErrInvalidField{
|
||||||
|
|
|
@ -733,6 +733,29 @@ func TestValidateHTTPRoute(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`,
|
expectErr: `invalid element at index 0 of list "rules": invalid element at index 0 of list "filters": exactly one of request_header_modifier, response_header_modifier, or url_rewrite`,
|
||||||
},
|
},
|
||||||
|
"filter req+rewrite on two rules is not allowed": {
|
||||||
|
route: &pbmesh.HTTPRoute{
|
||||||
|
ParentRefs: []*pbmesh.ParentReference{
|
||||||
|
newParentRef(catalog.ServiceType, "web", ""),
|
||||||
|
},
|
||||||
|
Rules: []*pbmesh.HTTPRouteRule{{
|
||||||
|
Filters: []*pbmesh.HTTPRouteFilter{
|
||||||
|
{
|
||||||
|
RequestHeaderModifier: &pbmesh.HTTPHeaderFilter{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
UrlRewrite: &pbmesh.HTTPURLRewriteFilter{
|
||||||
|
PathPrefix: "/blah",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
BackendRefs: []*pbmesh.HTTPBackendRef{{
|
||||||
|
BackendRef: newBackendRef(catalog.ServiceType, "api", ""),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
expectErr: `invalid element at index 0 of list "rules": exactly one of request_header_modifier or url_rewrite can be set at a time`,
|
||||||
|
},
|
||||||
"filter req+resp+rewrite header mod is bad": {
|
"filter req+resp+rewrite header mod is bad": {
|
||||||
route: &pbmesh.HTTPRoute{
|
route: &pbmesh.HTTPRoute{
|
||||||
ParentRefs: []*pbmesh.ParentReference{
|
ParentRefs: []*pbmesh.ParentReference{
|
||||||
|
@ -1081,12 +1104,6 @@ func getXRouteTimeoutsTestCases() map[string]xRouteTimeoutsTestcase {
|
||||||
},
|
},
|
||||||
expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "request" field: timeout cannot be negative: -1s`,
|
expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "request" field: timeout cannot be negative: -1s`,
|
||||||
},
|
},
|
||||||
"bad backend request": {
|
|
||||||
timeouts: &pbmesh.HTTPRouteTimeouts{
|
|
||||||
BackendRequest: durationpb.New(-1 * time.Second),
|
|
||||||
},
|
|
||||||
expectErr: `invalid element at index 0 of list "rules": invalid "timeouts" field: invalid "backend_request" field: timeout cannot be negative: -1s`,
|
|
||||||
},
|
|
||||||
"bad idle": {
|
"bad idle": {
|
||||||
timeouts: &pbmesh.HTTPRouteTimeouts{
|
timeouts: &pbmesh.HTTPRouteTimeouts{
|
||||||
Idle: durationpb.New(-1 * time.Second),
|
Idle: durationpb.New(-1 * time.Second),
|
||||||
|
@ -1095,9 +1112,8 @@ func getXRouteTimeoutsTestCases() map[string]xRouteTimeoutsTestcase {
|
||||||
},
|
},
|
||||||
"good all": {
|
"good all": {
|
||||||
timeouts: &pbmesh.HTTPRouteTimeouts{
|
timeouts: &pbmesh.HTTPRouteTimeouts{
|
||||||
Request: durationpb.New(1 * time.Second),
|
Request: durationpb.New(1 * time.Second),
|
||||||
BackendRequest: durationpb.New(2 * time.Second),
|
Idle: durationpb.New(3 * time.Second),
|
||||||
Idle: durationpb.New(3 * time.Second),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ package types
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
@ -206,6 +207,10 @@ func validateHeaderMatchType(typ pbmesh.HeaderMatchType) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func errTimeoutCannotBeNegative(d time.Duration) error {
|
||||||
|
return fmt.Errorf("timeout cannot be negative: %v", d)
|
||||||
|
}
|
||||||
|
|
||||||
func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error {
|
func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error {
|
||||||
if timeouts == nil {
|
if timeouts == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -218,16 +223,7 @@ func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error {
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
errs = append(errs, resource.ErrInvalidField{
|
errs = append(errs, resource.ErrInvalidField{
|
||||||
Name: "request",
|
Name: "request",
|
||||||
Wrapped: fmt.Errorf("timeout cannot be negative: %v", val),
|
Wrapped: errTimeoutCannotBeNegative(val),
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if timeouts.BackendRequest != nil {
|
|
||||||
val := timeouts.BackendRequest.AsDuration()
|
|
||||||
if val < 0 {
|
|
||||||
errs = append(errs, resource.ErrInvalidField{
|
|
||||||
Name: "backend_request",
|
|
||||||
Wrapped: fmt.Errorf("timeout cannot be negative: %v", val),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +232,7 @@ func validateHTTPTimeouts(timeouts *pbmesh.HTTPRouteTimeouts) []error {
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
errs = append(errs, resource.ErrInvalidField{
|
errs = append(errs, resource.ErrInvalidField{
|
||||||
Name: "idle",
|
Name: "idle",
|
||||||
Wrapped: fmt.Errorf("timeout cannot be negative: %v", val),
|
Wrapped: errTimeoutCannotBeNegative(val),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
|
||||||
|
package protoutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Clone[T proto.Message](v T) T {
|
||||||
|
return proto.Clone(v).(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloneSlice[T proto.Message](in []T) []T {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make([]T, 0, len(in))
|
||||||
|
for _, v := range in {
|
||||||
|
out = append(out, Clone[T](v))
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
|
@ -24,39 +24,18 @@ const (
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute.
|
// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute
|
||||||
// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration
|
// or GRPCRoute.
|
||||||
// and MUST BE >= 1ms.
|
|
||||||
//
|
|
||||||
// ALTERNATIVE: not using policy attachment semantics
|
|
||||||
type HTTPRouteTimeouts struct {
|
type HTTPRouteTimeouts struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Request specifies the duration for processing an HTTP client request after which the
|
// RequestTimeout is the total amount of time permitted for the entire
|
||||||
// gateway will time out if unable to send a response.
|
// downstream request (and retries) to be processed.
|
||||||
// Whether the gateway starts the timeout before or after the entire client request stream
|
|
||||||
// has been received, is implementation-dependent.
|
|
||||||
//
|
|
||||||
// For example, setting the `rules.timeouts.request` field to the value `10s` in an
|
|
||||||
// `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds
|
|
||||||
// to complete.
|
|
||||||
//
|
|
||||||
// When this field is unspecified, request timeout behavior is implementation-dependent.
|
|
||||||
Request *durationpb.Duration `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"`
|
Request *durationpb.Duration `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"`
|
||||||
// BackendRequest specifies a timeout for an individual request from the gateway
|
// Idle specifies the total amount of time permitted for the request stream to be idle.
|
||||||
// to a backend service. Typically used in conjuction with retry configuration,
|
Idle *durationpb.Duration `protobuf:"bytes,2,opt,name=idle,proto3" json:"idle,omitempty"`
|
||||||
// if supported by an implementation.
|
|
||||||
//
|
|
||||||
// The value of BackendRequest defaults to and must be <= the value of Request timeout.
|
|
||||||
//
|
|
||||||
// Support: Extended
|
|
||||||
//
|
|
||||||
// TODO(rb): net-new feature
|
|
||||||
BackendRequest *durationpb.Duration `protobuf:"bytes,2,opt,name=backend_request,json=backendRequest,proto3" json:"backend_request,omitempty"`
|
|
||||||
// TODO(RB): this is a consul-only feature
|
|
||||||
Idle *durationpb.Duration `protobuf:"bytes,3,opt,name=idle,proto3" json:"idle,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HTTPRouteTimeouts) Reset() {
|
func (x *HTTPRouteTimeouts) Reset() {
|
||||||
|
@ -98,13 +77,6 @@ func (x *HTTPRouteTimeouts) GetRequest() *durationpb.Duration {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HTTPRouteTimeouts) GetBackendRequest() *durationpb.Duration {
|
|
||||||
if x != nil {
|
|
||||||
return x.BackendRequest
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HTTPRouteTimeouts) GetIdle() *durationpb.Duration {
|
func (x *HTTPRouteTimeouts) GetIdle() *durationpb.Duration {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Idle
|
return x.Idle
|
||||||
|
@ -121,37 +93,33 @@ var file_pbmesh_v2beta1_http_route_timeouts_proto_rawDesc = []byte{
|
||||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73,
|
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73,
|
||||||
0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74,
|
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74,
|
||||||
0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x01, 0x0a, 0x11, 0x48, 0x54,
|
0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x77, 0x0a, 0x11, 0x48, 0x54, 0x54,
|
||||||
0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12,
|
0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x12, 0x33,
|
||||||
0x33, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||||
0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x71,
|
0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x5f,
|
0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x04, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
|
0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, 0x64,
|
||||||
0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
|
0x6c, 0x65, 0x42, 0x97, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
||||||
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x04, 0x69, 0x64, 0x6c, 0x65,
|
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x6d, 0x65, 0x73, 0x68,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x16, 0x48, 0x74, 0x74, 0x70, 0x52, 0x6f,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x6e, 0x52, 0x04, 0x69, 0x64, 0x6c, 0x65, 0x42, 0x97, 0x02, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e,
|
0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
|
||||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f,
|
||||||
0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x16, 0x48,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, 0x62, 0x6d,
|
||||||
0x74, 0x74, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x73,
|
0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x6d, 0x65, 0x73, 0x68,
|
||||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x4d, 0xaa, 0x02, 0x1d,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f,
|
0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||||
0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x1d,
|
||||||
0x63, 0x2f, 0x70, 0x62, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31,
|
0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||||
0x3b, 0x6d, 0x65, 0x73, 0x68, 0x76, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x48,
|
0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x29,
|
||||||
0x43, 0x4d, 0xaa, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43,
|
0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x2e, 0x56, 0x32, 0x62, 0x65, 0x74,
|
0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50,
|
||||||
0x61, 0x31, 0xca, 0x02, 0x1d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43,
|
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68,
|
||||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74,
|
0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x4d,
|
||||||
0x61, 0x31, 0xe2, 0x02, 0x29, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43,
|
0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72,
|
||||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x4d, 0x65, 0x73, 0x68, 0x5c, 0x56, 0x32, 0x62, 0x65, 0x74,
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
|
|
||||||
0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73,
|
|
||||||
0x75, 0x6c, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x68, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x65, 0x74, 0x61,
|
|
||||||
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -173,13 +141,12 @@ var file_pbmesh_v2beta1_http_route_timeouts_proto_goTypes = []interface{}{
|
||||||
}
|
}
|
||||||
var file_pbmesh_v2beta1_http_route_timeouts_proto_depIdxs = []int32{
|
var file_pbmesh_v2beta1_http_route_timeouts_proto_depIdxs = []int32{
|
||||||
1, // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.request:type_name -> google.protobuf.Duration
|
1, // 0: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.request:type_name -> google.protobuf.Duration
|
||||||
1, // 1: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.backend_request:type_name -> google.protobuf.Duration
|
1, // 1: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.idle:type_name -> google.protobuf.Duration
|
||||||
1, // 2: hashicorp.consul.mesh.v2beta1.HTTPRouteTimeouts.idle:type_name -> google.protobuf.Duration
|
2, // [2:2] is the sub-list for method output_type
|
||||||
3, // [3:3] is the sub-list for method output_type
|
2, // [2:2] is the sub-list for method input_type
|
||||||
3, // [3:3] is the sub-list for method input_type
|
2, // [2:2] is the sub-list for extension type_name
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
2, // [2:2] is the sub-list for extension extendee
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
0, // [0:2] is the sub-list for field type_name
|
||||||
0, // [0:3] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_pbmesh_v2beta1_http_route_timeouts_proto_init() }
|
func init() { file_pbmesh_v2beta1_http_route_timeouts_proto_init() }
|
||||||
|
|
|
@ -7,35 +7,13 @@ package hashicorp.consul.mesh.v2beta1;
|
||||||
|
|
||||||
import "google/protobuf/duration.proto";
|
import "google/protobuf/duration.proto";
|
||||||
|
|
||||||
// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute.
|
// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute
|
||||||
// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration
|
// or GRPCRoute.
|
||||||
// and MUST BE >= 1ms.
|
|
||||||
//
|
|
||||||
// ALTERNATIVE: not using policy attachment semantics
|
|
||||||
message HTTPRouteTimeouts {
|
message HTTPRouteTimeouts {
|
||||||
// Request specifies the duration for processing an HTTP client request after which the
|
// RequestTimeout is the total amount of time permitted for the entire
|
||||||
// gateway will time out if unable to send a response.
|
// downstream request (and retries) to be processed.
|
||||||
// Whether the gateway starts the timeout before or after the entire client request stream
|
|
||||||
// has been received, is implementation-dependent.
|
|
||||||
//
|
|
||||||
// For example, setting the `rules.timeouts.request` field to the value `10s` in an
|
|
||||||
// `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds
|
|
||||||
// to complete.
|
|
||||||
//
|
|
||||||
// When this field is unspecified, request timeout behavior is implementation-dependent.
|
|
||||||
google.protobuf.Duration request = 1;
|
google.protobuf.Duration request = 1;
|
||||||
|
|
||||||
// BackendRequest specifies a timeout for an individual request from the gateway
|
// Idle specifies the total amount of time permitted for the request stream to be idle.
|
||||||
// to a backend service. Typically used in conjuction with retry configuration,
|
google.protobuf.Duration idle = 2;
|
||||||
// if supported by an implementation.
|
|
||||||
//
|
|
||||||
// The value of BackendRequest defaults to and must be <= the value of Request timeout.
|
|
||||||
//
|
|
||||||
// Support: Extended
|
|
||||||
//
|
|
||||||
// TODO(rb): net-new feature
|
|
||||||
google.protobuf.Duration backend_request = 2;
|
|
||||||
|
|
||||||
// TODO(RB): this is a consul-only feature
|
|
||||||
google.protobuf.Duration idle = 3;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue