Skip to content

Commit

Permalink
feature: Allow Gateways to select the target port, fixes #50
Browse files Browse the repository at this point in the history
  • Loading branch information
rg0now committed Jul 23, 2024
1 parent 542a4d1 commit 450f86e
Show file tree
Hide file tree
Showing 9 changed files with 472 additions and 122 deletions.
4 changes: 2 additions & 2 deletions internal/renderer/gateway_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func TestRenderGatewayUtil(t *testing.T) {
}

_, err := r.renderListener(gw, c.gwConf, &l,
[]*stnrgwv1.UDPRoute{}, addr)
[]*stnrgwv1.UDPRoute{}, addr, nil)

if err != nil {
setListenerStatus(gw, &l, err, conflicted, 0)
Expand Down Expand Up @@ -324,7 +324,7 @@ func TestRenderGatewayUtil(t *testing.T) {
}

_, err := r.renderListener(gw, c.gwConf, &l,
[]*stnrgwv1.UDPRoute{}, addr)
[]*stnrgwv1.UDPRoute{}, addr, nil)

if err != nil {
setListenerStatus(gw, &l, err, conflicted, 0)
Expand Down
11 changes: 9 additions & 2 deletions internal/renderer/listener_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func stnrListenerName(gw *gwapiv1.Gateway, l *gwapiv1.Listener) string {
return fmt.Sprintf("%s/%s", store.GetObjectKey(gw), string(l.Name))
}

func (r *Renderer) renderListener(gw *gwapiv1.Gateway, gwConf *stnrgwv1.GatewayConfig, l *gwapiv1.Listener, rs []*stnrgwv1.UDPRoute, ap gwAddrPort) (*stnrconfv1.ListenerConfig, error) {
func (r *Renderer) renderListener(gw *gwapiv1.Gateway, gwConf *stnrgwv1.GatewayConfig, l *gwapiv1.Listener, rs []*stnrgwv1.UDPRoute, ap gwAddrPort, targetPorts map[string]int) (*stnrconfv1.ListenerConfig, error) {
// r.log.V(4).Info("renderListener", "gateway", store.GetObjectKey(gw), "gateway-config",
// store.GetObjectKey(gwConf), "listener", l.Name, "route number", len(rs), "public-addr", ap.String())

Expand All @@ -28,11 +28,18 @@ func (r *Renderer) renderListener(gw *gwapiv1.Gateway, gwConf *stnrgwv1.GatewayC
return nil, err
}

port := int(l.Port)
if targetPorts != nil {
if p, ok := targetPorts[string(l.Name)]; ok {
port = p
}
}

lc := stnrconfv1.ListenerConfig{
Name: stnrListenerName(gw, l),
Protocol: proto.String(),
Addr: "$STUNNER_ADDR", // Addr will be filled in from the pod environment
Port: int(l.Port),
Port: port,
}

// set public address-port
Expand Down
36 changes: 18 additions & 18 deletions internal/renderer/listener_render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-udp", lc.Name, "name")
assert.Equal(t, "TURN-UDP", lc.Protocol, "proto")
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestRenderListenerRender(t *testing.T) {
addr: "1.2.3.4",
port: 1234,
}
_, err = r.renderListener(gw, c.gwConf, &l, []*stnrgwv1.UDPRoute{}, addr)
_, err = r.renderListener(gw, c.gwConf, &l, []*stnrgwv1.UDPRoute{}, addr, nil)
assert.Error(t, err, "render fails")
},
},
Expand Down Expand Up @@ -121,7 +121,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 4321,
}

lc, err := r.renderListener(gw, c.gwConf, &l, []*stnrgwv1.UDPRoute{}, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, []*stnrgwv1.UDPRoute{}, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tcp", lc.Name, "name")
assert.Equal(t, "TURN-TCP", lc.Protocol, "proto")
Expand Down Expand Up @@ -166,7 +166,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 4321,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-udp", lc.Name, "name")
assert.Equal(t, "TURN-UDP", lc.Protocol, "proto")
Expand Down Expand Up @@ -212,7 +212,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 4321,
}

_, err = r.renderListener(gw, c.gwConf, &l, rs, addr)
_, err = r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.Error(t, err, "wrong-proto")
},
},
Expand Down Expand Up @@ -272,7 +272,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-udp", lc.Name, "name")
assert.Equal(t, "TURN-UDP", lc.Protocol, "proto")
Expand All @@ -282,7 +282,7 @@ func TestRenderListenerRender(t *testing.T) {
assert.Equal(t, "", lc.Key, "key")

l = ls[1]
lc, err = r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err = r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand All @@ -292,7 +292,7 @@ func TestRenderListenerRender(t *testing.T) {
assert.Equal(t, testutils.TestKey64, lc.Key, "key")

l = ls[2]
lc, err = r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err = r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-dtls", lc.Name, "name")
assert.Equal(t, "TURN-DTLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -353,7 +353,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -406,7 +406,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -461,7 +461,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -516,7 +516,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -575,7 +575,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -634,7 +634,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -693,7 +693,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -752,7 +752,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -814,7 +814,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down Expand Up @@ -878,7 +878,7 @@ func TestRenderListenerRender(t *testing.T) {
port: 1234,
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr)
lc, err := r.renderListener(gw, c.gwConf, &l, rs, addr, nil)
assert.NoError(t, err, "renderListener")
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tls", lc.Name, "name")
assert.Equal(t, "TURN-TLS", lc.Protocol, "proto")
Expand Down
8 changes: 6 additions & 2 deletions internal/renderer/render_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,14 @@ func (r *Renderer) renderForGateways(c *RenderContext) error {
// recreate the LoadBalancer service, otherwise a changed
// GatewayConfig.Spec.LoadBalancerServiceAnnotation or Gateway annotation may not
// be reflected back to the service
if s := r.createLbService4Gateway(c, gw); s != nil {
targetPorts := map[string]int{} // when the user selects a particular target port
if s, ports := r.createLbService4Gateway(c, gw); s != nil {
log.Info("Creating public service for gateway", "service",
store.GetObjectKey(s), "gateway", store.GetObjectKey(gw),
"service", store.DumpObject(s))

c.update.UpsertQueue.Services.Upsert(s)
targetPorts = ports
}

udpPorts := make(map[int]bool)
Expand All @@ -287,7 +289,9 @@ func (r *Renderer) renderForGateways(c *RenderContext) error {
continue
}

lc, err := r.renderListener(gw, c.gwConf, &l, rs, pubGwAddrs[j])
// the Gateway may remap the listener's target port from an annotation:
// this is indicated in targetPorts
lc, err := r.renderListener(gw, c.gwConf, &l, rs, pubGwAddrs[j], targetPorts)
if err != nil {
// all listener rendering errors are critical: prevent the
// rendering of the listener config
Expand Down
90 changes: 90 additions & 0 deletions internal/renderer/render_pipeline_managed_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1971,5 +1971,95 @@ func TestRenderPipelineManagedMode(t *testing.T) {
config.DataplaneMode = config.NewDataplaneMode(opdefault.DefaultDataplaneMode)
},
},
{
name: "targetport enforced",
cls: []gwapiv1.GatewayClass{testutils.TestGwClass},
cfs: []stnrgwv1.GatewayConfig{testutils.TestGwConfig},
gws: []gwapiv1.Gateway{testutils.TestGw},
rs: []stnrgwv1.UDPRoute{testutils.TestUDPRoute},
svcs: []corev1.Service{testutils.TestSvc},
dps: []stnrgwv1.Dataplane{testutils.TestDataplane},
prep: func(c *renderTestConfig) {
gw := testutils.TestGw.DeepCopy()
gw.SetAnnotations(map[string]string{
opdefault.TargetPortAnnotationKey: "{\"gateway-1-listener-udp\":11,\"dummy\":12,\"gateway-1-listener-tcp\":13}",
})
c.gws = []gwapiv1.Gateway{*gw}

// update owner ref so that we accept the public IP
s := testutils.TestSvc.DeepCopy()
s.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: gwapiv1.GroupVersion.String(),
Kind: "Gateway",
UID: testutils.TestGw.GetUID(),
Name: testutils.TestGw.GetName(),
}})
c.svcs = []corev1.Service{*s}
},
tester: func(t *testing.T, r *Renderer) {
config.DataplaneMode = config.DataplaneModeManaged
config.EnableEndpointDiscovery = true
config.EnableRelayToClusterIP = true

gc, err := r.getGatewayClass()
assert.NoError(t, err, "gw-class found")
c := &RenderContext{gc: gc, gws: store.NewGatewayStore(), log: logr.Discard()}
c.gwConf, err = r.getGatewayConfig4Class(c)
assert.NoError(t, err, "gw-conf found")
assert.Equal(t, "gatewayconfig-ok", c.gwConf.GetName(),
"gatewayconfig name")

c.update = event.NewEventUpdate(0)
assert.NotNil(t, c.update, "update event create")

gws := r.getGateways4Class(c)
assert.Len(t, gws, 1, "gateways for class")
gw := gws[0]

c.gws.ResetGateways([]*gwapiv1.Gateway{gw})

err = r.renderForGateways(c)
assert.NoError(t, err, "render success")

// config-queue
cs := c.update.ConfigQueue
assert.Len(t, cs, 1, "configmap ready")
conf := cs[0]

assert.Equal(t, "testnamespace/gateway-1", conf.Admin.Name, "name")
assert.Equal(t, testutils.TestLogLevel, conf.Admin.LogLevel,
"loglevel")

assert.Equal(t, testutils.TestRealm, conf.Auth.Realm, "realm")
assert.Equal(t, "static", conf.Auth.Type, "auth-type")
assert.Equal(t, testutils.TestUsername, conf.Auth.Credentials["username"],
"username")
assert.Equal(t, testutils.TestPassword, conf.Auth.Credentials["password"],
"password")

assert.Len(t, conf.Listeners, 2, "listener num")
lc := conf.Listeners[0]
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-udp", lc.Name, "name")
assert.Equal(t, "TURN-UDP", lc.Protocol, "proto")
assert.Equal(t, 11, lc.Port, "port") // targetport!!!!
assert.Equal(t, "1.2.3.4", lc.PublicAddr, "public-ip")
assert.Equal(t, 1, lc.PublicPort, "public-port")
assert.Len(t, lc.Routes, 1, "route num")
assert.Equal(t, lc.Routes[0], "testnamespace/udproute-ok", "udp route")

lc = conf.Listeners[1]
assert.Equal(t, "testnamespace/gateway-1/gateway-1-listener-tcp", lc.Name, "name")
assert.Equal(t, "TURN-TCP", lc.Protocol, "proto")
assert.Equal(t, 13, lc.Port, "port") // targetport!!!
assert.Equal(t, "1.2.3.4", lc.PublicAddr, "public-ip")
assert.Equal(t, 2, lc.PublicPort, "public-port")
assert.Len(t, lc.Routes, 0, "route num")

// restore EDS
config.EnableEndpointDiscovery = opdefault.DefaultEnableEndpointDiscovery
config.EnableRelayToClusterIP = opdefault.DefaultEnableRelayToClusterIP
config.DataplaneMode = config.NewDataplaneMode(opdefault.DefaultDataplaneMode)
},
},
})
}
Loading

0 comments on commit 450f86e

Please sign in to comment.