mirror of https://github.com/status-im/consul.git
Ingress gateway header manip plumbing
This commit is contained in:
parent
d776a2d236
commit
f439dfc04f
|
@ -54,6 +54,7 @@ func (s *handlerIngressGateway) initialize(ctx context.Context) (ConfigSnapshot,
|
||||||
snap.IngressGateway.WatchedUpstreamEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
snap.IngressGateway.WatchedUpstreamEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
||||||
snap.IngressGateway.WatchedGateways = make(map[string]map[string]context.CancelFunc)
|
snap.IngressGateway.WatchedGateways = make(map[string]map[string]context.CancelFunc)
|
||||||
snap.IngressGateway.WatchedGatewayEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
snap.IngressGateway.WatchedGatewayEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
||||||
|
snap.IngressGateway.Listeners = make(map[IngressListenerKey]structs.IngressListener)
|
||||||
return snap, nil
|
return snap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +83,13 @@ func (s *handlerIngressGateway) handleUpdate(ctx context.Context, u cache.Update
|
||||||
snap.IngressGateway.TLSEnabled = gatewayConf.TLS.Enabled
|
snap.IngressGateway.TLSEnabled = gatewayConf.TLS.Enabled
|
||||||
snap.IngressGateway.TLSSet = true
|
snap.IngressGateway.TLSSet = true
|
||||||
|
|
||||||
|
// Load each listener's config from the config entry so we don't have to
|
||||||
|
// pass listener config through "upstreams" types as that grows.
|
||||||
|
for _, l := range gatewayConf.Listeners {
|
||||||
|
key := IngressListenerKey{Protocol: l.Protocol, Port: l.Port}
|
||||||
|
snap.IngressGateway.Listeners[key] = l
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.watchIngressLeafCert(ctx, snap); err != nil {
|
if err := s.watchIngressLeafCert(ctx, snap); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,6 +321,10 @@ type configSnapshotIngressGateway struct {
|
||||||
// to. This is constructed from the ingress-gateway config entry, and uses
|
// to. This is constructed from the ingress-gateway config entry, and uses
|
||||||
// the GatewayServices RPC to retrieve them.
|
// the GatewayServices RPC to retrieve them.
|
||||||
Upstreams map[IngressListenerKey]structs.Upstreams
|
Upstreams map[IngressListenerKey]structs.Upstreams
|
||||||
|
|
||||||
|
// Listeners is the original listener config from the ingress-gateway config
|
||||||
|
// entry to save us trying to pass fields through Upstreams
|
||||||
|
Listeners map[IngressListenerKey]structs.IngressListener
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *configSnapshotIngressGateway) IsEmpty() bool {
|
func (c *configSnapshotIngressGateway) IsEmpty() bool {
|
||||||
|
|
|
@ -1681,6 +1681,15 @@ func testConfigSnapshotIngressGateway(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Listeners: map[IngressListenerKey]structs.IngressListener{
|
||||||
|
{protocol, 9191}: {
|
||||||
|
Port: 9191,
|
||||||
|
Protocol: protocol,
|
||||||
|
Services: []structs.IngressService{
|
||||||
|
{Name: "db"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return snap
|
return snap
|
||||||
|
|
|
@ -168,6 +168,7 @@ func (e *IngressGatewayConfigEntry) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
declaredHosts := make(map[string]bool)
|
declaredHosts := make(map[string]bool)
|
||||||
|
serviceNames := make(map[ServiceID]struct{})
|
||||||
for i, s := range listener.Services {
|
for i, s := range listener.Services {
|
||||||
if err := validateInnerEnterpriseMeta(&s.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
|
if err := validateInnerEnterpriseMeta(&s.EnterpriseMeta, &e.EnterpriseMeta); err != nil {
|
||||||
return fmt.Errorf("Services[%d].%v", i, err)
|
return fmt.Errorf("Services[%d].%v", i, err)
|
||||||
|
@ -197,6 +198,11 @@ func (e *IngressGatewayConfigEntry) Validate() error {
|
||||||
if s.NamespaceOrDefault() == WildcardSpecifier {
|
if s.NamespaceOrDefault() == WildcardSpecifier {
|
||||||
return fmt.Errorf("Wildcard namespace is not supported for ingress services (listener on port %d)", listener.Port)
|
return fmt.Errorf("Wildcard namespace is not supported for ingress services (listener on port %d)", listener.Port)
|
||||||
}
|
}
|
||||||
|
sid := NewServiceID(s.Name, &s.EnterpriseMeta)
|
||||||
|
if _, ok := serviceNames[sid]; ok {
|
||||||
|
return fmt.Errorf("Service %s cannot be added multiple times (listener on port %d)", sid, listener.Port)
|
||||||
|
}
|
||||||
|
serviceNames[sid] = struct{}{}
|
||||||
|
|
||||||
for _, h := range s.Hosts {
|
for _, h := range s.Hosts {
|
||||||
if declaredHosts[h] {
|
if declaredHosts[h] {
|
||||||
|
|
|
@ -523,6 +523,27 @@ func TestIngressGatewayConfigEntry(t *testing.T) {
|
||||||
},
|
},
|
||||||
validateErr: "response headers only valid for http",
|
validateErr: "response headers only valid for http",
|
||||||
},
|
},
|
||||||
|
"duplicate services not allowed": {
|
||||||
|
entry: &IngressGatewayConfigEntry{
|
||||||
|
Kind: "ingress-gateway",
|
||||||
|
Name: "ingress-web",
|
||||||
|
Listeners: []IngressListener{
|
||||||
|
{
|
||||||
|
Port: 1111,
|
||||||
|
Protocol: "http",
|
||||||
|
Services: []IngressService{
|
||||||
|
{
|
||||||
|
Name: "web",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "web",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validateErr: "Service web cannot be added multiple times (listener on port 1111)",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
testConfigEntryNormalizeAndValidate(t, cases)
|
testConfigEntryNormalizeAndValidate(t, cases)
|
||||||
|
|
|
@ -375,9 +375,11 @@ type Upstream struct {
|
||||||
// MeshGateway is the configuration for mesh gateway usage of this upstream
|
// MeshGateway is the configuration for mesh gateway usage of this upstream
|
||||||
MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"`
|
MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"`
|
||||||
|
|
||||||
// IngressHosts are a list of hosts that should route to this upstream from
|
// IngressHosts are a list of hosts that should route to this upstream from an
|
||||||
// an ingress gateway. This cannot and should not be set by a user, it is
|
// ingress gateway. This cannot and should not be set by a user, it is used
|
||||||
// used internally to store the association of hosts to an upstream service.
|
// internally to store the association of hosts to an upstream service.
|
||||||
|
// TODO(banks): we shouldn't need this any more now we pass through full
|
||||||
|
// listener config in the ingress snapshot.
|
||||||
IngressHosts []string `json:"-" bexpr:"-"`
|
IngressHosts []string `json:"-" bexpr:"-"`
|
||||||
|
|
||||||
// CentrallyConfigured indicates whether the upstream was defined in a proxy
|
// CentrallyConfigured indicates whether the upstream was defined in a proxy
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
envoy_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||||
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
||||||
|
|
||||||
|
@ -29,7 +30,11 @@ func (s *ResourceGenerator) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot)
|
||||||
case structs.ServiceKindConnectProxy:
|
case structs.ServiceKindConnectProxy:
|
||||||
return s.routesForConnectProxy(cfgSnap.ConnectProxy.DiscoveryChain)
|
return s.routesForConnectProxy(cfgSnap.ConnectProxy.DiscoveryChain)
|
||||||
case structs.ServiceKindIngressGateway:
|
case structs.ServiceKindIngressGateway:
|
||||||
return s.routesForIngressGateway(cfgSnap.IngressGateway.Upstreams, cfgSnap.IngressGateway.DiscoveryChain)
|
return s.routesForIngressGateway(
|
||||||
|
cfgSnap.IngressGateway.Listeners,
|
||||||
|
cfgSnap.IngressGateway.Upstreams,
|
||||||
|
cfgSnap.IngressGateway.DiscoveryChain,
|
||||||
|
)
|
||||||
case structs.ServiceKindTerminatingGateway:
|
case structs.ServiceKindTerminatingGateway:
|
||||||
return s.routesFromSnapshotTerminatingGateway(cfgSnap)
|
return s.routesFromSnapshotTerminatingGateway(cfgSnap)
|
||||||
case structs.ServiceKindMeshGateway:
|
case structs.ServiceKindMeshGateway:
|
||||||
|
@ -160,6 +165,7 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, a
|
||||||
// routesForIngressGateway returns the xDS API representation of the
|
// routesForIngressGateway returns the xDS API representation of the
|
||||||
// "routes" in the snapshot.
|
// "routes" in the snapshot.
|
||||||
func (s *ResourceGenerator) routesForIngressGateway(
|
func (s *ResourceGenerator) routesForIngressGateway(
|
||||||
|
listeners map[proxycfg.IngressListenerKey]structs.IngressListener,
|
||||||
upstreams map[proxycfg.IngressListenerKey]structs.Upstreams,
|
upstreams map[proxycfg.IngressListenerKey]structs.Upstreams,
|
||||||
chains map[string]*structs.CompiledDiscoveryChain,
|
chains map[string]*structs.CompiledDiscoveryChain,
|
||||||
) ([]proto.Message, error) {
|
) ([]proto.Message, error) {
|
||||||
|
@ -190,6 +196,42 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if we need to configure any special settings on this route config
|
||||||
|
if lCfg, ok := listeners[listenerKey]; ok {
|
||||||
|
if is := findIngressServiceMatchingUpstream(lCfg, u); is != nil {
|
||||||
|
// Set up any header manipulation we need
|
||||||
|
if is.RequestHeaders != nil {
|
||||||
|
virtualHost.RequestHeadersToAdd = append(
|
||||||
|
virtualHost.RequestHeadersToAdd,
|
||||||
|
makeHeadersValueOptions(is.RequestHeaders.Add, true)...,
|
||||||
|
)
|
||||||
|
virtualHost.RequestHeadersToAdd = append(
|
||||||
|
virtualHost.RequestHeadersToAdd,
|
||||||
|
makeHeadersValueOptions(is.RequestHeaders.Set, false)...,
|
||||||
|
)
|
||||||
|
virtualHost.RequestHeadersToRemove = append(
|
||||||
|
virtualHost.RequestHeadersToRemove,
|
||||||
|
is.RequestHeaders.Remove...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if is.ResponseHeaders != nil {
|
||||||
|
virtualHost.ResponseHeadersToAdd = append(
|
||||||
|
virtualHost.ResponseHeadersToAdd,
|
||||||
|
makeHeadersValueOptions(is.ResponseHeaders.Add, true)...,
|
||||||
|
)
|
||||||
|
virtualHost.ResponseHeadersToAdd = append(
|
||||||
|
virtualHost.ResponseHeadersToAdd,
|
||||||
|
makeHeadersValueOptions(is.ResponseHeaders.Set, false)...,
|
||||||
|
)
|
||||||
|
virtualHost.ResponseHeadersToRemove = append(
|
||||||
|
virtualHost.ResponseHeadersToRemove,
|
||||||
|
is.ResponseHeaders.Remove...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
upstreamRoute.VirtualHosts = append(upstreamRoute.VirtualHosts, virtualHost)
|
upstreamRoute.VirtualHosts = append(upstreamRoute.VirtualHosts, virtualHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +241,36 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeHeadersValueOptions(vals map[string]string, add bool) []*envoy_core_v3.HeaderValueOption {
|
||||||
|
opts := make([]*envoy_core_v3.HeaderValueOption, 0, len(vals))
|
||||||
|
for k, v := range vals {
|
||||||
|
o := &envoy_core_v3.HeaderValueOption{
|
||||||
|
Header: &envoy_core_v3.HeaderValue{
|
||||||
|
Key: k,
|
||||||
|
Value: v,
|
||||||
|
},
|
||||||
|
Append: makeBoolValue(add),
|
||||||
|
}
|
||||||
|
opts = append(opts, o)
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
func findIngressServiceMatchingUpstream(l structs.IngressListener, u structs.Upstream) *structs.IngressService {
|
||||||
|
// Hunt through for the matching service. We validate now that there is
|
||||||
|
// only one IngressService for each unique name although originally that
|
||||||
|
// wasn't checked as it didn't matter. Assume there is only one now
|
||||||
|
// though!
|
||||||
|
wantSID := u.DestinationID()
|
||||||
|
for _, s := range l.Services {
|
||||||
|
sid := structs.NewServiceID(s.Name, &s.EnterpriseMeta)
|
||||||
|
if wantSID.Matches(sid) {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func generateUpstreamIngressDomains(listenerKey proxycfg.IngressListenerKey, u structs.Upstream) []string {
|
func generateUpstreamIngressDomains(listenerKey proxycfg.IngressListenerKey, u structs.Upstream) []string {
|
||||||
var domains []string
|
var domains []string
|
||||||
domainsSet := make(map[string]bool)
|
domainsSet := make(map[string]bool)
|
||||||
|
|
|
@ -189,6 +189,33 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ingress-with-chain-and-router-header-manip",
|
||||||
|
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
k := proxycfg.IngressListenerKey{Port: 9191, Protocol: "http"}
|
||||||
|
l := snap.IngressGateway.Listeners[k]
|
||||||
|
l.Services[0].RequestHeaders = &structs.HTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"bar": "baz",
|
||||||
|
},
|
||||||
|
Remove: []string{"qux"},
|
||||||
|
}
|
||||||
|
l.Services[0].ResponseHeaders = &structs.HTTPHeaderModifiers{
|
||||||
|
Add: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
Set: map[string]string{
|
||||||
|
"bar": "baz",
|
||||||
|
},
|
||||||
|
Remove: []string{"qux"},
|
||||||
|
}
|
||||||
|
snap.IngressGateway.Listeners[k] = l
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "terminating-gateway-lb-config",
|
name: "terminating-gateway-lb-config",
|
||||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||||
|
|
401
agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.envoy-1-18-x.golden
vendored
Normal file
401
agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.envoy-1-18-x.golden
vendored
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||||
|
"name": "9191",
|
||||||
|
"virtualHosts": [
|
||||||
|
{
|
||||||
|
"name": "db",
|
||||||
|
"domains": [
|
||||||
|
"db.ingress.*",
|
||||||
|
"db.ingress.*:9191"
|
||||||
|
],
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"path": "/exact"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"safeRegex": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "/regex"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"presentMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"presentMatch": true,
|
||||||
|
"invertMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"exactMatch": "exact"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"prefixMatch": "prefix"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"suffixMatch": "suffix"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "regex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": ":method",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "GET|PUT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"exactMatch": "exact"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ":method",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "GET|PUT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam1",
|
||||||
|
"stringMatch": {
|
||||||
|
"exact": "exact"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam2",
|
||||||
|
"stringMatch": {
|
||||||
|
"safeRegex": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "regex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam3",
|
||||||
|
"presentMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"prefixRewrite": "/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"prefixRewrite": "/nested/newlocation"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/timeout"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"timeout": "33s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-connect"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "connect-failure",
|
||||||
|
"numRetries": 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-codes"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "retriable-status-codes",
|
||||||
|
"numRetries": 15,
|
||||||
|
"retriableStatusCodes": [
|
||||||
|
401,
|
||||||
|
409,
|
||||||
|
451
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-both"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-both.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "connect-failure,retriable-status-codes",
|
||||||
|
"retriableStatusCodes": [
|
||||||
|
401,
|
||||||
|
409,
|
||||||
|
451
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/split-3-ways"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"weightedClusters": {
|
||||||
|
"clusters": [
|
||||||
|
{
|
||||||
|
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 9550
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"totalWeight": 10000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestHeadersToAdd": [
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "foo",
|
||||||
|
"value": "bar"
|
||||||
|
},
|
||||||
|
"append": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "bar",
|
||||||
|
"value": "baz"
|
||||||
|
},
|
||||||
|
"append": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestHeadersToRemove": [
|
||||||
|
"qux"
|
||||||
|
],
|
||||||
|
"responseHeadersToAdd": [
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "foo",
|
||||||
|
"value": "bar"
|
||||||
|
},
|
||||||
|
"append": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "bar",
|
||||||
|
"value": "baz"
|
||||||
|
},
|
||||||
|
"append": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseHeadersToRemove": [
|
||||||
|
"qux"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validateClusters": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
401
agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.v2compat.envoy-1-16-x.golden
vendored
Normal file
401
agent/xds/testdata/routes/ingress-with-chain-and-router-header-manip.v2compat.envoy-1-16-x.golden
vendored
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||||
|
"name": "9191",
|
||||||
|
"virtualHosts": [
|
||||||
|
{
|
||||||
|
"name": "db",
|
||||||
|
"domains": [
|
||||||
|
"db.ingress.*",
|
||||||
|
"db.ingress.*:9191"
|
||||||
|
],
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"path": "/exact"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"safeRegex": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "/regex"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"presentMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"presentMatch": true,
|
||||||
|
"invertMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-not-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"exactMatch": "exact"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"prefixMatch": "prefix"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-prefix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"suffixMatch": "suffix"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-suffix.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "regex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": ":method",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "GET|PUT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "x-debug",
|
||||||
|
"exactMatch": "exact"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ":method",
|
||||||
|
"safeRegexMatch": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "GET|PUT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam1",
|
||||||
|
"stringMatch": {
|
||||||
|
"exact": "exact"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-exact.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam2",
|
||||||
|
"stringMatch": {
|
||||||
|
"safeRegex": {
|
||||||
|
"googleRe2": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"regex": "regex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/",
|
||||||
|
"queryParameters": [
|
||||||
|
{
|
||||||
|
"name": "secretparam3",
|
||||||
|
"presentMatch": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prm-present.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "nil-match.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "empty-match-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "empty-match-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix-rewrite-1.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"prefixRewrite": "/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/prefix"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "prefix-rewrite-2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"prefixRewrite": "/nested/newlocation"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/timeout"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "req-timeout.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"timeout": "33s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-connect"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-connect.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "connect-failure",
|
||||||
|
"numRetries": 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-codes"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-codes.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "retriable-status-codes",
|
||||||
|
"numRetries": 15,
|
||||||
|
"retriableStatusCodes": [
|
||||||
|
401,
|
||||||
|
409,
|
||||||
|
451
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/retry-both"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "retry-both.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"retryPolicy": {
|
||||||
|
"retryOn": "connect-failure,retriable-status-codes",
|
||||||
|
"retriableStatusCodes": [
|
||||||
|
401,
|
||||||
|
409,
|
||||||
|
451
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/split-3-ways"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"weightedClusters": {
|
||||||
|
"clusters": [
|
||||||
|
{
|
||||||
|
"name": "big-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 9550
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "goldilocks-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lil-bit-side.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"weight": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"totalWeight": 10000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"prefix": "/"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestHeadersToAdd": [
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "foo",
|
||||||
|
"value": "bar"
|
||||||
|
},
|
||||||
|
"append": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "bar",
|
||||||
|
"value": "baz"
|
||||||
|
},
|
||||||
|
"append": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestHeadersToRemove": [
|
||||||
|
"qux"
|
||||||
|
],
|
||||||
|
"responseHeadersToAdd": [
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "foo",
|
||||||
|
"value": "bar"
|
||||||
|
},
|
||||||
|
"append": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"key": "bar",
|
||||||
|
"value": "baz"
|
||||||
|
},
|
||||||
|
"append": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseHeadersToRemove": [
|
||||||
|
"qux"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"validateClusters": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.api.v2.RouteConfiguration",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
Loading…
Reference in New Issue