Skip to content

Commit 06a15b7

Browse files
committed
Refactors InferencePool v1 Status
Signed-off-by: Daneyon Hansen <[email protected]>
1 parent 137a0b4 commit 06a15b7

File tree

9 files changed

+259
-130
lines changed

9 files changed

+259
-130
lines changed

api/v1/inferencepool_types.go

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ type InferencePool struct {
3838
// +required
3939
Spec InferencePoolSpec `json:"spec,omitzero"`
4040

41-
// Status defines the observed state of InferencePool.
41+
// Status defines the observed state of the InferencePool.
4242
//
43-
// +kubebuilder:default={parent: {{parentRef: {kind: "Status", name: "default"}, conditions: {{type: "Accepted", status: "Unknown", reason: "Pending", message: "Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}}}
4443
// +optional
45-
Status InferencePoolStatus `json:"status,omitzero"`
44+
//nolint:kubeapilinter // ignore kubeapilinter here as we want to follow K8s conventions.
45+
Status InferencePoolStatus `json:"status,omitempty"`
4646
}
4747

4848
// InferencePoolList contains a list of InferencePool.
@@ -145,57 +145,60 @@ const (
145145
FailClose ExtensionFailureMode = "FailClose"
146146
)
147147

148-
// InferencePoolStatus defines the observed state of InferencePool.
149-
// +kubebuilder:validation:MinProperties=1
148+
// InferencePoolStatus defines the observed state of the InferencePool.
150149
type InferencePoolStatus struct {
151-
// Parents is a list of parent resources (usually Gateways) that are
152-
// associated with the InferencePool, and the status of the InferencePool with respect to
153-
// each parent.
150+
// Parents is a list of parent resources, typically Gateways, that are associated with
151+
// the InferencePool, and the status of the InferencePool with respect to each parent.
154152
//
155-
// A maximum of 32 Gateways will be represented in this list. When the list contains
156-
// `kind: Status, name: default`, it indicates that the InferencePool is not
157-
// associated with any Gateway and a controller must perform the following:
153+
// A controller that manages the InferencePool, must add an entry for each parent it manages
154+
// and remove the parent entry when the controller no longer considers the InferencePool to
155+
// be associated with that parent.
158156
//
159-
// - Remove the parent when setting the "Accepted" condition.
160-
// - Add the parent when the controller will no longer manage the InferencePool
161-
// and no other parents exist.
157+
// A maximum of 32 parents will be represented in this list. When the list is empty,
158+
// it indicates that the InferencePool is not associated with any parents.
162159
//
163160
// +kubebuilder:validation:MaxItems=32
164161
// +optional
165162
// +listType=atomic
166163
Parents []PoolStatus `json:"parent,omitempty"`
167164
}
168165

169-
// PoolStatus defines the observed state of InferencePool from a Gateway.
166+
// PoolStatus defines the observed state of the InferencePool.
170167
type PoolStatus struct {
171-
// Conditions track the state of the InferencePool.
168+
// Conditions is a list of status conditions that provide information about the observed
169+
// state of the InferencePool. This field is required to be set by the controller that
170+
// manages the InferencePool.
172171
//
173172
// Known condition types are:
174173
//
175174
// * "Accepted"
176175
// * "ResolvedRefs"
177176
//
178-
// +optional
177+
// +required
179178
// +listType=map
180179
// +listMapKey=type
180+
// +kubebuilder:validation:MinItems=1
181181
// +kubebuilder:validation:MaxItems=8
182-
// +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}
183-
Conditions []metav1.Condition `json:"conditions,omitempty"`
182+
//nolint:kubeapilinter // ignore kubeapilinter here as we want conditions to be required.
183+
Conditions []metav1.Condition `json:"conditions"`
184184

185-
// GatewayRef indicates the gateway that observed state of InferencePool.
185+
// ParentRef is used to identify the parent resource that this status
186+
// is associated with. It is used to match the InferencePool with the parent
187+
// resource, such as a Gateway.
188+
//
186189
// +required
187-
GatewayRef ParentGatewayReference `json:"parentRef,omitzero"`
190+
ParentRef ParentReference `json:"parentRef,omitzero"`
188191
}
189192

190-
// InferencePoolConditionType is a type of condition for the InferencePool
193+
// InferencePoolConditionType is a type of status condition for the InferencePool.
191194
type InferencePoolConditionType string
192195

193-
// InferencePoolReason is the reason for a given InferencePoolConditionType
196+
// InferencePoolReason is the reason for a type of InferencePool status condition.
194197
type InferencePoolReason string
195198

196199
const (
197-
// This condition indicates whether the InferencePool has been accepted or rejected
198-
// by a Gateway, and why.
200+
// InferencePoolConditionAccepted is a type of condition that indicates whether
201+
// the InferencePool has been accepted or rejected by a Gateway, and why.
199202
//
200203
// Possible reasons for this condition to be True are:
201204
//
@@ -214,18 +217,19 @@ const (
214217
// prefer to use the reasons listed above to improve interoperability.
215218
InferencePoolConditionAccepted InferencePoolConditionType = "Accepted"
216219

217-
// This reason is used with the "Accepted" condition when the InferencePool has been
218-
// accepted by the Gateway.
220+
// InferencePoolReasonAccepted is a reason used with the "Accepted" condition
221+
// when the InferencePool has been accepted by the Gateway.
219222
InferencePoolReasonAccepted InferencePoolReason = "Accepted"
220223

221-
// This reason is used with the "Accepted" condition when the InferencePool
222-
// has not been accepted by a Gateway because the Gateway does not support
223-
// InferencePool as a backend.
224+
// InferencePoolReasonNotSupportedByGateway is a reason used with the "Accepted"
225+
// condition when the InferencePool has not been accepted by a Gateway because
226+
// the Gateway does not support InferencePool as a backend.
224227
InferencePoolReasonNotSupportedByGateway InferencePoolReason = "NotSupportedByGateway"
225228

226-
// This reason is used with the "Accepted" condition when the InferencePool is
227-
// referenced by an HTTPRoute that has been rejected by the Gateway. The user
228-
// should inspect the status of the referring HTTPRoute for the specific reason.
229+
// InferencePoolReasonHTTPRouteNotAccepted is a reason used with the "Accepted"
230+
// condition when the InferencePool is referenced by an HTTPRoute that has been
231+
// rejected by the Gateway. The user should inspect the status of the referring
232+
// HTTPRoute for the specific reason.
229233
InferencePoolReasonHTTPRouteNotAccepted InferencePoolReason = "HTTPRouteNotAccepted"
230234

231235
// This reason is used with the "Accepted" when a controller has not yet
@@ -234,8 +238,8 @@ const (
234238
)
235239

236240
const (
237-
// This condition indicates whether the controller was able to resolve all
238-
// the object references for the InferencePool.
241+
// InferencePoolConditionResolvedRefs is a type of condition that indicates whether
242+
// the controller was able to resolve all the object references for the InferencePool.
239243
//
240244
// Possible reasons for this condition to be True are:
241245
//
@@ -249,39 +253,44 @@ const (
249253
// prefer to use the reasons listed above to improve interoperability.
250254
InferencePoolConditionResolvedRefs InferencePoolConditionType = "ResolvedRefs"
251255

252-
// This reason is used with the "ResolvedRefs" condition when the condition
253-
// is true.
256+
// InferencePoolReasonResolvedRefs is a reason used with the "ResolvedRefs"
257+
// condition when the condition is true.
254258
InferencePoolReasonResolvedRefs InferencePoolReason = "ResolvedRefs"
255259

256-
// This reason is used with the "ResolvedRefs" condition when the
257-
// Extension is invalid in some way. This can include an unsupported kind
258-
// or API group, or a reference to a resource that can not be found.
260+
// InferencePoolReasonInvalidExtensionRef is a reason used with the "ResolvedRefs"
261+
// condition when the Extension is invalid in some way. This can include an
262+
// unsupported kind or API group, or a reference to a resource that cannot be found.
259263
InferencePoolReasonInvalidExtensionRef InferencePoolReason = "InvalidExtensionRef"
260264
)
261265

262-
// ParentGatewayReference identifies an API object including its namespace,
263-
// defaulting to Gateway.
264-
type ParentGatewayReference struct {
265-
// Group is the group of the referent.
266+
// ParentReference identifies an API object. It is used to associate the InferencePool with a
267+
// parent resource, such as a Gateway.
268+
type ParentReference struct {
269+
// Group is the group of the referent API object. When unspecified, the referent is assumed
270+
// to be in the "gateway.networking.k8s.io" API group.
266271
//
267272
// +optional
268273
// +kubebuilder:default="gateway.networking.k8s.io"
269274
Group *Group `json:"group,omitempty"`
270275

271-
// Kind is kind of the referent. For example "Gateway".
276+
// Kind is the kind of the referent API object. When unspecified, the referent is assumed
277+
// to be a "Gateway" kind.
272278
//
273279
// +optional
274280
// +kubebuilder:default=Gateway
275-
Kind Kind `json:"kind,omitempty"`
281+
//nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means default value.
282+
Kind *Kind `json:"kind,omitempty"`
276283

277-
// Name is the name of the referent.
284+
// Name is the name of the referent API object.
285+
//
278286
// +required
279287
Name ObjectName `json:"name,omitempty"`
280288

281-
// Namespace is the namespace of the referent. If not present,
282-
// the namespace of the referent is assumed to be the same as
283-
// the namespace of the referring object.
289+
// Namespace is the namespace of the referent API object. When unspecified,
290+
// the namespace of the referent is assumed to be the same as the namespace
291+
// of the referring object.
284292
//
285293
// +optional
286-
Namespace Namespace `json:"namespace,omitempty"`
294+
//nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means same namespace.
295+
Namespace *Namespace `json:"namespace,omitempty"`
287296
}

api/v1/zz_generated.deepcopy.go

Lines changed: 15 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apix/v1alpha2/inferencepool_conversion.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ package v1alpha2
1919
import (
2020
"errors"
2121
"fmt"
22+
"time"
2223

24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2325
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2426
runtime "k8s.io/apimachinery/pkg/runtime"
2527

@@ -39,11 +41,20 @@ func (src *InferencePool) ConvertTo(dst *v1.InferencePool) error {
3941
if err != nil {
4042
return err
4143
}
42-
dst.TypeMeta = src.TypeMeta
44+
45+
// v1 requires at least one condition per parent.
46+
ensureV1StatusConditionsMinimum(v1Status)
47+
48+
meta := metav1.TypeMeta{
49+
Kind: src.Kind,
50+
APIVersion: v1.GroupVersion.Version, // Ensure the API version is set correctly.
51+
}
52+
dst.TypeMeta = meta
4353
dst.ObjectMeta = src.ObjectMeta
4454
dst.Spec.TargetPorts = []v1.Port{{Number: v1.PortNumber(src.Spec.TargetPortNumber)}}
4555
dst.Spec.EndpointPickerRef = endpointPickRef
4656
dst.Status = *v1Status
57+
4758
if src.Spec.Selector != nil {
4859
dst.Spec.Selector.MatchLabels = make(map[v1.LabelKey]v1.LabelValue, len(src.Spec.Selector))
4960
for k, v := range src.Spec.Selector {
@@ -66,11 +77,17 @@ func (dst *InferencePool) ConvertFrom(src *v1.InferencePool) error {
6677
if err != nil {
6778
return err
6879
}
69-
dst.TypeMeta = src.TypeMeta
80+
81+
meta := metav1.TypeMeta{
82+
Kind: src.Kind,
83+
APIVersion: GroupVersion.Version, // Ensure the API version is set correctly.
84+
}
85+
dst.TypeMeta = meta
7086
dst.ObjectMeta = src.ObjectMeta
7187
dst.Spec.TargetPortNumber = int32(src.Spec.TargetPorts[0].Number)
7288
dst.Spec.ExtensionRef = extensionRef
7389
dst.Status = *status
90+
7491
if src.Spec.Selector.MatchLabels != nil {
7592
dst.Spec.Selector = make(map[LabelKey]LabelValue, len(src.Spec.Selector.MatchLabels))
7693
for k, v := range src.Spec.Selector.MatchLabels {
@@ -88,7 +105,11 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error
88105
if err != nil {
89106
return nil, err
90107
}
91-
return convert[v1.InferencePoolStatus](u)
108+
out, err := convert[v1.InferencePoolStatus](u)
109+
if err != nil {
110+
return nil, err
111+
}
112+
return out, nil
92113
}
93114

94115
func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, error) {
@@ -166,3 +187,23 @@ func convert[T any](u *unstructured.Unstructured) (*T, error) {
166187
}
167188
return &res, nil
168189
}
190+
191+
// Ensure v1's PoolStatus.Conditions has at least one entry.
192+
func ensureV1StatusConditionsMinimum(s *v1.InferencePoolStatus) {
193+
if s == nil {
194+
return
195+
}
196+
epoch := metav1.NewTime(time.Unix(0, 0))
197+
for i := range s.Parents {
198+
ps := &s.Parents[i]
199+
if len(ps.Conditions) == 0 {
200+
ps.Conditions = []metav1.Condition{{
201+
Type: string(v1.InferencePoolConditionAccepted),
202+
Status: metav1.ConditionUnknown,
203+
Reason: string(v1.InferencePoolReasonPending),
204+
Message: "Waiting for controller",
205+
LastTransitionTime: epoch,
206+
}}
207+
}
208+
}
209+
}

0 commit comments

Comments
 (0)