diff --git a/agent/consul/discoverychain/compile.go b/agent/consul/discoverychain/compile.go index f091f91b9f..733ead473b 100644 --- a/agent/consul/discoverychain/compile.go +++ b/agent/consul/discoverychain/compile.go @@ -552,7 +552,12 @@ func (c *compiler) assembleChain() error { routeNode.Routes = append(routeNode.Routes, compiledRoute) dest := route.Destination - + if dest == nil { + dest = &structs.ServiceRouteDestination{ + Service: c.serviceName, + Namespace: router.NamespaceOrDefault(), + } + } svc := defaultIfEmpty(dest.Service, c.serviceName) destNamespace := defaultIfEmpty(dest.Namespace, router.NamespaceOrDefault()) diff --git a/agent/consul/discoverychain/compile_test.go b/agent/consul/discoverychain/compile_test.go index 00fec07531..d86c93cbd1 100644 --- a/agent/consul/discoverychain/compile_test.go +++ b/agent/consul/discoverychain/compile_test.go @@ -28,6 +28,7 @@ func TestCompile(t *testing.T) { "router with defaults and resolver": testcase_RouterWithDefaults_NoSplit_WithResolver(), "router with defaults and noop split": testcase_RouterWithDefaults_WithNoopSplit_DefaultResolver(), "router with defaults and noop split and resolver": testcase_RouterWithDefaults_WithNoopSplit_WithResolver(), + "router with no destination": testcase_JustRouterWithNoDestination(), "route bypasses splitter": testcase_RouteBypassesSplit(), "noop split": testcase_NoopSplit_DefaultResolver(), "noop split with protocol from proxy defaults": testcase_NoopSplit_DefaultResolver_ProtocolFromProxyDefaults(), @@ -184,6 +185,68 @@ func testcase_JustRouterWithDefaults() compileTestCase { return compileTestCase{entries: entries, expect: expect} } +func testcase_JustRouterWithNoDestination() compileTestCase { + entries := newEntries() + setServiceProtocol(entries, "main", "http") + + entries.AddRouters( + &structs.ServiceRouterConfigEntry{ + Kind: "service-router", + Name: "main", + Routes: []structs.ServiceRoute{ + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathPrefix: "/", + }, + }, + }, + }, + }, + ) + + expect := &structs.CompiledDiscoveryChain{ + Protocol: "http", + StartNode: "router:main.default", + Nodes: map[string]*structs.DiscoveryGraphNode{ + "router:main.default": &structs.DiscoveryGraphNode{ + Type: structs.DiscoveryGraphNodeTypeRouter, + Name: "main.default", + Routes: []*structs.DiscoveryRoute{ + { + Definition: &structs.ServiceRoute{ + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathPrefix: "/", + }, + }, + }, + NextNode: "resolver:main.default.dc1", + }, + { + Definition: newDefaultServiceRoute("main", "default"), + NextNode: "resolver:main.default.dc1", + }, + }, + }, + "resolver:main.default.dc1": &structs.DiscoveryGraphNode{ + Type: structs.DiscoveryGraphNodeTypeResolver, + Name: "main.default.dc1", + Resolver: &structs.DiscoveryResolver{ + Default: true, + ConnectTimeout: 5 * time.Second, + Target: "main.default.dc1", + }, + }, + }, + Targets: map[string]*structs.DiscoveryTarget{ + "main.default.dc1": newTarget("main", "", "default", "dc1", nil), + }, + } + + return compileTestCase{entries: entries, expect: expect} +} + func testcase_RouterWithDefaults_NoSplit_WithResolver() compileTestCase { entries := newEntries() setServiceProtocol(entries, "main", "http")