Skip to content

Commit d05e2ba

Browse files
committed
add status to inference pools
1 parent 1609e25 commit d05e2ba

File tree

11 files changed

+1219
-65
lines changed

11 files changed

+1219
-65
lines changed

internal/controller/handler.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,17 +361,19 @@ func (h *eventHandlerImpl) updateStatuses(ctx context.Context, gr *graph.Graph,
361361
transitionTime,
362362
h.cfg.gatewayCtlrName,
363363
)
364+
inferencePoolReqs := status.PrepareInferencePoolRequests(gr.ReferencedInferencePools, transitionTime)
364365

365366
reqs := make(
366367
[]status.UpdateRequest,
367368
0,
368-
len(gcReqs)+len(routeReqs)+len(polReqs)+len(ngfPolReqs)+len(snippetsFilterReqs),
369+
len(gcReqs)+len(routeReqs)+len(polReqs)+len(ngfPolReqs)+len(snippetsFilterReqs)+len(inferencePoolReqs),
369370
)
370371
reqs = append(reqs, gcReqs...)
371372
reqs = append(reqs, routeReqs...)
372373
reqs = append(reqs, polReqs...)
373374
reqs = append(reqs, ngfPolReqs...)
374375
reqs = append(reqs, snippetsFilterReqs...)
376+
reqs = append(reqs, inferencePoolReqs...)
375377

376378
h.cfg.statusUpdater.UpdateGroup(ctx, groupAllExceptGateways, reqs...)
377379

internal/controller/state/conditions/conditions.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
inference "sigs.k8s.io/gateway-api-inference-extension/api/v1"
78
v1 "sigs.k8s.io/gateway-api/apis/v1"
89
"sigs.k8s.io/gateway-api/apis/v1alpha2"
910

@@ -1108,3 +1109,55 @@ func NewBackendTLSPolicyNoValidCACertificate(message string) Condition {
11081109
Message: message,
11091110
}
11101111
}
1112+
1113+
// NewInferencePoolAccepted returns a Condition that indicates that the InferencePool is accepted by the Gateway.
1114+
func NewInferencePoolAccepted() Condition {
1115+
return Condition{
1116+
Type: string(inference.InferencePoolConditionAccepted),
1117+
Status: metav1.ConditionTrue,
1118+
Reason: string(inference.InferencePoolConditionAccepted),
1119+
Message: "InferencePool is accepted by the Gateway.",
1120+
}
1121+
}
1122+
1123+
// NewInferencePoolResolvedRefs returns a Condition that
1124+
// indicates that all references in the InferencePool are resolved.
1125+
func NewInferencePoolResolvedRefs() Condition {
1126+
return Condition{
1127+
Type: string(inference.InferencePoolConditionResolvedRefs),
1128+
Status: metav1.ConditionTrue,
1129+
Reason: string(inference.InferencePoolConditionResolvedRefs),
1130+
Message: "Inference pool references a valid ExtensionRef.",
1131+
}
1132+
}
1133+
1134+
// NewDefaultInferenceConditions returns the default Conditions
1135+
// that must be present in the status of an InferencePool.
1136+
func NewDefaultInferenceConditions() []Condition {
1137+
return []Condition{
1138+
NewInferencePoolAccepted(),
1139+
NewInferencePoolResolvedRefs(),
1140+
}
1141+
}
1142+
1143+
// NewInferencePoolInvalidHTTPRouteNotAccepted returns a Condition that indicates that the InferencePool is not
1144+
// accepted because the associated HTTPRoute is not accepted by the Gateway.
1145+
func NewInferencePoolInvalidHTTPRouteNotAccepted(msg string) Condition {
1146+
return Condition{
1147+
Type: string(inference.InferencePoolConditionAccepted),
1148+
Status: metav1.ConditionFalse,
1149+
Reason: string(inference.InferencePoolReasonHTTPRouteNotAccepted),
1150+
Message: msg,
1151+
}
1152+
}
1153+
1154+
// NewInferencePoolInvalidExtensionref returns a Condition that indicates that the InferencePool is not
1155+
// accepted because the ExtensionRef is invalid.
1156+
func NewInferencePoolInvalidExtensionref(msg string) Condition {
1157+
return Condition{
1158+
Type: string(inference.InferencePoolConditionResolvedRefs),
1159+
Status: metav1.ConditionFalse,
1160+
Reason: string(inference.InferencePoolReasonInvalidExtensionRef),
1161+
Message: msg,
1162+
}
1163+
}

internal/controller/state/graph/graph.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ func BuildGraph(
260260
processedSnippetsFilters,
261261
state.InferencePools,
262262
)
263-
referencedInferencePools := buildReferencedInferencePools(routes, gws, state.InferencePools)
263+
264+
referencedInferencePools := buildReferencedInferencePools(routes, gws, state.InferencePools, state.Services)
264265

265266
l4routes := buildL4RoutesForGateways(
266267
state.TLSRoutes,

internal/controller/state/graph/inferencepools.go

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package graph
22

33
import (
4+
"fmt"
5+
6+
v1 "k8s.io/api/core/v1"
47
"k8s.io/apimachinery/pkg/types"
58
"sigs.k8s.io/controller-runtime/pkg/client"
69
inference "sigs.k8s.io/gateway-api-inference-extension/api/v1"
10+
apiv1 "sigs.k8s.io/gateway-api/apis/v1"
711

12+
"github.com/nginx/nginx-gateway-fabric/v2/internal/controller/state/conditions"
813
"github.com/nginx/nginx-gateway-fabric/v2/internal/framework/controller"
914
"github.com/nginx/nginx-gateway-fabric/v2/internal/framework/kinds"
1015
)
@@ -14,6 +19,12 @@ import (
1419
type ReferencedInferencePool struct {
1520
// Source is the original InferencePool that this ReferencedInferencePool is based on.
1621
Source *inference.InferencePool
22+
// Gateways are the Gateways that this ReferencedInferencePool is attached to.
23+
Gateways []*apiv1.Gateway
24+
// HTTPRoutes are the HTTPRoutes that reference this InferencePool.
25+
HTTPRoutes []*L7Route
26+
// Conditions contains the conditions that should be applied to the InferencePool.
27+
Conditions []conditions.Condition
1728
}
1829

1930
// buildReferencedInferencePools builds a map of InferencePools that are referenced by HTTPRoutes
@@ -22,8 +33,9 @@ func buildReferencedInferencePools(
2233
routes map[RouteKey]*L7Route,
2334
gws map[types.NamespacedName]*Gateway,
2435
inferencePools map[types.NamespacedName]*inference.InferencePool,
36+
services map[types.NamespacedName]*v1.Service,
2537
) map[types.NamespacedName]*ReferencedInferencePool {
26-
referencedInferencePools := make(map[types.NamespacedName]*ReferencedInferencePool)
38+
referencedInferencePools := make(map[types.NamespacedName]*ReferencedInferencePool, len(inferencePools))
2739

2840
for _, gw := range gws {
2941
if gw == nil {
@@ -37,6 +49,20 @@ func buildReferencedInferencePools(
3749
return nil
3850
}
3951

52+
// validate each referenced InferencePool and add conditions.
53+
for _, refPool := range referencedInferencePools {
54+
routeCond := validateInferencePoolRoutesAcceptance(refPool.Source, refPool.HTTPRoutes)
55+
56+
if routeCond != nil {
57+
refPool.Conditions = append(refPool.Conditions, *routeCond)
58+
}
59+
60+
extensionRefCond := validateInferencePoolExtensionRef(refPool.Source, services)
61+
if extensionRefCond != nil {
62+
refPool.Conditions = append(refPool.Conditions, *extensionRefCond)
63+
}
64+
}
65+
4066
return referencedInferencePools
4167
}
4268

@@ -48,8 +74,9 @@ func processInferencePoolsForGateway(
4874
inferencePools map[types.NamespacedName]*inference.InferencePool,
4975
) {
5076
gwKey := client.ObjectKeyFromObject(gw.Source)
77+
5178
for _, route := range routes {
52-
if !route.Valid || !routeBelongsToGateway(route.ParentRefs, gwKey) {
79+
if !routeBelongsToGateway(route.ParentRefs, gwKey) {
5380
continue
5481
}
5582

@@ -70,13 +97,83 @@ func processInferencePoolsForGateway(
7097
}
7198

7299
if _, referenced := referencedInferencePools[poolName]; !referenced {
73-
referencedInferencePools[poolName] = &ReferencedInferencePool{}
100+
referencedInferencePools[poolName] = &ReferencedInferencePool{
101+
Conditions: make([]conditions.Condition, 0, 2),
102+
Gateways: make([]*apiv1.Gateway, 0),
103+
HTTPRoutes: make([]*L7Route, 0),
104+
}
74105
}
75106

76107
if pool, exists := inferencePools[poolName]; exists {
77108
referencedInferencePools[poolName].Source = pool
109+
referencedInferencePools[poolName].Gateways = append(
110+
referencedInferencePools[poolName].Gateways,
111+
gw.Source,
112+
)
113+
referencedInferencePools[poolName].HTTPRoutes = append(
114+
referencedInferencePools[poolName].HTTPRoutes,
115+
route,
116+
)
78117
}
79118
}
80119
}
81120
}
82121
}
122+
123+
// validateInferencePoolExtensionRef validates the ExtensionRef of the InferencePool.
124+
func validateInferencePoolExtensionRef(
125+
ip *inference.InferencePool,
126+
svc map[types.NamespacedName]*v1.Service,
127+
) *conditions.Condition {
128+
var failingCond conditions.Condition
129+
if ip == nil {
130+
return nil
131+
}
132+
133+
// if kind is empty, it defaults to Service
134+
kind := string(ip.Spec.EndpointPickerRef.Kind)
135+
if kind == "" {
136+
kind = kinds.Service
137+
}
138+
139+
if kind != kinds.Service {
140+
failingCond = conditions.NewInferencePoolInvalidExtensionref("Invalid ExtensionRef kind: " + kind)
141+
return &failingCond
142+
}
143+
144+
eppNsName := types.NamespacedName{
145+
Name: string(ip.Spec.EndpointPickerRef.Name),
146+
Namespace: ip.GetNamespace(),
147+
}
148+
149+
if _, ok := svc[eppNsName]; !ok {
150+
failingCond = conditions.NewInferencePoolInvalidExtensionref("ExtensionRef Service not found: " + eppNsName.String())
151+
return &failingCond
152+
}
153+
154+
return nil
155+
}
156+
157+
// validateInferencePoolRoutesAcceptance checks if the routes that reference the InferencePool
158+
// are accepted by the Gateway.
159+
func validateInferencePoolRoutesAcceptance(ip *inference.InferencePool, routes []*L7Route) *conditions.Condition {
160+
if ip == nil || len(routes) == 0 {
161+
return nil
162+
}
163+
164+
// we do not to validate that the route belongs to the gateway or not
165+
// we only process routes that belong to the gateway in the first place
166+
for _, route := range routes {
167+
if !route.Valid {
168+
cond := conditions.NewInferencePoolInvalidHTTPRouteNotAccepted(
169+
fmt.Sprintf("Referenced HTTPRoute %s/%s is not accepted by the Gateway",
170+
route.Source.GetNamespace(),
171+
route.Source.GetName(),
172+
),
173+
)
174+
return &cond
175+
}
176+
}
177+
178+
return nil
179+
}

0 commit comments

Comments
 (0)