mirror of https://github.com/status-im/consul.git
connect: fix failover through a mesh gateway to a remote datacenter (#6259)
Failover is pushed entirely down to the data plane by creating envoy clusters and putting each successive destination in a different load assignment priority band. For example this shows that normally requests go to 1.2.3.4:8080 but when that fails they go to 6.7.8.9:8080: - name: foo load_assignment: cluster_name: foo policy: overprovisioning_factor: 100000 endpoints: - priority: 0 lb_endpoints: - endpoint: address: socket_address: address: 1.2.3.4 port_value: 8080 - priority: 1 lb_endpoints: - endpoint: address: socket_address: address: 6.7.8.9 port_value: 8080 Mesh gateways route requests based solely on the SNI header tacked onto the TLS layer. Envoy currently only lets you configure the outbound SNI header at the cluster layer. If you try to failover through a mesh gateway you ideally would configure the SNI value per endpoint, but that's not possible in envoy today. This PR introduces a simpler way around the problem for now: 1. We identify any target of failover that will use mesh gateway mode local or remote and then further isolate any resolver node in the compiled discovery chain that has a failover destination set to one of those targets. 2. For each of these resolvers we will perform a small measurement of comparative healths of the endpoints that come back from the health API for the set of primary target and serial failover targets. We walk the list of targets in order and if any endpoint is healthy we return that target, otherwise we move on to the next target. 3. The CDS and EDS endpoints both perform the measurements in (2) for the affected resolver nodes. 4. For CDS this measurement selects which TLS SNI field to use for the cluster (note the cluster is always going to be named for the primary target) 5. For EDS this measurement selects which set of endpoints will populate the cluster. Priority tiered failover is ignored. One of the big downsides to this approach to failover is that the failover detection and correction is going to be controlled by consul rather than deferring that entirely to the data plane as with the prior version. This also means that we are bound to only failover using official health signals and cannot make use of data plane signals like outlier detection to affect failover. In this specific scenario the lack of data plane signals is ok because the effectiveness is already muted by the fact that the ultimate destination endpoints will have their data plane signals scrambled when they pass through the mesh gateway wrapper anyway so we're not losing much. Another related fix is that we now use the endpoint health from the underlying service, not the health of the gateway (regardless of failover mode).
This commit is contained in:
parent
9f58504f1c
commit
8e22d80e35
|
@ -16,7 +16,7 @@ func TestCompiledDiscoveryChain(t *testing.T) {
|
|||
typ := &CompiledDiscoveryChain{RPC: rpc}
|
||||
|
||||
// just do the default chain
|
||||
chain := discoverychain.TestCompileConfigEntries(t, "web", "default", "dc1", nil)
|
||||
chain := discoverychain.TestCompileConfigEntries(t, "web", "default", "dc1", "dc1", nil)
|
||||
|
||||
// Expect the proper RPC call. This also sets the expected value
|
||||
// since that is return-by-pointer in the arguments.
|
||||
|
|
|
@ -58,8 +58,9 @@ func (c *DiscoveryChain) Get(args *structs.DiscoveryChainRequest, reply *structs
|
|||
// Then we compile it into something useful.
|
||||
chain, err := discoverychain.Compile(discoverychain.CompileRequest{
|
||||
ServiceName: args.Name,
|
||||
CurrentNamespace: evalNS,
|
||||
CurrentDatacenter: evalDC,
|
||||
EvaluateInNamespace: evalNS,
|
||||
EvaluateInDatacenter: evalDC,
|
||||
UseInDatacenter: c.srv.config.Datacenter,
|
||||
OverrideMeshGateway: args.OverrideMeshGateway,
|
||||
OverrideProtocol: args.OverrideProtocol,
|
||||
OverrideConnectTimeout: args.OverrideConnectTimeout,
|
||||
|
|
|
@ -11,9 +11,10 @@ import (
|
|||
)
|
||||
|
||||
type CompileRequest struct {
|
||||
ServiceName string
|
||||
CurrentNamespace string
|
||||
CurrentDatacenter string
|
||||
ServiceName string
|
||||
EvaluateInNamespace string
|
||||
EvaluateInDatacenter string
|
||||
UseInDatacenter string // where the results will be used from
|
||||
|
||||
// OverrideMeshGateway allows for the setting to be overridden for any
|
||||
// resolver in the compiled chain.
|
||||
|
@ -52,19 +53,23 @@ type CompileRequest struct {
|
|||
// valid.
|
||||
func Compile(req CompileRequest) (*structs.CompiledDiscoveryChain, error) {
|
||||
var (
|
||||
serviceName = req.ServiceName
|
||||
currentNamespace = req.CurrentNamespace
|
||||
currentDatacenter = req.CurrentDatacenter
|
||||
entries = req.Entries
|
||||
serviceName = req.ServiceName
|
||||
evaluateInNamespace = req.EvaluateInNamespace
|
||||
evaluateInDatacenter = req.EvaluateInDatacenter
|
||||
useInDatacenter = req.UseInDatacenter
|
||||
entries = req.Entries
|
||||
)
|
||||
if serviceName == "" {
|
||||
return nil, fmt.Errorf("serviceName is required")
|
||||
}
|
||||
if currentNamespace == "" {
|
||||
return nil, fmt.Errorf("currentNamespace is required")
|
||||
if evaluateInNamespace == "" {
|
||||
return nil, fmt.Errorf("evaluateInNamespace is required")
|
||||
}
|
||||
if currentDatacenter == "" {
|
||||
return nil, fmt.Errorf("currentDatacenter is required")
|
||||
if evaluateInDatacenter == "" {
|
||||
return nil, fmt.Errorf("evaluateInDatacenter is required")
|
||||
}
|
||||
if useInDatacenter == "" {
|
||||
return nil, fmt.Errorf("useInDatacenter is required")
|
||||
}
|
||||
if entries == nil {
|
||||
return nil, fmt.Errorf("entries is required")
|
||||
|
@ -72,8 +77,9 @@ func Compile(req CompileRequest) (*structs.CompiledDiscoveryChain, error) {
|
|||
|
||||
c := &compiler{
|
||||
serviceName: serviceName,
|
||||
currentNamespace: currentNamespace,
|
||||
currentDatacenter: currentDatacenter,
|
||||
evaluateInNamespace: evaluateInNamespace,
|
||||
evaluateInDatacenter: evaluateInDatacenter,
|
||||
useInDatacenter: useInDatacenter,
|
||||
overrideMeshGateway: req.OverrideMeshGateway,
|
||||
overrideProtocol: req.OverrideProtocol,
|
||||
overrideConnectTimeout: req.OverrideConnectTimeout,
|
||||
|
@ -106,8 +112,9 @@ func Compile(req CompileRequest) (*structs.CompiledDiscoveryChain, error) {
|
|||
// for assembling a discovery chain from raw config entries.
|
||||
type compiler struct {
|
||||
serviceName string
|
||||
currentNamespace string
|
||||
currentDatacenter string
|
||||
evaluateInNamespace string
|
||||
evaluateInDatacenter string
|
||||
useInDatacenter string
|
||||
overrideMeshGateway structs.MeshGatewayConfig
|
||||
overrideProtocol string
|
||||
overrideConnectTimeout time.Duration
|
||||
|
@ -298,8 +305,8 @@ func (c *compiler) compile() (*structs.CompiledDiscoveryChain, error) {
|
|||
|
||||
return &structs.CompiledDiscoveryChain{
|
||||
ServiceName: c.serviceName,
|
||||
Namespace: c.currentNamespace,
|
||||
Datacenter: c.currentDatacenter,
|
||||
Namespace: c.evaluateInNamespace,
|
||||
Datacenter: c.evaluateInDatacenter,
|
||||
CustomizationHash: customizationHash,
|
||||
Protocol: c.protocol,
|
||||
StartNode: c.startNode,
|
||||
|
@ -590,8 +597,8 @@ func (c *compiler) newTarget(service, serviceSubset, namespace, datacenter strin
|
|||
t := structs.NewDiscoveryTarget(
|
||||
service,
|
||||
serviceSubset,
|
||||
defaultIfEmpty(namespace, c.currentNamespace),
|
||||
defaultIfEmpty(datacenter, c.currentDatacenter),
|
||||
defaultIfEmpty(namespace, c.evaluateInNamespace),
|
||||
defaultIfEmpty(datacenter, c.evaluateInDatacenter),
|
||||
)
|
||||
|
||||
prev, ok := c.loadedTargets[t.ID]
|
||||
|
@ -806,19 +813,24 @@ RESOLVE_AGAIN:
|
|||
|
||||
target.Subset = resolver.Subsets[target.ServiceSubset]
|
||||
|
||||
// Default mesh gateway settings
|
||||
if serviceDefault := c.entries.GetService(target.Service); serviceDefault != nil {
|
||||
target.MeshGateway = serviceDefault.MeshGateway
|
||||
}
|
||||
// TODO (mesh-gateway)- maybe allow using a gateway within a datacenter at some point
|
||||
if target.Datacenter == c.useInDatacenter {
|
||||
target.MeshGateway.Mode = structs.MeshGatewayModeDefault
|
||||
} else {
|
||||
// Default mesh gateway settings
|
||||
if serviceDefault := c.entries.GetService(target.Service); serviceDefault != nil {
|
||||
target.MeshGateway = serviceDefault.MeshGateway
|
||||
}
|
||||
|
||||
if c.entries.GlobalProxy != nil && target.MeshGateway.Mode == structs.MeshGatewayModeDefault {
|
||||
target.MeshGateway.Mode = c.entries.GlobalProxy.MeshGateway.Mode
|
||||
}
|
||||
if c.entries.GlobalProxy != nil && target.MeshGateway.Mode == structs.MeshGatewayModeDefault {
|
||||
target.MeshGateway.Mode = c.entries.GlobalProxy.MeshGateway.Mode
|
||||
}
|
||||
|
||||
if c.overrideMeshGateway.Mode != structs.MeshGatewayModeDefault {
|
||||
if target.MeshGateway.Mode != c.overrideMeshGateway.Mode {
|
||||
target.MeshGateway.Mode = c.overrideMeshGateway.Mode
|
||||
c.customizedBy.MeshGateway = true
|
||||
if c.overrideMeshGateway.Mode != structs.MeshGatewayModeDefault {
|
||||
if target.MeshGateway.Mode != c.overrideMeshGateway.Mode {
|
||||
target.MeshGateway.Mode = c.overrideMeshGateway.Mode
|
||||
c.customizedBy.MeshGateway = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,13 @@ func TestCompile(t *testing.T) {
|
|||
"service redirect": testcase_ServiceRedirect(),
|
||||
"service and subset redirect": testcase_ServiceAndSubsetRedirect(),
|
||||
"datacenter redirect": testcase_DatacenterRedirect(),
|
||||
"datacenter redirect with mesh gateways": testcase_DatacenterRedirect_WithMeshGateways(),
|
||||
"service failover": testcase_ServiceFailover(),
|
||||
"service failover through redirect": testcase_ServiceFailoverThroughRedirect(),
|
||||
"circular resolver failover": testcase_Resolver_CircularFailover(),
|
||||
"service and subset failover": testcase_ServiceAndSubsetFailover(),
|
||||
"datacenter failover": testcase_DatacenterFailover(),
|
||||
"service failover with mesh gateways": testcase_ServiceFailover_WithMeshGateways(),
|
||||
"datacenter failover with mesh gateways": testcase_DatacenterFailover_WithMeshGateways(),
|
||||
"noop split to resolver with default subset": testcase_NoopSplit_WithDefaultSubset(),
|
||||
"resolver with default subset": testcase_Resolve_WithDefaultSubset(),
|
||||
"resolver with no entries and inferring defaults": testcase_DefaultResolver(),
|
||||
|
@ -91,10 +92,11 @@ func TestCompile(t *testing.T) {
|
|||
}
|
||||
|
||||
req := CompileRequest{
|
||||
ServiceName: "main",
|
||||
CurrentNamespace: "default",
|
||||
CurrentDatacenter: "dc1",
|
||||
Entries: tc.entries,
|
||||
ServiceName: "main",
|
||||
EvaluateInNamespace: "default",
|
||||
EvaluateInDatacenter: "dc1",
|
||||
UseInDatacenter: "dc1",
|
||||
Entries: tc.entries,
|
||||
}
|
||||
if tc.setup != nil {
|
||||
tc.setup(&req)
|
||||
|
@ -941,6 +943,49 @@ func testcase_DatacenterRedirect() compileTestCase {
|
|||
return compileTestCase{entries: entries, expect: expect}
|
||||
}
|
||||
|
||||
func testcase_DatacenterRedirect_WithMeshGateways() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.GlobalProxy = &structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
Name: structs.ProxyConfigGlobal,
|
||||
MeshGateway: structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
},
|
||||
}
|
||||
entries.AddResolvers(
|
||||
&structs.ServiceResolverConfigEntry{
|
||||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
Redirect: &structs.ServiceResolverRedirect{
|
||||
Datacenter: "dc9",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
expect := &structs.CompiledDiscoveryChain{
|
||||
Protocol: "tcp",
|
||||
StartNode: "resolver:main.default.dc9",
|
||||
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||
"resolver:main.default.dc9": &structs.DiscoveryGraphNode{
|
||||
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||
Name: "main.default.dc9",
|
||||
Resolver: &structs.DiscoveryResolver{
|
||||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "main.default.dc9",
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
"main.default.dc9": newTarget("main", "", "default", "dc9", func(t *structs.DiscoveryTarget) {
|
||||
t.MeshGateway = structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
}
|
||||
}),
|
||||
},
|
||||
}
|
||||
return compileTestCase{entries: entries, expect: expect}
|
||||
}
|
||||
|
||||
func testcase_ServiceFailover() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.AddResolvers(
|
||||
|
@ -1145,7 +1190,7 @@ func testcase_DatacenterFailover() compileTestCase {
|
|||
return compileTestCase{entries: entries, expect: expect}
|
||||
}
|
||||
|
||||
func testcase_ServiceFailover_WithMeshGateways() compileTestCase {
|
||||
func testcase_DatacenterFailover_WithMeshGateways() compileTestCase {
|
||||
entries := newEntries()
|
||||
entries.GlobalProxy = &structs.ProxyConfigEntry{
|
||||
Kind: structs.ProxyDefaults,
|
||||
|
@ -1159,7 +1204,7 @@ func testcase_ServiceFailover_WithMeshGateways() compileTestCase {
|
|||
Kind: "service-resolver",
|
||||
Name: "main",
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {Service: "backup"},
|
||||
"*": {Datacenters: []string{"dc2", "dc4"}},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -1175,18 +1220,22 @@ func testcase_ServiceFailover_WithMeshGateways() compileTestCase {
|
|||
ConnectTimeout: 5 * time.Second,
|
||||
Target: "main.default.dc1",
|
||||
Failover: &structs.DiscoveryFailover{
|
||||
Targets: []string{"backup.default.dc1"},
|
||||
Targets: []string{
|
||||
"main.default.dc2",
|
||||
"main.default.dc4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
"main.default.dc1": newTarget("main", "", "default", "dc1", func(t *structs.DiscoveryTarget) {
|
||||
"main.default.dc1": newTarget("main", "", "default", "dc1", nil),
|
||||
"main.default.dc2": newTarget("main", "", "default", "dc2", func(t *structs.DiscoveryTarget) {
|
||||
t.MeshGateway = structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
}
|
||||
}),
|
||||
"backup.default.dc1": newTarget("backup", "", "default", "dc1", func(t *structs.DiscoveryTarget) {
|
||||
"main.default.dc4": newTarget("main", "", "default", "dc4", func(t *structs.DiscoveryTarget) {
|
||||
t.MeshGateway = structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
}
|
||||
|
@ -1308,11 +1357,7 @@ func testcase_DefaultResolver_WithProxyDefaults() compileTestCase {
|
|||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
"main.default.dc1": newTarget("main", "", "default", "dc1", func(t *structs.DiscoveryTarget) {
|
||||
t.MeshGateway = structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeRemote,
|
||||
}
|
||||
}),
|
||||
"main.default.dc1": newTarget("main", "", "default", "dc1", nil),
|
||||
},
|
||||
}
|
||||
return compileTestCase{entries: entries, expect: expect, expectIsDefault: true}
|
||||
|
|
|
@ -9,8 +9,9 @@ import (
|
|||
func TestCompileConfigEntries(
|
||||
t testing.T,
|
||||
serviceName string,
|
||||
currentNamespace string,
|
||||
currentDatacenter string,
|
||||
evaluateInNamespace string,
|
||||
evaluateInDatacenter string,
|
||||
useInDatacenter string,
|
||||
setup func(req *CompileRequest),
|
||||
entries ...structs.ConfigEntry,
|
||||
) *structs.CompiledDiscoveryChain {
|
||||
|
@ -19,10 +20,11 @@ func TestCompileConfigEntries(
|
|||
set.AddEntries(entries...)
|
||||
|
||||
req := CompileRequest{
|
||||
ServiceName: serviceName,
|
||||
CurrentNamespace: currentNamespace,
|
||||
CurrentDatacenter: currentDatacenter,
|
||||
Entries: set,
|
||||
ServiceName: serviceName,
|
||||
EvaluateInNamespace: evaluateInNamespace,
|
||||
EvaluateInDatacenter: evaluateInDatacenter,
|
||||
UseInDatacenter: useInDatacenter,
|
||||
Entries: set,
|
||||
}
|
||||
if setup != nil {
|
||||
setup(&req)
|
||||
|
|
|
@ -444,11 +444,14 @@ func (s *Store) testCompileDiscoveryChain(
|
|||
|
||||
// Note we use an arbitrary namespace and datacenter as those would not
|
||||
// currently affect the graph compilation in ways that matter here.
|
||||
//
|
||||
// TODO(rb): we should thread a better value than "dc1" down here as that is going to sometimes show up in user facing errors
|
||||
req := discoverychain.CompileRequest{
|
||||
ServiceName: chainName,
|
||||
CurrentNamespace: "default",
|
||||
CurrentDatacenter: "dc1",
|
||||
Entries: speculativeEntries,
|
||||
ServiceName: chainName,
|
||||
EvaluateInNamespace: "default",
|
||||
EvaluateInDatacenter: "dc1",
|
||||
UseInDatacenter: "dc1",
|
||||
Entries: speculativeEntries,
|
||||
}
|
||||
_, err = discoverychain.Compile(req)
|
||||
return err
|
||||
|
|
|
@ -3,6 +3,7 @@ package agent
|
|||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -188,6 +189,11 @@ func TestDiscoveryChainRead(t *testing.T) {
|
|||
Kind: structs.ServiceResolver,
|
||||
Name: "web",
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Failover: map[string]structs.ServiceResolverFailover{
|
||||
"*": {
|
||||
Datacenters: []string{"dc2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, &out))
|
||||
require.True(t, out)
|
||||
|
@ -203,31 +209,49 @@ func TestDiscoveryChainRead(t *testing.T) {
|
|||
obj, err := a.srv.DiscoveryChainRead(resp, req)
|
||||
r.Check(err)
|
||||
|
||||
value := obj.(discoveryChainReadResponse)
|
||||
chain := value.Chain
|
||||
|
||||
// light comparison
|
||||
node := chain.Nodes["resolver:web.default.dc1"]
|
||||
if node == nil {
|
||||
r.Fatalf("missing node")
|
||||
}
|
||||
if node.Resolver.Default {
|
||||
r.Fatalf("not refreshed yet")
|
||||
}
|
||||
|
||||
// Should be a cache hit! The data should've updated in the cache
|
||||
// in the background so this should've been fetched directly from
|
||||
// the cache.
|
||||
if resp.Header().Get("X-Cache") != "HIT" {
|
||||
r.Fatalf("should be a cache hit")
|
||||
}
|
||||
|
||||
value := obj.(discoveryChainReadResponse)
|
||||
|
||||
expect := &structs.CompiledDiscoveryChain{
|
||||
ServiceName: "web",
|
||||
Namespace: "default",
|
||||
Datacenter: "dc1",
|
||||
Protocol: "tcp",
|
||||
StartNode: "resolver:web.default.dc1",
|
||||
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||
"resolver:web.default.dc1": &structs.DiscoveryGraphNode{
|
||||
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||
Name: "web.default.dc1",
|
||||
Resolver: &structs.DiscoveryResolver{
|
||||
ConnectTimeout: 33 * time.Second,
|
||||
Target: "web.default.dc1",
|
||||
Failover: &structs.DiscoveryFailover{
|
||||
Targets: []string{"web.default.dc2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
"web.default.dc1": structs.NewDiscoveryTarget("web", "", "default", "dc1"),
|
||||
"web.default.dc2": structs.NewDiscoveryTarget("web", "", "default", "dc2"),
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(expect, value.Chain) {
|
||||
r.Fatalf("should be equal: expected=%+v, got=%+v", expect, value.Chain)
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
// TODO(namespaces): add a test
|
||||
|
||||
expectTarget := structs.NewDiscoveryTarget("web", "", "default", "dc1")
|
||||
expectTarget.MeshGateway = structs.MeshGatewayConfig{
|
||||
expectTarget_DC2 := structs.NewDiscoveryTarget("web", "", "default", "dc2")
|
||||
expectTarget_DC2.MeshGateway = structs.MeshGatewayConfig{
|
||||
Mode: structs.MeshGatewayModeLocal,
|
||||
}
|
||||
|
||||
|
@ -245,11 +269,15 @@ func TestDiscoveryChainRead(t *testing.T) {
|
|||
Resolver: &structs.DiscoveryResolver{
|
||||
ConnectTimeout: 22 * time.Second,
|
||||
Target: "web.default.dc1",
|
||||
Failover: &structs.DiscoveryFailover{
|
||||
Targets: []string{"web.default.dc2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Targets: map[string]*structs.DiscoveryTarget{
|
||||
expectTarget.ID: expectTarget,
|
||||
"web.default.dc1": structs.NewDiscoveryTarget("web", "", "default", "dc1"),
|
||||
expectTarget_DC2.ID: expectTarget_DC2,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ func TestManager_BasicLifecycle(t *testing.T) {
|
|||
roots, leaf := TestCerts(t)
|
||||
|
||||
dbDefaultChain := func() *structs.CompiledDiscoveryChain {
|
||||
return discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1",
|
||||
return discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
// This is because structs.TestUpstreams uses an opaque config
|
||||
// to override connect timeouts.
|
||||
|
@ -59,7 +59,7 @@ func TestManager_BasicLifecycle(t *testing.T) {
|
|||
)
|
||||
}
|
||||
dbSplitChain := func() *structs.CompiledDiscoveryChain {
|
||||
return discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1",
|
||||
return discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
// This is because structs.TestUpstreams uses an opaque config
|
||||
// to override connect timeouts.
|
||||
|
@ -201,6 +201,10 @@ func TestManager_BasicLifecycle(t *testing.T) {
|
|||
"db.default.dc1": TestUpstreamNodes(t),
|
||||
},
|
||||
},
|
||||
WatchedGateways: nil, // Clone() clears this out
|
||||
WatchedGatewayEndpoints: map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": {},
|
||||
},
|
||||
UpstreamEndpoints: map[string]structs.CheckServiceNodes{},
|
||||
},
|
||||
Datacenter: "dc1",
|
||||
|
@ -241,6 +245,10 @@ func TestManager_BasicLifecycle(t *testing.T) {
|
|||
"v2.db.default.dc1": TestUpstreamNodesAlternate(t),
|
||||
},
|
||||
},
|
||||
WatchedGateways: nil, // Clone() clears this out
|
||||
WatchedGatewayEndpoints: map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": {},
|
||||
},
|
||||
UpstreamEndpoints: map[string]structs.CheckServiceNodes{},
|
||||
},
|
||||
Datacenter: "dc1",
|
||||
|
|
|
@ -12,7 +12,10 @@ type configSnapshotConnectProxy struct {
|
|||
DiscoveryChain map[string]*structs.CompiledDiscoveryChain // this is keyed by the Upstream.Identifier(), not the chain name
|
||||
WatchedUpstreams map[string]map[string]context.CancelFunc
|
||||
WatchedUpstreamEndpoints map[string]map[string]structs.CheckServiceNodes
|
||||
UpstreamEndpoints map[string]structs.CheckServiceNodes // DEPRECATED:see:WatchedUpstreamEndpoints
|
||||
WatchedGateways map[string]map[string]context.CancelFunc
|
||||
WatchedGatewayEndpoints map[string]map[string]structs.CheckServiceNodes
|
||||
|
||||
UpstreamEndpoints map[string]structs.CheckServiceNodes // DEPRECATED:see:WatchedUpstreamEndpoints
|
||||
}
|
||||
|
||||
type configSnapshotMeshGateway struct {
|
||||
|
@ -74,6 +77,7 @@ func (s *ConfigSnapshot) Clone() (*ConfigSnapshot, error) {
|
|||
switch s.Kind {
|
||||
case structs.ServiceKindConnectProxy:
|
||||
snap.ConnectProxy.WatchedUpstreams = nil
|
||||
snap.ConnectProxy.WatchedGateways = nil
|
||||
case structs.ServiceKindMeshGateway:
|
||||
snap.MeshGateway.WatchedDatacenters = nil
|
||||
snap.MeshGateway.WatchedServices = nil
|
||||
|
|
|
@ -148,40 +148,30 @@ func (s *state) initWatches() error {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *state) watchConnectProxyService(ctx context.Context, correlationId string, service string, dc string, filter string, meshGatewayMode structs.MeshGatewayMode) error {
|
||||
switch meshGatewayMode {
|
||||
case structs.MeshGatewayModeRemote:
|
||||
return s.cache.Notify(ctx, cachetype.InternalServiceDumpName, &structs.ServiceDumpRequest{
|
||||
Datacenter: dc,
|
||||
QueryOptions: structs.QueryOptions{Token: s.token},
|
||||
ServiceKind: structs.ServiceKindMeshGateway,
|
||||
UseServiceKind: true,
|
||||
Source: *s.source,
|
||||
}, correlationId, s.ch)
|
||||
case structs.MeshGatewayModeLocal:
|
||||
return s.cache.Notify(ctx, cachetype.InternalServiceDumpName, &structs.ServiceDumpRequest{
|
||||
Datacenter: s.source.Datacenter,
|
||||
QueryOptions: structs.QueryOptions{Token: s.token},
|
||||
ServiceKind: structs.ServiceKindMeshGateway,
|
||||
UseServiceKind: true,
|
||||
Source: *s.source,
|
||||
}, correlationId, s.ch)
|
||||
default:
|
||||
// This includes both the None and Default modes on purpose
|
||||
return s.cache.Notify(ctx, cachetype.HealthServicesName, &structs.ServiceSpecificRequest{
|
||||
Datacenter: dc,
|
||||
QueryOptions: structs.QueryOptions{
|
||||
Token: s.token,
|
||||
Filter: filter,
|
||||
},
|
||||
ServiceName: service,
|
||||
Connect: true,
|
||||
// Note that Identifier doesn't type-prefix for service any more as it's
|
||||
// the default and makes metrics and other things much cleaner. It's
|
||||
// simpler for us if we have the type to make things unambiguous.
|
||||
Source: *s.source,
|
||||
}, correlationId, s.ch)
|
||||
}
|
||||
func (s *state) watchMeshGateway(ctx context.Context, dc string, upstreamID string) error {
|
||||
return s.cache.Notify(ctx, cachetype.InternalServiceDumpName, &structs.ServiceDumpRequest{
|
||||
Datacenter: dc,
|
||||
QueryOptions: structs.QueryOptions{Token: s.token},
|
||||
ServiceKind: structs.ServiceKindMeshGateway,
|
||||
UseServiceKind: true,
|
||||
Source: *s.source,
|
||||
}, "mesh-gateway:"+dc+":"+upstreamID, s.ch)
|
||||
}
|
||||
|
||||
func (s *state) watchConnectProxyService(ctx context.Context, correlationId string, service string, dc string, filter string) error {
|
||||
return s.cache.Notify(ctx, cachetype.HealthServicesName, &structs.ServiceSpecificRequest{
|
||||
Datacenter: dc,
|
||||
QueryOptions: structs.QueryOptions{
|
||||
Token: s.token,
|
||||
Filter: filter,
|
||||
},
|
||||
ServiceName: service,
|
||||
Connect: true,
|
||||
// Note that Identifier doesn't type-prefix for service any more as it's
|
||||
// the default and makes metrics and other things much cleaner. It's
|
||||
// simpler for us if we have the type to make things unambiguous.
|
||||
Source: *s.source,
|
||||
}, correlationId, s.ch)
|
||||
}
|
||||
|
||||
// initWatchesConnectProxy sets up the watches needed based on current proxy registration
|
||||
|
@ -361,6 +351,9 @@ func (s *state) initialConfigSnapshot() ConfigSnapshot {
|
|||
snap.ConnectProxy.DiscoveryChain = make(map[string]*structs.CompiledDiscoveryChain)
|
||||
snap.ConnectProxy.WatchedUpstreams = make(map[string]map[string]context.CancelFunc)
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
||||
snap.ConnectProxy.WatchedGateways = make(map[string]map[string]context.CancelFunc)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints = make(map[string]map[string]structs.CheckServiceNodes)
|
||||
|
||||
snap.ConnectProxy.UpstreamEndpoints = make(map[string]structs.CheckServiceNodes) // TODO(rb): deprecated
|
||||
case structs.ServiceKindMeshGateway:
|
||||
snap.MeshGateway.WatchedServices = make(map[string]context.CancelFunc)
|
||||
|
@ -515,6 +508,23 @@ func (s *state) handleUpdateConnectProxy(u cache.UpdateEvent, snap *ConfigSnapsh
|
|||
}
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints[svc][targetID] = resp.Nodes
|
||||
|
||||
case strings.HasPrefix(u.CorrelationID, "mesh-gateway:"):
|
||||
resp, ok := u.Result.(*structs.IndexedCheckServiceNodes)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for service response: %T", u.Result)
|
||||
}
|
||||
correlationID := strings.TrimPrefix(u.CorrelationID, "mesh-gateway:")
|
||||
dc, svc, ok := removeColonPrefix(correlationID)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid correlation id %q", u.CorrelationID)
|
||||
}
|
||||
m, ok := snap.ConnectProxy.WatchedGatewayEndpoints[svc]
|
||||
if !ok {
|
||||
m = make(map[string]structs.CheckServiceNodes)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints[svc] = m
|
||||
}
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints[svc][dc] = resp.Nodes
|
||||
|
||||
case strings.HasPrefix(u.CorrelationID, "upstream:"+serviceIDPrefix):
|
||||
resp, ok := u.Result.(*structs.IndexedCheckServiceNodes)
|
||||
if !ok {
|
||||
|
@ -561,6 +571,12 @@ func (s *state) resetWatchesFromChain(
|
|||
if _, ok := snap.ConnectProxy.WatchedUpstreamEndpoints[id]; !ok {
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints[id] = make(map[string]structs.CheckServiceNodes)
|
||||
}
|
||||
if _, ok := snap.ConnectProxy.WatchedGateways[id]; !ok {
|
||||
snap.ConnectProxy.WatchedGateways[id] = make(map[string]context.CancelFunc)
|
||||
}
|
||||
if _, ok := snap.ConnectProxy.WatchedGatewayEndpoints[id]; !ok {
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints[id] = make(map[string]structs.CheckServiceNodes)
|
||||
}
|
||||
|
||||
// We could invalidate this selectively based on a hash of the relevant
|
||||
// resolver information, but for now just reset anything about this
|
||||
|
@ -574,29 +590,26 @@ func (s *state) resetWatchesFromChain(
|
|||
cancelFn()
|
||||
}
|
||||
|
||||
needGateways := make(map[string]struct{})
|
||||
for _, target := range chain.Targets {
|
||||
s.logger.Printf("[TRACE] proxycfg: upstream=%q:chain=%q: initializing watch of target %s", id, chain.ServiceName, target.ID)
|
||||
|
||||
// We'll get endpoints from the gateway query, but the health still has
|
||||
// to come from the backing service query.
|
||||
switch target.MeshGateway.Mode {
|
||||
case structs.MeshGatewayModeRemote:
|
||||
needGateways[target.Datacenter] = struct{}{}
|
||||
case structs.MeshGatewayModeLocal:
|
||||
needGateways[s.source.Datacenter] = struct{}{}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(s.ctx)
|
||||
|
||||
// TODO (mesh-gateway)- maybe allow using a gateway within a datacenter at some point
|
||||
meshGateway := structs.MeshGatewayModeDefault
|
||||
if target.Datacenter != s.source.Datacenter {
|
||||
meshGateway = target.MeshGateway.Mode
|
||||
}
|
||||
|
||||
// if the default mode
|
||||
if meshGateway == structs.MeshGatewayModeDefault {
|
||||
meshGateway = structs.MeshGatewayModeNone
|
||||
}
|
||||
|
||||
err := s.watchConnectProxyService(
|
||||
ctx,
|
||||
"upstream-target:"+target.ID+":"+id,
|
||||
target.Service,
|
||||
target.Datacenter,
|
||||
target.Subset.Filter,
|
||||
meshGateway,
|
||||
)
|
||||
if err != nil {
|
||||
cancel()
|
||||
|
@ -606,6 +619,33 @@ func (s *state) resetWatchesFromChain(
|
|||
snap.ConnectProxy.WatchedUpstreams[id][target.ID] = cancel
|
||||
}
|
||||
|
||||
for dc, _ := range needGateways {
|
||||
if _, ok := snap.ConnectProxy.WatchedGateways[id][dc]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
s.logger.Printf("[TRACE] proxycfg: upstream=%q:chain=%q: initializing watch of mesh gateway in dc %s", id, chain.ServiceName, dc)
|
||||
|
||||
ctx, cancel := context.WithCancel(s.ctx)
|
||||
err := s.watchMeshGateway(ctx, dc, id)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
|
||||
snap.ConnectProxy.WatchedGateways[id][dc] = cancel
|
||||
}
|
||||
|
||||
for dc, cancelFn := range snap.ConnectProxy.WatchedGateways[id] {
|
||||
if _, ok := needGateways[dc]; ok {
|
||||
continue
|
||||
}
|
||||
s.logger.Printf("[TRACE] proxycfg: upstream=%q:chain=%q: stopping watch of mesh gateway in dc %s", id, chain.ServiceName, dc)
|
||||
delete(snap.ConnectProxy.WatchedGateways[id], dc)
|
||||
delete(snap.ConnectProxy.WatchedGatewayEndpoints[id], dc)
|
||||
cancelFn()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
cache.UpdateEvent{
|
||||
CorrelationID: "discovery-chain:api",
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api", "default", "dc1",
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api", "default", "dc1", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = meshGatewayProxyConfigValue
|
||||
}),
|
||||
|
@ -430,7 +430,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
cache.UpdateEvent{
|
||||
CorrelationID: "discovery-chain:api-failover-remote?dc=dc2",
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-remote", "default", "dc2",
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-remote", "default", "dc2", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = structs.MeshGatewayModeRemote
|
||||
}),
|
||||
|
@ -440,7 +440,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
cache.UpdateEvent{
|
||||
CorrelationID: "discovery-chain:api-failover-local?dc=dc2",
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-local", "default", "dc2",
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-local", "default", "dc2", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = structs.MeshGatewayModeLocal
|
||||
}),
|
||||
|
@ -450,7 +450,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
cache.UpdateEvent{
|
||||
CorrelationID: "discovery-chain:api-failover-direct?dc=dc2",
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-direct", "default", "dc2",
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-failover-direct", "default", "dc2", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = structs.MeshGatewayModeNone
|
||||
}),
|
||||
|
@ -460,7 +460,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
cache.UpdateEvent{
|
||||
CorrelationID: "discovery-chain:api-dc2",
|
||||
Result: &structs.DiscoveryChainResponse{
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-dc2", "default", "dc1",
|
||||
Chain: discoverychain.TestCompileConfigEntries(t, "api-dc2", "default", "dc1", "dc1",
|
||||
func(req *discoverychain.CompileRequest) {
|
||||
req.OverrideMeshGateway.Mode = meshGatewayProxyConfigValue
|
||||
},
|
||||
|
@ -482,16 +482,16 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
stage1 := verificationStage{
|
||||
requiredWatches: map[string]verifyWatchRequest{
|
||||
"upstream-target:api.default.dc1:api": genVerifyServiceWatch("api", "", "dc1", true),
|
||||
"upstream-target:api-failover-remote.default.dc2:api-failover-remote?dc=dc2": genVerifyGatewayWatch("dc2"),
|
||||
"upstream-target:api-failover-local.default.dc2:api-failover-local?dc=dc2": genVerifyGatewayWatch("dc1"),
|
||||
"upstream-target:api-failover-remote.default.dc2:api-failover-remote?dc=dc2": genVerifyServiceWatch("api-failover-remote", "", "dc2", true),
|
||||
"upstream-target:api-failover-local.default.dc2:api-failover-local?dc=dc2": genVerifyServiceWatch("api-failover-local", "", "dc2", true),
|
||||
"upstream-target:api-failover-direct.default.dc2:api-failover-direct?dc=dc2": genVerifyServiceWatch("api-failover-direct", "", "dc2", true),
|
||||
"mesh-gateway:dc2:api-failover-remote?dc=dc2": genVerifyGatewayWatch("dc2"),
|
||||
"mesh-gateway:dc1:api-failover-local?dc=dc2": genVerifyGatewayWatch("dc1"),
|
||||
},
|
||||
}
|
||||
|
||||
if meshGatewayProxyConfigValue == structs.MeshGatewayModeDefault {
|
||||
stage1.requiredWatches["upstream-target:api.default.dc2:api-dc2"] = genVerifyServiceWatch("api", "", "dc2", true)
|
||||
} else {
|
||||
stage1.requiredWatches["upstream-target:api.default.dc2:api-dc2"] = genVerifyGatewayWatch("dc1")
|
||||
if meshGatewayProxyConfigValue == structs.MeshGatewayModeLocal {
|
||||
stage1.requiredWatches["mesh-gateway:dc1:api-dc2"] = genVerifyGatewayWatch("dc1")
|
||||
}
|
||||
|
||||
return testCase{
|
||||
|
|
|
@ -157,6 +157,45 @@ func TestUpstreamNodes(t testing.T) structs.CheckServiceNodes {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUpstreamNodesInStatus(t testing.T, status string) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test1",
|
||||
Node: "test1",
|
||||
Address: "10.10.1.1",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
Checks: structs.HealthChecks{
|
||||
&structs.HealthCheck{
|
||||
Node: "test1",
|
||||
ServiceName: "web",
|
||||
Name: "force",
|
||||
Status: status,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test2",
|
||||
Node: "test2",
|
||||
Address: "10.10.1.2",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
Checks: structs.HealthChecks{
|
||||
&structs.HealthCheck{
|
||||
Node: "test2",
|
||||
ServiceName: "web",
|
||||
Name: "force",
|
||||
Status: status,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpstreamNodesDC2(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
|
@ -180,6 +219,68 @@ func TestUpstreamNodesDC2(t testing.T) structs.CheckServiceNodes {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUpstreamNodesInStatusDC2(t testing.T, status string) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test1",
|
||||
Node: "test1",
|
||||
Address: "10.20.1.1",
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
Checks: structs.HealthChecks{
|
||||
&structs.HealthCheck{
|
||||
Node: "test1",
|
||||
ServiceName: "web",
|
||||
Name: "force",
|
||||
Status: status,
|
||||
},
|
||||
},
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test2",
|
||||
Node: "test2",
|
||||
Address: "10.20.1.2",
|
||||
Datacenter: "dc2",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
Checks: structs.HealthChecks{
|
||||
&structs.HealthCheck{
|
||||
Node: "test2",
|
||||
ServiceName: "web",
|
||||
Name: "force",
|
||||
Status: status,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpstreamNodesDC3(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test1",
|
||||
Node: "test1",
|
||||
Address: "10.30.1.1",
|
||||
Datacenter: "dc3",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "test2",
|
||||
Node: "test2",
|
||||
Address: "10.30.1.2",
|
||||
Datacenter: "dc3",
|
||||
},
|
||||
Service: structs.TestNodeService(t),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpstreamNodesAlternate(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
|
@ -203,6 +304,35 @@ func TestUpstreamNodesAlternate(t testing.T) structs.CheckServiceNodes {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGatewayNodesDC1(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "mesh-gateway-1",
|
||||
Node: "mesh-gateway",
|
||||
Address: "10.10.1.1",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.10.1.1", 8443,
|
||||
structs.ServiceAddress{Address: "10.10.1.1", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.118.1.1", Port: 443}),
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "mesh-gateway-2",
|
||||
Node: "mesh-gateway",
|
||||
Address: "10.10.1.2",
|
||||
Datacenter: "dc1",
|
||||
},
|
||||
Service: structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.10.1.2", 8443,
|
||||
structs.ServiceAddress{Address: "10.0.1.2", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.118.1.2", Port: 443}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGatewayNodesDC2(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
|
@ -232,6 +362,35 @@ func TestGatewayNodesDC2(t testing.T) structs.CheckServiceNodes {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGatewayNodesDC3(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "mesh-gateway-1",
|
||||
Node: "mesh-gateway",
|
||||
Address: "10.30.1.1",
|
||||
Datacenter: "dc3",
|
||||
},
|
||||
Service: structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.30.1.1", 8443,
|
||||
structs.ServiceAddress{Address: "10.0.1.1", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.38.1.1", Port: 443}),
|
||||
},
|
||||
structs.CheckServiceNode{
|
||||
Node: &structs.Node{
|
||||
ID: "mesh-gateway-2",
|
||||
Node: "mesh-gateway",
|
||||
Address: "10.30.1.2",
|
||||
Datacenter: "dc3",
|
||||
},
|
||||
Service: structs.TestNodeServiceMeshGatewayWithAddrs(t,
|
||||
"10.30.1.2", 8443,
|
||||
structs.ServiceAddress{Address: "10.30.1.2", Port: 8443},
|
||||
structs.ServiceAddress{Address: "198.38.1.2", Port: 443}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGatewayServiceGroupBarDC1(t testing.T) structs.CheckServiceNodes {
|
||||
return structs.CheckServiceNodes{
|
||||
structs.CheckServiceNode{
|
||||
|
@ -441,6 +600,38 @@ func TestConfigSnapshotDiscoveryChainWithFailover(t testing.T) *ConfigSnapshot {
|
|||
return testConfigSnapshotDiscoveryChain(t, "failover")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithFailoverThroughRemoteGateway(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithFailoverThroughRemoteGatewayTriggered(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-remote-gateway-triggered")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughRemoteGateway(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughRemoteGatewayTriggered(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-double-remote-gateway-triggered")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithFailoverThroughLocalGateway(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithFailoverThroughLocalGatewayTriggered(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-local-gateway-triggered")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughLocalGateway(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChainWithDoubleFailoverThroughLocalGatewayTriggered(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "failover-through-double-local-gateway-triggered")
|
||||
}
|
||||
|
||||
func TestConfigSnapshotDiscoveryChain_SplitterWithResolverRedirectMultiDC(t testing.T) *ConfigSnapshot {
|
||||
return testConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc")
|
||||
}
|
||||
|
@ -486,6 +677,94 @@ func testConfigSnapshotDiscoveryChain(t testing.T, variation string, additionalE
|
|||
},
|
||||
},
|
||||
)
|
||||
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{
|
||||
|
@ -543,7 +822,7 @@ func testConfigSnapshotDiscoveryChain(t testing.T, variation string, additionalE
|
|||
entries = append(entries, additionalEntries...)
|
||||
}
|
||||
|
||||
dbChain := discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1", compileSetup, entries...)
|
||||
dbChain := discoverychain.TestCompileConfigEntries(t, "db", "default", "dc1", "dc1", compileSetup, entries...)
|
||||
|
||||
snap := &ConfigSnapshot{
|
||||
Kind: structs.ServiceKindConnectProxy,
|
||||
|
@ -582,6 +861,57 @@ func testConfigSnapshotDiscoveryChain(t testing.T, variation string, additionalE
|
|||
case "failover":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["fail.default.dc1"] =
|
||||
TestUpstreamNodesAlternate(t)
|
||||
case "failover-through-remote-gateway-triggered":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc1"] =
|
||||
TestUpstreamNodesInStatus(t, "critical")
|
||||
fallthrough
|
||||
case "failover-through-remote-gateway":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc2"] =
|
||||
TestUpstreamNodesDC2(t)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints = map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": map[string]structs.CheckServiceNodes{
|
||||
"dc2": TestGatewayNodesDC2(t),
|
||||
},
|
||||
}
|
||||
case "failover-through-double-remote-gateway-triggered":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc1"] =
|
||||
TestUpstreamNodesInStatus(t, "critical")
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc2"] =
|
||||
TestUpstreamNodesInStatusDC2(t, "critical")
|
||||
fallthrough
|
||||
case "failover-through-double-remote-gateway":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc3"] = TestUpstreamNodesDC2(t)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints = map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": map[string]structs.CheckServiceNodes{
|
||||
"dc2": TestGatewayNodesDC2(t),
|
||||
"dc3": TestGatewayNodesDC3(t),
|
||||
},
|
||||
}
|
||||
case "failover-through-local-gateway-triggered":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc1"] =
|
||||
TestUpstreamNodesInStatus(t, "critical")
|
||||
fallthrough
|
||||
case "failover-through-local-gateway":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc2"] =
|
||||
TestUpstreamNodesDC2(t)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints = map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": map[string]structs.CheckServiceNodes{
|
||||
"dc1": TestGatewayNodesDC1(t),
|
||||
},
|
||||
}
|
||||
case "failover-through-double-local-gateway-triggered":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc1"] =
|
||||
TestUpstreamNodesInStatus(t, "critical")
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc2"] =
|
||||
TestUpstreamNodesInStatusDC2(t, "critical")
|
||||
fallthrough
|
||||
case "failover-through-double-local-gateway":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"]["db.default.dc3"] = TestUpstreamNodesDC2(t)
|
||||
snap.ConnectProxy.WatchedGatewayEndpoints = map[string]map[string]structs.CheckServiceNodes{
|
||||
"db": map[string]structs.CheckServiceNodes{
|
||||
"dc1": TestGatewayNodesDC1(t),
|
||||
},
|
||||
}
|
||||
case "splitter-with-resolver-redirect-multidc":
|
||||
snap.ConnectProxy.WatchedUpstreamEndpoints["db"] = map[string]structs.CheckServiceNodes{
|
||||
"v1.db.default.dc1": TestUpstreamNodes(t),
|
||||
|
|
|
@ -40,6 +40,24 @@ type CompiledDiscoveryChain struct {
|
|||
Targets map[string]*DiscoveryTarget `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (c *CompiledDiscoveryChain) WillFailoverThroughMeshGateway(node *DiscoveryGraphNode) bool {
|
||||
if node.Type != DiscoveryGraphNodeTypeResolver {
|
||||
return false
|
||||
}
|
||||
failover := node.Resolver.Failover
|
||||
|
||||
if failover != nil && len(failover.Targets) > 0 {
|
||||
for _, failTargetID := range failover.Targets {
|
||||
failTarget := c.Targets[failTargetID]
|
||||
switch failTarget.MeshGateway.Mode {
|
||||
case MeshGatewayModeLocal, MeshGatewayModeRemote:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsDefault returns true if the compiled chain represents no routing, no
|
||||
// splitting, and only the default resolution. We have to be careful here to
|
||||
// avoid returning "yep this is default" when the only resolver action being
|
||||
|
|
|
@ -246,6 +246,13 @@ func (s *Server) makeUpstreamClustersForDiscoveryChain(
|
|||
panic("chain must be provided")
|
||||
}
|
||||
|
||||
id := upstream.Identifier()
|
||||
chainEndpointMap, ok := cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[id]
|
||||
if !ok {
|
||||
// this should not happen
|
||||
return nil, fmt.Errorf("no endpoint map for upstream %q", id)
|
||||
}
|
||||
|
||||
// TODO(rb): make escape hatches work with chains
|
||||
|
||||
var out []*envoy.Cluster
|
||||
|
@ -254,13 +261,31 @@ func (s *Server) makeUpstreamClustersForDiscoveryChain(
|
|||
if node.Type != structs.DiscoveryGraphNodeTypeResolver {
|
||||
continue
|
||||
}
|
||||
failover := node.Resolver.Failover
|
||||
targetID := node.Resolver.Target
|
||||
|
||||
target := chain.Targets[targetID]
|
||||
|
||||
// Determine if we have to generate the entire cluster differently.
|
||||
failoverThroughMeshGateway := chain.WillFailoverThroughMeshGateway(node)
|
||||
|
||||
sni := TargetSNI(target, cfgSnap)
|
||||
clusterName := CustomizeClusterName(sni, chain)
|
||||
|
||||
if failoverThroughMeshGateway {
|
||||
actualTargetID := firstHealthyTarget(
|
||||
chain.Targets,
|
||||
chainEndpointMap,
|
||||
targetID,
|
||||
failover.Targets,
|
||||
)
|
||||
|
||||
if actualTargetID != targetID {
|
||||
actualTarget := chain.Targets[actualTargetID]
|
||||
sni = TargetSNI(actualTarget, cfgSnap)
|
||||
}
|
||||
}
|
||||
|
||||
s.Logger.Printf("[DEBUG] xds.clusters - generating cluster for %s", clusterName)
|
||||
c := &envoy.Cluster{
|
||||
Name: clusterName,
|
||||
|
|
|
@ -115,6 +115,46 @@ func TestClustersFromSnapshot(t *testing.T) {
|
|||
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: "splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain_SplitterWithResolverRedirectMultiDC,
|
||||
|
|
|
@ -35,8 +35,8 @@ func (s *Server) endpointsFromSnapshot(cfgSnap *proxycfg.ConfigSnapshot, token s
|
|||
// endpointsFromSnapshotConnectProxy returns the xDS API representation of the "endpoints"
|
||||
// (upstream instances) in the snapshot.
|
||||
func (s *Server) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapshot, token string) ([]proto.Message, error) {
|
||||
// TODO(rb): this sizing is a low bound.
|
||||
resources := make([]proto.Message, 0, len(cfgSnap.ConnectProxy.UpstreamEndpoints))
|
||||
resources := make([]proto.Message, 0,
|
||||
len(cfgSnap.ConnectProxy.UpstreamEndpoints)+len(cfgSnap.ConnectProxy.WatchedUpstreamEndpoints))
|
||||
|
||||
// TODO(rb): should naming from 1.5 -> 1.6 for clusters remain unchanged?
|
||||
|
||||
|
@ -67,11 +67,6 @@ func (s *Server) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnaps
|
|||
} else {
|
||||
// Newfangled discovery chain plumbing.
|
||||
|
||||
chainEndpointMap, ok := cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[id]
|
||||
if !ok {
|
||||
continue // skip the upstream (should not happen)
|
||||
}
|
||||
|
||||
// Find all resolver nodes.
|
||||
for _, node := range chain.Nodes {
|
||||
if node.Type != structs.DiscoveryGraphNodeTypeResolver {
|
||||
|
@ -82,43 +77,62 @@ func (s *Server) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnaps
|
|||
|
||||
target := chain.Targets[targetID]
|
||||
|
||||
endpoints, ok := chainEndpointMap[targetID]
|
||||
if !ok {
|
||||
continue // skip the cluster (should not happen)
|
||||
sni := TargetSNI(target, cfgSnap)
|
||||
clusterName := CustomizeClusterName(sni, chain)
|
||||
|
||||
// Determine if we have to generate the entire cluster differently.
|
||||
failoverThroughMeshGateway := chain.WillFailoverThroughMeshGateway(node)
|
||||
|
||||
if failoverThroughMeshGateway {
|
||||
actualTargetID := firstHealthyTarget(
|
||||
chain.Targets,
|
||||
cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[id],
|
||||
targetID,
|
||||
failover.Targets,
|
||||
)
|
||||
if actualTargetID != targetID {
|
||||
targetID = actualTargetID
|
||||
target = chain.Targets[actualTargetID]
|
||||
}
|
||||
|
||||
failover = nil
|
||||
}
|
||||
|
||||
primaryGroup, valid := makeLoadAssignmentEndpointGroup(
|
||||
chain.Targets,
|
||||
cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[id],
|
||||
cfgSnap.ConnectProxy.WatchedGatewayEndpoints[id],
|
||||
targetID,
|
||||
cfgSnap.Datacenter,
|
||||
)
|
||||
if !valid {
|
||||
continue // skip the cluster if we're still populating the snapshot
|
||||
}
|
||||
|
||||
var endpointGroups []loadAssignmentEndpointGroup
|
||||
|
||||
primaryGroup := loadAssignmentEndpointGroup{
|
||||
Endpoints: endpoints,
|
||||
OnlyPassing: target.Subset.OnlyPassing,
|
||||
}
|
||||
|
||||
if failover != nil && len(failover.Targets) > 0 {
|
||||
endpointGroups = make([]loadAssignmentEndpointGroup, 0, len(failover.Targets)+1)
|
||||
|
||||
endpointGroups = append(endpointGroups, primaryGroup)
|
||||
|
||||
for _, failTargetID := range failover.Targets {
|
||||
failEndpoints, ok := chainEndpointMap[failTargetID]
|
||||
if !ok {
|
||||
continue // skip the failover target (should not happen)
|
||||
failoverGroup, valid := makeLoadAssignmentEndpointGroup(
|
||||
chain.Targets,
|
||||
cfgSnap.ConnectProxy.WatchedUpstreamEndpoints[id],
|
||||
cfgSnap.ConnectProxy.WatchedGatewayEndpoints[id],
|
||||
failTargetID,
|
||||
cfgSnap.Datacenter,
|
||||
)
|
||||
if !valid {
|
||||
continue // skip the failover target if we're still populating the snapshot
|
||||
}
|
||||
|
||||
failTarget := chain.Targets[failTargetID]
|
||||
|
||||
endpointGroups = append(endpointGroups, loadAssignmentEndpointGroup{
|
||||
Endpoints: failEndpoints,
|
||||
OnlyPassing: failTarget.Subset.OnlyPassing,
|
||||
})
|
||||
endpointGroups = append(endpointGroups, failoverGroup)
|
||||
}
|
||||
} else {
|
||||
endpointGroups = append(endpointGroups, primaryGroup)
|
||||
}
|
||||
|
||||
sni := TargetSNI(target, cfgSnap)
|
||||
clusterName := CustomizeClusterName(sni, chain)
|
||||
|
||||
la := makeLoadAssignment(
|
||||
clusterName,
|
||||
endpointGroups,
|
||||
|
@ -210,8 +224,9 @@ func makeEndpoint(clusterName, host string, port int) envoyendpoint.LbEndpoint {
|
|||
}
|
||||
|
||||
type loadAssignmentEndpointGroup struct {
|
||||
Endpoints structs.CheckServiceNodes
|
||||
OnlyPassing bool
|
||||
Endpoints structs.CheckServiceNodes
|
||||
OnlyPassing bool
|
||||
OverrideHealth envoycore.HealthStatus
|
||||
}
|
||||
|
||||
func makeLoadAssignment(clusterName string, endpointGroups []loadAssignmentEndpointGroup, localDatacenter string) *envoy.ClusterLoadAssignment {
|
||||
|
@ -235,33 +250,12 @@ func makeLoadAssignment(clusterName string, endpointGroups []loadAssignmentEndpo
|
|||
for _, ep := range endpoints {
|
||||
// TODO (mesh-gateway) - should we respect the translate_wan_addrs configuration here or just always use the wan for cross-dc?
|
||||
addr, port := ep.BestAddress(localDatacenter != ep.Node.Datacenter)
|
||||
healthStatus := envoycore.HealthStatus_HEALTHY
|
||||
weight := 1
|
||||
if ep.Service.Weights != nil {
|
||||
weight = ep.Service.Weights.Passing
|
||||
healthStatus, weight := calculateEndpointHealthAndWeight(ep, endpointGroup.OnlyPassing)
|
||||
|
||||
if endpointGroup.OverrideHealth != envoycore.HealthStatus_UNKNOWN {
|
||||
healthStatus = endpointGroup.OverrideHealth
|
||||
}
|
||||
|
||||
for _, chk := range ep.Checks {
|
||||
if chk.Status == api.HealthCritical {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
}
|
||||
if endpointGroup.OnlyPassing && chk.Status != api.HealthPassing {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
}
|
||||
if chk.Status == api.HealthWarning && ep.Service.Weights != nil {
|
||||
weight = ep.Service.Weights.Warning
|
||||
}
|
||||
}
|
||||
// Make weights fit Envoy's limits. A zero weight means that either Warning
|
||||
// (likely) or Passing (weirdly) weight has been set to 0 effectively making
|
||||
// this instance unhealthy and should not be sent traffic.
|
||||
if weight < 1 {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
weight = 1
|
||||
}
|
||||
if weight > 128 {
|
||||
weight = 128
|
||||
}
|
||||
es = append(es, envoyendpoint.LbEndpoint{
|
||||
HostIdentifier: &envoyendpoint.LbEndpoint_Endpoint{
|
||||
Endpoint: &envoyendpoint.Endpoint{
|
||||
|
@ -281,3 +275,89 @@ func makeLoadAssignment(clusterName string, endpointGroups []loadAssignmentEndpo
|
|||
|
||||
return cla
|
||||
}
|
||||
|
||||
func makeLoadAssignmentEndpointGroup(
|
||||
targets map[string]*structs.DiscoveryTarget,
|
||||
targetHealth map[string]structs.CheckServiceNodes,
|
||||
gatewayHealth map[string]structs.CheckServiceNodes,
|
||||
targetID string,
|
||||
currentDatacenter string,
|
||||
) (loadAssignmentEndpointGroup, bool) {
|
||||
realEndpoints, ok := targetHealth[targetID]
|
||||
if !ok {
|
||||
// skip the cluster if we're still populating the snapshot
|
||||
return loadAssignmentEndpointGroup{}, false
|
||||
}
|
||||
target := targets[targetID]
|
||||
|
||||
var gatewayDatacenter string
|
||||
switch target.MeshGateway.Mode {
|
||||
case structs.MeshGatewayModeRemote:
|
||||
gatewayDatacenter = target.Datacenter
|
||||
case structs.MeshGatewayModeLocal:
|
||||
gatewayDatacenter = currentDatacenter
|
||||
}
|
||||
|
||||
if gatewayDatacenter == "" {
|
||||
return loadAssignmentEndpointGroup{
|
||||
Endpoints: realEndpoints,
|
||||
OnlyPassing: target.Subset.OnlyPassing,
|
||||
}, true
|
||||
}
|
||||
|
||||
// If using a mesh gateway we need to pull those endpoints instead.
|
||||
gatewayEndpoints, ok := gatewayHealth[gatewayDatacenter]
|
||||
if !ok {
|
||||
// skip the cluster if we're still populating the snapshot
|
||||
return loadAssignmentEndpointGroup{}, false
|
||||
}
|
||||
|
||||
// But we will use the health from the actual backend service.
|
||||
overallHealth := envoycore.HealthStatus_UNHEALTHY
|
||||
for _, ep := range realEndpoints {
|
||||
health, _ := calculateEndpointHealthAndWeight(ep, target.Subset.OnlyPassing)
|
||||
if health == envoycore.HealthStatus_HEALTHY {
|
||||
overallHealth = envoycore.HealthStatus_HEALTHY
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return loadAssignmentEndpointGroup{
|
||||
Endpoints: gatewayEndpoints,
|
||||
OverrideHealth: overallHealth,
|
||||
}, true
|
||||
}
|
||||
|
||||
func calculateEndpointHealthAndWeight(
|
||||
ep structs.CheckServiceNode,
|
||||
onlyPassing bool,
|
||||
) (envoycore.HealthStatus, int) {
|
||||
healthStatus := envoycore.HealthStatus_HEALTHY
|
||||
weight := 1
|
||||
if ep.Service.Weights != nil {
|
||||
weight = ep.Service.Weights.Passing
|
||||
}
|
||||
|
||||
for _, chk := range ep.Checks {
|
||||
if chk.Status == api.HealthCritical {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
}
|
||||
if onlyPassing && chk.Status != api.HealthPassing {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
}
|
||||
if chk.Status == api.HealthWarning && ep.Service.Weights != nil {
|
||||
weight = ep.Service.Weights.Warning
|
||||
}
|
||||
}
|
||||
// Make weights fit Envoy's limits. A zero weight means that either Warning
|
||||
// (likely) or Passing (weirdly) weight has been set to 0 effectively making
|
||||
// this instance unhealthy and should not be sent traffic.
|
||||
if weight < 1 {
|
||||
healthStatus = envoycore.HealthStatus_UNHEALTHY
|
||||
weight = 1
|
||||
}
|
||||
if weight > 128 {
|
||||
weight = 128
|
||||
}
|
||||
return healthStatus, weight
|
||||
}
|
||||
|
|
|
@ -253,6 +253,46 @@ func Test_endpointsFromSnapshot(t *testing.T) {
|
|||
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: "splitter-with-resolver-redirect",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChain_SplitterWithResolverRedirectMultiDC,
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package xds
|
||||
|
||||
import (
|
||||
envoycore "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
func firstHealthyTarget(
|
||||
targets map[string]*structs.DiscoveryTarget,
|
||||
targetHealth map[string]structs.CheckServiceNodes,
|
||||
primaryTarget string,
|
||||
secondaryTargets []string,
|
||||
) string {
|
||||
series := make([]string, 0, len(secondaryTargets)+1)
|
||||
series = append(series, primaryTarget)
|
||||
series = append(series, secondaryTargets...)
|
||||
|
||||
for _, targetID := range series {
|
||||
target, ok := targets[targetID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
endpoints, ok := targetHealth[targetID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, ep := range endpoints {
|
||||
healthStatus, _ := calculateEndpointHealthAndWeight(ep, target.Subset.OnlyPassing)
|
||||
if healthStatus == envoycore.HealthStatus_HEALTHY {
|
||||
return targetID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return primaryTarget // if everything is broken just use the primary for now
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package xds
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFirstHealthyTarget(t *testing.T) {
|
||||
passing := proxycfg.TestUpstreamNodesInStatus(t, "passing")
|
||||
warning := proxycfg.TestUpstreamNodesInStatus(t, "warning")
|
||||
critical := proxycfg.TestUpstreamNodesInStatus(t, "critical")
|
||||
|
||||
warnOnlyPassingTarget := structs.NewDiscoveryTarget("all-warn", "", "default", "dc1")
|
||||
warnOnlyPassingTarget.Subset.OnlyPassing = true
|
||||
failOnlyPassingTarget := structs.NewDiscoveryTarget("all-fail", "", "default", "dc1")
|
||||
failOnlyPassingTarget.Subset.OnlyPassing = true
|
||||
|
||||
targets := map[string]*structs.DiscoveryTarget{
|
||||
"all-ok.default.dc1": structs.NewDiscoveryTarget("all-ok", "", "default", "dc1"),
|
||||
"all-warn.default.dc1": structs.NewDiscoveryTarget("all-warn", "", "default", "dc1"),
|
||||
"all-fail.default.dc1": structs.NewDiscoveryTarget("all-fail", "", "default", "dc1"),
|
||||
"all-warn-onlypassing.default.dc1": warnOnlyPassingTarget,
|
||||
"all-fail-onlypassing.default.dc1": failOnlyPassingTarget,
|
||||
}
|
||||
targetHealth := map[string]structs.CheckServiceNodes{
|
||||
"all-ok.default.dc1": passing,
|
||||
"all-warn.default.dc1": warning,
|
||||
"all-fail.default.dc1": critical,
|
||||
"all-warn-onlypassing.default.dc1": warning,
|
||||
"all-fail-onlypassing.default.dc1": critical,
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
primary string
|
||||
secondary []string
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
primary: "all-ok.default.dc1",
|
||||
expect: "all-ok.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-warn.default.dc1",
|
||||
expect: "all-warn.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-fail.default.dc1",
|
||||
expect: "all-fail.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-warn-onlypassing.default.dc1",
|
||||
expect: "all-warn-onlypassing.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-fail-onlypassing.default.dc1",
|
||||
expect: "all-fail-onlypassing.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-ok.default.dc1",
|
||||
secondary: []string{
|
||||
"all-warn.default.dc1",
|
||||
},
|
||||
expect: "all-ok.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-warn.default.dc1",
|
||||
secondary: []string{
|
||||
"all-ok.default.dc1",
|
||||
},
|
||||
expect: "all-warn.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-warn-onlypassing.default.dc1",
|
||||
secondary: []string{
|
||||
"all-ok.default.dc1",
|
||||
},
|
||||
expect: "all-ok.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-fail.default.dc1",
|
||||
secondary: []string{
|
||||
"all-ok.default.dc1",
|
||||
},
|
||||
expect: "all-ok.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-fail-onlypassing.default.dc1",
|
||||
secondary: []string{
|
||||
"all-ok.default.dc1",
|
||||
},
|
||||
expect: "all-ok.default.dc1",
|
||||
},
|
||||
{
|
||||
primary: "all-fail.default.dc1",
|
||||
secondary: []string{
|
||||
"all-warn-onlypassing.default.dc1",
|
||||
"all-warn.default.dc1",
|
||||
"all-ok.default.dc1",
|
||||
},
|
||||
expect: "all-warn.default.dc1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
name := fmt.Sprintf("%s and %v", tc.primary, tc.secondary)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
targetID := firstHealthyTarget(targets, targetHealth, tc.primary, tc.secondary)
|
||||
require.Equal(t, tc.expect, targetID)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -189,6 +189,16 @@ func TestListenersFromSnapshot(t *testing.T) {
|
|||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithOverrides,
|
||||
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-local-gateway",
|
||||
create: proxycfg.TestConfigSnapshotDiscoveryChainWithFailoverThroughLocalGateway,
|
||||
setup: nil,
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway",
|
||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.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",
|
||||
"name": "a236e964:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "a236e964:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc3.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc3.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
116
agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
116
agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
116
agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
116
agent/xds/testdata/clusters/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "33s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
},
|
||||
"commonLbConfig": {
|
||||
"healthyPanicThreshold": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"tlsContext": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul"
|
||||
},
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"name": "local_app",
|
||||
"type": "STATIC",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "local_app",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "78ebd528:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"clusterName": "a236e964:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "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.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "198.38.1.1",
|
||||
"portValue": 443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "198.38.1.2",
|
||||
"portValue": 443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "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.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.1",
|
||||
"portValue": 8443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "10.10.1.2",
|
||||
"portValue": 8443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
41
agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
41
agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "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.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "198.18.1.1",
|
||||
"portValue": 443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "198.18.1.2",
|
||||
"portValue": 443
|
||||
}
|
||||
}
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"loadBalancingWeight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
41
agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
41
agent/xds/testdata/endpoints/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||
"clusterName": "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.api.v2.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
116
agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
116
agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-local-gateway.golden
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "db:127.0.0.1:9191",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 9191
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "upstream_db_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "prepared_query:geo-cache:127.10.10.10:8181",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.10.10.10",
|
||||
"portValue": 8181
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"stat_prefix": "upstream_prepared_query_geo-cache_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "public_listener:0.0.0.0:9999",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "0.0.0.0",
|
||||
"portValue": 9999
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"tlsContext": {
|
||||
"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
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "local_app",
|
||||
"stat_prefix": "public_listener_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
116
agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
116
agent/xds/testdata/listeners/connect-proxy-with-tcp-chain-failover-through-remote-gateway.golden
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "db:127.0.0.1:9191",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.0.0.1",
|
||||
"portValue": 9191
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "",
|
||||
"stat_prefix": "upstream_db_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "prepared_query:geo-cache:127.10.10.10:8181",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "127.10.10.10",
|
||||
"portValue": 8181
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul",
|
||||
"stat_prefix": "upstream_prepared_query_geo-cache_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"name": "public_listener:0.0.0.0:9999",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "0.0.0.0",
|
||||
"portValue": 9999
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"tlsContext": {
|
||||
"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
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.ext_authz",
|
||||
"config": {
|
||||
"grpc_service": {
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "local_agent"
|
||||
},
|
||||
"initial_metadata": [
|
||||
{
|
||||
"key": "x-consul-token",
|
||||
"value": "my-token"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stat_prefix": "connect_authz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.tcp_proxy",
|
||||
"config": {
|
||||
"cluster": "local_app",
|
||||
"stat_prefix": "public_listener_tcp"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.api.v2.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
"prefix": "/"
|
||||
},
|
||||
"route": {
|
||||
"cluster": "78ebd528:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
"cluster": "a236e964:db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
bind_addr = "0.0.0.0"
|
||||
advertise_addr = "{{ GetInterfaceIP \"eth0\" }}"
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
snapshot_envoy_admin localhost:19000 s1 primary || true
|
||||
snapshot_envoy_admin localhost:19001 s2 primary || true
|
||||
snapshot_envoy_admin localhost:19002 s2 secondary || true
|
||||
snapshot_envoy_admin localhost:19003 mesh-gateway secondary || true
|
|
@ -0,0 +1,25 @@
|
|||
enable_central_service_config = true
|
||||
|
||||
config_entries {
|
||||
bootstrap {
|
||||
kind = "service-defaults"
|
||||
name = "s2"
|
||||
|
||||
protocol = "http"
|
||||
|
||||
mesh_gateway {
|
||||
mode = "none"
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap {
|
||||
kind = "service-resolver"
|
||||
name = "s2"
|
||||
|
||||
failover = {
|
||||
"*" = {
|
||||
datacenters = ["secondary"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eEuo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry service-defaults s2
|
||||
wait_for_config_entry service-resolver s2
|
||||
|
||||
# also wait for replication to make it to the remote dc
|
||||
wait_for_config_entry service-defaults s2 secondary
|
||||
wait_for_config_entry service-resolver s2 secondary
|
||||
|
||||
gen_envoy_bootstrap s1 19000 primary
|
||||
gen_envoy_bootstrap s2 19001 primary
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "s1 proxy is running correct version" {
|
||||
assert_envoy_version 19000
|
||||
}
|
||||
|
||||
@test "s1 proxy admin is up on :19000" {
|
||||
retry_default curl -f -s localhost:19000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19001" {
|
||||
retry_default curl -f -s localhost:19001/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s1
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21001 s2
|
||||
}
|
||||
|
||||
@test "s2 proxies should be healthy in primary" {
|
||||
assert_service_has_healthy_instances s2 1 primary
|
||||
}
|
||||
|
||||
@test "s2 proxies should be healthy in secondary" {
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
################
|
||||
# PHASE 1: we show that by default requests are served from the primary
|
||||
|
||||
# Note: when failover is configured the cluster is named for the original
|
||||
# service not any destination related to failover.
|
||||
@test "s1 upstream should have healthy endpoints for s2 in both primary and failover" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 2
|
||||
}
|
||||
|
||||
@test "s1 upstream should be able to connect to s2 via upstream s2 to start" {
|
||||
assert_expected_fortio_name s2
|
||||
}
|
||||
|
||||
@test "s1 upstream made 1 connection" {
|
||||
assert_envoy_metric 127.0.0.1:19000 "cluster.s2.default.primary.*cx_total" 1
|
||||
}
|
||||
|
||||
################
|
||||
# PHASE 2: we show that in failover requests are served from the secondary
|
||||
#
|
||||
@test "terminate instance of s2 primary envoy which should trigger failover to s2 secondary when tcp check fails" {
|
||||
kill_envoy s2 primary
|
||||
}
|
||||
|
||||
@test "s2 proxies should be unhealthy in primary" {
|
||||
assert_service_has_healthy_instances s2 0 primary
|
||||
}
|
||||
|
||||
@test "s1 upstream should have healthy endpoints for s2 secondary and unhealthy endpoints for s2 primary" {
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary UNHEALTHY 1
|
||||
}
|
||||
|
||||
@test "s1 upstream should be able to connect to s2 in secondary now" {
|
||||
assert_expected_fortio_name s2-secondary
|
||||
}
|
||||
|
||||
@test "s1 upstream made 2 connections" {
|
||||
assert_envoy_metric 127.0.0.1:19000 "cluster.s2.default.primary.*cx_total" 2
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
services {
|
||||
name = "mesh-gateway"
|
||||
kind = "mesh-gateway"
|
||||
port = 4432
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
retry_join_wan = ["consul-primary"]
|
|
@ -0,0 +1 @@
|
|||
# we don't want an s1 service in the secondary dc
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eEuo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry service-defaults s2 secondary
|
||||
wait_for_config_entry service-resolver s2 secondary
|
||||
|
||||
gen_envoy_bootstrap s2 19002 secondary
|
||||
gen_envoy_bootstrap mesh-gateway 19003 secondary true
|
||||
retry_default docker_consul secondary curl -s "http://localhost:8500/v1/catalog/service/consul?dc=primary" >/dev/null
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "s2 proxy is running correct version" {
|
||||
assert_envoy_version 19002
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19002" {
|
||||
retry_default curl -f -s localhost:19002/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "gateway-secondary proxy admin is up on :19003" {
|
||||
retry_default curl -f -s localhost:19003/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s2 secondary
|
||||
}
|
||||
|
||||
@test "s2 proxy should be healthy" {
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
@test "gateway-secondary is NOT used for the upstream connection" {
|
||||
assert_envoy_metric 127.0.0.1:19003 "cluster.s2.default.secondary.*cx_total" 0
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
export REQUIRED_SERVICES="
|
||||
s1 s1-sidecar-proxy
|
||||
s2 s2-sidecar-proxy
|
||||
s2-secondary s2-sidecar-proxy-secondary
|
||||
gateway-secondary
|
||||
"
|
||||
export REQUIRE_SECONDARY=1
|
|
@ -0,0 +1,2 @@
|
|||
bind_addr = "0.0.0.0"
|
||||
advertise_addr = "{{ GetInterfaceIP \"eth0\" }}"
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
snapshot_envoy_admin localhost:19000 s1 primary || true
|
||||
snapshot_envoy_admin localhost:19001 s2 primary || true
|
||||
snapshot_envoy_admin localhost:19002 s2 secondary || true
|
||||
snapshot_envoy_admin localhost:19003 mesh-gateway secondary || true
|
|
@ -0,0 +1,25 @@
|
|||
enable_central_service_config = true
|
||||
|
||||
config_entries {
|
||||
bootstrap {
|
||||
kind = "service-defaults"
|
||||
name = "s2"
|
||||
|
||||
protocol = "http"
|
||||
|
||||
mesh_gateway {
|
||||
mode = "remote"
|
||||
}
|
||||
}
|
||||
|
||||
bootstrap {
|
||||
kind = "service-resolver"
|
||||
name = "s2"
|
||||
|
||||
failover = {
|
||||
"*" = {
|
||||
datacenters = ["secondary"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eEuo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry service-defaults s2
|
||||
wait_for_config_entry service-resolver s2
|
||||
|
||||
# also wait for replication to make it to the remote dc
|
||||
wait_for_config_entry service-defaults s2 secondary
|
||||
wait_for_config_entry service-resolver s2 secondary
|
||||
|
||||
gen_envoy_bootstrap s1 19000 primary
|
||||
gen_envoy_bootstrap s2 19001 primary
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "s1 proxy is running correct version" {
|
||||
assert_envoy_version 19000
|
||||
}
|
||||
|
||||
@test "s1 proxy admin is up on :19000" {
|
||||
retry_default curl -f -s localhost:19000/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19001" {
|
||||
retry_default curl -f -s localhost:19001/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s1 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s1
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21001 s2
|
||||
}
|
||||
|
||||
@test "s2 proxies should be healthy in primary" {
|
||||
assert_service_has_healthy_instances s2 1 primary
|
||||
}
|
||||
|
||||
@test "s2 proxies should be healthy in secondary" {
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
################
|
||||
# PHASE 1: we show that by default requests are served from the primary
|
||||
|
||||
# Note: when failover is configured the cluster is named for the original
|
||||
# service not any destination related to failover.
|
||||
@test "s1 upstream should have healthy endpoints for s2 in both primary and failover" {
|
||||
# in mesh gateway remote or local mode only the current leg of failover manifests in the load assignments
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary UNHEALTHY 0
|
||||
}
|
||||
|
||||
@test "s1 upstream should be able to connect to s2 via upstream s2 to start" {
|
||||
assert_expected_fortio_name s2
|
||||
}
|
||||
|
||||
@test "s1 upstream made 1 connection" {
|
||||
assert_envoy_metric 127.0.0.1:19000 "cluster.s2.default.primary.*cx_total" 1
|
||||
}
|
||||
|
||||
################
|
||||
# PHASE 2: we show that in failover requests are served from the secondary
|
||||
#
|
||||
@test "terminate instance of s2 primary envoy which should trigger failover to s2 secondary when tcp check fails" {
|
||||
kill_envoy s2 primary
|
||||
}
|
||||
|
||||
@test "s2 proxies should be unhealthy in primary" {
|
||||
assert_service_has_healthy_instances s2 0 primary
|
||||
}
|
||||
|
||||
@test "s1 upstream should have healthy endpoints for s2 secondary" {
|
||||
# in mesh gateway remote or local mode only the current leg of failover manifests in the load assignments
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary HEALTHY 1
|
||||
assert_upstream_has_endpoints_in_status 127.0.0.1:19000 s2.default.primary UNHEALTHY 0
|
||||
}
|
||||
|
||||
@test "s1 upstream should be able to connect to s2 in secondary now" {
|
||||
assert_expected_fortio_name s2-secondary
|
||||
}
|
||||
|
||||
@test "s1 upstream made 2 connections" {
|
||||
assert_envoy_metric 127.0.0.1:19000 "cluster.s2.default.primary.*cx_total" 2
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
services {
|
||||
name = "mesh-gateway"
|
||||
kind = "mesh-gateway"
|
||||
port = 4432
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
retry_join_wan = ["consul-primary"]
|
|
@ -0,0 +1 @@
|
|||
# we don't want an s1 service in the secondary dc
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eEuo pipefail
|
||||
|
||||
# wait for bootstrap to apply config entries
|
||||
wait_for_config_entry service-defaults s2 secondary
|
||||
wait_for_config_entry service-resolver s2 secondary
|
||||
|
||||
gen_envoy_bootstrap s2 19002 secondary
|
||||
gen_envoy_bootstrap mesh-gateway 19003 secondary true
|
||||
retry_default docker_consul secondary curl -s "http://localhost:8500/v1/catalog/service/consul?dc=primary" >/dev/null
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "s2 proxy is running correct version" {
|
||||
assert_envoy_version 19002
|
||||
}
|
||||
|
||||
@test "s2 proxy admin is up on :19002" {
|
||||
retry_default curl -f -s localhost:19002/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "gateway-secondary proxy admin is up on :19003" {
|
||||
retry_default curl -f -s localhost:19003/stats -o /dev/null
|
||||
}
|
||||
|
||||
@test "s2 proxy listener should be up and have right cert" {
|
||||
assert_proxy_presents_cert_uri localhost:21000 s2 secondary
|
||||
}
|
||||
|
||||
@test "s2 proxy should be healthy" {
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
@test "gateway-secondary is used for the upstream connection" {
|
||||
assert_envoy_metric 127.0.0.1:19003 "cluster.s2.default.secondary.*cx_total" 1
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
export REQUIRED_SERVICES="
|
||||
s1 s1-sidecar-proxy
|
||||
s2 s2-sidecar-proxy
|
||||
s2-secondary s2-sidecar-proxy-secondary
|
||||
gateway-secondary
|
||||
"
|
||||
export REQUIRE_SECONDARY=1
|
|
@ -19,9 +19,9 @@ load helpers
|
|||
}
|
||||
|
||||
@test "s2 proxy should be healthy" {
|
||||
assert_service_has_healthy_instances s2 1
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
@test "gateway-secondary is used for the upstream connection" {
|
||||
assert_envoy_metric 127.0.0.1:19003 "cluster.s2.default.secondary.*cx_total" 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@ load helpers
|
|||
}
|
||||
|
||||
@test "s2 proxy should be healthy" {
|
||||
assert_service_has_healthy_instances s2 1
|
||||
assert_service_has_healthy_instances s2 1 secondary
|
||||
}
|
||||
|
||||
@test "gateway-secondary is used for the upstream connection" {
|
||||
assert_envoy_metric 127.0.0.1:19003 "cluster.s2.default.secondary.*cx_total" 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -413,7 +413,7 @@ services:
|
|||
- consul-secondary
|
||||
image: "fortio/fortio"
|
||||
environment:
|
||||
- "FORTIO_NAME=s1"
|
||||
- "FORTIO_NAME=s1-secondary"
|
||||
command:
|
||||
- "server"
|
||||
- "-http-port"
|
||||
|
@ -429,7 +429,7 @@ services:
|
|||
- consul-secondary
|
||||
image: "fortio/fortio"
|
||||
environment:
|
||||
- "FORTIO_NAME=s2"
|
||||
- "FORTIO_NAME=s2-secondary"
|
||||
command:
|
||||
- "server"
|
||||
- "-http-port"
|
||||
|
@ -556,4 +556,4 @@ services:
|
|||
volumes:
|
||||
- *workdir-volume
|
||||
network_mode: service:consul-secondary
|
||||
pid: host
|
||||
pid: host
|
||||
|
|
|
@ -246,7 +246,8 @@ function assert_envoy_metric {
|
|||
|
||||
function get_healthy_service_count {
|
||||
local SERVICE_NAME=$1
|
||||
run retry_default curl -s -f 127.0.0.1:8500/v1/health/connect/${SERVICE_NAME}?passing
|
||||
local DC=$2
|
||||
run retry_default curl -s -f "127.0.0.1:8500/v1/health/connect/${SERVICE_NAME}?dc=${DC}&passing"
|
||||
[ "$status" -eq 0 ]
|
||||
echo "$output" | jq --raw-output '. | length'
|
||||
}
|
||||
|
@ -254,8 +255,9 @@ function get_healthy_service_count {
|
|||
function assert_service_has_healthy_instances_once {
|
||||
local SERVICE_NAME=$1
|
||||
local EXPECT_COUNT=$2
|
||||
local DC=${3:-primary}
|
||||
|
||||
GOT_COUNT=$(get_healthy_service_count $SERVICE_NAME)
|
||||
GOT_COUNT=$(get_healthy_service_count $SERVICE_NAME $DC)
|
||||
|
||||
[ "$GOT_COUNT" -eq $EXPECT_COUNT ]
|
||||
}
|
||||
|
@ -263,8 +265,9 @@ function assert_service_has_healthy_instances_once {
|
|||
function assert_service_has_healthy_instances {
|
||||
local SERVICE_NAME=$1
|
||||
local EXPECT_COUNT=$2
|
||||
local DC=${3:-primary}
|
||||
|
||||
run retry_long assert_service_has_healthy_instances_once $SERVICE_NAME $EXPECT_COUNT
|
||||
run retry_long assert_service_has_healthy_instances_once $SERVICE_NAME $EXPECT_COUNT $DC
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
|
@ -444,7 +447,9 @@ function assert_expected_fortio_name {
|
|||
local EXPECT_NAME=$1
|
||||
|
||||
GOT=$(get_upstream_fortio_name)
|
||||
echo "GOT $GOT"
|
||||
|
||||
[ "$GOT" == "FORTIO_NAME=${EXPECT_NAME}" ]
|
||||
if [ "$GOT" != "FORTIO_NAME=${EXPECT_NAME}" ]; then
|
||||
echo "expected name: $EXPECT_NAME, actual name: $GOT" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue