Merge pull request #6053 from hashicorp/gateways_and_resolvers
Integrate Mesh Gateways with ServiceResolverSubsets
This commit is contained in:
commit
c49f2fb9b8
|
@ -3954,6 +3954,15 @@ func (a *Agent) registerCache() {
|
||||||
RefreshTimer: 0 * time.Second,
|
RefreshTimer: 0 * time.Second,
|
||||||
RefreshTimeout: 10 * time.Minute,
|
RefreshTimeout: 10 * time.Minute,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
a.cache.RegisterType(cachetype.ConfigEntriesName, &cachetype.ConfigEntries{
|
||||||
|
RPC: a,
|
||||||
|
}, &cache.RegisterOptions{
|
||||||
|
// Maintain a blocking query, retry dropped connections quickly
|
||||||
|
Refresh: true,
|
||||||
|
RefreshTimer: 0 * time.Second,
|
||||||
|
RefreshTimeout: 10 * time.Minute,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultProxyCommand returns the default Connect managed proxy command.
|
// defaultProxyCommand returns the default Connect managed proxy command.
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package cachetype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/cache"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Recommended name for registration.
|
||||||
|
const ConfigEntriesName = "config-entries"
|
||||||
|
|
||||||
|
// ConfigEntries supports fetching discovering configuration entries
|
||||||
|
type ConfigEntries struct {
|
||||||
|
RPC RPC
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigEntries) Fetch(opts cache.FetchOptions, req cache.Request) (cache.FetchResult, error) {
|
||||||
|
var result cache.FetchResult
|
||||||
|
|
||||||
|
// The request should be a ConfigEntryQuery.
|
||||||
|
reqReal, ok := req.(*structs.ConfigEntryQuery)
|
||||||
|
if !ok {
|
||||||
|
return result, fmt.Errorf(
|
||||||
|
"Internal cache failure: request wrong type: %T", req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the minimum query index to our current index so we block
|
||||||
|
reqReal.QueryOptions.MinQueryIndex = opts.MinIndex
|
||||||
|
reqReal.QueryOptions.MaxQueryTime = opts.Timeout
|
||||||
|
|
||||||
|
// Always allow stale - there's no point in hitting leader if the request is
|
||||||
|
// going to be served from cache and endup arbitrarily stale anyway. This
|
||||||
|
// allows cached service-discover to automatically read scale across all
|
||||||
|
// servers too.
|
||||||
|
reqReal.AllowStale = true
|
||||||
|
|
||||||
|
// Fetch
|
||||||
|
var reply structs.IndexedConfigEntries
|
||||||
|
if err := c.RPC.RPC("ConfigEntry.List", reqReal, &reply); err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Value = &reply
|
||||||
|
result.Index = reply.QueryMeta.Index
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigEntries) SupportsBlocking() bool {
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package cachetype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/cache"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigEntries(t *testing.T) {
|
||||||
|
rpc := TestRPC(t)
|
||||||
|
typ := &ConfigEntries{RPC: rpc}
|
||||||
|
|
||||||
|
// Expect the proper RPC call. This also sets the expected value
|
||||||
|
// since that is return-by-pointer in the arguments.
|
||||||
|
var resp *structs.IndexedConfigEntries
|
||||||
|
rpc.On("RPC", "ConfigEntry.List", mock.Anything, mock.Anything).Return(nil).
|
||||||
|
Run(func(args mock.Arguments) {
|
||||||
|
req := args.Get(1).(*structs.ConfigEntryQuery)
|
||||||
|
require.Equal(t, uint64(24), req.QueryOptions.MinQueryIndex)
|
||||||
|
require.Equal(t, 1*time.Second, req.QueryOptions.MaxQueryTime)
|
||||||
|
require.True(t, req.AllowStale)
|
||||||
|
require.Equal(t, structs.ServiceResolver, req.Kind)
|
||||||
|
require.Equal(t, "", req.Name)
|
||||||
|
|
||||||
|
reply := args.Get(2).(*structs.IndexedConfigEntries)
|
||||||
|
reply.Kind = structs.ServiceResolver
|
||||||
|
reply.Entries = []structs.ConfigEntry{
|
||||||
|
&structs.ServiceResolverConfigEntry{Kind: structs.ServiceResolver, Name: "foo"},
|
||||||
|
&structs.ServiceResolverConfigEntry{Kind: structs.ServiceResolver, Name: "bar"},
|
||||||
|
}
|
||||||
|
reply.QueryMeta.Index = 48
|
||||||
|
resp = reply
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fetch
|
||||||
|
resultA, err := typ.Fetch(cache.FetchOptions{
|
||||||
|
MinIndex: 24,
|
||||||
|
Timeout: 1 * time.Second,
|
||||||
|
}, &structs.ConfigEntryQuery{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, cache.FetchResult{
|
||||||
|
Value: resp,
|
||||||
|
Index: 48,
|
||||||
|
}, resultA)
|
||||||
|
|
||||||
|
rpc.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigEntries_badReqType(t *testing.T) {
|
||||||
|
rpc := TestRPC(t)
|
||||||
|
typ := &ConfigEntries{RPC: rpc}
|
||||||
|
|
||||||
|
// Fetch
|
||||||
|
_, err := typ.Fetch(cache.FetchOptions{}, cache.TestRequest(
|
||||||
|
t, cache.RequestInfo{Key: "foo", MinIndex: 64}))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "wrong type")
|
||||||
|
rpc.AssertExpectations(t)
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ type configSnapshotMeshGateway struct {
|
||||||
WatchedServices map[string]context.CancelFunc
|
WatchedServices map[string]context.CancelFunc
|
||||||
WatchedDatacenters map[string]context.CancelFunc
|
WatchedDatacenters map[string]context.CancelFunc
|
||||||
ServiceGroups map[string]structs.CheckServiceNodes
|
ServiceGroups map[string]structs.CheckServiceNodes
|
||||||
|
ServiceResolvers map[string]*structs.ServiceResolverConfigEntry
|
||||||
GatewayGroups map[string]structs.CheckServiceNodes
|
GatewayGroups map[string]structs.CheckServiceNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ const (
|
||||||
intentionsWatchID = "intentions"
|
intentionsWatchID = "intentions"
|
||||||
serviceListWatchID = "service-list"
|
serviceListWatchID = "service-list"
|
||||||
datacentersWatchID = "datacenters"
|
datacentersWatchID = "datacenters"
|
||||||
|
serviceResolversWatchID = "service-resolvers"
|
||||||
serviceIDPrefix = string(structs.UpstreamDestTypeService) + ":"
|
serviceIDPrefix = string(structs.UpstreamDestTypeService) + ":"
|
||||||
preparedQueryIDPrefix = string(structs.UpstreamDestTypePreparedQuery) + ":"
|
preparedQueryIDPrefix = string(structs.UpstreamDestTypePreparedQuery) + ":"
|
||||||
defaultPreparedQueryPollInterval = 30 * time.Second
|
defaultPreparedQueryPollInterval = 30 * time.Second
|
||||||
|
@ -347,9 +348,10 @@ func (s *state) run() {
|
||||||
case structs.ServiceKindMeshGateway:
|
case structs.ServiceKindMeshGateway:
|
||||||
snap.MeshGateway.WatchedServices = make(map[string]context.CancelFunc)
|
snap.MeshGateway.WatchedServices = make(map[string]context.CancelFunc)
|
||||||
snap.MeshGateway.WatchedDatacenters = make(map[string]context.CancelFunc)
|
snap.MeshGateway.WatchedDatacenters = make(map[string]context.CancelFunc)
|
||||||
// TODO (mesh-gateway) - maybe reuse UpstreamEndpoints?
|
|
||||||
snap.MeshGateway.ServiceGroups = make(map[string]structs.CheckServiceNodes)
|
snap.MeshGateway.ServiceGroups = make(map[string]structs.CheckServiceNodes)
|
||||||
snap.MeshGateway.GatewayGroups = make(map[string]structs.CheckServiceNodes)
|
snap.MeshGateway.GatewayGroups = make(map[string]structs.CheckServiceNodes)
|
||||||
|
// there is no need to initialize the map of service resolvers as we
|
||||||
|
// fully rebuild it every time we get updates
|
||||||
}
|
}
|
||||||
|
|
||||||
// This turns out to be really fiddly/painful by just using time.Timer.C
|
// This turns out to be really fiddly/painful by just using time.Timer.C
|
||||||
|
@ -675,7 +677,17 @@ func (s *state) handleUpdateMeshGateway(u cache.UpdateEvent, snap *ConfigSnapsho
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (mesh-gateway) also should watch the resolver config for the service here
|
err = s.cache.Notify(ctx, cachetype.ConfigEntriesName, &structs.ConfigEntryQuery{
|
||||||
|
Datacenter: s.source.Datacenter,
|
||||||
|
QueryOptions: structs.QueryOptions{Token: s.token},
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
}, serviceResolversWatchID, s.ch)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("[ERR] mesh-gateway: failed to register watch for service-resolver config entries")
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
snap.MeshGateway.WatchedServices[svcName] = cancel
|
snap.MeshGateway.WatchedServices[svcName] = cancel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -735,6 +747,19 @@ func (s *state) handleUpdateMeshGateway(u cache.UpdateEvent, snap *ConfigSnapsho
|
||||||
cancelFn()
|
cancelFn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case serviceResolversWatchID:
|
||||||
|
configEntries, ok := u.Result.(*structs.IndexedConfigEntries)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid type for services response: %T", u.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvers := make(map[string]*structs.ServiceResolverConfigEntry)
|
||||||
|
for _, entry := range configEntries.Entries {
|
||||||
|
if resolver, ok := entry.(*structs.ServiceResolverConfigEntry); ok {
|
||||||
|
resolvers[resolver.Name] = resolver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snap.MeshGateway.ServiceResolvers = resolvers
|
||||||
default:
|
default:
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(u.CorrelationID, "connect-service:"):
|
case strings.HasPrefix(u.CorrelationID, "connect-service:"):
|
||||||
|
|
|
@ -2,6 +2,7 @@ package proxycfg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
@ -85,7 +86,7 @@ func TestCerts(t testing.T) (*structs.IndexedCARoots, *structs.IssuedCert) {
|
||||||
ca := connect.TestCA(t, nil)
|
ca := connect.TestCA(t, nil)
|
||||||
roots := &structs.IndexedCARoots{
|
roots := &structs.IndexedCARoots{
|
||||||
ActiveRootID: ca.ID,
|
ActiveRootID: ca.ID,
|
||||||
TrustDomain: connect.TestClusterID,
|
TrustDomain: fmt.Sprintf("%s.consul", connect.TestClusterID),
|
||||||
Roots: []*structs.CARoot{ca},
|
Roots: []*structs.CARoot{ca},
|
||||||
}
|
}
|
||||||
return roots, TestLeafForCA(t, ca)
|
return roots, TestLeafForCA(t, ca)
|
||||||
|
@ -183,7 +184,75 @@ func TestGatewayNodesDC2(t testing.T) structs.CheckServiceNodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGatewayServicesDC1(t testing.T) structs.CheckServiceNodes {
|
func TestGatewayServiceGroupBarDC1(t testing.T) structs.CheckServiceNodes {
|
||||||
|
return structs.CheckServiceNodes{
|
||||||
|
structs.CheckServiceNode{
|
||||||
|
Node: &structs.Node{
|
||||||
|
ID: "bar-node-1",
|
||||||
|
Node: "bar-node-1",
|
||||||
|
Address: "10.1.1.4",
|
||||||
|
Datacenter: "dc1",
|
||||||
|
},
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "bar-sidecar-proxy",
|
||||||
|
Address: "172.16.1.6",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "1",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "bar",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
structs.CheckServiceNode{
|
||||||
|
Node: &structs.Node{
|
||||||
|
ID: "bar-node-2",
|
||||||
|
Node: "bar-node-2",
|
||||||
|
Address: "10.1.1.5",
|
||||||
|
Datacenter: "dc1",
|
||||||
|
},
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "bar-sidecar-proxy",
|
||||||
|
Address: "172.16.1.7",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "1",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "bar",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
structs.CheckServiceNode{
|
||||||
|
Node: &structs.Node{
|
||||||
|
ID: "bar-node-3",
|
||||||
|
Node: "bar-node-3",
|
||||||
|
Address: "10.1.1.6",
|
||||||
|
Datacenter: "dc1",
|
||||||
|
},
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "bar-sidecar-proxy",
|
||||||
|
Address: "172.16.1.8",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "2",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "bar",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGatewayServiceGroupFooDC1(t testing.T) structs.CheckServiceNodes {
|
||||||
return structs.CheckServiceNodes{
|
return structs.CheckServiceNodes{
|
||||||
structs.CheckServiceNode{
|
structs.CheckServiceNode{
|
||||||
Node: &structs.Node{
|
Node: &structs.Node{
|
||||||
|
@ -192,7 +261,19 @@ func TestGatewayServicesDC1(t testing.T) structs.CheckServiceNodes {
|
||||||
Address: "10.1.1.1",
|
Address: "10.1.1.1",
|
||||||
Datacenter: "dc1",
|
Datacenter: "dc1",
|
||||||
},
|
},
|
||||||
Service: structs.TestNodeServiceProxy(t),
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "foo-sidecar-proxy",
|
||||||
|
Address: "172.16.1.3",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "1",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "foo",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
structs.CheckServiceNode{
|
structs.CheckServiceNode{
|
||||||
Node: &structs.Node{
|
Node: &structs.Node{
|
||||||
|
@ -201,7 +282,69 @@ func TestGatewayServicesDC1(t testing.T) structs.CheckServiceNodes {
|
||||||
Address: "10.1.1.2",
|
Address: "10.1.1.2",
|
||||||
Datacenter: "dc1",
|
Datacenter: "dc1",
|
||||||
},
|
},
|
||||||
Service: structs.TestNodeServiceProxy(t),
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "foo-sidecar-proxy",
|
||||||
|
Address: "172.16.1.4",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "1",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "foo",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
structs.CheckServiceNode{
|
||||||
|
Node: &structs.Node{
|
||||||
|
ID: "foo-node-3",
|
||||||
|
Node: "foo-node-3",
|
||||||
|
Address: "10.1.1.3",
|
||||||
|
Datacenter: "dc1",
|
||||||
|
},
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "foo-sidecar-proxy",
|
||||||
|
Address: "172.16.1.5",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "2",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "foo",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
structs.CheckServiceNode{
|
||||||
|
Node: &structs.Node{
|
||||||
|
ID: "foo-node-4",
|
||||||
|
Node: "foo-node-4",
|
||||||
|
Address: "10.1.1.7",
|
||||||
|
Datacenter: "dc1",
|
||||||
|
},
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Kind: structs.ServiceKindConnectProxy,
|
||||||
|
Service: "foo-sidecar-proxy",
|
||||||
|
Address: "172.16.1.9",
|
||||||
|
Port: 2222,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"version": "2",
|
||||||
|
},
|
||||||
|
Proxy: structs.ConnectProxyConfig{
|
||||||
|
DestinationServiceName: "foo",
|
||||||
|
Upstreams: structs.TestUpstreams(t),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Checks: structs.HealthChecks{
|
||||||
|
&structs.HealthCheck{
|
||||||
|
Node: "foo-node-4",
|
||||||
|
ServiceName: "foo-sidecar-proxy",
|
||||||
|
Name: "proxy-alive",
|
||||||
|
Status: "warning",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +411,8 @@ func TestConfigSnapshotMeshGateway(t testing.T) *ConfigSnapshot {
|
||||||
"dc2": nil,
|
"dc2": nil,
|
||||||
},
|
},
|
||||||
ServiceGroups: map[string]structs.CheckServiceNodes{
|
ServiceGroups: map[string]structs.CheckServiceNodes{
|
||||||
"foo": TestGatewayServicesDC1(t),
|
"foo": TestGatewayServiceGroupFooDC1(t),
|
||||||
|
"bar": TestGatewayServiceGroupBarDC1(t),
|
||||||
},
|
},
|
||||||
GatewayGroups: map[string]structs.CheckServiceNodes{
|
GatewayGroups: map[string]structs.CheckServiceNodes{
|
||||||
"dc2": TestGatewayNodesDC2(t),
|
"dc2": TestGatewayNodesDC2(t),
|
||||||
|
|
|
@ -387,6 +387,31 @@ func (c *ConfigEntryQuery) RequestDatacenter() string {
|
||||||
return c.Datacenter
|
return c.Datacenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ConfigEntryQuery) CacheInfo() cache.RequestInfo {
|
||||||
|
info := cache.RequestInfo{
|
||||||
|
Token: r.Token,
|
||||||
|
Datacenter: r.Datacenter,
|
||||||
|
MinIndex: r.MinQueryIndex,
|
||||||
|
Timeout: r.MaxQueryTime,
|
||||||
|
MaxAge: r.MaxAge,
|
||||||
|
MustRevalidate: r.MustRevalidate,
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := hashstructure.Hash([]interface{}{
|
||||||
|
r.Kind,
|
||||||
|
r.Name,
|
||||||
|
r.Filter,
|
||||||
|
}, nil)
|
||||||
|
if err == nil {
|
||||||
|
// If there is an error, we don't set the key. A blank key forces
|
||||||
|
// no cache for this request so the request is forwarded directly
|
||||||
|
// to the server.
|
||||||
|
info.Key = strconv.FormatUint(v, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceConfigRequest is used when requesting the resolved configuration
|
// ServiceConfigRequest is used when requesting the resolved configuration
|
||||||
// for a service.
|
// for a service.
|
||||||
type ServiceConfigRequest struct {
|
type ServiceConfigRequest struct {
|
||||||
|
|
|
@ -84,33 +84,42 @@ func (s *Server) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapsh
|
||||||
// for a mesh gateway. This will include 1 cluster per remote datacenter as well as
|
// for a mesh gateway. This will include 1 cluster per remote datacenter as well as
|
||||||
// 1 cluster for each service subset.
|
// 1 cluster for each service subset.
|
||||||
func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot, token string) ([]proto.Message, error) {
|
func (s *Server) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot, token string) ([]proto.Message, error) {
|
||||||
// TODO (mesh-gateway) will need to generate 1 cluster for each service subset as well.
|
// 1 cluster per remote dc + 1 cluster per local service (this is a lower bound - all subset specific clusters will be appended)
|
||||||
|
clusters := make([]proto.Message, 0, len(cfgSnap.MeshGateway.GatewayGroups)+len(cfgSnap.MeshGateway.ServiceGroups))
|
||||||
|
|
||||||
// 1 cluster per remote dc + 1 cluster per local service
|
|
||||||
clusters := make([]proto.Message, len(cfgSnap.MeshGateway.GatewayGroups)+len(cfgSnap.MeshGateway.ServiceGroups))
|
|
||||||
|
|
||||||
var err error
|
|
||||||
idx := 0
|
|
||||||
// generate the remote dc clusters
|
// generate the remote dc clusters
|
||||||
for dc, _ := range cfgSnap.MeshGateway.GatewayGroups {
|
for dc, _ := range cfgSnap.MeshGateway.GatewayGroups {
|
||||||
clusterName := DatacenterSNI(dc, cfgSnap)
|
clusterName := DatacenterSNI(dc, cfgSnap)
|
||||||
|
|
||||||
clusters[idx], err = s.makeMeshGatewayCluster(clusterName, cfgSnap)
|
cluster, err := s.makeMeshGatewayCluster(clusterName, cfgSnap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
idx += 1
|
clusters = append(clusters, cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate the per-service clusters
|
// generate the per-service clusters
|
||||||
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
|
for svc, _ := range cfgSnap.MeshGateway.ServiceGroups {
|
||||||
clusterName := ServiceSNI(svc, "default", cfgSnap.Datacenter, cfgSnap)
|
clusterName := ServiceSNI(svc, "", "default", cfgSnap.Datacenter, cfgSnap)
|
||||||
|
|
||||||
clusters[idx], err = s.makeMeshGatewayCluster(clusterName, cfgSnap)
|
cluster, err := s.makeMeshGatewayCluster(clusterName, cfgSnap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
idx += 1
|
clusters = append(clusters, cluster)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the service subset clusters
|
||||||
|
for svc, resolver := range cfgSnap.MeshGateway.ServiceResolvers {
|
||||||
|
for subsetName, _ := range resolver.Subsets {
|
||||||
|
clusterName := ServiceSNI(svc, subsetName, "default", cfgSnap.Datacenter, cfgSnap)
|
||||||
|
|
||||||
|
cluster, err := s.makeMeshGatewayCluster(clusterName, cfgSnap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
clusters = append(clusters, cluster)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return clusters, nil
|
return clusters, nil
|
||||||
|
@ -174,7 +183,7 @@ func (s *Server) makeUpstreamCluster(upstream structs.Upstream, cfgSnap *proxycf
|
||||||
if upstream.Datacenter != "" {
|
if upstream.Datacenter != "" {
|
||||||
dc = upstream.Datacenter
|
dc = upstream.Datacenter
|
||||||
}
|
}
|
||||||
sni := ServiceSNI(upstream.DestinationName, ns, dc, cfgSnap)
|
sni := ServiceSNI(upstream.DestinationName, "", ns, dc, cfgSnap)
|
||||||
|
|
||||||
cfg, err := ParseUpstreamConfig(upstream.Config)
|
cfg, err := ParseUpstreamConfig(upstream.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/proxycfg"
|
"github.com/hashicorp/consul/agent/proxycfg"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
testinf "github.com/mitchellh/go-testing-interface"
|
testinf "github.com/mitchellh/go-testing-interface"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -102,6 +103,27 @@ func TestClustersFromSnapshot(t *testing.T) {
|
||||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||||
setup: nil,
|
setup: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "mesh-gateway-service-subsets",
|
||||||
|
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.MeshGateway.ServiceResolvers = map[string]*structs.ServiceResolverConfigEntry{
|
||||||
|
"bar": &structs.ServiceResolverConfigEntry{
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
Name: "bar",
|
||||||
|
Subsets: map[string]structs.ServiceResolverSubset{
|
||||||
|
"v1": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.Version == 1",
|
||||||
|
},
|
||||||
|
"v2": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.Version == 2",
|
||||||
|
OnlyPassing: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -190,7 +212,7 @@ func expectClustersJSONResources(t *testing.T, snap *proxycfg.ConfigSnapshot, to
|
||||||
|
|
||||||
},
|
},
|
||||||
"connectTimeout": "1s",
|
"connectTimeout": "1s",
|
||||||
"tlsContext": ` + expectedUpstreamTLSContextJSON(t, snap, "db.default.dc1.internal.11111111-2222-3333-4444-555555555555") + `
|
"tlsContext": ` + expectedUpstreamTLSContextJSON(t, snap, "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul") + `
|
||||||
}`,
|
}`,
|
||||||
"prepared_query:geo-cache": `
|
"prepared_query:geo-cache": `
|
||||||
{
|
{
|
||||||
|
@ -208,7 +230,7 @@ func expectClustersJSONResources(t *testing.T, snap *proxycfg.ConfigSnapshot, to
|
||||||
|
|
||||||
},
|
},
|
||||||
"connectTimeout": "5s",
|
"connectTimeout": "5s",
|
||||||
"tlsContext": ` + expectedUpstreamTLSContextJSON(t, snap, "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555") + `
|
"tlsContext": ` + expectedUpstreamTLSContextJSON(t, snap, "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul") + `
|
||||||
}`,
|
}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/proxycfg"
|
"github.com/hashicorp/consul/agent/proxycfg"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
|
|
||||||
|
bexpr "github.com/hashicorp/go-bexpr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// endpointsFromSnapshot returns the xDS API representation of the "endpoints"
|
// endpointsFromSnapshot returns the xDS API representation of the "endpoints"
|
||||||
|
@ -143,7 +145,7 @@ func (s *Server) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsh
|
||||||
|
|
||||||
// generate the endpoints for the local service groups
|
// generate the endpoints for the local service groups
|
||||||
for svc, endpoints := range cfgSnap.MeshGateway.ServiceGroups {
|
for svc, endpoints := range cfgSnap.MeshGateway.ServiceGroups {
|
||||||
clusterName := ServiceSNI(svc, "default", cfgSnap.Datacenter, cfgSnap)
|
clusterName := ServiceSNI(svc, "", "default", cfgSnap.Datacenter, cfgSnap)
|
||||||
la := makeLoadAssignment(
|
la := makeLoadAssignment(
|
||||||
clusterName,
|
clusterName,
|
||||||
0,
|
0,
|
||||||
|
@ -155,6 +157,51 @@ func (s *Server) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapsh
|
||||||
resources = append(resources, la)
|
resources = append(resources, la)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate the endpoints for the service subsets
|
||||||
|
for svc, resolver := range cfgSnap.MeshGateway.ServiceResolvers {
|
||||||
|
for subsetName, subset := range resolver.Subsets {
|
||||||
|
clusterName := ServiceSNI(svc, subsetName, "default", cfgSnap.Datacenter, cfgSnap)
|
||||||
|
|
||||||
|
endpoints := cfgSnap.MeshGateway.ServiceGroups[svc]
|
||||||
|
|
||||||
|
// locally execute the subsets filter
|
||||||
|
filterExp := subset.Filter
|
||||||
|
if subset.OnlyPassing {
|
||||||
|
// we could do another filter pass without bexpr but this simplifies things a bit
|
||||||
|
if filterExp != "" {
|
||||||
|
// TODO (filtering) - Update to "and all Checks as chk { chk.Status == passing }"
|
||||||
|
// once the syntax is supported
|
||||||
|
filterExp = fmt.Sprintf("(%s) and not Checks.Status != passing", filterExp)
|
||||||
|
} else {
|
||||||
|
filterExp = "not Checks.Status != passing"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if filterExp != "" {
|
||||||
|
filter, err := bexpr.CreateFilter(filterExp, nil, endpoints)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := filter.Execute(endpoints)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
endpoints = raw.(structs.CheckServiceNodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
la := makeLoadAssignment(
|
||||||
|
clusterName,
|
||||||
|
0,
|
||||||
|
[]structs.CheckServiceNodes{
|
||||||
|
endpoints,
|
||||||
|
},
|
||||||
|
cfgSnap.Datacenter,
|
||||||
|
)
|
||||||
|
resources = append(resources, la)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return resources, nil
|
return resources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,40 @@ func Test_endpointsFromSnapshot(t *testing.T) {
|
||||||
create: proxycfg.TestConfigSnapshotMeshGateway,
|
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||||
setup: nil,
|
setup: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "mesh-gateway-service-subsets",
|
||||||
|
create: proxycfg.TestConfigSnapshotMeshGateway,
|
||||||
|
setup: func(snap *proxycfg.ConfigSnapshot) {
|
||||||
|
snap.MeshGateway.ServiceResolvers = map[string]*structs.ServiceResolverConfigEntry{
|
||||||
|
"bar": &structs.ServiceResolverConfigEntry{
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
Name: "bar",
|
||||||
|
Subsets: map[string]structs.ServiceResolverSubset{
|
||||||
|
"v1": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.version == 1",
|
||||||
|
},
|
||||||
|
"v2": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.version == 2",
|
||||||
|
OnlyPassing: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"foo": &structs.ServiceResolverConfigEntry{
|
||||||
|
Kind: structs.ServiceResolver,
|
||||||
|
Name: "foo",
|
||||||
|
Subsets: map[string]structs.ServiceResolverSubset{
|
||||||
|
"v1": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.version == 1",
|
||||||
|
},
|
||||||
|
"v2": structs.ServiceResolverSubset{
|
||||||
|
Filter: "Service.Meta.version == 2",
|
||||||
|
OnlyPassing: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -10,7 +10,10 @@ func DatacenterSNI(dc string, cfgSnap *proxycfg.ConfigSnapshot) string {
|
||||||
return fmt.Sprintf("%s.internal.%s", dc, cfgSnap.Roots.TrustDomain)
|
return fmt.Sprintf("%s.internal.%s", dc, cfgSnap.Roots.TrustDomain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServiceSNI(service string, namespace string, datacenter string, cfgSnap *proxycfg.ConfigSnapshot) string {
|
func ServiceSNI(service string, subset string, namespace string, datacenter string, cfgSnap *proxycfg.ConfigSnapshot) string {
|
||||||
// TODO (mesh-gateway) - support service subsets here too
|
if subset == "" {
|
||||||
return fmt.Sprintf("%s.%s.%s.internal.%s", service, namespace, datacenter, cfgSnap.Roots.TrustDomain)
|
return fmt.Sprintf("%s.%s.%s.internal.%s", service, namespace, datacenter, cfgSnap.Roots.TrustDomain)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s.%s.%s.%s.internal.%s", subset, service, namespace, datacenter, cfgSnap.Roots.TrustDomain)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555"
|
"sni": "geo-cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
},
|
},
|
||||||
"outlierDetection": {
|
"outlierDetection": {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
"resources": [
|
"resources": [
|
||||||
{
|
{
|
||||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
"name": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"type": "EDS",
|
"type": "EDS",
|
||||||
"edsClusterConfig": {
|
"edsClusterConfig": {
|
||||||
"edsConfig": {
|
"edsConfig": {
|
||||||
|
@ -19,7 +19,23 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
"name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555",
|
"name": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"type": "EDS",
|
||||||
|
"edsClusterConfig": {
|
||||||
|
"edsConfig": {
|
||||||
|
"ads": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectTimeout": "5s",
|
||||||
|
"outlierDetection": {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.Cluster",
|
||||||
|
"name": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"type": "EDS",
|
"type": "EDS",
|
||||||
"edsClusterConfig": {
|
"edsClusterConfig": {
|
||||||
"edsConfig": {
|
"edsConfig": {
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
{
|
||||||
|
"versionInfo": "00000001",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "dc2.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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.3",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.4",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.5",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.9",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.6",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.7",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.8",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "v1.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.6",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.7",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "v2.bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.8",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "v1.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.3",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.4",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "v2.foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.5",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeUrl": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"nonce": "00000001"
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
"resources": [
|
"resources": [
|
||||||
{
|
{
|
||||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
"clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{
|
{
|
||||||
"lbEndpoints": [
|
"lbEndpoints": [
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
"clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555",
|
"clusterName": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{
|
{
|
||||||
"lbEndpoints": [
|
"lbEndpoints": [
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
"endpoint": {
|
"endpoint": {
|
||||||
"address": {
|
"address": {
|
||||||
"socketAddress": {
|
"socketAddress": {
|
||||||
"address": "127.0.0.2",
|
"address": "172.16.1.3",
|
||||||
"portValue": 2222
|
"portValue": 2222
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,77 @@
|
||||||
"endpoint": {
|
"endpoint": {
|
||||||
"address": {
|
"address": {
|
||||||
"socketAddress": {
|
"socketAddress": {
|
||||||
"address": "127.0.0.2",
|
"address": "172.16.1.4",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.5",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.9",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
|
||||||
|
"clusterName": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"lbEndpoints": [
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.6",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.7",
|
||||||
|
"portValue": 2222
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"healthStatus": "HEALTHY",
|
||||||
|
"loadBalancingWeight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"endpoint": {
|
||||||
|
"address": {
|
||||||
|
"socketAddress": {
|
||||||
|
"address": "172.16.1.8",
|
||||||
"portValue": 2222
|
"portValue": 2222
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_bar_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_bar_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_baz_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_baz_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,14 +108,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_default_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_default_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,14 +155,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_foo_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_foo_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_lan_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_lan_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_wan_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_wan_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
{
|
{
|
||||||
"filterChainMatch": {
|
"filterChainMatch": {
|
||||||
"serverNames": [
|
"serverNames": [
|
||||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555"
|
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"name": "envoy.tcp_proxy",
|
"name": "envoy.tcp_proxy",
|
||||||
"config": {
|
"config": {
|
||||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555",
|
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||||
"stat_prefix": "mesh_gateway_remote_default_dc2_tcp"
|
"stat_prefix": "mesh_gateway_remote_default_dc2_tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue