Skip to content

Commit 436f66c

Browse files
authored
fix: fuse duplicate hosts (#68)
This PR fixes an issue where registered routes with the same host would be rejected by envoy. Hosts (called domains in the envoy config) must be unique across all virtual hosts ([ref](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-virtualhost)). In a previous chassis PR (#67), the requirement for a host to be set when calling `WithRoute` was removed. This PR now will add routes without a specified host to a default host (which is `*` for now but should be configurable). The other changes are just little cleanup items.
1 parent a419e37 commit 436f66c

File tree

5 files changed

+65
-23
lines changed

5 files changed

+65
-23
lines changed

services/core/fuse/config.yaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ service:
22
name: fuse
33
domain: core
44
entrypoint: http://localhost:2221
5-
advertise_address: 127.0.0.1
5+
6+
logging:
7+
level: debug
8+
69
network:
7-
port: 18000
10+
bind_port: 18000
11+
internal:
12+
host: localhost
13+
port: 18000
814

915
fuse:
1016
address: http://localhost:18000
1117
listener:
12-
address: 0.0.0.0
13-
port: 10000
18+
address: localhost
19+
port: 10000

services/core/fuse/control_plane/controller.go

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package control_plane
22

33
import (
4+
"cmp"
45
"context"
56
"errors"
6-
"fmt"
77
"net/http"
8+
"slices"
89
"time"
910

1011
ntv1 "github.com/steady-bytes/draft/api/core/control_plane/networking/v1"
@@ -307,7 +308,14 @@ func makeCluster(r *ntv1.Route, loadAssignment *endpoint.ClusterLoadAssignment)
307308
//
308309
// `nt_route` :route configuration that is being added to the snapshot.
309310
func makeRouterConfig(routes map[string]*anypb.Any) *route.RouteConfiguration {
310-
var virtualHosts []*route.VirtualHost
311+
var (
312+
virtualHosts []*route.VirtualHost
313+
defaultVirtualHost = &route.VirtualHost{
314+
Name: "default",
315+
Domains: []string{"*"},
316+
Routes: []*route.Route{},
317+
}
318+
)
311319

312320
for _, rt := range routes {
313321
r := &ntv1.Route{}
@@ -316,13 +324,9 @@ func makeRouterConfig(routes map[string]*anypb.Any) *route.RouteConfiguration {
316324
return nil
317325
}
318326

319-
http := fmt.Sprintf("%s:80", r.Match.Host)
320-
https := fmt.Sprintf("%s:443", r.Match.Host)
321-
322-
virtualHosts = append(virtualHosts, &route.VirtualHost{
323-
Name: r.Name,
324-
Domains: []string{r.Match.Host, http, https},
325-
Routes: []*route.Route{{
327+
// if no host is requested, add to default host
328+
if r.Match.Host == "" {
329+
defaultVirtualHost.Routes = append(defaultVirtualHost.Routes, &route.Route{
326330
Match: &route.RouteMatch{
327331
PathSpecifier: &route.RouteMatch_Prefix{
328332
Prefix: r.Match.Prefix,
@@ -338,7 +342,44 @@ func makeRouterConfig(routes map[string]*anypb.Any) *route.RouteConfiguration {
338342
},
339343
},
340344
TypedPerFilterConfig: map[string]*anypb.Any{},
341-
}}})
345+
})
346+
} else {
347+
virtualHosts = append(virtualHosts, &route.VirtualHost{
348+
Name: r.Name,
349+
Domains: []string{r.Match.Host},
350+
Routes: []*route.Route{{
351+
Match: &route.RouteMatch{
352+
PathSpecifier: &route.RouteMatch_Prefix{
353+
Prefix: r.Match.Prefix,
354+
},
355+
},
356+
Action: &route.Route_Route{
357+
Route: &route.RouteAction{
358+
ClusterSpecifier: &route.RouteAction_Cluster{
359+
Cluster: clusterName(r),
360+
},
361+
// disable with 0 value
362+
Timeout: &durationpb.Duration{},
363+
},
364+
},
365+
TypedPerFilterConfig: map[string]*anypb.Any{},
366+
}}})
367+
}
368+
}
369+
370+
// only include the default virtual host if it's being used
371+
if len(defaultVirtualHost.Routes) > 0 {
372+
virtualHosts = append(virtualHosts, defaultVirtualHost)
373+
}
374+
375+
// TODO: This is a bit of a hack to force simple prefixes like "/" to be pushed to the last place in the routes slice.
376+
// Doing this is important since you might have multiple services (routes) attached to a single host with
377+
// one hosting a web-client with a prefix of "/" and others hosting APIs with prefixes like "/examples.crud.v1.CrudService/".
378+
// This needs to be revisited with a proper pattern defined for enabling developers to define RouteMatch ordering.
379+
for _, vh := range virtualHosts {
380+
slices.SortFunc(vh.Routes, func(a, b *route.Route) int {
381+
return cmp.Compare(b.Match.GetPrefix(), a.Match.GetPrefix())
382+
})
342383
}
343384

344385
return &route.RouteConfiguration{

services/core/fuse/go.mod

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@ module github.com/steady-bytes/draft/services/core/fuse
22

33
go 1.23.2
44

5-
// replace (
6-
// github.com/steady-bytes/draft/api => ../../../api
7-
// github.com/steady-bytes/draft/pkg/chassis => ../../../pkg/chassis
8-
// )
9-
105
require (
116
connectrpc.com/connect v1.16.2
127
github.com/envoyproxy/go-control-plane v0.12.0
138
github.com/google/uuid v1.6.0
149
github.com/steady-bytes/draft/api v1.0.0
15-
github.com/steady-bytes/draft/pkg/chassis v0.4.1
10+
github.com/steady-bytes/draft/pkg/chassis v0.4.3
1611
github.com/steady-bytes/draft/pkg/loggers v0.2.3
1712
google.golang.org/protobuf v1.34.2
1813
)

services/core/fuse/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
163163
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
164164
github.com/steady-bytes/draft/api v1.0.0 h1:QIvboAJgU0fBOV6BKChLMhHYIjBTR53+LJaR3w3g0NY=
165165
github.com/steady-bytes/draft/api v1.0.0/go.mod h1:mlwxjvRiqvwySGdzVmF8voFhMffWq2F7dyd+xt6kENA=
166-
github.com/steady-bytes/draft/pkg/chassis v0.4.1 h1:ZJLaNUyxnhm8vAzvNYDus+xUarczBGNQOtwi12m2EJM=
167-
github.com/steady-bytes/draft/pkg/chassis v0.4.1/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM=
166+
github.com/steady-bytes/draft/pkg/chassis v0.4.3 h1:M2uCRbPbU8McweZBEQSmehOfyYsa8vkUFjgjhZ/0Wz0=
167+
github.com/steady-bytes/draft/pkg/chassis v0.4.3/go.mod h1:Ee6UcaJ5rJbElW7t0pgryhir3qb12rmHhHKiyrTrdxM=
168168
github.com/steady-bytes/draft/pkg/loggers v0.2.3 h1:tZadHH8f9fo+tRHVp3BaJlVYvKlrlX8Hd6LxncUVgAM=
169169
github.com/steady-bytes/draft/pkg/loggers v0.2.3/go.mod h1:nXeOQ6lXhsVWHzRqVcJz0JIeSW75ORVN+0izJwwnH+Y=
170170
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

services/core/fuse/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func main() {
1919

2020
defer chassis.New(logger).
2121
Register(chassis.RegistrationOptions{
22-
Namespace: "fuse",
22+
Namespace: "core",
2323
}).
2424
WithRPCHandler(xdsServer).
2525
WithRPCHandler(controlPlaneRPC).

0 commit comments

Comments
 (0)