proxycfg: change how various proxycfg test helpers for making ConfigSnapshot copies works to be more correct and less error prone (#12531)
Prior to this PR for the envoy xDS golden tests in the agent/xds package we were hand-creating a proxycfg.ConfigSnapshot structure in the proper format for input to the xDS generator. Over time this intermediate structure has gotten trickier to build correctly for the various tests. This PR proposes to switch to using the existing mechanism for turning a structs.NodeService and a sequence of cache.UpdateEvent copies into a proxycfg.ConfigSnapshot, as that is less error prone to construct and aligns more with how the data arrives. NOTE: almost all of this is in test-related code. I tried super hard to craft correct event inputs to get the golden files to be the same, or similar enough after construction to feel ok that i recreated the spirit of the original test cases.
This commit is contained in:
parent
19fe3e14d1
commit
cc4733e60d
|
@ -152,10 +152,26 @@ func newState(ns *structs.NodeService, token string, config stateConfig) (*state
|
|||
return nil, err
|
||||
}
|
||||
|
||||
handler, err := newKindHandler(config, s, ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &state{
|
||||
logger: config.logger.With("proxy", s.proxyID, "kind", s.kind),
|
||||
serviceInstance: s,
|
||||
handler: handler,
|
||||
ch: ch,
|
||||
snapCh: make(chan ConfigSnapshot, 1),
|
||||
reqCh: make(chan chan *ConfigSnapshot, 1),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newKindHandler(config stateConfig, s serviceInstance, ch chan cache.UpdateEvent) (kindHandler, error) {
|
||||
var handler kindHandler
|
||||
h := handlerState{stateConfig: config, serviceInstance: s, ch: ch}
|
||||
|
||||
switch ns.Kind {
|
||||
switch s.kind {
|
||||
case structs.ServiceKindConnectProxy:
|
||||
handler = &handlerConnectProxy{handlerState: h}
|
||||
case structs.ServiceKindTerminatingGateway:
|
||||
|
@ -170,14 +186,7 @@ func newState(ns *structs.NodeService, token string, config stateConfig) (*state
|
|||
return nil, errors.New("not a connect-proxy, terminating-gateway, mesh-gateway, or ingress-gateway")
|
||||
}
|
||||
|
||||
return &state{
|
||||
logger: config.logger.With("proxy", s.proxyID, "kind", s.kind),
|
||||
serviceInstance: s,
|
||||
handler: handler,
|
||||
ch: ch,
|
||||
snapCh: make(chan ConfigSnapshot, 1),
|
||||
reqCh: make(chan chan *ConfigSnapshot, 1),
|
||||
}, nil
|
||||
return handler, nil
|
||||
}
|
||||
|
||||
func newServiceInstanceFromNodeService(ns *structs.NodeService, token string) (serviceInstance, error) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,271 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/go-testing-interface"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// TestConfigSnapshot returns a fully populated snapshot
|
||||
func TestConfigSnapshot(t testing.T, nsFn func(ns *structs.NodeService), extraUpdates []cache.UpdateEvent) *ConfigSnapshot {
|
||||
roots, leaf := TestCerts(t)
|
||||
|
||||
// no entries implies we'll get a default chain
|
||||
dbChain := discoverychain.TestCompileConfigEntries(t, "db", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
assert.True(t, dbChain.IsDefault())
|
||||
|
||||
var (
|
||||
upstreams = structs.TestUpstreams(t)
|
||||
dbUpstream = upstreams[0]
|
||||
geoUpstream = upstreams[1]
|
||||
|
||||
dbUID = NewUpstreamID(&dbUpstream)
|
||||
geoUID = NewUpstreamID(&geoUpstream)
|
||||
|
||||
webSN = structs.ServiceIDString("web", nil)
|
||||
)
|
||||
|
||||
baseEvents := []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: leafWatchID,
|
||||
Result: leaf,
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionsWatchID,
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil, // no intentions defined
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: svcChecksWatchIDPrefix + webSN,
|
||||
Result: []structs.CheckType{},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream:" + geoUID.String(),
|
||||
Result: &structs.PreparedQueryExecuteResponse{
|
||||
Nodes: TestPreparedQueryNodes(t, "geo-cache"),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + dbUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: dbChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + dbChain.ID() + ":" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodes(t, "db"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindConnectProxy,
|
||||
Service: "web-sidecar-proxy",
|
||||
Port: 9999,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
DestinationServiceID: "web",
|
||||
DestinationServiceName: "web",
|
||||
LocalServiceAddress: "127.0.0.1",
|
||||
LocalServicePort: 8080,
|
||||
Config: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
Upstreams: upstreams,
|
||||
},
|
||||
Meta: nil,
|
||||
TaggedAddresses: nil,
|
||||
}, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates))
|
||||
}
|
||||
|
||||
// TestConfigSnapshotDiscoveryChain returns a fully populated snapshot using a discovery chain
|
||||
func TestConfigSnapshotDiscoveryChain(
|
||||
t testing.T,
|
||||
variation string,
|
||||
nsFn func(ns *structs.NodeService),
|
||||
extraUpdates []cache.UpdateEvent,
|
||||
additionalEntries ...structs.ConfigEntry,
|
||||
) *ConfigSnapshot {
|
||||
roots, leaf := TestCerts(t)
|
||||
|
||||
var (
|
||||
upstreams = structs.TestUpstreams(t)
|
||||
geoUpstream = upstreams[1]
|
||||
|
||||
geoUID = NewUpstreamID(&geoUpstream)
|
||||
|
||||
webSN = structs.ServiceIDString("web", nil)
|
||||
)
|
||||
|
||||
baseEvents := testSpliceEvents([]cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: leafWatchID,
|
||||
Result: leaf,
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionsWatchID,
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil, // no intentions defined
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: svcChecksWatchIDPrefix + webSN,
|
||||
Result: []structs.CheckType{},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream:" + geoUID.String(),
|
||||
Result: &structs.PreparedQueryExecuteResponse{
|
||||
Nodes: TestPreparedQueryNodes(t, "geo-cache"),
|
||||
},
|
||||
},
|
||||
}, setupTestVariationConfigEntriesAndSnapshot(
|
||||
t, variation, upstreams, additionalEntries...,
|
||||
))
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindConnectProxy,
|
||||
Service: "web-sidecar-proxy",
|
||||
Port: 9999,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
DestinationServiceID: "web",
|
||||
DestinationServiceName: "web",
|
||||
LocalServiceAddress: "127.0.0.1",
|
||||
LocalServicePort: 8080,
|
||||
Config: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
Upstreams: upstreams,
|
||||
},
|
||||
Meta: nil,
|
||||
TaggedAddresses: nil,
|
||||
}, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates))
|
||||
}
|
||||
|
||||
func TestConfigSnapshotExposeConfig(t testing.T, nsFn func(ns *structs.NodeService)) *ConfigSnapshot {
|
||||
roots, leaf := TestCerts(t)
|
||||
|
||||
var (
|
||||
webSN = structs.ServiceIDString("web", nil)
|
||||
)
|
||||
|
||||
baseEvents := []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: leafWatchID, Result: leaf,
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionsWatchID,
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil, // no intentions defined
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: svcChecksWatchIDPrefix + webSN,
|
||||
Result: []structs.CheckType{},
|
||||
},
|
||||
}
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindConnectProxy,
|
||||
Service: "web-sidecar-proxy",
|
||||
Address: "1.2.3.4",
|
||||
Port: 8080,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
DestinationServiceID: "web",
|
||||
DestinationServiceName: "web",
|
||||
LocalServicePort: 8080,
|
||||
Expose: structs.ExposeConfig{
|
||||
Checks: false,
|
||||
Paths: []structs.ExposePath{
|
||||
{
|
||||
LocalPathPort: 8080,
|
||||
Path: "/health1",
|
||||
ListenerPort: 21500,
|
||||
},
|
||||
{
|
||||
LocalPathPort: 8080,
|
||||
Path: "/health2",
|
||||
ListenerPort: 21501,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Meta: nil,
|
||||
TaggedAddresses: nil,
|
||||
}, nsFn, nil, baseEvents)
|
||||
}
|
||||
|
||||
func TestConfigSnapshotGRPCExposeHTTP1(t testing.T) *ConfigSnapshot {
|
||||
roots, leaf := TestCerts(t)
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindConnectProxy,
|
||||
Service: "grpc-proxy",
|
||||
Address: "1.2.3.4",
|
||||
Port: 8080,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
DestinationServiceName: "grpc",
|
||||
DestinationServiceID: "grpc",
|
||||
LocalServicePort: 8080,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "grpc",
|
||||
},
|
||||
Expose: structs.ExposeConfig{
|
||||
Checks: false,
|
||||
Paths: []structs.ExposePath{
|
||||
{
|
||||
LocalPathPort: 8090,
|
||||
Path: "/healthz",
|
||||
ListenerPort: 21500,
|
||||
Protocol: "http",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Meta: nil,
|
||||
TaggedAddresses: nil,
|
||||
}, nil, nil, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: leafWatchID,
|
||||
Result: leaf,
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionsWatchID,
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil, // no intentions defined
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: svcChecksWatchIDPrefix + structs.ServiceIDString("grpc", nil),
|
||||
Result: []structs.CheckType{},
|
||||
},
|
||||
})
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,442 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/go-testing-interface"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func TestConfigSnapshotMeshGateway(t testing.T, variant string, nsFn func(ns *structs.NodeService), extraUpdates []cache.UpdateEvent) *ConfigSnapshot {
|
||||
roots, _ := TestCerts(t)
|
||||
|
||||
var (
|
||||
populateServices = true
|
||||
useFederationStates = false
|
||||
deleteCrossDCEntry = false
|
||||
)
|
||||
|
||||
switch variant {
|
||||
case "default":
|
||||
case "federation-states":
|
||||
populateServices = true
|
||||
useFederationStates = true
|
||||
deleteCrossDCEntry = true
|
||||
case "newer-info-in-federation-states":
|
||||
populateServices = true
|
||||
useFederationStates = true
|
||||
deleteCrossDCEntry = false
|
||||
case "older-info-in-federation-states":
|
||||
populateServices = true
|
||||
useFederationStates = true
|
||||
deleteCrossDCEntry = false
|
||||
case "no-services":
|
||||
populateServices = false
|
||||
useFederationStates = false
|
||||
deleteCrossDCEntry = false
|
||||
case "service-subsets":
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "service-subsets2": // TODO(rb): make this merge with 'service-subsets'
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "default-service-subsets2": // TODO(rb): rename to strip the 2 when the prior is merged with 'service-subsets'
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "ignore-extra-resolvers":
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "notfound",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "service-timeouts":
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
ConnectTimeout: 10 * time.Second,
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "non-hash-lb-injected":
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: "service-resolvers", // serviceResolversWatchID
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
Policy: "least_request",
|
||||
LeastRequestConfig: &structs.LeastRequestConfig{
|
||||
ChoiceCount: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
case "hash-lb-ignored":
|
||||
extraUpdates = append(extraUpdates, cache.UpdateEvent{
|
||||
CorrelationID: "service-resolvers", // serviceResolversWatchID
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
default:
|
||||
t.Fatalf("unknown variant: %s", variant)
|
||||
return nil
|
||||
}
|
||||
|
||||
baseEvents := []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceListWatchID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: datacentersWatchID,
|
||||
Result: &[]string{"dc1"},
|
||||
},
|
||||
}
|
||||
|
||||
if populateServices || useFederationStates {
|
||||
baseEvents = testSpliceEvents(baseEvents, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: datacentersWatchID,
|
||||
Result: &[]string{"dc1", "dc2", "dc4", "dc6"},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if populateServices {
|
||||
var (
|
||||
foo = structs.NewServiceName("foo", nil)
|
||||
bar = structs.NewServiceName("bar", nil)
|
||||
)
|
||||
baseEvents = testSpliceEvents(baseEvents, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: "mesh-gateway:dc2",
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC2(t),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "mesh-gateway:dc4",
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC4Hostname(t),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "mesh-gateway:dc6",
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC6Hostname(t),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceListWatchID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: []structs.ServiceName{
|
||||
foo,
|
||||
bar,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "connect-service:" + foo.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestGatewayServiceGroupFooDC1(t),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "connect-service:" + bar.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestGatewayServiceGroupBarDC1(t),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolversWatchID,
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
//
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if useFederationStates {
|
||||
nsFn = testSpliceNodeServiceFunc(nsFn, func(ns *structs.NodeService) {
|
||||
ns.Meta[structs.MetaWANFederationKey] = "1"
|
||||
})
|
||||
|
||||
if deleteCrossDCEntry {
|
||||
baseEvents = testSpliceEvents(baseEvents, []cache.UpdateEvent{
|
||||
{
|
||||
// Have the cross-dc query mechanism not work for dc2 so
|
||||
// fedstates will infill.
|
||||
CorrelationID: "mesh-gateway:dc2",
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: nil,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
dc2Nodes := TestGatewayNodesDC2(t)
|
||||
switch variant {
|
||||
case "newer-info-in-federation-states":
|
||||
// Create a duplicate entry in FedStateGateways, with a high ModifyIndex, to
|
||||
// verify that fresh data in the federation state is preferred over stale data
|
||||
// in GatewayGroups.
|
||||
svc := structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.0.1.3", 8443,
|
||||
structs.ServiceAddress{Address: "10.0.1.3", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.18.1.3", Port: 443},
|
||||
)
|
||||
svc.RaftIndex.ModifyIndex = math.MaxUint64
|
||||
|
||||
dc2Nodes = structs.CheckServiceNodes{
|
||||
{
|
||||
Node: dc2Nodes[0].Node,
|
||||
Service: svc,
|
||||
},
|
||||
}
|
||||
case "older-info-in-federation-states":
|
||||
// Create a duplicate entry in FedStateGateways, with a low ModifyIndex, to
|
||||
// verify that stale data in the federation state is ignored in favor of the
|
||||
// fresher data in GatewayGroups.
|
||||
svc := structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.0.1.3", 8443,
|
||||
structs.ServiceAddress{Address: "10.0.1.3", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.18.1.3", Port: 443},
|
||||
)
|
||||
svc.RaftIndex.ModifyIndex = 0
|
||||
|
||||
dc2Nodes = structs.CheckServiceNodes{
|
||||
{
|
||||
Node: dc2Nodes[0].Node,
|
||||
Service: svc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
baseEvents = testSpliceEvents(baseEvents, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: federationStateListGatewaysWatchID,
|
||||
Result: &structs.DatacenterIndexedCheckServiceNodes{
|
||||
DatacenterNodes: map[string]structs.CheckServiceNodes{
|
||||
"dc2": dc2Nodes,
|
||||
"dc4": TestGatewayNodesDC4Hostname(t),
|
||||
"dc6": TestGatewayNodesDC6Hostname(t),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: consulServerListWatchID,
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: nil, // TODO
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindMeshGateway,
|
||||
Service: "mesh-gateway",
|
||||
Address: "1.2.3.4",
|
||||
Port: 8443,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
Config: map[string]interface{}{},
|
||||
},
|
||||
Meta: make(map[string]string),
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
structs.TaggedAddressLAN: {
|
||||
Address: "1.2.3.4",
|
||||
Port: 8443,
|
||||
},
|
||||
structs.TaggedAddressWAN: {
|
||||
Address: "198.18.0.1",
|
||||
Port: 443,
|
||||
},
|
||||
},
|
||||
}, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates))
|
||||
}
|
|
@ -0,0 +1,643 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/go-testing-interface"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
agentcache "github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func TestConfigSnapshotTerminatingGateway(
|
||||
t testing.T,
|
||||
populateServices bool,
|
||||
nsFn func(ns *structs.NodeService),
|
||||
extraUpdates []agentcache.UpdateEvent,
|
||||
) *ConfigSnapshot {
|
||||
roots, _ := TestCerts(t)
|
||||
|
||||
var (
|
||||
web = structs.NewServiceName("web", nil)
|
||||
api = structs.NewServiceName("api", nil)
|
||||
db = structs.NewServiceName("db", nil)
|
||||
cache = structs.NewServiceName("cache", nil)
|
||||
)
|
||||
|
||||
baseEvents := []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: rootsWatchID,
|
||||
Result: roots,
|
||||
},
|
||||
{
|
||||
CorrelationID: gatewayServicesWatchID,
|
||||
Result: &structs.IndexedGatewayServices{
|
||||
Services: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if populateServices {
|
||||
webNodes := TestUpstreamNodes(t, web.Name)
|
||||
webNodes[0].Service.Meta = map[string]string{"version": "1"}
|
||||
webNodes[1].Service.Meta = map[string]string{"version": "2"}
|
||||
|
||||
apiNodes := structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "api",
|
||||
Node: "test1",
|
||||
Address: "10.10.1.1",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "api",
|
||||
Address: "api.mydomain",
|
||||
Port: 8081,
|
||||
},
|
||||
Checks: structs.HealthChecks{
|
||||
{Status: "critical"},
|
||||
},
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test2",
|
||||
Node: "test2",
|
||||
Address: "10.10.1.2",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "api",
|
||||
Address: "api.altdomain",
|
||||
Port: 8081,
|
||||
Meta: map[string]string{
|
||||
"domain": "alt",
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test3",
|
||||
Node: "test3",
|
||||
Address: "10.10.1.3",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "api",
|
||||
Address: "10.10.1.3",
|
||||
Port: 8081,
|
||||
},
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test4",
|
||||
Node: "test4",
|
||||
Address: "10.10.1.4",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "api",
|
||||
Address: "api.thirddomain",
|
||||
Port: 8081,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Has failing instance
|
||||
dbNodes := structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "db",
|
||||
Node: "test4",
|
||||
Address: "10.10.1.4",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "db",
|
||||
Address: "db.mydomain",
|
||||
Port: 8081,
|
||||
},
|
||||
Checks: structs.HealthChecks{
|
||||
{Status: "critical"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Has passing instance but failing subset
|
||||
cacheNodes := structs.CheckServiceNodes{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
ID: "cache",
|
||||
Node: "test5",
|
||||
Address: "10.10.1.5",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "cache",
|
||||
Address: "cache.mydomain",
|
||||
Port: 8081,
|
||||
},
|
||||
},
|
||||
{
|
||||
Node: &structs.Node{
|
||||
ID: "cache",
|
||||
Node: "test5",
|
||||
Address: "10.10.1.5",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "cache",
|
||||
Address: "cache.mydomain",
|
||||
Port: 8081,
|
||||
Meta: map[string]string{
|
||||
"Env": "prod",
|
||||
},
|
||||
},
|
||||
Checks: structs.HealthChecks{
|
||||
{Status: "critical"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
baseEvents = testSpliceEvents(baseEvents, []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: gatewayServicesWatchID,
|
||||
Result: &structs.IndexedGatewayServices{
|
||||
Services: []*structs.GatewayService{
|
||||
{
|
||||
Service: web,
|
||||
CAFile: "ca.cert.pem",
|
||||
},
|
||||
{
|
||||
Service: api,
|
||||
CAFile: "ca.cert.pem",
|
||||
CertFile: "api.cert.pem",
|
||||
KeyFile: "api.key.pem",
|
||||
},
|
||||
{
|
||||
Service: db,
|
||||
},
|
||||
{
|
||||
Service: cache,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: externalServiceIDPrefix + web.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: webNodes,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: externalServiceIDPrefix + api.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: apiNodes,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: externalServiceIDPrefix + db.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: dbNodes,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: externalServiceIDPrefix + cache.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: cacheNodes,
|
||||
},
|
||||
},
|
||||
// ========
|
||||
// no intentions defined for these services
|
||||
{
|
||||
CorrelationID: serviceIntentionsIDPrefix + web.String(),
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceIntentionsIDPrefix + api.String(),
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceIntentionsIDPrefix + db.String(),
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceIntentionsIDPrefix + cache.String(),
|
||||
Result: &structs.IndexedIntentionMatches{
|
||||
Matches: []structs.Intentions{
|
||||
nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
// ========
|
||||
{
|
||||
CorrelationID: serviceLeafIDPrefix + web.String(),
|
||||
Result: &structs.IssuedCert{
|
||||
CertPEM: golden(t, "test-leaf-cert"),
|
||||
PrivateKeyPEM: golden(t, "test-leaf-key"),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceLeafIDPrefix + api.String(),
|
||||
Result: &structs.IssuedCert{
|
||||
CertPEM: golden(t, "alt-test-leaf-cert"),
|
||||
PrivateKeyPEM: golden(t, "alt-test-leaf-key"),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceLeafIDPrefix + db.String(),
|
||||
Result: &structs.IssuedCert{
|
||||
CertPEM: golden(t, "db-test-leaf-cert"),
|
||||
PrivateKeyPEM: golden(t, "db-test-leaf-key"),
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceLeafIDPrefix + cache.String(),
|
||||
Result: &structs.IssuedCert{
|
||||
CertPEM: golden(t, "cache-test-leaf-cert"),
|
||||
PrivateKeyPEM: golden(t, "cache-test-leaf-key"),
|
||||
},
|
||||
},
|
||||
// ========
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "tcp"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + api.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "tcp"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + db.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "tcp"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + cache.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "tcp"},
|
||||
},
|
||||
},
|
||||
// ========
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + web.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + api.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + db.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + cache.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: nil,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return testConfigSnapshotFixture(t, &structs.NodeService{
|
||||
Kind: structs.ServiceKindTerminatingGateway,
|
||||
Service: "terminating-gateway",
|
||||
Address: "1.2.3.4",
|
||||
Port: 8443,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
structs.TaggedAddressWAN: {
|
||||
Address: "198.18.0.1",
|
||||
Port: 443,
|
||||
},
|
||||
},
|
||||
}, nsFn, nil, testSpliceEvents(baseEvents, extraUpdates))
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotTerminatingGatewayServiceSubsets(t, false)
|
||||
}
|
||||
func TestConfigSnapshotTerminatingGatewayServiceSubsetsWebAndCache(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotTerminatingGatewayServiceSubsets(t, true)
|
||||
}
|
||||
func testConfigSnapshotTerminatingGatewayServiceSubsets(t testing.T, alsoAdjustCache bool) *ConfigSnapshot {
|
||||
var (
|
||||
web = structs.NewServiceName("web", nil)
|
||||
cache = structs.NewServiceName("cache", nil)
|
||||
)
|
||||
|
||||
events := []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + web.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if alsoAdjustCache {
|
||||
events = testSpliceEvents(events, []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + cache.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "cache",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"prod": {
|
||||
Filter: "Service.Meta.Env == prod",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, events)
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTerminatingGatewayDefaultServiceSubset(t testing.T) *ConfigSnapshot {
|
||||
web := structs.NewServiceName("web", nil)
|
||||
|
||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + web.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// {
|
||||
// CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
// Result: &structs.ServiceConfigResponse{
|
||||
// ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
// },
|
||||
// },
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTerminatingGatewayLBConfig(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotTerminatingGatewayLBConfig(t, "default")
|
||||
}
|
||||
func TestConfigSnapshotTerminatingGatewayLBConfigNoHashPolicies(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotTerminatingGatewayLBConfig(t, "no-hash-policies")
|
||||
}
|
||||
func testConfigSnapshotTerminatingGatewayLBConfig(t testing.T, variant string) *ConfigSnapshot {
|
||||
web := structs.NewServiceName("web", nil)
|
||||
|
||||
entry := &structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: structs.HashPolicyCookie,
|
||||
FieldValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: structs.HashPolicyHeader,
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
switch variant {
|
||||
case "default":
|
||||
case "no-hash-policies":
|
||||
entry.LoadBalancer.HashPolicies = nil
|
||||
default:
|
||||
t.Fatalf("unknown variant %q", variant)
|
||||
return nil
|
||||
}
|
||||
|
||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + web.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{entry},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTerminatingGatewayHostnameSubsets(t testing.T) *ConfigSnapshot {
|
||||
var (
|
||||
api = structs.NewServiceName("api", nil)
|
||||
cache = structs.NewServiceName("cache", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + api.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "api",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"alt": {
|
||||
Filter: "Service.Meta.domain == alt",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + cache.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "cache",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"prod": {
|
||||
Filter: "Service.Meta.Env == prod",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + api.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + cache.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers(t testing.T) *ConfigSnapshot {
|
||||
var (
|
||||
web = structs.NewServiceName("web", nil)
|
||||
notfound = structs.NewServiceName("notfound", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshotTerminatingGateway(t, true, nil, []agentcache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + web.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceResolverIDPrefix + notfound.String(),
|
||||
Result: &structs.IndexedConfigEntries{
|
||||
Kind: structs.ServiceResolver,
|
||||
Entries: []structs.ConfigEntry{
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "notfound",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: serviceConfigIDPrefix + web.String(),
|
||||
Result: &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,519 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/go-testing-interface"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func TestConfigSnapshotTransparentProxy(t testing.T) *ConfigSnapshot {
|
||||
// DiscoveryChain without an UpstreamConfig should yield a
|
||||
// filter chain when in transparent proxy mode
|
||||
var (
|
||||
google = structs.NewServiceName("google", nil)
|
||||
googleUID = NewUpstreamIDFromServiceName(google)
|
||||
googleChain = discoverychain.TestCompileConfigEntries(t, "google", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
noEndpoints = structs.NewServiceName("no-endpoints", nil)
|
||||
noEndpointsUID = NewUpstreamIDFromServiceName(noEndpoints)
|
||||
noEndpointsChain = discoverychain.TestCompileConfigEntries(t, "no-endpoints", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
db = structs.NewServiceName("db", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Mode = structs.ProxyModeTransparent
|
||||
}, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionUpstreamsID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: structs.ServiceList{
|
||||
google,
|
||||
noEndpoints,
|
||||
// In transparent proxy mode, watches for
|
||||
// upstreams in the local DC are handled by the
|
||||
// IntentionUpstreams watch!
|
||||
db,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + googleUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: googleChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + noEndpointsUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: noEndpointsChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:google.default.default.dc1:" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Address: "8.8.8.8",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "google",
|
||||
Address: "9.9.9.9",
|
||||
Port: 9090,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "10.0.0.1"},
|
||||
structs.TaggedAddressVirtualIP: {Address: "240.0.0.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:google-v2.default.default.dc1:" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// Other targets of the discovery chain should be ignored.
|
||||
// We only match on the upstream's virtual IP, not the IPs of other targets.
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Address: "7.7.7.7",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "google-v2",
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "10.10.10.10"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + noEndpointsChain.ID() + ":" + noEndpointsUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// DiscoveryChains without endpoints do not get a
|
||||
// filter chain because there are no addresses to
|
||||
// match on.
|
||||
Nodes: []structs.CheckServiceNode{},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTransparentProxyHTTPUpstream(t testing.T) *ConfigSnapshot {
|
||||
// DiscoveryChain without an UpstreamConfig should yield a
|
||||
// filter chain when in transparent proxy mode
|
||||
var (
|
||||
google = structs.NewServiceName("google", nil)
|
||||
googleUID = NewUpstreamIDFromServiceName(google)
|
||||
googleChain = discoverychain.TestCompileConfigEntries(t, "google", "default", "default", "dc1", connect.TestClusterID+".consul", nil,
|
||||
// Set default service protocol to HTTP
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
noEndpoints = structs.NewServiceName("no-endpoints", nil)
|
||||
noEndpointsUID = NewUpstreamIDFromServiceName(noEndpoints)
|
||||
noEndpointsChain = discoverychain.TestCompileConfigEntries(t, "no-endpoints", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
db = structs.NewServiceName("db", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Mode = structs.ProxyModeTransparent
|
||||
}, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionUpstreamsID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: structs.ServiceList{
|
||||
google,
|
||||
noEndpoints,
|
||||
// In transparent proxy mode, watches for
|
||||
// upstreams in the local DC are handled by the
|
||||
// IntentionUpstreams watch!
|
||||
db,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + googleUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: googleChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + noEndpointsUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: noEndpointsChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:google.default.default.dc1:" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Address: "8.8.8.8",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "google",
|
||||
Address: "9.9.9.9",
|
||||
Port: 9090,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "10.0.0.1"},
|
||||
structs.TaggedAddressVirtualIP: {Address: "240.0.0.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:google-v2.default.default.dc1:" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// Other targets of the discovery chain should be ignored.
|
||||
// We only match on the upstream's virtual IP, not the IPs of other targets.
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Address: "7.7.7.7",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "google-v2",
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "10.10.10.10"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + noEndpointsChain.ID() + ":" + noEndpointsUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// DiscoveryChains without endpoints do not get a
|
||||
// filter chain because there are no addresses to
|
||||
// match on.
|
||||
Nodes: []structs.CheckServiceNode{},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTransparentProxyCatalogDestinationsOnly(t testing.T) *ConfigSnapshot {
|
||||
// DiscoveryChain without an UpstreamConfig should yield a
|
||||
// filter chain when in transparent proxy mode
|
||||
var (
|
||||
google = structs.NewServiceName("google", nil)
|
||||
googleUID = NewUpstreamIDFromServiceName(google)
|
||||
googleChain = discoverychain.TestCompileConfigEntries(t, "google", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
noEndpoints = structs.NewServiceName("no-endpoints", nil)
|
||||
noEndpointsUID = NewUpstreamIDFromServiceName(noEndpoints)
|
||||
noEndpointsChain = discoverychain.TestCompileConfigEntries(t, "no-endpoints", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
db = structs.NewServiceName("db", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Mode = structs.ProxyModeTransparent
|
||||
}, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: &structs.MeshConfigEntry{
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{
|
||||
MeshDestinationsOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionUpstreamsID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: structs.ServiceList{
|
||||
google,
|
||||
noEndpoints,
|
||||
// In transparent proxy mode, watches for
|
||||
// upstreams in the local DC are handled by the
|
||||
// IntentionUpstreams watch!
|
||||
db,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + googleUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: googleChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + noEndpointsUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: noEndpointsChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + googleChain.ID() + ":" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Address: "8.8.8.8",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "google",
|
||||
Address: "9.9.9.9",
|
||||
Port: 9090,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + noEndpointsChain.ID() + ":" + noEndpointsUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// DiscoveryChains without endpoints do not get a
|
||||
// filter chain because there are no addresses to
|
||||
// match on.
|
||||
Nodes: []structs.CheckServiceNode{},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTransparentProxyDialDirectly(t testing.T) *ConfigSnapshot {
|
||||
// DiscoveryChain without an UpstreamConfig should yield a
|
||||
// filter chain when in transparent proxy mode
|
||||
var (
|
||||
kafka = structs.NewServiceName("kafka", nil)
|
||||
kafkaUID = NewUpstreamIDFromServiceName(kafka)
|
||||
kafkaChain = discoverychain.TestCompileConfigEntries(t, "kafka", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
mongo = structs.NewServiceName("mongo", nil)
|
||||
mongoUID = NewUpstreamIDFromServiceName(mongo)
|
||||
mongoChain = discoverychain.TestCompileConfigEntries(t, "mongo", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
db = structs.NewServiceName("db", nil)
|
||||
)
|
||||
|
||||
return TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Mode = structs.ProxyModeTransparent
|
||||
}, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionUpstreamsID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: structs.ServiceList{
|
||||
kafka,
|
||||
mongo,
|
||||
// In transparent proxy mode, watches for
|
||||
// upstreams in the local DC are handled by the
|
||||
// IntentionUpstreams watch!
|
||||
db,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + kafkaUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: kafkaChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + mongoUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: mongoChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + mongoChain.ID() + ":" + mongoUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
// There should still be a filter chain for mongo's virtual address
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "mongo",
|
||||
Address: "10.10.10.10",
|
||||
Port: 27017,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "6.6.6.6"},
|
||||
},
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
TransparentProxy: structs.TransparentProxyConfig{
|
||||
DialedDirectly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "mongo",
|
||||
Address: "10.10.10.12",
|
||||
Port: 27017,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
"virtual": {Address: "6.6.6.6"},
|
||||
},
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
TransparentProxy: structs.TransparentProxyConfig{
|
||||
DialedDirectly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + kafkaChain.ID() + ":" + kafkaUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{
|
||||
{
|
||||
Node: &structs.Node{
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "kafka",
|
||||
Address: "9.9.9.9",
|
||||
Port: 9092,
|
||||
Proxy: structs.ConnectProxyConfig{
|
||||
TransparentProxy: structs.TransparentProxyConfig{
|
||||
DialedDirectly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly(t testing.T) *ConfigSnapshot {
|
||||
// DiscoveryChain without an UpstreamConfig should yield a
|
||||
// filter chain when in transparent proxy mode
|
||||
var (
|
||||
google = structs.NewServiceName("google", nil)
|
||||
googleUID = NewUpstreamIDFromServiceName(google)
|
||||
googleChain = discoverychain.TestCompileConfigEntries(t, "google", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
kafka = structs.NewServiceName("kafka", nil)
|
||||
kafkaUID = NewUpstreamIDFromServiceName(kafka)
|
||||
kafkaChain = discoverychain.TestCompileConfigEntries(t, "kafka", "default", "default", "dc1", connect.TestClusterID+".consul", nil)
|
||||
|
||||
db = structs.NewServiceName("db", nil)
|
||||
)
|
||||
|
||||
// DiscoveryChain without an UpstreamConfig should yield a filter chain when in transparent proxy mode
|
||||
|
||||
tgate := structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
Address: "8.8.8.8",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: &structs.NodeService{
|
||||
Service: "tgate1",
|
||||
Kind: structs.ServiceKind(structs.TerminatingGateway),
|
||||
Address: "9.9.9.9",
|
||||
Port: 9090,
|
||||
TaggedAddresses: map[string]structs.ServiceAddress{
|
||||
structs.ServiceGatewayVirtualIPTag(google): {Address: "10.0.0.1"},
|
||||
structs.ServiceGatewayVirtualIPTag(kafka): {Address: "10.0.0.2"},
|
||||
"virtual": {Address: "6.6.6.6"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return TestConfigSnapshot(t, func(ns *structs.NodeService) {
|
||||
ns.Proxy.Mode = structs.ProxyModeTransparent
|
||||
}, []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: &structs.MeshConfigEntry{
|
||||
TransparentProxy: structs.TransparentProxyMeshConfig{
|
||||
MeshDestinationsOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: intentionUpstreamsID,
|
||||
Result: &structs.IndexedServiceList{
|
||||
Services: structs.ServiceList{
|
||||
google,
|
||||
kafka,
|
||||
// In transparent proxy mode, watches for
|
||||
// upstreams in the local DC are handled by the
|
||||
// IntentionUpstreams watch!
|
||||
db,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + googleUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: googleChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + kafkaUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: kafkaChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + googleChain.ID() + ":" + googleUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{tgate},
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + kafkaChain.ID() + ":" + kafkaUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: []structs.CheckServiceNode{tgate},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,764 @@
|
|||
package proxycfg
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/go-testing-interface"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func setupTestVariationConfigEntriesAndSnapshot(
|
||||
t testing.T,
|
||||
variation string,
|
||||
upstreams structs.Upstreams,
|
||||
additionalEntries ...structs.ConfigEntry,
|
||||
) []cache.UpdateEvent {
|
||||
var (
|
||||
dbUpstream = upstreams[0]
|
||||
|
||||
dbUID = NewUpstreamID(&dbUpstream)
|
||||
)
|
||||
|
||||
dbChain := setupTestVariationDiscoveryChain(t, variation, additionalEntries...)
|
||||
|
||||
events := []cache.UpdateEvent{
|
||||
{
|
||||
CorrelationID: "discovery-chain:" + dbUID.String(),
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: dbChain,
|
||||
},
|
||||
},
|
||||
{
|
||||
CorrelationID: "upstream-target:" + dbChain.ID() + ":" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodes(t, "db"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
switch variation {
|
||||
case "default":
|
||||
case "simple-with-overrides":
|
||||
case "simple":
|
||||
case "external-sni":
|
||||
case "failover":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:fail.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesAlternate(t),
|
||||
},
|
||||
})
|
||||
case "failover-through-remote-gateway-triggered":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatus(t, "critical"),
|
||||
},
|
||||
})
|
||||
fallthrough
|
||||
case "failover-through-remote-gateway":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesDC2(t),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "mesh-gateway:dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC2(t),
|
||||
},
|
||||
})
|
||||
case "failover-through-double-remote-gateway-triggered":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatus(t, "critical"),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatusDC2(t, "critical"),
|
||||
},
|
||||
})
|
||||
fallthrough
|
||||
case "failover-through-double-remote-gateway":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc3:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesDC2(t),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "mesh-gateway:dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC2(t),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "mesh-gateway:dc3:" + dbUID.String(),
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC3(t),
|
||||
},
|
||||
})
|
||||
case "failover-through-local-gateway-triggered":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatus(t, "critical"),
|
||||
},
|
||||
})
|
||||
fallthrough
|
||||
case "failover-through-local-gateway":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesDC2(t),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "mesh-gateway:dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC1(t),
|
||||
},
|
||||
})
|
||||
case "failover-through-double-local-gateway-triggered":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatus(t, "critical"),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesInStatusDC2(t, "critical"),
|
||||
},
|
||||
})
|
||||
fallthrough
|
||||
case "failover-through-double-local-gateway":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:db.default.default.dc3:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesDC2(t),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "mesh-gateway:dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedNodesWithGateways{
|
||||
Nodes: TestGatewayNodesDC1(t),
|
||||
},
|
||||
})
|
||||
case "splitter-with-resolver-redirect-multidc":
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:v1.db.default.default.dc1:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodes(t, "db"),
|
||||
},
|
||||
})
|
||||
events = append(events, cache.UpdateEvent{
|
||||
CorrelationID: "upstream-target:v2.db.default.default.dc2:" + dbUID.String(),
|
||||
Result: &structs.IndexedCheckServiceNodes{
|
||||
Nodes: TestUpstreamNodesDC2(t),
|
||||
},
|
||||
})
|
||||
case "chain-and-splitter":
|
||||
case "grpc-router":
|
||||
case "chain-and-router":
|
||||
case "lb-resolver":
|
||||
default:
|
||||
t.Fatalf("unexpected variation: %q", variation)
|
||||
return nil
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
func setupTestVariationDiscoveryChain(
|
||||
t testing.T,
|
||||
variation string,
|
||||
additionalEntries ...structs.ConfigEntry,
|
||||
) *structs.CompiledDiscoveryChain {
|
||||
// Compile a chain.
|
||||
var (
|
||||
entries []structs.ConfigEntry
|
||||
compileSetup func(req *discoverychain.CompileRequest)
|
||||
)
|
||||
|
||||
switch variation {
|
||||
case "default":
|
||||
// no config entries
|
||||
case "simple-with-overrides":
|
||||
compileSetup = func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = structs.MeshGatewayModeLocal
|
||||
req.OverrideProtocol = "grpc"
|
||||
req.OverrideConnectTimeout = 66 * time.Second
|
||||
}
|
||||
fallthrough
|
||||
case "simple":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
)
|
||||
case "external-sni":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
ExternalSNI: "db.some.other.service.mesh",
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
)
|
||||
case "failover":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Service: "fail",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "failover-through-remote-gateway-triggered":
|
||||
fallthrough
|
||||
case "failover-through-remote-gateway":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Datacenters: []string{"dc2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "failover-through-double-remote-gateway-triggered":
|
||||
fallthrough
|
||||
case "failover-through-double-remote-gateway":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Datacenters: []string{"dc2", "dc3"},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "failover-through-local-gateway-triggered":
|
||||
fallthrough
|
||||
case "failover-through-local-gateway":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeLocal,
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Datacenters: []string{"dc2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "failover-through-double-local-gateway-triggered":
|
||||
fallthrough
|
||||
case "failover-through-double-local-gateway":
|
||||
entries = append(entries,
|
||||
&structs.ServiceConfigEntry{
|
||||
Kind: structs.ServiceDefaults,
|
||||
Name: "db",
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeLocal,
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Datacenters: []string{"dc2", "dc3"},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "splitter-with-resolver-redirect-multidc":
|
||||
entries = append(entries,
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceSplitterConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
Splits: []structs.ServiceSplit{
|
||||
{Weight: 50, Service: "db-dc1"},
|
||||
{Weight: 50, Service: "db-dc2"},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db-dc1",
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Service: "db",
|
||||
ServiceSubset: "v1",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db-dc2",
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Service: "db",
|
||||
ServiceSubset: "v2",
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == v1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == v2",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "chain-and-splitter":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceSplitterConfigEntry{
|
||||
Kind: structs.ServiceSplitter,
|
||||
Name: "db",
|
||||
Splits: []structs.ServiceSplit{
|
||||
{
|
||||
Weight: 95.5,
|
||||
Service: "big-side",
|
||||
RequestHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "big"},
|
||||
},
|
||||
ResponseHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "big"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Weight: 4,
|
||||
Service: "goldilocks-side",
|
||||
RequestHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "goldilocks"},
|
||||
},
|
||||
ResponseHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "goldilocks"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Weight: 0.5,
|
||||
Service: "lil-bit-side",
|
||||
RequestHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "small"},
|
||||
},
|
||||
ResponseHeaders: &structs.HTTPHeaderModifiers{
|
||||
Set: map[string]string{"x-split-leg": "small"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "grpc-router":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "grpc",
|
||||
},
|
||||
},
|
||||
&structs.ServiceRouterConfigEntry{
|
||||
Kind: structs.ServiceRouter,
|
||||
Name: "db",
|
||||
Routes: []structs.ServiceRoute{
|
||||
{
|
||||
Match: &structs.ServiceRouteMatch{
|
||||
HTTP: &structs.ServiceRouteHTTPMatch{
|
||||
PathExact: "/fgrpc.PingServer/Ping",
|
||||
},
|
||||
},
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "prefix",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "chain-and-router":
|
||||
entries = append(entries,
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
},
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceSplitterConfigEntry{
|
||||
Kind: structs.ServiceSplitter,
|
||||
Name: "split-3-ways",
|
||||
Splits: []structs.ServiceSplit{
|
||||
{Weight: 95.5, Service: "big-side"},
|
||||
{Weight: 4, Service: "goldilocks-side"},
|
||||
{Weight: 0.5, Service: "lil-bit-side"},
|
||||
},
|
||||
},
|
||||
&structs.ServiceRouterConfigEntry{
|
||||
Kind: structs.ServiceRouter,
|
||||
Name: "db",
|
||||
Routes: []structs.ServiceRoute{
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/prefix",
|
||||
}),
|
||||
Destination: toService("prefix"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathExact: "/exact",
|
||||
}),
|
||||
Destination: toService("exact"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathRegex: "/regex",
|
||||
}),
|
||||
Destination: toService("regex"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Present: true,
|
||||
}),
|
||||
Destination: toService("hdr-present"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Present: true,
|
||||
Invert: true,
|
||||
}),
|
||||
Destination: toService("hdr-not-present"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Exact: "exact",
|
||||
}),
|
||||
Destination: toService("hdr-exact"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Prefix: "prefix",
|
||||
}),
|
||||
Destination: toService("hdr-prefix"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Suffix: "suffix",
|
||||
}),
|
||||
Destination: toService("hdr-suffix"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchHeader(structs.ServiceRouteHTTPMatchHeader{
|
||||
Name: "x-debug",
|
||||
Regex: "regex",
|
||||
}),
|
||||
Destination: toService("hdr-regex"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
Methods: []string{"GET", "PUT"},
|
||||
}),
|
||||
Destination: toService("just-methods"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
Header: []structs.ServiceRouteHTTPMatchHeader{
|
||||
{
|
||||
Name: "x-debug",
|
||||
Exact: "exact",
|
||||
},
|
||||
},
|
||||
Methods: []string{"GET", "PUT"},
|
||||
}),
|
||||
Destination: toService("hdr-exact-with-method"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchParam(structs.ServiceRouteHTTPMatchQueryParam{
|
||||
Name: "secretparam1",
|
||||
Exact: "exact",
|
||||
}),
|
||||
Destination: toService("prm-exact"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchParam(structs.ServiceRouteHTTPMatchQueryParam{
|
||||
Name: "secretparam2",
|
||||
Regex: "regex",
|
||||
}),
|
||||
Destination: toService("prm-regex"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchParam(structs.ServiceRouteHTTPMatchQueryParam{
|
||||
Name: "secretparam3",
|
||||
Present: true,
|
||||
}),
|
||||
Destination: toService("prm-present"),
|
||||
},
|
||||
{
|
||||
Match: nil,
|
||||
Destination: toService("nil-match"),
|
||||
},
|
||||
{
|
||||
Match: &structs.ServiceRouteMatch{},
|
||||
Destination: toService("empty-match-1"),
|
||||
},
|
||||
{
|
||||
Match: &structs.ServiceRouteMatch{
|
||||
HTTP: &structs.ServiceRouteHTTPMatch{},
|
||||
},
|
||||
Destination: toService("empty-match-2"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/prefix",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "prefix-rewrite-1",
|
||||
PrefixRewrite: "/",
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/prefix",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "prefix-rewrite-2",
|
||||
PrefixRewrite: "/nested/newlocation",
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/timeout",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "req-timeout",
|
||||
RequestTimeout: 33 * time.Second,
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/retry-connect",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "retry-connect",
|
||||
NumRetries: 15,
|
||||
RetryOnConnectFailure: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/retry-codes",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "retry-codes",
|
||||
NumRetries: 15,
|
||||
RetryOnStatusCodes: []uint32{401, 409, 451},
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/retry-both",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "retry-both",
|
||||
RetryOnConnectFailure: true,
|
||||
RetryOnStatusCodes: []uint32{401, 409, 451},
|
||||
},
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/split-3-ways",
|
||||
}),
|
||||
Destination: toService("split-3-ways"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
PathExact: "/header-manip",
|
||||
}),
|
||||
Destination: &structs.ServiceRouteDestination{
|
||||
Service: "header-manip",
|
||||
RequestHeaders: &structs.HTTPHeaderModifiers{
|
||||
Add: map[string]string{
|
||||
"request": "bar",
|
||||
},
|
||||
Set: map[string]string{
|
||||
"bar": "baz",
|
||||
},
|
||||
Remove: []string{"qux"},
|
||||
},
|
||||
ResponseHeaders: &structs.HTTPHeaderModifiers{
|
||||
Add: map[string]string{
|
||||
"response": "bar",
|
||||
},
|
||||
Set: map[string]string{
|
||||
"bar": "baz",
|
||||
},
|
||||
Remove: []string{"qux"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
case "lb-resolver":
|
||||
entries = append(entries,
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceSplitterConfigEntry{
|
||||
Kind: structs.ServiceSplitter,
|
||||
Name: "db",
|
||||
Splits: []structs.ServiceSplit{
|
||||
{Weight: 95.5, Service: "something-else"},
|
||||
{Weight: 4.5, Service: "db"},
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "db",
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 30,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: "cookie",
|
||||
FieldValue: "chocolate-chip",
|
||||
CookieConfig: &structs.CookieConfig{Session: true},
|
||||
},
|
||||
{
|
||||
Field: "header",
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
default:
|
||||
t.Fatalf("unexpected variation: %q", variation)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(additionalEntries) > 0 {
|
||||
entries = append(entries, additionalEntries...)
|
||||
}
|
||||
|
||||
return discoverychain.TestCompileConfigEntries(t, "db", "default", "default", "dc1", connect.TestClusterID+".consul", compileSetup, entries...)
|
||||
}
|
||||
|
||||
func httpMatch(http *structs.ServiceRouteHTTPMatch) *structs.ServiceRouteMatch {
|
||||
return &structs.ServiceRouteMatch{HTTP: http}
|
||||
}
|
||||
func httpMatchHeader(headers ...structs.ServiceRouteHTTPMatchHeader) *structs.ServiceRouteMatch {
|
||||
return httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
Header: headers,
|
||||
})
|
||||
}
|
||||
func httpMatchParam(params ...structs.ServiceRouteHTTPMatchQueryParam) *structs.ServiceRouteMatch {
|
||||
return httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
QueryParam: params,
|
||||
})
|
||||
}
|
||||
func toService(svc string) *structs.ServiceRouteDestination {
|
||||
return &structs.ServiceRouteDestination{Service: svc}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1094,7 +1094,7 @@ func TestServer_DeltaAggregatedResources_v3_ACLEnforcement(t *testing.T) {
|
|||
acl: `service "not-ingress" { policy = "write" }`,
|
||||
token: "service-write-on-not-ingress",
|
||||
wantDenied: true,
|
||||
cfgSnap: proxycfg.TestConfigSnapshotIngressGateway(t),
|
||||
cfgSnap: proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp", "default", nil, nil, nil),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1384,7 +1384,7 @@ func TestServer_DeltaAggregatedResources_v3_IngressEmptyResponse(t *testing.T) {
|
|||
assertDeltaChanBlocked(t, envoy.deltaStream.sendCh)
|
||||
|
||||
// Deliver a new snapshot with no services
|
||||
snap := proxycfg.TestConfigSnapshotIngressGatewayNoServices(t)
|
||||
snap := proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp", "default", nil, nil, nil)
|
||||
mgr.DeliverConfig(t, sid, snap)
|
||||
|
||||
// REQ: clusters
|
||||
|
|
|
@ -222,356 +222,268 @@ func TestEndpointsFromSnapshot(t *testing.T) {
|
|||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
create func(t testinf.T) *proxycfg.ConfigSnapshot
|
||||
// Setup is called before the test starts. It is passed the snapshot from
|
||||
// create func and is allowed to modify it in any way to setup the
|
||||
// test input.
|
||||
setup func(snap *proxycfg.ConfigSnapshot)
|
||||
name string
|
||||
create func(t testinf.T) *proxycfg.ConfigSnapshot
|
||||
overrideGoldenName string
|
||||
}{
|
||||
{
|
||||
name: "defaults",
|
||||
create: proxycfg.TestConfigSnapshot,
|
||||
setup: nil, // Default snapshot
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway",
|
||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-using-federation-states",
|
||||
create: proxycfg.TestConfigSnapshotMeshGatewayUsingFederationStates,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-newer-information-in-federation-states",
|
||||
create: proxycfg.TestConfigSnapshotMeshGatewayNewerInformationInFederationStates,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-older-information-in-federation-states",
|
||||
create: proxycfg.TestConfigSnapshotMeshGatewayOlderInformationInFederationStates,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-no-services",
|
||||
create: proxycfg.TestConfigSnapshotMeshGatewayNoServices,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-failover",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailover,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailoverThroughRemoteGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailoverThroughRemoteGatewayTriggered,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughRemoteGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughRemoteGatewayTriggered,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-local-gateway",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailoverThroughLocalGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailoverThroughLocalGatewayTriggered,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughLocalGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughLocalGatewayTriggered,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-default-chain-and-custom-cluster",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainDefault,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.Proxy.Upstreams[0].Config["envoy_cluster_json"] =
|
||||
customAppClusterJSON(t, customClusterJSONOptions{
|
||||
Name: "myservice",
|
||||
})
|
||||
snap.ConnectProxy.UpstreamConfig = map[proxycfg.UpstreamID]*structs.Upstream{
|
||||
UID("db"): {
|
||||
// The local bind port is overridden by the escape hatch, but is required for explicit upstreams.
|
||||
LocalBindPort: 9191,
|
||||
Config: map[string]interface{}{
|
||||
"envoy_cluster_json": customAppClusterJSON(t, customClusterJSONOptions{
|
||||
Name: "myservice",
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
name: "defaults",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshot(t, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain_SplitterWithResolverRedirectMultiDC,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-service-subsets",
|
||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.MeshGateway.ServiceResolvers = map[structs.ServiceName]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceName("bar", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceName("foo", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
name: "mesh-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "default", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-default-service-subset",
|
||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.MeshGateway.ServiceResolvers = map[structs.ServiceName]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceName("bar", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceName("foo", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
name: "mesh-gateway-using-federation-states",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "federation-states", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-gateway",
|
||||
create: proxycfg.TestConfigSnapshotIngressGateway,
|
||||
setup: nil,
|
||||
name: "mesh-gateway-newer-information-in-federation-states",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "newer-info-in-federation-states", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-gateway-no-services",
|
||||
create: proxycfg.TestConfigSnapshotIngressGatewayNoServices,
|
||||
setup: nil,
|
||||
name: "mesh-gateway-older-information-in-federation-states",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "older-info-in-federation-states", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain",
|
||||
create: proxycfg.TestConfigSnapshotIngress,
|
||||
setup: nil,
|
||||
name: "mesh-gateway-no-services",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "no-services", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotIngressExternalSNI,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithOverrides,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-failover",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithFailover,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-remote-gateway",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithFailoverThroughRemoteGateway,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-and-failover",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithFailoverThroughRemoteGatewayTriggered,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-remote-gateway",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithDoubleFailoverThroughRemoteGateway,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-remote-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithDoubleFailoverThroughRemoteGatewayTriggered,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-local-gateway",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithFailoverThroughLocalGateway,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-remote-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithFailoverThroughLocalGatewayTriggered,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-local-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-local-gateway",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithDoubleFailoverThroughLocalGateway,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-failover-through-local-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithDoubleFailoverThroughLocalGatewayTriggered,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotIngress_SplitterWithResolverRedirectMultiDC,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-tcp-chain-double-failover-through-local-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-default-chain-and-custom-cluster",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", func(ns *structs.NodeService) {
|
||||
ns.Proxy.Upstreams[0].Config["envoy_cluster_json"] =
|
||||
customAppClusterJSON(t, customClusterJSONOptions{
|
||||
Name: "myservice",
|
||||
})
|
||||
}, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-no-services",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGatewayNoServices,
|
||||
setup: nil,
|
||||
name: "splitter-with-resolver-redirect",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-service-subsets",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "service-subsets2", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-default-service-subset",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotMeshGateway(t, "default-service-subsets2", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"default", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-gateway-no-services",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp",
|
||||
"default", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"simple", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-external-sni",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"external-sni", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-failover",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-remote-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-remote-gateway", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-remote-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-remote-gateway-triggered", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-remote-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-double-remote-gateway", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-remote-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-double-remote-gateway-triggered", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-local-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-local-gateway", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-failover-through-local-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-local-gateway-triggered", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-local-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-double-local-gateway", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-tcp-chain-double-failover-through-local-gateway-triggered",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"failover-through-double-local-gateway-triggered", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-splitter-with-resolver-redirect",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"splitter-with-resolver-redirect-multidc", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotTerminatingGateway(t, true, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-no-services",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotTerminatingGateway(t, false, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-service-subsets",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceName]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceName("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceName("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGatewayServiceSubsets,
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-default-service-subset",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceName]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceName("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.NewServiceName("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGatewayDefaultServiceSubset,
|
||||
},
|
||||
{
|
||||
name: "ingress-multiple-listeners-duplicate-service",
|
||||
create: proxycfg.TestConfigSnapshotIngress_MultipleListenersDuplicateService,
|
||||
setup: nil,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -590,10 +502,6 @@ func TestEndpointsFromSnapshot(t *testing.T) {
|
|||
// golden files for every test case and so not be any use!
|
||||
setupTLSRootsAndLeaf(t, snap)
|
||||
|
||||
if tt.setup != nil {
|
||||
tt.setup(snap)
|
||||
}
|
||||
|
||||
// Need server just for logger dependency
|
||||
g := newResourceGenerator(testutil.Logger(t), nil, nil, false)
|
||||
g.ProxyFeatures = sf
|
||||
|
|
|
@ -22,7 +22,7 @@ func (s *ResourceGenerator) makeIngressGatewayListeners(address string, cfgSnap
|
|||
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
||||
listenerCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no listener config found for listener on port %d", listenerKey.Port)
|
||||
return nil, fmt.Errorf("no listener config found for listener on proto/port %s/%d", listenerKey.Protocol, listenerKey.Port)
|
||||
}
|
||||
|
||||
tlsContext, err := makeDownstreamTLSContextFromSnapshotListenerConfig(cfgSnap, listenerCfg)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,11 +30,7 @@ func (s *ResourceGenerator) routesFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot)
|
|||
case structs.ServiceKindConnectProxy:
|
||||
return s.routesForConnectProxy(cfgSnap)
|
||||
case structs.ServiceKindIngressGateway:
|
||||
return s.routesForIngressGateway(
|
||||
cfgSnap.IngressGateway.Listeners,
|
||||
cfgSnap.IngressGateway.Upstreams,
|
||||
cfgSnap.IngressGateway.DiscoveryChain,
|
||||
)
|
||||
return s.routesForIngressGateway(cfgSnap)
|
||||
case structs.ServiceKindTerminatingGateway:
|
||||
return s.routesFromSnapshotTerminatingGateway(cfgSnap)
|
||||
case structs.ServiceKindMeshGateway:
|
||||
|
@ -170,14 +166,9 @@ func makeNamedDefaultRouteWithLB(clusterName string, lb *structs.LoadBalancer, a
|
|||
|
||||
// routesForIngressGateway returns the xDS API representation of the
|
||||
// "routes" in the snapshot.
|
||||
func (s *ResourceGenerator) routesForIngressGateway(
|
||||
listeners map[proxycfg.IngressListenerKey]structs.IngressListener,
|
||||
upstreams map[proxycfg.IngressListenerKey]structs.Upstreams,
|
||||
chains map[proxycfg.UpstreamID]*structs.CompiledDiscoveryChain,
|
||||
) ([]proto.Message, error) {
|
||||
|
||||
func (s *ResourceGenerator) routesForIngressGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
var result []proto.Message
|
||||
for listenerKey, upstreams := range upstreams {
|
||||
for listenerKey, upstreams := range cfgSnap.IngressGateway.Upstreams {
|
||||
// Do not create any route configuration for TCP listeners
|
||||
if listenerKey.Protocol == "tcp" {
|
||||
continue
|
||||
|
@ -196,7 +187,7 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
|||
|
||||
for _, u := range upstreams {
|
||||
uid := proxycfg.NewUpstreamID(&u)
|
||||
chain := chains[uid]
|
||||
chain := cfgSnap.IngressGateway.DiscoveryChain[uid]
|
||||
if chain == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -209,14 +200,15 @@ func (s *ResourceGenerator) routesForIngressGateway(
|
|||
|
||||
// Lookup listener and service config details from ingress gateway
|
||||
// definition.
|
||||
lCfg, ok := listeners[listenerKey]
|
||||
lCfg, ok := cfgSnap.IngressGateway.Listeners[listenerKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing ingress listener config (listener on port %d)", listenerKey.Port)
|
||||
return nil, fmt.Errorf("missing ingress listener config (service %q listener on proto/port %s/%d)",
|
||||
u.DestinationID(), listenerKey.Protocol, listenerKey.Port)
|
||||
}
|
||||
svc := findIngressServiceMatchingUpstream(lCfg, u)
|
||||
if svc == nil {
|
||||
return nil, fmt.Errorf("missing service in listener config (service %q listener on port %d)",
|
||||
u.DestinationID(), listenerKey.Port)
|
||||
return nil, fmt.Errorf("missing service in listener config (service %q listener on proto/port %s/%d)",
|
||||
u.DestinationID(), listenerKey.Protocol, listenerKey.Port)
|
||||
}
|
||||
|
||||
if err := injectHeaderManipToVirtualHost(svc, virtualHost); err != nil {
|
||||
|
|
|
@ -12,8 +12,6 @@ import (
|
|||
testinf "github.com/mitchellh/go-testing-interface"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/discoverychain"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/agent/xds/proxysupport"
|
||||
|
@ -23,307 +21,159 @@ import (
|
|||
func TestRoutesFromSnapshot(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
create func(t testinf.T) *proxycfg.ConfigSnapshot
|
||||
// Setup is called before the test starts. It is passed the snapshot from
|
||||
// create func and is allowed to modify it in any way to setup the
|
||||
// test input.
|
||||
setup func(snap *proxycfg.ConfigSnapshot)
|
||||
name string
|
||||
create func(t testinf.T) *proxycfg.ConfigSnapshot
|
||||
overrideGoldenName string
|
||||
}{
|
||||
{
|
||||
name: "defaults-no-chain",
|
||||
create: proxycfg.TestConfigSnapshot,
|
||||
setup: nil, // Default snapshot
|
||||
name: "defaults",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshot(t, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainExternalSNI,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-external-sni",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "external-sni", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-and-overrides",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "simple-with-overrides", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain_SplitterWithResolverRedirectMultiDC,
|
||||
setup: nil,
|
||||
name: "splitter-with-resolver-redirect",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-splitter",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithSplitter,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-and-splitter",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-splitter", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-grpc-router",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithGRPCRouter,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-grpc-router",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "grpc-router", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-with-chain-and-router",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithRouter,
|
||||
setup: nil,
|
||||
name: "connect-proxy-with-chain-and-router",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "chain-and-router", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "connect-proxy-lb-in-resolver",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithLB,
|
||||
setup: nil,
|
||||
name: "connect-proxy-lb-in-resolver",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotDiscoveryChain(t, "lb-resolver", nil, nil)
|
||||
},
|
||||
},
|
||||
// TODO(rb): test match stanza skipped for grpc
|
||||
// Start ingress gateway test cases
|
||||
{
|
||||
name: "ingress-defaults-no-chain",
|
||||
create: proxycfg.TestConfigSnapshotIngressGateway,
|
||||
setup: nil, // Default snapshot
|
||||
name: "ingress-defaults-no-chain",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, false, "tcp",
|
||||
"default", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain",
|
||||
create: proxycfg.TestConfigSnapshotIngress,
|
||||
setup: nil,
|
||||
name: "ingress-with-chain",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"simple", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-external-sni",
|
||||
create: proxycfg.TestConfigSnapshotIngressExternalSNI,
|
||||
setup: nil,
|
||||
name: "ingress-with-chain-external-sni",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "tcp",
|
||||
"external-sni", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-overrides",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithOverrides,
|
||||
setup: nil,
|
||||
name: "ingress-splitter-with-resolver-redirect",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"splitter-with-resolver-redirect-multidc", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotIngress_SplitterWithResolverRedirectMultiDC,
|
||||
setup: nil,
|
||||
name: "ingress-with-chain-and-splitter",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"chain-and-splitter", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-splitter",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithSplitter,
|
||||
setup: nil,
|
||||
name: "ingress-with-grpc-router",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"grpc-router", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-grpc-router",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithGRPCRouter,
|
||||
setup: nil,
|
||||
name: "ingress-with-chain-and-router",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"chain-and-router", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-router",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "ingress-lb-in-resolver",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithLB,
|
||||
setup: nil,
|
||||
name: "ingress-lb-in-resolver",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGateway(t, true, "http",
|
||||
"lb-resolver", nil, nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-http-multiple-services",
|
||||
create: proxycfg.TestConfigSnapshotIngress_HTTPMultipleServices,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
{
|
||||
DestinationName: "foo",
|
||||
LocalBindPort: 8080,
|
||||
IngressHosts: []string{
|
||||
"test1.example.com",
|
||||
"test2.example.com",
|
||||
"test2.example.com:8080",
|
||||
},
|
||||
},
|
||||
{
|
||||
DestinationName: "bar",
|
||||
LocalBindPort: 8080,
|
||||
},
|
||||
},
|
||||
{Protocol: "http", Port: 443}: {
|
||||
{
|
||||
DestinationName: "baz",
|
||||
LocalBindPort: 443,
|
||||
},
|
||||
{
|
||||
DestinationName: "qux",
|
||||
LocalBindPort: 443,
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.IngressGateway.Listeners = map[proxycfg.IngressListenerKey]structs.IngressListener{
|
||||
{Protocol: "http", Port: 8080}: {
|
||||
Port: 8080,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "foo",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{Protocol: "http", Port: 443}: {
|
||||
Port: 443,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "baz",
|
||||
},
|
||||
{
|
||||
Name: "qux",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// We do not add baz/qux here so that we test the chain.IsDefault() case
|
||||
entries := []structs.ConfigEntry{
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "bar",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
}
|
||||
fooChain := discoverychain.TestCompileConfigEntries(t, "foo", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
||||
barChain := discoverychain.TestCompileConfigEntries(t, "bar", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
||||
bazChain := discoverychain.TestCompileConfigEntries(t, "baz", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
||||
quxChain := discoverychain.TestCompileConfigEntries(t, "qux", "default", "default", "dc1", connect.TestClusterID+".consul", nil, entries...)
|
||||
|
||||
snap.IngressGateway.DiscoveryChain = map[proxycfg.UpstreamID]*structs.CompiledDiscoveryChain{
|
||||
UID("foo"): fooChain,
|
||||
UID("bar"): barChain,
|
||||
UID("baz"): bazChain,
|
||||
UID("qux"): quxChain,
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "ingress-with-chain-and-router-header-manip",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "router-header-manip", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
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: "ingress-with-sds-listener-level",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
// Listener-level SDS means all services share the default route.
|
||||
listenerSDS: true,
|
||||
}),
|
||||
name: "ingress-with-sds-listener-level-wildcard",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-listener-level-wildcard", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-listener-level-wildcard",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
// Listener-level SDS means all services share the default route.
|
||||
listenerSDS: true,
|
||||
wildcard: true,
|
||||
}),
|
||||
name: "ingress-with-sds-service-level",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
listenerSDS: false,
|
||||
// Services should get separate routes and no default since they all
|
||||
// have custom certs.
|
||||
webSDS: true,
|
||||
fooSDS: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "ingress-with-sds-service-level-mixed-tls",
|
||||
create: proxycfg.TestConfigSnapshotIngressWithRouter,
|
||||
setup: setupIngressWithTwoHTTPServices(t, ingressSDSOpts{
|
||||
listenerSDS: false,
|
||||
// Web needs a separate route as it has custom filter chain but foo
|
||||
// should use default route for listener.
|
||||
webSDS: true,
|
||||
fooSDS: false,
|
||||
}),
|
||||
name: "ingress-with-sds-service-level-mixed-tls",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotIngressGatewayWithChain(t, "sds-service-level-mixed-tls", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating-gateway-lb-config",
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGateway,
|
||||
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||
snap.TerminatingGateway.ServiceResolvers = map[structs.ServiceName]*structs.ServiceResolverConfigEntry{
|
||||
structs.NewServiceName("web", nil): {
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
DefaultSubset: "v2",
|
||||
Subsets: map[string]structs.ServiceResolverSubset{
|
||||
"v1": {
|
||||
Filter: "Service.Meta.Version == 1",
|
||||
},
|
||||
"v2": {
|
||||
Filter: "Service.Meta.Version == 2",
|
||||
OnlyPassing: true,
|
||||
},
|
||||
},
|
||||
LoadBalancer: &structs.LoadBalancer{
|
||||
Policy: "ring_hash",
|
||||
RingHashConfig: &structs.RingHashConfig{
|
||||
MinimumRingSize: 20,
|
||||
MaximumRingSize: 50,
|
||||
},
|
||||
HashPolicies: []structs.HashPolicy{
|
||||
{
|
||||
Field: structs.HashPolicyCookie,
|
||||
FieldValue: "chocolate-chip",
|
||||
Terminal: true,
|
||||
},
|
||||
{
|
||||
Field: structs.HashPolicyHeader,
|
||||
FieldValue: "x-user-id",
|
||||
},
|
||||
{
|
||||
SourceIP: true,
|
||||
Terminal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
snap.TerminatingGateway.ServiceConfigs[structs.NewServiceName("web", nil)] = &structs.ServiceConfigResponse{
|
||||
ProxyConfig: map[string]interface{}{"protocol": "http"},
|
||||
}
|
||||
},
|
||||
create: proxycfg.TestConfigSnapshotTerminatingGatewayLBConfig,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -342,10 +192,6 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
// golden files for every test case and so not be any use!
|
||||
setupTLSRootsAndLeaf(t, snap)
|
||||
|
||||
if tt.setup != nil {
|
||||
tt.setup(snap)
|
||||
}
|
||||
|
||||
g := newResourceGenerator(testutil.Logger(t), nil, nil, false)
|
||||
g.ProxyFeatures = sf
|
||||
|
||||
|
@ -627,158 +473,3 @@ func TestEnvoyLBConfig_InjectToRouteAction(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type ingressSDSOpts struct {
|
||||
listenerSDS, webSDS, fooSDS, wildcard bool
|
||||
entMetas map[string]*structs.EnterpriseMeta
|
||||
}
|
||||
|
||||
// setupIngressWithTwoHTTPServices can be used with
|
||||
// proxycfg.TestConfigSnapshotIngressWithRouter to generate a setup func for an
|
||||
// ingress listener with multiple HTTP services and varying SDS configurations
|
||||
// since those affect how we generate routes.
|
||||
func setupIngressWithTwoHTTPServices(t *testing.T, o ingressSDSOpts) func(snap *proxycfg.ConfigSnapshot) {
|
||||
return func(snap *proxycfg.ConfigSnapshot) {
|
||||
|
||||
snap.IngressGateway.TLSConfig.SDS = nil
|
||||
|
||||
webUpstream := structs.Upstream{
|
||||
DestinationName: "web",
|
||||
// We use empty not default here because of the way upstream identifiers
|
||||
// vary between OSS and Enterprise currently causing test conflicts. In
|
||||
// real life `proxycfg` always sets ingress upstream namespaces to
|
||||
// `NamespaceOrDefault` which shouldn't matter because we should be
|
||||
// consistent within a single binary it's just inconvenient if OSS and
|
||||
// enterprise tests generate different output.
|
||||
DestinationNamespace: o.entMetas["web"].NamespaceOrEmpty(),
|
||||
DestinationPartition: o.entMetas["web"].PartitionOrEmpty(),
|
||||
LocalBindPort: 9191,
|
||||
IngressHosts: []string{
|
||||
"www.example.com",
|
||||
},
|
||||
}
|
||||
fooUpstream := structs.Upstream{
|
||||
DestinationName: "foo",
|
||||
DestinationNamespace: o.entMetas["foo"].NamespaceOrEmpty(),
|
||||
DestinationPartition: o.entMetas["foo"].PartitionOrEmpty(),
|
||||
LocalBindPort: 9191,
|
||||
IngressHosts: []string{
|
||||
"foo.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
webUID := proxycfg.NewUpstreamID(&webUpstream)
|
||||
fooUID := proxycfg.NewUpstreamID(&fooUpstream)
|
||||
|
||||
// Setup additional HTTP service on same listener with default router
|
||||
snap.IngressGateway.Upstreams = map[proxycfg.IngressListenerKey]structs.Upstreams{
|
||||
{Protocol: "http", Port: 9191}: {webUpstream, fooUpstream},
|
||||
}
|
||||
il := structs.IngressListener{
|
||||
Port: 9191,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "web",
|
||||
Hosts: []string{"www.example.com"},
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Hosts: []string{"foo.example.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for i, svc := range il.Services {
|
||||
if em, ok := o.entMetas[svc.Name]; ok && em != nil {
|
||||
il.Services[i].EnterpriseMeta = *em
|
||||
}
|
||||
}
|
||||
|
||||
// Now set the appropriate SDS configs
|
||||
if o.listenerSDS {
|
||||
il.TLS = &structs.GatewayTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "listener-cluster",
|
||||
CertResource: "listener-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
if o.webSDS {
|
||||
il.Services[0].TLS = &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "web-cluster",
|
||||
CertResource: "www-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
if o.fooSDS {
|
||||
il.Services[1].TLS = &structs.GatewayServiceTLSConfig{
|
||||
SDS: &structs.GatewayTLSSDSConfig{
|
||||
ClusterName: "foo-cluster",
|
||||
CertResource: "foo-cert",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if o.wildcard {
|
||||
// undo all that and set just a single wildcard config with no TLS to test
|
||||
// the lookup path where we have to compare an actual resolved upstream to
|
||||
// a wildcard config.
|
||||
il.Services = []structs.IngressService{
|
||||
{
|
||||
Name: "*",
|
||||
},
|
||||
}
|
||||
// We also don't support user-specified hosts with wildcard so remove
|
||||
// those from the upstreams.
|
||||
ups := snap.IngressGateway.Upstreams[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}]
|
||||
for i := range ups {
|
||||
ups[i].IngressHosts = nil
|
||||
}
|
||||
snap.IngressGateway.Upstreams[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}] = ups
|
||||
}
|
||||
|
||||
snap.IngressGateway.Listeners[proxycfg.IngressListenerKey{Protocol: "http", Port: 9191}] = il
|
||||
|
||||
entries := []structs.ConfigEntry{
|
||||
&structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
Config: map[string]interface{}{
|
||||
"protocol": "http",
|
||||
},
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: structs.ServiceResolver,
|
||||
Name: "foo",
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
},
|
||||
}
|
||||
for i, e := range entries {
|
||||
switch v := e.(type) {
|
||||
// Add other Service types here if we ever need them above
|
||||
case *structs.ServiceResolverConfigEntry:
|
||||
if em, ok := o.entMetas[v.Name]; ok && em != nil {
|
||||
v.EnterpriseMeta = *em
|
||||
entries[i] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webChain := discoverychain.TestCompileConfigEntries(t, "web",
|
||||
o.entMetas["web"].NamespaceOrDefault(),
|
||||
o.entMetas["web"].PartitionOrDefault(), "dc1",
|
||||
connect.TestClusterID+".consul", nil, entries...)
|
||||
fooChain := discoverychain.TestCompileConfigEntries(t, "foo",
|
||||
o.entMetas["foo"].NamespaceOrDefault(),
|
||||
o.entMetas["web"].PartitionOrDefault(), "dc1",
|
||||
connect.TestClusterID+".consul", nil, entries...)
|
||||
|
||||
snap.IngressGateway.DiscoveryChain[webUID] = webChain
|
||||
snap.IngressGateway.DiscoveryChain[fooUID] = fooChain
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "78ebd528~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "78ebd528~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "66s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"http2ProtocolOptions": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -114,6 +114,64 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "local_app",
|
||||
|
@ -138,6 +196,64 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
|
|
|
@ -114,6 +114,64 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "local_app",
|
||||
|
|
|
@ -114,6 +114,64 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "local_app",
|
||||
|
@ -139,6 +197,64 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"circuitBreakers": {
|
||||
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
},
|
||||
"transportSocket": {
|
||||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"matchSubjectAltNames": [
|
||||
{
|
||||
"exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/no-endpoints"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sni": "no-endpoints.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "original-destination",
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"clusterName": "78ebd528~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -107,6 +107,26 @@
|
|||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,6 +146,26 @@
|
|||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,26 @@
|
|||
"name": "tls",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext",
|
||||
"commonTlsContext": {
|
||||
"tlsParams": {
|
||||
|
||||
},
|
||||
"tlsCertificates": [
|
||||
{
|
||||
"certificateChain": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n"
|
||||
},
|
||||
"privateKey": {
|
||||
"inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n"
|
||||
}
|
||||
}
|
||||
],
|
||||
"validationContext": {
|
||||
"trustedCa": {
|
||||
"inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requireClientCertificate": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:10.0.0.1:9191",
|
||||
"name": "db:10.0.0.1:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.0.0.1",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
@ -28,11 +28,11 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:172.16.0.1:9191",
|
||||
"name": "db:172.16.0.1:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "172.16.0.1",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
@ -53,11 +53,11 @@
|
|||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:8.8.8.8:9191",
|
||||
"name": "db:8.8.8.8:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "8.8.8.8",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "http:1.2.3.4:9191",
|
||||
"name": "http:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
@ -17,7 +17,7 @@
|
|||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||
"statPrefix": "ingress_upstream_9191",
|
||||
"statPrefix": "ingress_upstream_8080",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "9191"
|
||||
"routeConfigName": "8080"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||
"statPrefix": "upstream.db.default.default.dc1",
|
||||
"rds": {
|
||||
"configSource": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
},
|
||||
"routeConfigName": "db"
|
||||
},
|
||||
"httpFilters": [
|
||||
{
|
||||
"name": "envoy.filters.http.grpc_stats",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig",
|
||||
"statsForAllMethods": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.http.grpc_http1_bridge"
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.http.router"
|
||||
}
|
||||
],
|
||||
"tracing": {
|
||||
"randomSampling": {
|
||||
|
||||
}
|
||||
},
|
||||
"http2ProtocolOptions": {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trafficDirection": "OUTBOUND"
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "db:1.2.3.4:9191",
|
||||
"name": "db:1.2.3.4:8080",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 9191
|
||||
"portValue": 8080
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "9191",
|
||||
"name": "8080",
|
||||
"virtualHosts": [
|
||||
{
|
||||
"name": "db",
|
||||
"domains": [
|
||||
"db.ingress.*",
|
||||
"db.ingress.*:9191"
|
||||
"db.ingress.*:8080"
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ func newTestSnapshot(
|
|||
dbServiceProtocol string,
|
||||
additionalEntries ...structs.ConfigEntry,
|
||||
) *proxycfg.ConfigSnapshot {
|
||||
snap := proxycfg.TestConfigSnapshotDiscoveryChainDefaultWithEntries(t, additionalEntries...)
|
||||
snap := proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", nil, nil, additionalEntries...)
|
||||
snap.ConnectProxy.PreparedQueryEndpoints = map[proxycfg.UpstreamID]structs.CheckServiceNodes{
|
||||
UID("prepared_query:geo-cache"): proxycfg.TestPreparedQueryNodes(t, "geo-cache"),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue