mirror of https://github.com/hashicorp/consul
Browse Source
Mesh gateways will now enable tcp connections with SNI names including peering information so that those connections may be proxied. Note: this does not change the callers to use these mesh gateways.pull/13294/head
R.B. Boyer
2 years ago
committed by
GitHub
19 changed files with 656 additions and 8 deletions
@ -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 ExportedPeeredServicesName = "exported-peered-services" |
||||
|
||||
type ExportedPeeredServices struct { |
||||
RegisterOptionsBlockingRefresh |
||||
RPC RPC |
||||
} |
||||
|
||||
func (c *ExportedPeeredServices) Fetch(opts cache.FetchOptions, req cache.Request) (cache.FetchResult, error) { |
||||
var result cache.FetchResult |
||||
|
||||
// The request should be a DCSpecificRequest.
|
||||
reqReal, ok := req.(*structs.DCSpecificRequest) |
||||
if !ok { |
||||
return result, fmt.Errorf( |
||||
"Internal cache failure: request wrong type: %T", req) |
||||
} |
||||
|
||||
// Lightweight copy this object so that manipulating QueryOptions doesn't race.
|
||||
dup := *reqReal |
||||
reqReal = &dup |
||||
|
||||
// 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 end up arbitrarily stale anyway. This
|
||||
// allows cached service-discover to automatically read scale across all
|
||||
// servers too.
|
||||
reqReal.AllowStale = true |
||||
|
||||
// Fetch
|
||||
var reply structs.IndexedExportedServiceList |
||||
if err := c.RPC.RPC("Internal.ExportedPeeredServices", reqReal, &reply); err != nil { |
||||
return result, err |
||||
} |
||||
|
||||
result.Value = &reply |
||||
result.Index = reply.QueryMeta.Index |
||||
return result, nil |
||||
} |
@ -0,0 +1,69 @@
|
||||
package cachetype |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/stretchr/testify/mock" |
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/hashicorp/consul/agent/cache" |
||||
"github.com/hashicorp/consul/agent/structs" |
||||
) |
||||
|
||||
func TestExportedPeeredServices(t *testing.T) { |
||||
rpc := TestRPC(t) |
||||
typ := &ExportedPeeredServices{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.IndexedExportedServiceList |
||||
rpc.On("RPC", "Internal.ExportedPeeredServices", mock.Anything, mock.Anything).Return(nil). |
||||
Run(func(args mock.Arguments) { |
||||
req := args.Get(1).(*structs.DCSpecificRequest) |
||||
require.Equal(t, uint64(24), req.QueryOptions.MinQueryIndex) |
||||
require.Equal(t, 1*time.Second, req.QueryOptions.MaxQueryTime) |
||||
require.True(t, req.AllowStale) |
||||
|
||||
reply := args.Get(2).(*structs.IndexedExportedServiceList) |
||||
reply.Services = map[string]structs.ServiceList{ |
||||
"my-peer": { |
||||
structs.ServiceName{ |
||||
Name: "foo", |
||||
}, |
||||
structs.ServiceName{ |
||||
Name: "bar", |
||||
}, |
||||
}, |
||||
} |
||||
reply.QueryMeta.Index = 48 |
||||
resp = reply |
||||
}) |
||||
|
||||
// Fetch
|
||||
resultA, err := typ.Fetch(cache.FetchOptions{ |
||||
MinIndex: 24, |
||||
Timeout: 1 * time.Second, |
||||
}, &structs.DCSpecificRequest{ |
||||
Datacenter: "dc1", |
||||
}) |
||||
require.NoError(t, err) |
||||
require.Equal(t, cache.FetchResult{ |
||||
Value: resp, |
||||
Index: 48, |
||||
}, resultA) |
||||
|
||||
rpc.AssertExpectations(t) |
||||
} |
||||
|
||||
func TestExportedPeeredServices_badReqType(t *testing.T) { |
||||
rpc := TestRPC(t) |
||||
typ := &ExportedPeeredServices{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) |
||||
} |
@ -0,0 +1,147 @@
|
||||
{ |
||||
"versionInfo": "00000001", |
||||
"resources": [ |
||||
{ |
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener", |
||||
"name": "default:1.2.3.4:8443", |
||||
"address": { |
||||
"socketAddress": { |
||||
"address": "1.2.3.4", |
||||
"portValue": 8443 |
||||
} |
||||
}, |
||||
"filterChains": [ |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"bar.default.default.peer1.external.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_local_peered.bar.default.default.dc1", |
||||
"cluster": "bar.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"foo.default.default.peer1.external.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_local_peered.foo.default.default.dc1", |
||||
"cluster": "foo.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"gir.default.default.peer2.external.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_local_peered.gir.default.default.dc1", |
||||
"cluster": "gir.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_remote.default.dc2", |
||||
"cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"*.dc4.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_remote.default.dc4", |
||||
"cluster": "dc4.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filterChainMatch": { |
||||
"serverNames": [ |
||||
"*.dc6.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
] |
||||
}, |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_remote.default.dc6", |
||||
"cluster": "dc6.internal.11111111-2222-3333-4444-555555555555.consul" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"filters": [ |
||||
{ |
||||
"name": "envoy.filters.network.sni_cluster", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "envoy.filters.network.tcp_proxy", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", |
||||
"statPrefix": "mesh_gateway_local.default", |
||||
"cluster": "" |
||||
} |
||||
} |
||||
] |
||||
} |
||||
], |
||||
"listenerFilters": [ |
||||
{ |
||||
"name": "envoy.filters.listener.tls_inspector", |
||||
"typedConfig": { |
||||
"@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" |
||||
} |
||||
} |
||||
] |
||||
} |
||||
], |
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", |
||||
"nonce": "00000001" |
||||
} |
Loading…
Reference in new issue