Skip to content
Draft
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
58 changes: 27 additions & 31 deletions controller/hybridgateway/route/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/go-logr/logr"
"github.com/samber/lo"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -453,10 +454,11 @@ func BuildResolvedRefsCondition(ctx context.Context, logger logr.Logger, cl clie
bRefNamespace = string(*bRef.Namespace)
}

// BackendRef group kind.
bRefGK := string(*bRef.Kind)
if gr := string(*bRef.Group); gr != "" {
bRefGK = fmt.Sprintf("%s/%s", gr, bRefGK)
// BackendRef group/kind (default to core/Service when unset).
bRefGroup, bRefKind := backendRefGroupKind(bRef.Group, bRef.Kind)
bRefGK := bRefKind
if bRefGroup != "" {
bRefGK = fmt.Sprintf("%s/%s", bRefGroup, bRefKind)
}

// Check if the group kind is supported for the reference.
Expand Down Expand Up @@ -918,21 +920,22 @@ func FilterOutGVKByKind(expectedGVKs []schema.GroupVersionKind, kindToFilter str
return filtered
}

// backendRefGroupKind returns the effective group and kind for a BackendRef,
// applying Gateway API defaults: kind defaults to "Service" and group defaults
// to "" (core) when nil or empty.
func backendRefGroupKind(group *gwtypes.Group, kind *gwtypes.Kind) (string, string) {
g := string(lo.FromPtr(group))
k := string(lo.FromPtr(kind))
if k == "" {
k = "Service"
}
return g, k
}

// IsBackendRefSupported returns true if the BackendRef group and kind are supported by Gateway API.
// Only core "Service" is supported.
func IsBackendRefSupported(group *gwtypes.Group, kind *gwtypes.Kind) bool {
if kind == nil {
return false
}

k := string(*kind)

// Acceptable group values for Service: nil, "", "core".
var g string
if group != nil {
g = string(*group)
}

g, k := backendRefGroupKind(group, kind)
return (g == "" || g == "core") && k == "Service"
}

Expand All @@ -955,30 +958,23 @@ func IsExtensionRefSupported(group gwtypes.Group, kind gwtypes.Kind) bool {
// Returns:
// - bool: true if the reference is permitted by the grant, false otherwise
func IsHTTPReferenceGranted(grantSpec gwtypes.ReferenceGrantSpec, backendRef gwtypes.HTTPBackendRef, fromNamespace string) bool {
var backendRefGroup gwtypes.Group
var backendRefKind gwtypes.Kind

if backendRef.Group != nil {
backendRefGroup = *backendRef.Group
}
if backendRef.Kind != nil {
backendRefKind = *backendRef.Kind
}
bRefGroup, bRefKind := backendRefGroupKind(backendRef.Group, backendRef.Kind)

for _, from := range grantSpec.From {
if from.Group != gwtypes.GroupName || from.Kind != "HTTPRoute" || fromNamespace != string(from.Namespace) {
continue
}

for _, to := range grantSpec.To {
if to.Group == "" {
to.Group = "core"
toGroup := string(to.Group)
if toGroup == "" {
toGroup = "core"
}
if backendRefGroup == "" {
backendRefGroup = "core"
if bRefGroup == "" {
bRefGroup = "core"
}
if backendRefGroup == to.Group &&
backendRefKind == to.Kind &&
if gwtypes.Group(bRefGroup) == gwtypes.Group(toGroup) &&
gwtypes.Kind(bRefKind) == to.Kind &&
(to.Name == nil || *to.Name == backendRef.Name) {
return true
}
Expand Down
62 changes: 60 additions & 2 deletions controller/hybridgateway/route/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1561,10 +1561,16 @@ func TestIsBackendRefSupported(t *testing.T) {
want: false,
},
{
name: "nil kind",
name: "nil kind defaults to Service",
group: groupPtr("core"),
kind: nil,
want: false,
want: true,
},
{
name: "empty kind defaults to Service",
group: groupPtr("core"),
kind: kindPtr(""),
want: true,
},
}

Expand Down Expand Up @@ -1612,6 +1618,58 @@ func TestIsHTTPReferenceGranted(t *testing.T) {
fromNamespace: "default",
want: true,
},
{
name: "granted when backend kind/group default to core/Service",
grantSpec: gwtypes.ReferenceGrantSpec{
From: []gwtypes.ReferenceGrantFrom{{
Group: gwtypes.GroupName,
Kind: "HTTPRoute",
Namespace: gwtypes.Namespace("default"),
}},
To: []gwtypes.ReferenceGrantTo{{
Group: gwtypes.Group("core"),
Kind: gwtypes.Kind("Service"),
Name: ptrObjName("my-service"),
}},
},
backendRef: gwtypes.HTTPBackendRef{
BackendRef: gwtypes.BackendRef{
BackendObjectReference: gwtypes.BackendObjectReference{
Name: gwtypes.ObjectName("my-service"),
Kind: nil,
Group: nil,
},
},
},
fromNamespace: "default",
want: true,
},
{
name: "granted when backend kind is empty string (defaults to Service)",
grantSpec: gwtypes.ReferenceGrantSpec{
From: []gwtypes.ReferenceGrantFrom{{
Group: gwtypes.GroupName,
Kind: "HTTPRoute",
Namespace: gwtypes.Namespace("default"),
}},
To: []gwtypes.ReferenceGrantTo{{
Group: gwtypes.Group("core"),
Kind: gwtypes.Kind("Service"),
Name: ptrObjName("my-service"),
}},
},
backendRef: gwtypes.HTTPBackendRef{
BackendRef: gwtypes.BackendRef{
BackendObjectReference: gwtypes.BackendObjectReference{
Name: gwtypes.ObjectName("my-service"),
Kind: kindPtr(""),
Group: groupPtr(""),
},
},
},
fromNamespace: "default",
want: true,
},
{
name: "not granted when group does not match",
grantSpec: gwtypes.ReferenceGrantSpec{
Expand Down
1 change: 0 additions & 1 deletion test/conformance/skipped_tests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ var skippedTestsForHybrid = []string{
tests.HTTPRoutePathMatchOrder.ShortName,
tests.HTTPRouteQueryParamMatching.ShortName,
tests.HTTPRouteReferenceGrant.ShortName,
tests.HTTPRouteSimpleSameNamespace.ShortName,
tests.HTTPRouteExactPathMatching.ShortName,
tests.HTTPRouteHostnameIntersection.ShortName,
tests.HTTPRouteCrossNamespace.ShortName,
Expand Down
Loading