Skip to content

Commit 8671366

Browse files
authored
Merge branch 'main' into docs/authentication-filter-proposal-functional-tests
2 parents 67292f2 + 89aee48 commit 8671366

File tree

17 files changed

+1387
-349
lines changed

17 files changed

+1387
-349
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ require (
2121
go.uber.org/zap v1.27.1
2222
golang.org/x/text v0.32.0
2323
google.golang.org/grpc v1.77.0
24-
google.golang.org/protobuf v1.36.10
24+
google.golang.org/protobuf v1.36.11
2525
gopkg.in/evanphx/json-patch.v4 v4.13.0
2626
k8s.io/api v0.34.3
2727
k8s.io/apiextensions-apiserver v0.34.3

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:
331331
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
332332
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
333333
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
334-
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
335-
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
334+
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
335+
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
336336
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
337337
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
338338
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

internal/controller/nginx/config/maps.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
44
"fmt"
5+
"sort"
56
"strings"
67
gotemplate "text/template"
78

@@ -185,14 +186,21 @@ func createAddHeadersMap(name string) shared.Map {
185186

186187
// buildInferenceMaps creates maps for InferencePool Backends.
187188
func buildInferenceMaps(groups []dataplane.BackendGroup) []shared.Map {
188-
inferenceMaps := make([]shared.Map, 0, len(groups))
189+
uniqueMaps := make(map[string]shared.Map)
189190

190191
for _, group := range groups {
191192
for _, backend := range group.Backends {
192193
if backend.EndpointPickerConfig == nil || backend.EndpointPickerConfig.EndpointPickerRef == nil {
193194
continue
194195
}
195196

197+
backendVarName := strings.ReplaceAll(backend.UpstreamName, "-", "_")
198+
mapKey := backendVarName // Use this as the key to detect duplicates
199+
200+
// Skip if we've already processed this upstream
201+
if _, exists := uniqueMaps[mapKey]; exists {
202+
continue
203+
}
196204
// Decide what the map must return when the picker didn’t set a value.
197205
var defaultResult string
198206
switch backend.EndpointPickerConfig.EndpointPickerRef.FailureMode {
@@ -230,14 +238,26 @@ func buildInferenceMaps(groups []dataplane.BackendGroup) []shared.Map {
230238
Result: defaultResult,
231239
})
232240

233-
backendVarName := strings.ReplaceAll(backend.UpstreamName, "-", "_")
234-
235-
inferenceMaps = append(inferenceMaps, shared.Map{
241+
uniqueMaps[mapKey] = shared.Map{
236242
Source: `$inference_workload_endpoint`,
237243
Variable: fmt.Sprintf("$inference_backend_%s", backendVarName),
238244
Parameters: params,
239-
})
245+
}
240246
}
241247
}
248+
249+
// Sort the map keys to ensure deterministic ordering
250+
mapKeys := make([]string, 0, len(uniqueMaps))
251+
for key := range uniqueMaps {
252+
mapKeys = append(mapKeys, key)
253+
}
254+
sort.Strings(mapKeys)
255+
256+
// Build the result slice in sorted order
257+
inferenceMaps := make([]shared.Map, 0, len(uniqueMaps))
258+
for _, key := range mapKeys {
259+
inferenceMaps = append(inferenceMaps, uniqueMaps[key])
260+
}
261+
242262
return inferenceMaps
243263
}

internal/controller/nginx/config/maps_test.go

Lines changed: 167 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -397,55 +397,183 @@ func TestCreateStreamMapsWithEmpty(t *testing.T) {
397397

398398
func TestBuildInferenceMaps(t *testing.T) {
399399
t.Parallel()
400-
g := NewWithT(t)
401400

402-
group := dataplane.BackendGroup{
403-
Backends: []dataplane.Backend{
404-
{
405-
UpstreamName: "upstream1",
406-
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
407-
NsName: "default",
408-
EndpointPickerRef: &inference.EndpointPickerRef{
409-
FailureMode: inference.EndpointPickerFailClose,
401+
tests := []struct {
402+
expectedConfig map[string]struct {
403+
failureMode inference.EndpointPickerFailureMode
404+
defaultResult string
405+
}
406+
name string
407+
backendGroups []dataplane.BackendGroup
408+
expectedMaps int
409+
}{
410+
{
411+
name: "unique backends with different failure modes, result is ordered by upstream name",
412+
backendGroups: []dataplane.BackendGroup{
413+
{
414+
Backends: []dataplane.Backend{
415+
{
416+
UpstreamName: "upstream2",
417+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
418+
NsName: "default",
419+
EndpointPickerRef: &inference.EndpointPickerRef{
420+
FailureMode: inference.EndpointPickerFailOpen,
421+
},
422+
},
423+
},
424+
{
425+
UpstreamName: "upstream1",
426+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
427+
NsName: "default",
428+
EndpointPickerRef: &inference.EndpointPickerRef{
429+
FailureMode: inference.EndpointPickerFailClose,
430+
},
431+
},
432+
},
433+
{
434+
UpstreamName: "upstream3",
435+
EndpointPickerConfig: nil,
436+
},
410437
},
411438
},
412439
},
413-
{
414-
UpstreamName: "upstream2",
415-
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
416-
NsName: "default",
417-
EndpointPickerRef: &inference.EndpointPickerRef{
418-
FailureMode: inference.EndpointPickerFailOpen,
440+
expectedMaps: 2,
441+
expectedConfig: map[string]struct {
442+
failureMode inference.EndpointPickerFailureMode
443+
defaultResult string
444+
}{
445+
"upstream1": {
446+
failureMode: inference.EndpointPickerFailClose,
447+
defaultResult: "invalid-backend-ref",
448+
},
449+
"upstream2": {
450+
failureMode: inference.EndpointPickerFailOpen,
451+
defaultResult: "upstream2",
452+
},
453+
},
454+
},
455+
{
456+
name: "duplicate upstreams should be deduplicated",
457+
backendGroups: []dataplane.BackendGroup{
458+
{
459+
Backends: []dataplane.Backend{
460+
{
461+
UpstreamName: "upstream1",
462+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
463+
NsName: "default",
464+
EndpointPickerRef: &inference.EndpointPickerRef{
465+
FailureMode: inference.EndpointPickerFailClose,
466+
},
467+
},
468+
},
469+
{
470+
UpstreamName: "upstream1", // Duplicate
471+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
472+
NsName: "default",
473+
EndpointPickerRef: &inference.EndpointPickerRef{
474+
FailureMode: inference.EndpointPickerFailClose,
475+
},
476+
},
477+
},
478+
},
479+
},
480+
{
481+
Backends: []dataplane.Backend{
482+
{
483+
UpstreamName: "upstream1", // Another duplicate
484+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
485+
NsName: "default",
486+
EndpointPickerRef: &inference.EndpointPickerRef{
487+
FailureMode: inference.EndpointPickerFailClose,
488+
},
489+
},
490+
},
491+
{
492+
UpstreamName: "upstream2",
493+
EndpointPickerConfig: &dataplane.EndpointPickerConfig{
494+
NsName: "default",
495+
EndpointPickerRef: &inference.EndpointPickerRef{
496+
FailureMode: inference.EndpointPickerFailOpen,
497+
},
498+
},
499+
},
419500
},
420501
},
421502
},
422-
{
423-
UpstreamName: "upstream3",
424-
EndpointPickerConfig: nil,
503+
expectedMaps: 2, // Only 2 unique upstreams
504+
expectedConfig: map[string]struct {
505+
failureMode inference.EndpointPickerFailureMode
506+
defaultResult string
507+
}{
508+
"upstream1": {
509+
failureMode: inference.EndpointPickerFailClose,
510+
defaultResult: "invalid-backend-ref",
511+
},
512+
"upstream2": {
513+
failureMode: inference.EndpointPickerFailOpen,
514+
defaultResult: "upstream2",
515+
},
425516
},
426517
},
518+
{
519+
name: "no endpoint picker configs",
520+
backendGroups: []dataplane.BackendGroup{
521+
{
522+
Backends: []dataplane.Backend{
523+
{
524+
UpstreamName: "upstream1",
525+
EndpointPickerConfig: nil,
526+
},
527+
{
528+
UpstreamName: "upstream2",
529+
EndpointPickerConfig: nil,
530+
},
531+
},
532+
},
533+
},
534+
expectedMaps: 0,
535+
},
427536
}
428537

429-
maps := buildInferenceMaps([]dataplane.BackendGroup{group})
430-
g.Expect(maps).To(HaveLen(2))
431-
g.Expect(maps[0].Source).To(Equal("$inference_workload_endpoint"))
432-
g.Expect(maps[0].Variable).To(Equal("$inference_backend_upstream1"))
433-
g.Expect(maps[0].Parameters).To(HaveLen(3))
434-
g.Expect(maps[0].Parameters[0].Value).To(Equal("\"\""))
435-
g.Expect(maps[0].Parameters[0].Result).To(Equal("upstream1"))
436-
g.Expect(maps[0].Parameters[1].Value).To(Equal("~.+"))
437-
g.Expect(maps[0].Parameters[1].Result).To(Equal("$inference_workload_endpoint"))
438-
g.Expect(maps[0].Parameters[2].Value).To(Equal("default"))
439-
g.Expect(maps[0].Parameters[2].Result).To(Equal("invalid-backend-ref"))
538+
for _, tc := range tests {
539+
t.Run(tc.name, func(t *testing.T) {
540+
t.Parallel()
541+
g := NewWithT(t)
542+
543+
maps := buildInferenceMaps(tc.backendGroups)
544+
g.Expect(maps).To(HaveLen(tc.expectedMaps))
440545

441-
// Check the second map
442-
g.Expect(maps[1].Source).To(Equal("$inference_workload_endpoint"))
443-
g.Expect(maps[1].Variable).To(Equal("$inference_backend_upstream2"))
444-
g.Expect(maps[1].Parameters).To(HaveLen(3))
445-
g.Expect(maps[1].Parameters[0].Value).To(Equal("\"\""))
446-
g.Expect(maps[1].Parameters[0].Result).To(Equal("upstream2"))
447-
g.Expect(maps[1].Parameters[1].Value).To(Equal("~.+"))
448-
g.Expect(maps[1].Parameters[1].Result).To(Equal("$inference_workload_endpoint"))
449-
g.Expect(maps[1].Parameters[2].Value).To(Equal("default"))
450-
g.Expect(maps[1].Parameters[2].Result).To(Equal("upstream2"))
546+
// Verify each map has the correct structure
547+
seenUpstreams := make(map[string]bool)
548+
for _, m := range maps {
549+
g.Expect(m.Source).To(Equal("$inference_workload_endpoint"))
550+
g.Expect(m.Parameters).To(HaveLen(3))
551+
552+
// Extract upstream name from variable name
553+
varName := strings.TrimPrefix(m.Variable, "$inference_backend_")
554+
upstreamName := strings.ReplaceAll(varName, "_", "-")
555+
556+
// Verify we haven't seen this upstream before (no duplicates)
557+
g.Expect(seenUpstreams[upstreamName]).To(BeFalse(), "Duplicate upstream found: %s", upstreamName)
558+
seenUpstreams[upstreamName] = true
559+
560+
// Verify parameter structure
561+
g.Expect(m.Parameters[0].Value).To(Equal("\"\""))
562+
g.Expect(m.Parameters[0].Result).To(Equal(upstreamName))
563+
g.Expect(m.Parameters[1].Value).To(Equal("~.+"))
564+
g.Expect(m.Parameters[1].Result).To(Equal("$inference_workload_endpoint"))
565+
g.Expect(m.Parameters[2].Value).To(Equal("default"))
566+
567+
// Verify the default result matches expected failure mode
568+
if expectedConfig, exists := tc.expectedConfig[upstreamName]; exists {
569+
g.Expect(m.Parameters[2].Result).To(Equal(expectedConfig.defaultResult))
570+
}
571+
}
572+
573+
// Verify all expected upstreams are present
574+
for expectedUpstream := range tc.expectedConfig {
575+
g.Expect(seenUpstreams[expectedUpstream]).To(BeTrue(), "Expected upstream not found: %s", expectedUpstream)
576+
}
577+
})
578+
}
451579
}

0 commit comments

Comments
 (0)