Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions internal/provider/kubernetes/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResour
// All other errors are just logged and ignored - these errors result in missing referenced backend resources
// in the resource tree, which is acceptable as the Gateway API translation layer will handle them.
// The Gateway API translation layer will surface these errors in the status of the resources referencing them.
for backendRef := range resourceMappings.allAssociatedBackendRefs {
for _, backendRef := range resourceMappings.allAssociatedBackendRefs {
backendRefKind := gatewayapi.KindDerefOr(backendRef.Kind, resource.KindService)
backendNs, backendName := string(*backendRef.Namespace), string(backendRef.Name)
logger := r.log.WithValues("kind", backendRefKind, "namespace", backendNs,
Expand Down Expand Up @@ -964,6 +964,27 @@ func getBackendRefs(backendCluster egv1a1.BackendCluster) []gwapiv1.BackendObjec
return backendRefs
}

func backendRefKey(ref *gwapiv1.BackendObjectReference) utils.NamespacedNameWithGroupKind {
if ref == nil {
return utils.NamespacedNameWithGroupKind{}
}
namespace := gatewayapi.NamespaceDerefOr(ref.Namespace, "")
group := gatewayapi.GroupDerefOr(ref.Group, "")
kind := gatewayapi.KindDerefOr(ref.Kind, resource.KindService)
return utils.NamespacedNameWithGroupKind{
NamespacedName: types.NamespacedName{Namespace: namespace, Name: string(ref.Name)},
GroupKind: schema.GroupKind{Group: group, Kind: kind},
}
}

func (rm *resourceMappings) insertBackendRef(ref gwapiv1.BackendObjectReference) {
key := backendRefKey(&ref)
if _, exists := rm.allAssociatedBackendRefs[key]; exists {
return
}
rm.allAssociatedBackendRefs[key] = ref
}

// processBackendRef adds the referenced BackendRef to the resourceMap for later processBackendRefs.
// If BackendRef exists in a different namespace and there is a ReferenceGrant, adds ReferenceGrant to the resourceTree.
func (r *gatewayAPIReconciler) processBackendRef(
Expand All @@ -976,12 +997,14 @@ func (r *gatewayAPIReconciler) processBackendRef(
backendRef gwapiv1.BackendObjectReference,
) error {
backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, ownerNS)
resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
normalizedRef := gwapiv1.BackendObjectReference{
Group: backendRef.Group,
Kind: backendRef.Kind,
Namespace: gatewayapi.NamespacePtr(backendNamespace),
Name: backendRef.Name,
})
Port: backendRef.Port,
}
resourceMap.insertBackendRef(normalizedRef)

if backendNamespace != ownerNS {
from := ObjectKindNamespacedName{
Expand Down Expand Up @@ -1516,7 +1539,7 @@ func (r *gatewayAPIReconciler) processServiceClusterForGatewayClass(ep *egv1a1.E
}
}

resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
resourceMap.insertBackendRef(gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind("Service")),
Namespace: gatewayapi.NamespacePtr(proxySvcNamespace),
Name: gwapiv1.ObjectName(proxySvcName),
Expand Down Expand Up @@ -1545,7 +1568,7 @@ func (r *gatewayAPIReconciler) processServiceClusterForGateway(ep *egv1a1.EnvoyP
}
}

resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
resourceMap.insertBackendRef(gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind("Service")),
Namespace: gatewayapi.NamespacePtr(proxySvcNamespace),
Name: gwapiv1.ObjectName(proxySvcName),
Expand Down Expand Up @@ -2456,12 +2479,14 @@ func (r *gatewayAPIReconciler) processEnvoyProxy(ep *egv1a1.EnvoyProxy, resource

for _, backendRef := range backendRefs {
backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, ep.Namespace)
resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
normalizedRef := gwapiv1.BackendObjectReference{
Group: backendRef.Group,
Kind: backendRef.Kind,
Namespace: gatewayapi.NamespacePtr(backendNamespace),
Name: backendRef.Name,
})
Port: backendRef.Port,
}
resourceMap.insertBackendRef(normalizedRef)
}
}

Expand Down
41 changes: 32 additions & 9 deletions internal/provider/kubernetes/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,15 @@ func TestProcessBackendRefsWithCustomBackends(t *testing.T) {

// Create resource mappings
resourceMappings := &resourceMappings{
allAssociatedBackendRefs: sets.New[gwapiv1.BackendObjectReference](),
allAssociatedBackendRefs: make(map[utils.NamespacedNameWithGroupKind]gwapiv1.BackendObjectReference),
allAssociatedNamespaces: sets.New[string](),
allAssociatedBackendRefExtensionFilters: sets.New[utils.NamespacedNameWithGroupKind](),
extensionRefFilters: tc.existingExtFilters,
}

// Add backend refs to the mapping
for _, backendRef := range tc.backendRefs {
resourceMappings.allAssociatedBackendRefs.Insert(backendRef)
resourceMappings.insertBackendRef(backendRef)
}

// Create empty resource tree
Expand Down Expand Up @@ -1303,11 +1303,14 @@ func TestProcessServiceClusterForGatewayClass(t *testing.T) {

r.processServiceClusterForGatewayClass(tc.envoyProxy, tc.gatewayClass, resourceMap)

require.Contains(t, resourceMap.allAssociatedBackendRefs, gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind("Service")),
expectedRef := gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind(resource.KindService)),
Namespace: gatewayapi.NamespacePtr(r.namespace),
Name: gwapiv1.ObjectName(tc.expectedSvcName),
})
}
key := backendRefKey(&expectedRef)
require.Contains(t, resourceMap.allAssociatedBackendRefs, key)
require.Equal(t, expectedRef, resourceMap.allAssociatedBackendRefs[key])
})
}
}
Expand Down Expand Up @@ -1457,11 +1460,14 @@ func TestProcessServiceClusterForGateway(t *testing.T) {

r.processServiceClusterForGateway(tc.envoyProxy, tc.gateway, resourceMap)

require.Contains(t, resourceMap.allAssociatedBackendRefs, gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind("Service")),
expectedRef := gwapiv1.BackendObjectReference{
Kind: ptr.To(gwapiv1.Kind(resource.KindService)),
Namespace: gatewayapi.NamespacePtr(tc.expectedSvcNamespace),
Name: gwapiv1.ObjectName(tc.expectedSvcName),
})
}
key := backendRefKey(&expectedRef)
require.Contains(t, resourceMap.allAssociatedBackendRefs, key)
require.Equal(t, expectedRef, resourceMap.allAssociatedBackendRefs[key])
})
}
}
Expand All @@ -1481,6 +1487,23 @@ func newGatewayAPIReconciler(logger logging.Logger) *gatewayAPIReconciler {
}
}

func TestProcessBackendRefDeduplicatesLogicalBackend(t *testing.T) {
logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
r := newGatewayAPIReconciler(logger)
resourceTree := resource.NewResources()
resourceMap := newResourceMapping()

backendRef := gwapiv1.BackendObjectReference{
Namespace: gatewayapi.NamespacePtr("default"),
Name: "svc",
}

require.NoError(t, r.processBackendRef(t.Context(), resourceMap, resourceTree, resource.KindHTTPRoute, "default", "route-a", backendRef))
require.NoError(t, r.processBackendRef(t.Context(), resourceMap, resourceTree, resource.KindHTTPRoute, "default", "route-b", backendRef))

require.Len(t, resourceMap.allAssociatedBackendRefs, 1)
}

func TestProcessBackendRefs(t *testing.T) {
ns := "default"
ctb := test.GetClusterTrustBundle("fake-ctb")
Expand Down Expand Up @@ -1584,7 +1607,7 @@ func TestProcessBackendRefs(t *testing.T) {
resourceTree := resource.NewResources()
resourceMap := newResourceMapping()
backend := tc.backend
resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
resourceMap.insertBackendRef(gwapiv1.BackendObjectReference{
Kind: gatewayapi.KindPtr(resource.KindBackend),
Namespace: gatewayapi.NamespacePtr(backend.Namespace),
Name: gwapiv1.ObjectName(backend.Name),
Expand Down
6 changes: 3 additions & 3 deletions internal/provider/kubernetes/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ type resourceMappings struct {
allAssociatedTCPRoutes sets.Set[string]
// Set for storing UDPRoutes' NamespacedNames attaching to various Gateway objects.
allAssociatedUDPRoutes sets.Set[string]
// Set for storing backendRefs' BackendObjectReference referred by various Route objects.
allAssociatedBackendRefs sets.Set[gwapiv1.BackendObjectReference]
// Map caching BackendObjectReferences keyed by their normalized identifier.
allAssociatedBackendRefs map[utils.NamespacedNameWithGroupKind]gwapiv1.BackendObjectReference
// Set for storing ClientTrafficPolicies' NamespacedNames referred by various Route objects.
allAssociatedClientTrafficPolicies sets.Set[string]
// Set for storing BackendTrafficPolicies' NamespacedNames referred by various Route objects.
Expand Down Expand Up @@ -90,7 +90,7 @@ func newResourceMapping() *resourceMappings {
allAssociatedGRPCRoutes: sets.New[string](),
allAssociatedTCPRoutes: sets.New[string](),
allAssociatedUDPRoutes: sets.New[string](),
allAssociatedBackendRefs: sets.New[gwapiv1.BackendObjectReference](),
allAssociatedBackendRefs: make(map[utils.NamespacedNameWithGroupKind]gwapiv1.BackendObjectReference),
allAssociatedClientTrafficPolicies: sets.New[string](),
allAssociatedBackendTrafficPolicies: sets.New[string](),
allAssociatedSecurityPolicies: sets.New[string](),
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/kubernetes/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ func TestProcessHTTPRoutesWithCustomBackends(t *testing.T) {
// Verify results
require.NoError(t, err)
require.Len(t, resourceMap.extensionRefFilters, tc.expectedExtFiltersCount)
require.Equal(t, tc.expectedBackendRefsCount, resourceMap.allAssociatedBackendRefs.Len())
require.Len(t, resourceMap.allAssociatedBackendRefs, tc.expectedBackendRefsCount)

// Verify that HTTPRoutes were processed
require.Len(t, resourceTree.HTTPRoutes, 1)
Expand Down
Loading