Fix DialedDirectly configuration for Consul dataplane. (#15760)
Fix DialedDirectly configuration for Consul dataplane.
This commit is contained in:
parent
c73707ca3c
commit
50a5549f8a
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
connect: Fix issue where DialedDirectly configuration was not used by Consul Dataplane.
|
||||||
|
```
|
|
@ -1007,11 +1007,17 @@ RESOLVE_AGAIN:
|
||||||
// Default mesh gateway settings
|
// Default mesh gateway settings
|
||||||
if serviceDefault := c.entries.GetService(targetID); serviceDefault != nil {
|
if serviceDefault := c.entries.GetService(targetID); serviceDefault != nil {
|
||||||
target.MeshGateway = serviceDefault.MeshGateway
|
target.MeshGateway = serviceDefault.MeshGateway
|
||||||
|
target.TransparentProxy.DialedDirectly = serviceDefault.TransparentProxy.DialedDirectly
|
||||||
}
|
}
|
||||||
proxyDefault := c.entries.GetProxyDefaults(targetID.PartitionOrDefault())
|
proxyDefault := c.entries.GetProxyDefaults(targetID.PartitionOrDefault())
|
||||||
if proxyDefault != nil && target.MeshGateway.Mode == structs.MeshGatewayModeDefault {
|
if proxyDefault != nil {
|
||||||
|
if target.MeshGateway.Mode == structs.MeshGatewayModeDefault {
|
||||||
target.MeshGateway.Mode = proxyDefault.MeshGateway.Mode
|
target.MeshGateway.Mode = proxyDefault.MeshGateway.Mode
|
||||||
}
|
}
|
||||||
|
if !target.TransparentProxy.DialedDirectly {
|
||||||
|
target.TransparentProxy.DialedDirectly = proxyDefault.TransparentProxy.DialedDirectly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if c.overrideMeshGateway.Mode != structs.MeshGatewayModeDefault {
|
if c.overrideMeshGateway.Mode != structs.MeshGatewayModeDefault {
|
||||||
if target.MeshGateway.Mode != c.overrideMeshGateway.Mode {
|
if target.MeshGateway.Mode != c.overrideMeshGateway.Mode {
|
||||||
|
|
|
@ -82,6 +82,11 @@ func TestCompile(t *testing.T) {
|
||||||
// circular references
|
// circular references
|
||||||
"circular resolver redirect": testcase_Resolver_CircularRedirect(),
|
"circular resolver redirect": testcase_Resolver_CircularRedirect(),
|
||||||
"circular split": testcase_CircularSplit(),
|
"circular split": testcase_CircularSplit(),
|
||||||
|
|
||||||
|
// tproxy
|
||||||
|
"tproxy service defaults only": testcase_ServiceDefaultsTProxy(),
|
||||||
|
"tproxy proxy defaults only": testcase_ProxyDefaultsTProxy(),
|
||||||
|
"tproxy service defaults override": testcase_ServiceDefaultsOverrideTProxy(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range cases {
|
for name, tc := range cases {
|
||||||
|
@ -2942,6 +2947,119 @@ func testcase_LBResolver() compileTestCase {
|
||||||
return compileTestCase{entries: entries, expect: expect}
|
return compileTestCase{entries: entries, expect: expect}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testcase_ServiceDefaultsTProxy() compileTestCase {
|
||||||
|
entries := newEntries()
|
||||||
|
entries.AddServices(
|
||||||
|
&structs.ServiceConfigEntry{
|
||||||
|
Kind: structs.ServiceDefaults,
|
||||||
|
Name: "main",
|
||||||
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
|
DialedDirectly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
expect := &structs.CompiledDiscoveryChain{
|
||||||
|
Protocol: "tcp",
|
||||||
|
Default: true,
|
||||||
|
StartNode: "resolver:main.default.default.dc1",
|
||||||
|
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||||
|
"resolver:main.default.default.dc1": {
|
||||||
|
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||||
|
Name: "main.default.default.dc1",
|
||||||
|
Resolver: &structs.DiscoveryResolver{
|
||||||
|
Default: true,
|
||||||
|
ConnectTimeout: 5 * time.Second,
|
||||||
|
Target: "main.default.default.dc1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Targets: map[string]*structs.DiscoveryTarget{
|
||||||
|
"main.default.default.dc1": newTarget(structs.DiscoveryTargetOpts{Service: "main"}, func(t *structs.DiscoveryTarget) {
|
||||||
|
t.TransparentProxy.DialedDirectly = true
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return compileTestCase{entries: entries, expect: expect}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testcase_ProxyDefaultsTProxy() compileTestCase {
|
||||||
|
entries := newEntries()
|
||||||
|
entries.AddProxyDefaults(&structs.ProxyConfigEntry{
|
||||||
|
Kind: structs.ProxyDefaults,
|
||||||
|
Name: structs.ProxyConfigGlobal,
|
||||||
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
|
DialedDirectly: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect := &structs.CompiledDiscoveryChain{
|
||||||
|
Protocol: "tcp",
|
||||||
|
Default: true,
|
||||||
|
StartNode: "resolver:main.default.default.dc1",
|
||||||
|
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||||
|
"resolver:main.default.default.dc1": {
|
||||||
|
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||||
|
Name: "main.default.default.dc1",
|
||||||
|
Resolver: &structs.DiscoveryResolver{
|
||||||
|
Default: true,
|
||||||
|
ConnectTimeout: 5 * time.Second,
|
||||||
|
Target: "main.default.default.dc1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Targets: map[string]*structs.DiscoveryTarget{
|
||||||
|
"main.default.default.dc1": newTarget(structs.DiscoveryTargetOpts{Service: "main"}, func(t *structs.DiscoveryTarget) {
|
||||||
|
t.TransparentProxy.DialedDirectly = true
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return compileTestCase{entries: entries, expect: expect}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testcase_ServiceDefaultsOverrideTProxy() compileTestCase {
|
||||||
|
entries := newEntries()
|
||||||
|
entries.AddProxyDefaults(&structs.ProxyConfigEntry{
|
||||||
|
Kind: structs.ProxyDefaults,
|
||||||
|
Name: structs.ProxyConfigGlobal,
|
||||||
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
|
DialedDirectly: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
entries.AddServices(
|
||||||
|
&structs.ServiceConfigEntry{
|
||||||
|
Kind: structs.ServiceDefaults,
|
||||||
|
Name: "main",
|
||||||
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
|
DialedDirectly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
expect := &structs.CompiledDiscoveryChain{
|
||||||
|
Protocol: "tcp",
|
||||||
|
Default: true,
|
||||||
|
StartNode: "resolver:main.default.default.dc1",
|
||||||
|
Nodes: map[string]*structs.DiscoveryGraphNode{
|
||||||
|
"resolver:main.default.default.dc1": {
|
||||||
|
Type: structs.DiscoveryGraphNodeTypeResolver,
|
||||||
|
Name: "main.default.default.dc1",
|
||||||
|
Resolver: &structs.DiscoveryResolver{
|
||||||
|
Default: true,
|
||||||
|
ConnectTimeout: 5 * time.Second,
|
||||||
|
Target: "main.default.default.dc1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Targets: map[string]*structs.DiscoveryTarget{
|
||||||
|
"main.default.default.dc1": newTarget(structs.DiscoveryTargetOpts{Service: "main"}, func(t *structs.DiscoveryTarget) {
|
||||||
|
t.TransparentProxy.DialedDirectly = true
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return compileTestCase{entries: entries, expect: expect}
|
||||||
|
}
|
||||||
|
|
||||||
func newSimpleRoute(name string, muts ...func(*structs.ServiceRoute)) structs.ServiceRoute {
|
func newSimpleRoute(name string, muts ...func(*structs.ServiceRoute)) structs.ServiceRoute {
|
||||||
r := structs.ServiceRoute{
|
r := structs.ServiceRoute{
|
||||||
Match: &structs.ServiceRouteMatch{
|
Match: &structs.ServiceRouteMatch{
|
||||||
|
|
|
@ -2359,7 +2359,16 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
{
|
{
|
||||||
CorrelationID: "discovery-chain:" + dbUID.String(),
|
CorrelationID: "discovery-chain:" + dbUID.String(),
|
||||||
Result: &structs.DiscoveryChainResponse{
|
Result: &structs.DiscoveryChainResponse{
|
||||||
Chain: discoverychain.TestCompileConfigEntries(t, "db", "default", "default", "dc1", "trustdomain.consul", nil),
|
Chain: discoverychain.TestCompileConfigEntries(
|
||||||
|
t, "db", "default", "default", "dc1", "trustdomain.consul", nil,
|
||||||
|
&structs.ServiceConfigEntry{
|
||||||
|
Kind: structs.ServiceDefaults,
|
||||||
|
Name: "db",
|
||||||
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
|
DialedDirectly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Err: nil,
|
Err: nil,
|
||||||
},
|
},
|
||||||
|
@ -2396,7 +2405,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
Proxy: structs.ConnectProxyConfig{
|
Proxy: structs.ConnectProxyConfig{
|
||||||
DestinationServiceName: "db",
|
DestinationServiceName: "db",
|
||||||
TransparentProxy: structs.TransparentProxyConfig{
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
DialedDirectly: true,
|
DialedDirectly: false, // This is set true by the service-defaults entry above.
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RaftIndex: structs.RaftIndex{
|
RaftIndex: structs.RaftIndex{
|
||||||
|
@ -2455,7 +2464,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
Proxy: structs.ConnectProxyConfig{
|
Proxy: structs.ConnectProxyConfig{
|
||||||
DestinationServiceName: "db",
|
DestinationServiceName: "db",
|
||||||
TransparentProxy: structs.TransparentProxyConfig{
|
TransparentProxy: structs.TransparentProxyConfig{
|
||||||
DialedDirectly: true,
|
DialedDirectly: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RaftIndex: structs.RaftIndex{
|
RaftIndex: structs.RaftIndex{
|
||||||
|
|
|
@ -131,6 +131,7 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
|
||||||
}
|
}
|
||||||
upstreamsSnapshot.WatchedUpstreamEndpoints[uid][targetID] = resp.Nodes
|
upstreamsSnapshot.WatchedUpstreamEndpoints[uid][targetID] = resp.Nodes
|
||||||
|
|
||||||
|
// Skip adding passthroughs unless it's a connect sidecar in tproxy mode.
|
||||||
if s.kind != structs.ServiceKindConnectProxy || s.proxyCfg.Mode != structs.ProxyModeTransparent {
|
if s.kind != structs.ServiceKindConnectProxy || s.proxyCfg.Mode != structs.ProxyModeTransparent {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -148,7 +149,17 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
|
||||||
passthroughs := make(map[string]struct{})
|
passthroughs := make(map[string]struct{})
|
||||||
|
|
||||||
for _, node := range resp.Nodes {
|
for _, node := range resp.Nodes {
|
||||||
if !node.Service.Proxy.TransparentProxy.DialedDirectly {
|
dialedDirectly := node.Service.Proxy.TransparentProxy.DialedDirectly
|
||||||
|
// We must do a manual merge here on the DialedDirectly field, because the service-defaults
|
||||||
|
// and proxy-defaults are not automatically merged into the CheckServiceNodes when in
|
||||||
|
// agentless mode (because the streaming backend doesn't yet support the MergeCentralConfig field).
|
||||||
|
if chain := snap.ConnectProxy.DiscoveryChain[uid]; chain != nil {
|
||||||
|
if target := chain.Targets[targetID]; target != nil {
|
||||||
|
dialedDirectly = dialedDirectly || target.TransparentProxy.DialedDirectly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip adding a passthrough for the upstream node if not DialedDirectly.
|
||||||
|
if !dialedDirectly {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,10 +190,12 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
|
||||||
upstreamsSnapshot.PassthroughIndices[addr] = indexedTarget{idx: csnIdx, upstreamID: uid, targetID: targetID}
|
upstreamsSnapshot.PassthroughIndices[addr] = indexedTarget{idx: csnIdx, upstreamID: uid, targetID: targetID}
|
||||||
passthroughs[addr] = struct{}{}
|
passthroughs[addr] = struct{}{}
|
||||||
}
|
}
|
||||||
|
// Always clear out the existing target passthroughs list so that clusters are cleaned up
|
||||||
|
// correctly if no entries are populated.
|
||||||
|
upstreamsSnapshot.PassthroughUpstreams[uid] = make(map[string]map[string]struct{})
|
||||||
if len(passthroughs) > 0 {
|
if len(passthroughs) > 0 {
|
||||||
upstreamsSnapshot.PassthroughUpstreams[uid] = map[string]map[string]struct{}{
|
// Add the passthroughs to the target if any were found.
|
||||||
targetID: passthroughs,
|
upstreamsSnapshot.PassthroughUpstreams[uid][targetID] = passthroughs
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case strings.HasPrefix(u.CorrelationID, "mesh-gateway:"):
|
case strings.HasPrefix(u.CorrelationID, "mesh-gateway:"):
|
||||||
|
|
|
@ -194,6 +194,7 @@ type DiscoveryTarget struct {
|
||||||
|
|
||||||
MeshGateway MeshGatewayConfig `json:",omitempty"`
|
MeshGateway MeshGatewayConfig `json:",omitempty"`
|
||||||
Subset ServiceResolverSubset `json:",omitempty"`
|
Subset ServiceResolverSubset `json:",omitempty"`
|
||||||
|
TransparentProxy TransparentProxyConfig `json:",omitempty"`
|
||||||
|
|
||||||
ConnectTimeout time.Duration `json:",omitempty"`
|
ConnectTimeout time.Duration `json:",omitempty"`
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue