diff --git a/agent/consul/discoverychain/compile_test.go b/agent/consul/discoverychain/compile_test.go index 7e4c78dc85..af6597175a 100644 --- a/agent/consul/discoverychain/compile_test.go +++ b/agent/consul/discoverychain/compile_test.go @@ -51,7 +51,8 @@ func TestCompile(t *testing.T) { "default resolver with external sni": testcase_DefaultResolver_ExternalSNI(), "resolver with no entries and inferring defaults": testcase_DefaultResolver(), "default resolver with proxy defaults": testcase_DefaultResolver_WithProxyDefaults(), - "loadbalancer config": testcase_LBConfig(), + "loadbalancer splitter and resolver": testcase_LBSplitterAndResolver(), + "loadbalancer resolver": testcase_LBResolver(), "service redirect to service with default resolver is not a default chain": testcase_RedirectToDefaultResolverIsNotDefaultChain(), "all the bells and whistles": testcase_AllBellsAndWhistles(), @@ -2259,7 +2260,7 @@ func testcase_CircularSplit() compileTestCase { } } -func testcase_LBConfig() compileTestCase { +func testcase_LBSplitterAndResolver() compileTestCase { entries := newEntries() setServiceProtocol(entries, "foo", "http") setServiceProtocol(entries, "bar", "http") @@ -2442,6 +2443,66 @@ func testcase_LBConfig() compileTestCase { return compileTestCase{entries: entries, expect: expect} } +// ensure chain with LB cfg in resolver isn't a default chain (!IsDefault) +func testcase_LBResolver() compileTestCase { + entries := newEntries() + setServiceProtocol(entries, "main", "http") + + entries.AddResolvers( + &structs.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + LoadBalancer: &structs.LoadBalancer{ + EnvoyConfig: &structs.EnvoyLBConfig{ + Policy: "ring_hash", + RingHashConfig: &structs.RingHashConfig{ + MaximumRingSize: 101, + }, + HashPolicies: []structs.HashPolicy{ + { + SourceIP: true, + }, + }, + }, + }, + }, + ) + + expect := &structs.CompiledDiscoveryChain{ + Protocol: "http", + StartNode: "resolver:main.default.dc1", + Nodes: map[string]*structs.DiscoveryGraphNode{ + "resolver:main.default.dc1": { + Type: structs.DiscoveryGraphNodeTypeResolver, + Name: "main.default.dc1", + Resolver: &structs.DiscoveryResolver{ + Default: true, + ConnectTimeout: 5 * time.Second, + Target: "main.default.dc1", + }, + LoadBalancer: &structs.LoadBalancer{ + EnvoyConfig: &structs.EnvoyLBConfig{ + Policy: "ring_hash", + RingHashConfig: &structs.RingHashConfig{ + MaximumRingSize: 101, + }, + HashPolicies: []structs.HashPolicy{ + { + SourceIP: true, + }, + }, + }, + }, + }, + }, + Targets: map[string]*structs.DiscoveryTarget{ + "main.default.dc1": newTarget("main", "", "default", "dc1", nil), + }, + } + + return compileTestCase{entries: entries, expect: expect} +} + func newSimpleRoute(name string, muts ...func(*structs.ServiceRoute)) structs.ServiceRoute { r := structs.ServiceRoute{ Match: &structs.ServiceRouteMatch{ diff --git a/agent/structs/discovery_chain.go b/agent/structs/discovery_chain.go index 77eb03937c..5e2ff9498e 100644 --- a/agent/structs/discovery_chain.go +++ b/agent/structs/discovery_chain.go @@ -82,6 +82,9 @@ func (c *CompiledDiscoveryChain) IsDefault() bool { if !node.Resolver.Default { return false } + if node.LoadBalancer != nil { + return false + } target := c.Targets[node.Resolver.Target] diff --git a/api/discovery_chain.go b/api/discovery_chain.go index 75fdbaee25..f67f881c23 100644 --- a/api/discovery_chain.go +++ b/api/discovery_chain.go @@ -147,6 +147,9 @@ type DiscoveryGraphNode struct { // fields for Type==resolver Resolver *DiscoveryResolver + + // shared by Type==resolver || Type==splitter + LoadBalancer *LoadBalancer `json:",omitempty"` } // compiled form of ServiceRoute