Fix DialedDirectly configuration for Consul dataplane.

pull/15760/head
Derek Menteer 2022-12-09 15:59:56 -06:00
parent 348bbf60f1
commit 1824f4428a
5 changed files with 144 additions and 5 deletions

3
.changelog/15760.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
connect: Fix issue where DialedDirectly configuration was not used by Consul Dataplane.
```

View File

@ -1007,11 +1007,17 @@ RESOLVE_AGAIN:
// Default mesh gateway settings
if serviceDefault := c.entries.GetService(targetID); serviceDefault != nil {
target.MeshGateway = serviceDefault.MeshGateway
target.TransparentProxy = serviceDefault.TransparentProxy
}
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
}
if target.TransparentProxy.IsZero() {
target.TransparentProxy = proxyDefault.TransparentProxy
}
}
if c.overrideMeshGateway.Mode != structs.MeshGatewayModeDefault {
if target.MeshGateway.Mode != c.overrideMeshGateway.Mode {

View File

@ -82,6 +82,11 @@ func TestCompile(t *testing.T) {
// circular references
"circular resolver redirect": testcase_Resolver_CircularRedirect(),
"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 {
@ -2942,6 +2947,119 @@ func testcase_LBResolver() compileTestCase {
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 {
r := structs.ServiceRoute{
Match: &structs.ServiceRouteMatch{

View File

@ -131,6 +131,7 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
}
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 {
return nil
}
@ -148,7 +149,17 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv
passthroughs := make(map[string]struct{})
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
}

View File

@ -194,6 +194,7 @@ type DiscoveryTarget struct {
MeshGateway MeshGatewayConfig `json:",omitempty"`
Subset ServiceResolverSubset `json:",omitempty"`
TransparentProxy TransparentProxyConfig `json:",omitempty"`
ConnectTimeout time.Duration `json:",omitempty"`