Skip to content

Commit b2469b9

Browse files
committed
Implement new hook method PostEndpointsModifyHook
Signed-off-by: Marc Navarro Sonnenfeld <marcnavarro@tetrate.io>
1 parent 0fe85de commit b2469b9

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

internal/extension/registry/composite_hook_client.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010

1111
cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
12+
endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
1213
listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
1314
route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
1415
tls "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
@@ -70,6 +71,21 @@ func (c *compositeXDSHookClient) PostVirtualHostModifyHook(vh *route.VirtualHost
7071
return current, nil
7172
}
7273

74+
func (c *compositeXDSHookClient) PostEndpointsModifyHook(loadAssignment *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
75+
current := loadAssignment
76+
for _, entry := range c.entries {
77+
result, err := entry.client.PostEndpointsModifyHook(current)
78+
if err != nil {
79+
if entry.failOpen {
80+
continue
81+
}
82+
return nil, fmt.Errorf("extension %q: %w", entry.name, err)
83+
}
84+
current = result
85+
}
86+
return current, nil
87+
}
88+
7389
func (c *compositeXDSHookClient) PostHTTPListenerModifyHook(l *listener.Listener, extensionResources []*unstructured.Unstructured) (*listener.Listener, error) {
7490
current := l
7591
for _, entry := range c.entries {

internal/extension/registry/composite_hook_client_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"testing"
1111

1212
cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
13+
endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
1314
listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
1415
route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
1516
tls "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
@@ -29,6 +30,7 @@ import (
2930
type mockXDSHookClient struct {
3031
postRouteModifyHook func(r *route.Route, hostnames []string, resources []*unstructured.Unstructured) (*route.Route, error)
3132
postVirtualHostModifyHook func(vh *route.VirtualHost) (*route.VirtualHost, error)
33+
postEndpointsModifyHook func(loadAssignment *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error)
3234
postHTTPListenerModifyHook func(l *listener.Listener, resources []*unstructured.Unstructured) (*listener.Listener, error)
3335
postClusterModifyHook func(c *cluster.Cluster, resources []*unstructured.Unstructured) (*cluster.Cluster, error)
3436
postTranslateModifyHook func(clusters []*cluster.Cluster, secrets []*tls.Secret, listeners []*listener.Listener, routes []*route.RouteConfiguration, policies []*ir.UnstructuredRef) ([]*cluster.Cluster, []*tls.Secret, []*listener.Listener, []*route.RouteConfiguration, error)
@@ -50,6 +52,13 @@ func (m *mockXDSHookClient) PostVirtualHostModifyHook(vh *route.VirtualHost) (*r
5052
return vh, nil
5153
}
5254

55+
func (m *mockXDSHookClient) PostEndpointsModifyHook(loadAssignment *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
56+
if m.postEndpointsModifyHook != nil {
57+
return m.postEndpointsModifyHook(loadAssignment)
58+
}
59+
return loadAssignment, nil
60+
}
61+
5362
func (m *mockXDSHookClient) PostHTTPListenerModifyHook(l *listener.Listener, resources []*unstructured.Unstructured) (*listener.Listener, error) {
5463
if m.postHTTPListenerModifyHook != nil {
5564
return m.postHTTPListenerModifyHook(l, resources)
@@ -302,6 +311,81 @@ func TestCompositeHookClient_PostVirtualHostModifyHook(t *testing.T) {
302311
})
303312
}
304313

314+
func TestCompositeHookClient_PostEndpointsModifyHook(t *testing.T) {
315+
t.Run("chains two clients", func(t *testing.T) {
316+
client1 := &mockXDSHookClient{
317+
postEndpointsModifyHook: func(la *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
318+
la.ClusterName += "-ext1"
319+
return la, nil
320+
},
321+
}
322+
client2 := &mockXDSHookClient{
323+
postEndpointsModifyHook: func(la *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
324+
la.ClusterName += "-ext2"
325+
return la, nil
326+
},
327+
}
328+
329+
composite := &compositeXDSHookClient{
330+
entries: []hookClientEntry{
331+
{name: "ext1", client: client1},
332+
{name: "ext2", client: client2},
333+
},
334+
}
335+
336+
input := &endpoint.ClusterLoadAssignment{ClusterName: "test"}
337+
result, err := composite.PostEndpointsModifyHook(input)
338+
require.NoError(t, err)
339+
require.Equal(t, "test-ext1-ext2", result.ClusterName)
340+
})
341+
342+
t.Run("failOpen skips erroring extension", func(t *testing.T) {
343+
composite := &compositeXDSHookClient{
344+
entries: []hookClientEntry{
345+
{name: "ext1", client: &mockXDSHookClient{
346+
postEndpointsModifyHook: func(_ *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
347+
return nil, fmt.Errorf("extension error")
348+
},
349+
}, failOpen: true},
350+
{name: "ext2", client: &mockXDSHookClient{
351+
postEndpointsModifyHook: func(la *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
352+
la.ClusterName += "-ext2"
353+
return la, nil
354+
},
355+
}},
356+
},
357+
}
358+
359+
result, err := composite.PostEndpointsModifyHook(&endpoint.ClusterLoadAssignment{ClusterName: "test"})
360+
require.NoError(t, err)
361+
require.Equal(t, "test-ext2", result.ClusterName)
362+
})
363+
364+
t.Run("failClosed stops chain", func(t *testing.T) {
365+
client2Called := false
366+
composite := &compositeXDSHookClient{
367+
entries: []hookClientEntry{
368+
{name: "ext1", client: &mockXDSHookClient{
369+
postEndpointsModifyHook: func(_ *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
370+
return nil, fmt.Errorf("extension error")
371+
},
372+
}, failOpen: false},
373+
{name: "ext2", client: &mockXDSHookClient{
374+
postEndpointsModifyHook: func(la *endpoint.ClusterLoadAssignment) (*endpoint.ClusterLoadAssignment, error) {
375+
client2Called = true
376+
la.ClusterName += "-ext2"
377+
return la, nil
378+
},
379+
}},
380+
},
381+
}
382+
383+
_, err := composite.PostEndpointsModifyHook(&endpoint.ClusterLoadAssignment{ClusterName: "test"})
384+
require.Equal(t, fmt.Errorf(`extension "ext1": %w`, fmt.Errorf("extension error")), err)
385+
require.False(t, client2Called)
386+
})
387+
}
388+
305389
func TestCompositeHookClient_PostHTTPListenerModifyHook(t *testing.T) {
306390
t.Run("chains two clients", func(t *testing.T) {
307391
client1 := &mockXDSHookClient{

0 commit comments

Comments
 (0)