Skip to content

Commit 1acd61e

Browse files
committed
Add resilience tests for multiple ExtensionManagers chaining and resource isolation
Enhance the simple-extension-server with a configurable --suffix flag and resource-aware PostRouteModify to support testing multiple extension managers. Add resilience tests that verify sequential chaining of VirtualHost mutations and per-extension resource isolation via extensionRef filters. Signed-off-by: Marc Navarro Sonnenfeld <marcnavarro@tetrate.io>
1 parent 8c8a814 commit 1acd61e

13 files changed

Lines changed: 405 additions & 36 deletions

File tree

examples/envoy-ext-auth/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/envoyproxy/gateway-grcp-ext-auth
33
go 1.26.1
44

55
require (
6-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f
6+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097
77
github.com/golang/protobuf v1.5.4
88
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409
99
google.golang.org/grpc v1.79.2

examples/grpc-ext-proc/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ module github.com/envoyproxy/gateway-grpc-ext-proc
33
go 1.26.1
44

55
require (
6-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f
6+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097
77
google.golang.org/grpc v1.79.2
88
google.golang.org/protobuf v1.36.11
99
)
1010

1111
require (
1212
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
13-
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
13+
github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect
1414
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
1515
golang.org/x/net v0.51.0 // indirect
1616
golang.org/x/sys v0.41.0 // indirect

examples/grpc-ext-proc/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
22
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
33
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w=
44
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
5-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f h1:mmro2RvL73rtCCLoFLel4Tw1C4eECzuvRFN9HkHgOV4=
6-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f/go.mod h1:LvH/DJfCl4Wx096uo+ilpBo9tvnMXlAfD0+xIDob/Ic=
7-
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
8-
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
5+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097 h1:Ou9X6qsPOiDOsQgaboj3jlCE5ZYngdYeSVDKBcT95QE=
6+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097/go.mod h1:237/ZQHepDd4v5BjpRNFI2mMG7WEBd+mQnt8jwbqrnk=
7+
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
8+
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
99
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
1010
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
1111
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=

examples/simple-extension-server/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.26.1
44

55
require (
66
github.com/envoyproxy/gateway v1.7.0
7+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097
78
github.com/urfave/cli/v2 v2.27.7
89
google.golang.org/grpc v1.79.2
910
)
@@ -12,8 +13,7 @@ require (
1213
cel.dev/expr v0.25.1 // indirect
1314
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
1415
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
15-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f // indirect
16-
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
16+
github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect
1717
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
1818
github.com/russross/blackfriday/v2 v2.1.0 // indirect
1919
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect

examples/simple-extension-server/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3
88
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
99
github.com/envoyproxy/gateway v1.7.0 h1:noVz4fADhljSKpQFaspb25+C3kC8bBBisQZle9W0ei4=
1010
github.com/envoyproxy/gateway v1.7.0/go.mod h1:U/UXS8G6Q5SldcKubP8PZazD9OsNT0Mf1XzCVig0KkQ=
11-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f h1:mmro2RvL73rtCCLoFLel4Tw1C4eECzuvRFN9HkHgOV4=
12-
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260217184816-6318b674fe2f/go.mod h1:LvH/DJfCl4Wx096uo+ilpBo9tvnMXlAfD0+xIDob/Ic=
13-
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
14-
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
11+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097 h1:Ou9X6qsPOiDOsQgaboj3jlCE5ZYngdYeSVDKBcT95QE=
12+
github.com/envoyproxy/go-control-plane/envoy v1.37.1-0.20260304210048-a81710db7097/go.mod h1:237/ZQHepDd4v5BjpRNFI2mMG7WEBd+mQnt8jwbqrnk=
13+
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
14+
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
1515
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
1616
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
1717
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=

examples/simple-extension-server/main.go

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import (
1515
"strings"
1616
"syscall"
1717

18+
pb "github.com/envoyproxy/gateway/proto/extension"
19+
corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
1820
"github.com/urfave/cli/v2"
1921
"google.golang.org/grpc"
2022
"google.golang.org/grpc/codes"
2123
"google.golang.org/grpc/status"
22-
23-
pb "github.com/envoyproxy/gateway/proto/extension"
2424
)
2525

2626
func main() {
@@ -54,16 +54,25 @@ func main() {
5454
DefaultText: "Info",
5555
Value: "Info",
5656
},
57+
&cli.StringFlag{
58+
Name: "suffix",
59+
Usage: "suffix appended to VirtualHost domains and used in response headers",
60+
DefaultText: "extserver",
61+
Value: "extserver",
62+
},
5763
},
5864
},
5965
},
6066
}
61-
app.Run(os.Args)
67+
err := app.Run(os.Args)
68+
if err != nil {
69+
panic(err)
70+
}
6271
}
6372

6473
var grpcServer *grpc.Server
6574

66-
func handleSignals(cCtx *cli.Context) error {
75+
func handleSignals(_ *cli.Context) error {
6776
c := make(chan os.Signal, 1)
6877
signal.Notify(c, os.Interrupt, syscall.SIGQUIT)
6978
go func() {
@@ -94,57 +103,70 @@ func startExtensionServer(cCtx *cli.Context) error {
94103
var opts []grpc.ServerOption
95104
grpcServer = grpc.NewServer(opts...)
96105
sig := make(chan int, 1)
97-
pb.RegisterEnvoyGatewayExtensionServer(grpcServer, New(logger, sig))
106+
pb.RegisterEnvoyGatewayExtensionServer(grpcServer, New(logger, sig, cCtx.String("suffix")))
98107
return grpcServer.Serve(lis)
99108
}
100109

101110
type Server struct {
102111
pb.UnimplementedEnvoyGatewayExtensionServer
103-
sig chan int
104-
log *slog.Logger
112+
sig chan int
113+
log *slog.Logger
114+
suffix string
105115
}
106116

107-
func New(logger *slog.Logger, sig chan int) *Server {
117+
func New(logger *slog.Logger, sig chan int, suffix string) *Server {
108118
return &Server{
109-
log: logger,
110-
sig: sig,
119+
log: logger,
120+
sig: sig,
121+
suffix: suffix,
111122
}
112123
}
113124

114-
func (s *Server) PostRouteModify(ctx context.Context, req *pb.PostRouteModifyRequest) (*pb.PostRouteModifyResponse, error) {
125+
func (s *Server) PostRouteModify(_ context.Context, req *pb.PostRouteModifyRequest) (*pb.PostRouteModifyResponse, error) {
115126
s.log.Info("PostRouteModify callback was invoked")
116127

128+
if req.PostRouteContext != nil && len(req.PostRouteContext.ExtensionResources) > 0 {
129+
s.log.Info("PostRouteModify received extension resources, adding response header",
130+
slog.Int("count", len(req.PostRouteContext.ExtensionResources)))
131+
req.Route.ResponseHeadersToAdd = append(req.Route.ResponseHeadersToAdd, &corev3.HeaderValueOption{
132+
Header: &corev3.HeaderValue{
133+
Key: "x-ext-server",
134+
Value: s.suffix,
135+
},
136+
})
137+
}
138+
117139
return &pb.PostRouteModifyResponse{
118140
Route: req.Route,
119141
}, nil
120142
}
121143

122-
func (s *Server) PostVirtualHostModify(ctx context.Context, req *pb.PostVirtualHostModifyRequest) (*pb.PostVirtualHostModifyResponse, error) {
144+
func (s *Server) PostVirtualHostModify(_ context.Context, req *pb.PostVirtualHostModifyRequest) (*pb.PostVirtualHostModifyResponse, error) {
123145
s.log.Info("PostVirtualHostModify callback was invoked")
124146

125147
if strings.Contains(req.VirtualHost.Name, "fail") {
126148
s.log.Info("PostVirtualHostModify returning unavailable error")
127149
return nil, status.Error(codes.Unavailable, "Service is currently unavailable")
128-
} else {
129-
s.log.Info("PostVirtualHostModify sending response")
130-
if len(req.VirtualHost.Domains) > 0 {
131-
req.VirtualHost.Domains = append(req.VirtualHost.Domains, fmt.Sprintf("%s.extserver", req.VirtualHost.Domains[0]))
132-
}
133-
return &pb.PostVirtualHostModifyResponse{
134-
VirtualHost: req.VirtualHost,
135-
}, nil
136150
}
151+
152+
s.log.Info("PostVirtualHostModify sending response")
153+
if len(req.VirtualHost.Domains) > 0 {
154+
req.VirtualHost.Domains = append(req.VirtualHost.Domains, fmt.Sprintf("%s.%s", req.VirtualHost.Domains[0], s.suffix))
155+
}
156+
return &pb.PostVirtualHostModifyResponse{
157+
VirtualHost: req.VirtualHost,
158+
}, nil
137159
}
138160

139-
func (s *Server) PostHTTPListenerModify(ctx context.Context, req *pb.PostHTTPListenerModifyRequest) (*pb.PostHTTPListenerModifyResponse, error) {
161+
func (s *Server) PostHTTPListenerModify(_ context.Context, req *pb.PostHTTPListenerModifyRequest) (*pb.PostHTTPListenerModifyResponse, error) {
140162
s.log.Info("postHTTPListenerModify callback was invoked")
141163

142164
return &pb.PostHTTPListenerModifyResponse{
143165
Listener: req.Listener,
144166
}, nil
145167
}
146168

147-
func (s *Server) PostTranslateModify(ctx context.Context, req *pb.PostTranslateModifyRequest) (*pb.PostTranslateModifyResponse, error) {
169+
func (s *Server) PostTranslateModify(_ context.Context, req *pb.PostTranslateModifyRequest) (*pb.PostTranslateModifyResponse, error) {
148170
s.log.Info("PostTranslateModify callback was invoked")
149171

150172
return &pb.PostTranslateModifyResponse{
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: gateway-ext-server-a
5+
namespace: envoy-gateway-system
6+
spec:
7+
type: ClusterIP
8+
ports:
9+
- port: 5005
10+
targetPort: 5005
11+
protocol: TCP
12+
name: grpc-gw-ext
13+
selector:
14+
app.kubernetes.io/name: gateway-ext-server-a
15+
---
16+
apiVersion: apps/v1
17+
kind: Deployment
18+
metadata:
19+
name: gateway-ext-server-a
20+
namespace: envoy-gateway-system
21+
labels:
22+
app.kubernetes.io/name: gateway-ext-server-a
23+
spec:
24+
replicas: 1
25+
selector:
26+
matchLabels:
27+
app.kubernetes.io/name: gateway-ext-server-a
28+
template:
29+
metadata:
30+
labels:
31+
app.kubernetes.io/name: gateway-ext-server-a
32+
spec:
33+
containers:
34+
- name: gateway-ext-server-a
35+
image: envoyproxy/gateway-simple-extension-server:latest
36+
imagePullPolicy: IfNotPresent
37+
args:
38+
- server
39+
- --suffix=ext-a
40+
ports:
41+
- name: grpc-gw-ext
42+
containerPort: 5005
43+
protocol: TCP
44+
---
45+
apiVersion: v1
46+
kind: Service
47+
metadata:
48+
name: gateway-ext-server-b
49+
namespace: envoy-gateway-system
50+
spec:
51+
type: ClusterIP
52+
ports:
53+
- port: 5005
54+
targetPort: 5005
55+
protocol: TCP
56+
name: grpc-gw-ext
57+
selector:
58+
app.kubernetes.io/name: gateway-ext-server-b
59+
---
60+
apiVersion: apps/v1
61+
kind: Deployment
62+
metadata:
63+
name: gateway-ext-server-b
64+
namespace: envoy-gateway-system
65+
labels:
66+
app.kubernetes.io/name: gateway-ext-server-b
67+
spec:
68+
replicas: 1
69+
selector:
70+
matchLabels:
71+
app.kubernetes.io/name: gateway-ext-server-b
72+
template:
73+
metadata:
74+
labels:
75+
app.kubernetes.io/name: gateway-ext-server-b
76+
spec:
77+
containers:
78+
- name: gateway-ext-server-b
79+
image: envoyproxy/gateway-simple-extension-server:latest
80+
imagePullPolicy: IfNotPresent
81+
args:
82+
- server
83+
- --suffix=ext-b
84+
ports:
85+
- name: grpc-gw-ext
86+
containerPort: 5005
87+
protocol: TCP
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: envoy-gateway-config
5+
namespace: envoy-gateway-system
6+
data:
7+
envoy-gateway.yaml: |
8+
apiVersion: gateway.envoyproxy.io/v1alpha1
9+
kind: EnvoyGateway
10+
provider:
11+
type: Kubernetes
12+
gateway:
13+
controllerName: gateway.envoyproxy.io/gatewayclass-controller
14+
extensionApis:
15+
enableEnvoyPatchPolicy: true
16+
enableBackend: true
17+
extensionManagers:
18+
- name: ext-a
19+
resources:
20+
- group: ext-a.example.io
21+
version: v1
22+
kind: FooFilter
23+
hooks:
24+
xdsTranslator:
25+
post:
26+
- VirtualHost
27+
- Route
28+
service:
29+
fqdn:
30+
hostname: gateway-ext-server-a.envoy-gateway-system.svc.cluster.local
31+
port: 5005
32+
- name: ext-b
33+
resources:
34+
- group: ext-b.example.io
35+
version: v1
36+
kind: BarFilter
37+
hooks:
38+
xdsTranslator:
39+
post:
40+
- VirtualHost
41+
- Route
42+
service:
43+
fqdn:
44+
hostname: gateway-ext-server-b.envoy-gateway-system.svc.cluster.local
45+
port: 5005
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: foofilters.ext-a.example.io
5+
spec:
6+
group: ext-a.example.io
7+
names:
8+
kind: FooFilter
9+
plural: foofilters
10+
singular: foofilter
11+
scope: Namespaced
12+
versions:
13+
- name: v1
14+
served: true
15+
storage: true
16+
schema:
17+
openAPIV3Schema:
18+
type: object
19+
properties:
20+
spec:
21+
type: object
22+
properties:
23+
value:
24+
type: string
25+
---
26+
apiVersion: apiextensions.k8s.io/v1
27+
kind: CustomResourceDefinition
28+
metadata:
29+
name: barfilters.ext-b.example.io
30+
spec:
31+
group: ext-b.example.io
32+
names:
33+
kind: BarFilter
34+
plural: barfilters
35+
singular: barfilter
36+
scope: Namespaced
37+
versions:
38+
- name: v1
39+
served: true
40+
storage: true
41+
schema:
42+
openAPIV3Schema:
43+
type: object
44+
properties:
45+
spec:
46+
type: object
47+
properties:
48+
value:
49+
type: string

0 commit comments

Comments
 (0)