From 6bf0bc4c33dad5278e6d14d6550e7b271e857933 Mon Sep 17 00:00:00 2001 From: Daneyon Hansen Date: Thu, 21 Aug 2025 09:54:44 -0700 Subject: [PATCH 1/5] Refactors InferencePool v1 Status Signed-off-by: Daneyon Hansen --- api/v1/inferencepool_types.go | 126 ++++++++++-------- api/v1/zz_generated.deepcopy.go | 30 +++-- apix/v1alpha2/inferencepool_conversion.go | 67 +++++++++- .../v1alpha2/inferencepool_conversion_test.go | 106 ++++++++++++--- .../api/v1/inferencepoolstatus.go | 4 +- ...gatewayreference.go => parentreference.go} | 18 +-- .../api/v1/{poolstatus.go => parentstatus.go} | 24 ++-- client-go/applyconfiguration/utils.go | 8 +- ...ence.networking.k8s.io_inferencepools.yaml | 72 +++++----- conformance/utils/kubernetes/helpers.go | 12 +- 10 files changed, 308 insertions(+), 159 deletions(-) rename client-go/applyconfiguration/api/v1/{parentgatewayreference.go => parentreference.go} (69%) rename client-go/applyconfiguration/api/v1/{poolstatus.go => parentstatus.go} (57%) diff --git a/api/v1/inferencepool_types.go b/api/v1/inferencepool_types.go index 12f47deed..234b888a2 100644 --- a/api/v1/inferencepool_types.go +++ b/api/v1/inferencepool_types.go @@ -38,11 +38,11 @@ type InferencePool struct { // +required Spec InferencePoolSpec `json:"spec,omitzero"` - // Status defines the observed state of InferencePool. + // Status defines the observed state of the InferencePool. // - // +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"}}}}} // +optional - Status InferencePoolStatus `json:"status,omitzero"` + //nolint:kubeapilinter // ignore kubeapilinter to follow K8s conventions of optional but non-pointer. + Status InferencePoolStatus `json:"status,omitempty"` } // InferencePoolList contains a list of InferencePool. @@ -127,7 +127,7 @@ type EndpointPickerRef struct { //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as 0 usually means all ports. PortNumber *PortNumber `json:"portNumber,omitempty"` - // Configures how the gateway handles the case when the extension is not responsive. + // Configures how the parent handles the case when the extension is not responsive. // Defaults to failClose. // // +optional @@ -135,69 +135,73 @@ type EndpointPickerRef struct { FailureMode ExtensionFailureMode `json:"failureMode,omitempty"` } -// ExtensionFailureMode defines the options for how the gateway handles the case when the extension is not +// ExtensionFailureMode defines the options for how the parent handles the case when the extension is not // responsive. // +kubebuilder:validation:Enum=FailOpen;FailClose type ExtensionFailureMode string const ( - // FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails. + // FailOpen specifies that the proxy should forward the request to an endpoint of its picking when + // the Endpoint Picker fails. FailOpen ExtensionFailureMode = "FailOpen" // FailClose specifies that the proxy should drop the request when the Endpoint Picker fails. FailClose ExtensionFailureMode = "FailClose" ) -// InferencePoolStatus defines the observed state of InferencePool. -// +kubebuilder:validation:MinProperties=1 +// InferencePoolStatus defines the observed state of the InferencePool. type InferencePoolStatus struct { - // Parents is a list of parent resources (usually Gateways) that are - // associated with the InferencePool, and the status of the InferencePool with respect to - // each parent. + // Parents is a list of parent resources, typically Gateways, that are associated with + // the InferencePool, and the status of the InferencePool with respect to each parent. // - // A maximum of 32 Gateways will be represented in this list. When the list contains - // `kind: Status, name: default`, it indicates that the InferencePool is not - // associated with any Gateway and a controller must perform the following: + // A controller that manages the InferencePool, must add an entry for each parent it manages + // and remove the parent entry when the controller no longer considers the InferencePool to + // be associated with that parent. // - // - Remove the parent when setting the "Accepted" condition. - // - Add the parent when the controller will no longer manage the InferencePool - // and no other parents exist. + // A maximum of 32 parents will be represented in this list. When the list is empty, + // it indicates that the InferencePool is not associated with any parents. // // +kubebuilder:validation:MaxItems=32 // +optional // +listType=atomic - Parents []PoolStatus `json:"parent,omitempty"` + Parents []ParentStatus `json:"parents,omitempty"` } -// PoolStatus defines the observed state of InferencePool from a Gateway. -type PoolStatus struct { - // Conditions track the state of the InferencePool. +// ParentStatus defines the observed state of InferencePool from a Parent, i.e. Gateway. +type ParentStatus struct { + // Conditions is a list of status conditions that provide information about the observed + // state of the InferencePool. This field is required to be set by the controller that + // manages the InferencePool. // // Known condition types are: // // * "Accepted" // * "ResolvedRefs" // - // +optional + // +required // +listType=map // +listMapKey=type + // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} - Conditions []metav1.Condition `json:"conditions,omitempty"` + //nolint:kubeapilinter // ignore kubeapilinter here as we want conditions to be required. + Conditions []metav1.Condition `json:"conditions"` - // GatewayRef indicates the gateway that observed state of InferencePool. + // ParentRef is used to identify the parent resource that this status + // is associated with. It is used to match the InferencePool with the parent + // resource, such as a Gateway. + // // +required - GatewayRef ParentGatewayReference `json:"parentRef,omitzero"` + ParentRef ParentReference `json:"parentRef,omitzero"` } -// InferencePoolConditionType is a type of condition for the InferencePool +// InferencePoolConditionType is a type of status condition for the InferencePool. type InferencePoolConditionType string -// InferencePoolReason is the reason for a given InferencePoolConditionType +// InferencePoolReason is the reason for a type of InferencePool status condition. type InferencePoolReason string const ( - // This condition indicates whether the InferencePool has been accepted or rejected - // by a Gateway, and why. + // InferencePoolConditionAccepted is a type of condition that indicates whether + // the InferencePool has been accepted or rejected by a Parent, and why. // // Possible reasons for this condition to be True are: // @@ -205,7 +209,7 @@ const ( // // Possible reasons for this condition to be False are: // - // * "NotSupportedByGateway" + // * "NotSupportedByParent" // * "HTTPRouteNotAccepted" // // Possible reasons for this condition to be Unknown are: @@ -216,18 +220,19 @@ const ( // prefer to use the reasons listed above to improve interoperability. InferencePoolConditionAccepted InferencePoolConditionType = "Accepted" - // This reason is used with the "Accepted" condition when the InferencePool has been - // accepted by the Gateway. + // InferencePoolReasonAccepted is a reason used with the "Accepted" condition + // when the InferencePool has been accepted by the Parent. InferencePoolReasonAccepted InferencePoolReason = "Accepted" - // This reason is used with the "Accepted" condition when the InferencePool - // has not been accepted by a Gateway because the Gateway does not support - // InferencePool as a backend. - InferencePoolReasonNotSupportedByGateway InferencePoolReason = "NotSupportedByGateway" + // InferencePoolReasonNotSupportedByParent is a reason used with the "Accepted" + // condition when the InferencePool has not been accepted by a Parent because + // the Parent does not support InferencePool as a backend. + InferencePoolReasonNotSupportedByParent InferencePoolReason = "NotSupportedByParent" - // This reason is used with the "Accepted" condition when the InferencePool is - // referenced by an HTTPRoute that has been rejected by the Gateway. The user - // should inspect the status of the referring HTTPRoute for the specific reason. + // InferencePoolReasonHTTPRouteNotAccepted is a reason used with the "Accepted" + // condition when the InferencePool is referenced by an HTTPRoute that has been + // rejected by the Parent. The user should inspect the status of the referring + // HTTPRoute for the specific reason. InferencePoolReasonHTTPRouteNotAccepted InferencePoolReason = "HTTPRouteNotAccepted" // This reason is used with the "Accepted" when a controller has not yet @@ -236,8 +241,8 @@ const ( ) const ( - // This condition indicates whether the controller was able to resolve all - // the object references for the InferencePool. + // InferencePoolConditionResolvedRefs is a type of condition that indicates whether + // the controller was able to resolve all the object references for the InferencePool. // // Possible reasons for this condition to be True are: // @@ -251,39 +256,44 @@ const ( // prefer to use the reasons listed above to improve interoperability. InferencePoolConditionResolvedRefs InferencePoolConditionType = "ResolvedRefs" - // This reason is used with the "ResolvedRefs" condition when the condition - // is true. + // InferencePoolReasonResolvedRefs is a reason used with the "ResolvedRefs" + // condition when the condition is true. InferencePoolReasonResolvedRefs InferencePoolReason = "ResolvedRefs" - // This reason is used with the "ResolvedRefs" condition when the - // Extension is invalid in some way. This can include an unsupported kind - // or API group, or a reference to a resource that can not be found. + // InferencePoolReasonInvalidExtensionRef is a reason used with the "ResolvedRefs" + // condition when the Extension is invalid in some way. This can include an + // unsupported kind or API group, or a reference to a resource that cannot be found. InferencePoolReasonInvalidExtensionRef InferencePoolReason = "InvalidExtensionRef" ) -// ParentGatewayReference identifies an API object including its namespace, -// defaulting to Gateway. -type ParentGatewayReference struct { - // Group is the group of the referent. +// ParentReference identifies an API object. It is used to associate the InferencePool with a +// parent resource, such as a Gateway. +type ParentReference struct { + // Group is the group of the referent API object. When unspecified, the referent is assumed + // to be in the "gateway.networking.k8s.io" API group. // // +optional // +kubebuilder:default="gateway.networking.k8s.io" Group *Group `json:"group,omitempty"` - // Kind is kind of the referent. For example "Gateway". + // Kind is the kind of the referent API object. When unspecified, the referent is assumed + // to be a "Gateway" kind. // // +optional // +kubebuilder:default=Gateway - Kind Kind `json:"kind,omitempty"` + //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means default value. + Kind *Kind `json:"kind,omitempty"` - // Name is the name of the referent. + // Name is the name of the referent API object. + // // +required Name ObjectName `json:"name,omitempty"` - // Namespace is the namespace of the referent. If not present, - // the namespace of the referent is assumed to be the same as - // the namespace of the referring object. + // Namespace is the namespace of the referent API object. When unspecified, + // the namespace of the referent is assumed to be the same as the namespace + // of the referring object. // // +optional - Namespace Namespace `json:"namespace,omitempty"` + //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means same namespace. + Namespace *Namespace `json:"namespace,omitempty"` } diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 9e90d369f..2324328d2 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -136,7 +136,7 @@ func (in *InferencePoolStatus) DeepCopyInto(out *InferencePoolStatus) { *out = *in if in.Parents != nil { in, out := &in.Parents, &out.Parents - *out = make([]PoolStatus, len(*in)) + *out = make([]ParentStatus, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -176,27 +176,37 @@ func (in *LabelSelector) DeepCopy() *LabelSelector { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ParentGatewayReference) DeepCopyInto(out *ParentGatewayReference) { +func (in *ParentReference) DeepCopyInto(out *ParentReference) { *out = *in if in.Group != nil { in, out := &in.Group, &out.Group *out = new(Group) **out = **in } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentGatewayReference. -func (in *ParentGatewayReference) DeepCopy() *ParentGatewayReference { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. +func (in *ParentReference) DeepCopy() *ParentReference { if in == nil { return nil } - out := new(ParentGatewayReference) + out := new(ParentReference) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PoolStatus) DeepCopyInto(out *PoolStatus) { +func (in *ParentStatus) DeepCopyInto(out *ParentStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions @@ -205,15 +215,15 @@ func (in *PoolStatus) DeepCopyInto(out *PoolStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.GatewayRef.DeepCopyInto(&out.GatewayRef) + in.ParentRef.DeepCopyInto(&out.ParentRef) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolStatus. -func (in *PoolStatus) DeepCopy() *PoolStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentStatus. +func (in *ParentStatus) DeepCopy() *ParentStatus { if in == nil { return nil } - out := new(PoolStatus) + out := new(ParentStatus) in.DeepCopyInto(out) return out } diff --git a/apix/v1alpha2/inferencepool_conversion.go b/apix/v1alpha2/inferencepool_conversion.go index b817c47d5..562568b90 100644 --- a/apix/v1alpha2/inferencepool_conversion.go +++ b/apix/v1alpha2/inferencepool_conversion.go @@ -19,7 +19,9 @@ package v1alpha2 import ( "errors" "fmt" + "time" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" runtime "k8s.io/apimachinery/pkg/runtime" @@ -39,11 +41,20 @@ func (src *InferencePool) ConvertTo(dst *v1.InferencePool) error { if err != nil { return err } - dst.TypeMeta = src.TypeMeta + + // v1 requires at least one condition per parent. + ensureV1StatusConditionsMinimum(v1Status) + + meta := metav1.TypeMeta{ + Kind: src.Kind, + APIVersion: v1.GroupVersion.String(), // Ensure the API version is set correctly. + } + dst.TypeMeta = meta dst.ObjectMeta = src.ObjectMeta dst.Spec.TargetPorts = []v1.Port{{Number: v1.PortNumber(src.Spec.TargetPortNumber)}} dst.Spec.EndpointPickerRef = endpointPickRef dst.Status = *v1Status + if src.Spec.Selector != nil { dst.Spec.Selector.MatchLabels = make(map[v1.LabelKey]v1.LabelValue, len(src.Spec.Selector)) for k, v := range src.Spec.Selector { @@ -66,11 +77,17 @@ func (dst *InferencePool) ConvertFrom(src *v1.InferencePool) error { if err != nil { return err } - dst.TypeMeta = src.TypeMeta + + meta := metav1.TypeMeta{ + Kind: src.Kind, + APIVersion: GroupVersion.String(), // Ensure the API version is set correctly. + } + dst.TypeMeta = meta dst.ObjectMeta = src.ObjectMeta dst.Spec.TargetPortNumber = int32(src.Spec.TargetPorts[0].Number) dst.Spec.ExtensionRef = extensionRef dst.Status = *status + if src.Spec.Selector.MatchLabels != nil { dst.Spec.Selector = make(map[LabelKey]LabelValue, len(src.Spec.Selector.MatchLabels)) for k, v := range src.Spec.Selector.MatchLabels { @@ -88,7 +105,18 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error if err != nil { return nil, err } - return convert[v1.InferencePoolStatus](u) + + // v1alpha2 uses json:"parent" (singular), v1 uses json:"parents" + if v, ok := u.Object["parent"]; ok { + u.Object["parents"] = v + delete(u.Object, "parent") + } + + out, err := convert[v1.InferencePoolStatus](u) + if err != nil { + return nil, err + } + return out, nil } func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, error) { @@ -99,7 +127,18 @@ func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, err if err != nil { return nil, err } - return convert[InferencePoolStatus](u) + + // v1 uses json:"parents", v1alpha2 uses json:"parent" (singular) + if v, ok := u.Object["parents"]; ok { + u.Object["parent"] = v + delete(u.Object, "parents") + } + + out, err := convert[InferencePoolStatus](u) + if err != nil { + return nil, err + } + return out, nil } func convertExtensionRefToV1(src *Extension) (v1.EndpointPickerRef, error) { @@ -166,3 +205,23 @@ func convert[T any](u *unstructured.Unstructured) (*T, error) { } return &res, nil } + +// Ensure v1's PoolStatus.Conditions has at least one entry. +func ensureV1StatusConditionsMinimum(s *v1.InferencePoolStatus) { + if s == nil { + return + } + epoch := metav1.NewTime(time.Unix(0, 0)) + for i := range s.Parents { + ps := &s.Parents[i] + if len(ps.Conditions) == 0 { + ps.Conditions = []metav1.Condition{{ + Type: string(v1.InferencePoolConditionAccepted), + Status: metav1.ConditionUnknown, + Reason: string(v1.InferencePoolReasonPending), + Message: "Waiting for controller", + LastTransitionTime: epoch, + }} + } + } +} diff --git a/apix/v1alpha2/inferencepool_conversion_test.go b/apix/v1alpha2/inferencepool_conversion_test.go index 2c59fc632..8f678e9da 100644 --- a/apix/v1alpha2/inferencepool_conversion_test.go +++ b/apix/v1alpha2/inferencepool_conversion_test.go @@ -49,7 +49,7 @@ func TestInferencePoolConvertTo(t *testing.T) { src: &InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.x-k8s.io/v1alpha2", + APIVersion: GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -87,7 +87,7 @@ func TestInferencePoolConvertTo(t *testing.T) { want: &v1.InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.x-k8s.io/v1alpha2", + APIVersion: v1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -109,9 +109,9 @@ func TestInferencePoolConvertTo(t *testing.T) { }, }, Status: v1.InferencePoolStatus{ - Parents: []v1.PoolStatus{ + Parents: []v1.ParentStatus{ { - GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"}, + ParentRef: v1.ParentReference{Name: "my-gateway"}, Conditions: []metav1.Condition{ { Type: string(v1.InferencePoolConditionAccepted), @@ -131,7 +131,7 @@ func TestInferencePoolConvertTo(t *testing.T) { src: &InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.x-k8s.io/v1alpha2", + APIVersion: GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -162,7 +162,7 @@ func TestInferencePoolConvertTo(t *testing.T) { want: &v1.InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.x-k8s.io/v1alpha2", + APIVersion: v1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -177,9 +177,9 @@ func TestInferencePoolConvertTo(t *testing.T) { TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}}, }, Status: v1.InferencePoolStatus{ - Parents: []v1.PoolStatus{ + Parents: []v1.ParentStatus{ { - GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"}, + ParentRef: v1.ParentReference{Name: "my-gateway"}, Conditions: []metav1.Condition{ { Type: string(v1.InferencePoolConditionAccepted), @@ -194,6 +194,80 @@ func TestInferencePoolConvertTo(t *testing.T) { }, wantErr: false, }, + { + name: "synthesize status conditions only where empty", + src: &InferencePool{ + TypeMeta: metav1.TypeMeta{ + Kind: "InferencePool", + APIVersion: GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pool", + Namespace: "test-ns", + }, + Spec: InferencePoolSpec{ + Selector: map[LabelKey]LabelValue{"app": "my-model-server"}, + TargetPortNumber: 8080, + }, + Status: InferencePoolStatus{ + Parents: []PoolStatus{ + { + GatewayRef: ParentGatewayReference{Name: "gw-a"}, + Conditions: []metav1.Condition{{ + Type: string(InferencePoolConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(InferencePoolReasonAccepted), + LastTransitionTime: timestamp, + }}, + }, + { + GatewayRef: ParentGatewayReference{Name: "gw-b"}, + // Conditions empty -> should be synthesized + }, + }, + }, + }, + want: &v1.InferencePool{ + TypeMeta: metav1.TypeMeta{ + Kind: "InferencePool", + APIVersion: v1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pool", + Namespace: "test-ns", + }, + Spec: v1.InferencePoolSpec{ + Selector: v1.LabelSelector{ + MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "my-model-server"}, + }, + TargetPorts: []v1.Port{{Number: v1.PortNumber(8080)}}, + }, + Status: v1.InferencePoolStatus{ + Parents: []v1.ParentStatus{ + { + ParentRef: v1.ParentReference{Name: "gw-a"}, + Conditions: []metav1.Condition{{ + Type: string(v1.InferencePoolConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(v1.InferencePoolReasonAccepted), + LastTransitionTime: timestamp, + }}, + }, + { + ParentRef: v1.ParentReference{Name: "gw-b"}, + Conditions: []metav1.Condition{{ + Type: string(v1.InferencePoolConditionAccepted), + Status: metav1.ConditionUnknown, + Reason: string(v1.InferencePoolReasonPending), + Message: "Waiting for controller", + LastTransitionTime: timestamp, + }}, + }, + }, + }, + }, + wantErr: false, + }, } for _, tt := range tests { @@ -222,7 +296,7 @@ func TestInferencePoolConvertFrom(t *testing.T) { src: &v1.InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.k8s.io/v1", + APIVersion: v1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -244,9 +318,9 @@ func TestInferencePoolConvertFrom(t *testing.T) { }, }, Status: v1.InferencePoolStatus{ - Parents: []v1.PoolStatus{ + Parents: []v1.ParentStatus{ { - GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"}, + ParentRef: v1.ParentReference{Name: "my-gateway"}, Conditions: []metav1.Condition{ { Type: string(v1.InferencePoolConditionAccepted), @@ -262,7 +336,7 @@ func TestInferencePoolConvertFrom(t *testing.T) { want: &InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.k8s.io/v1", + APIVersion: GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -304,7 +378,7 @@ func TestInferencePoolConvertFrom(t *testing.T) { src: &v1.InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.k8s.io/v1", + APIVersion: v1.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", @@ -319,9 +393,9 @@ func TestInferencePoolConvertFrom(t *testing.T) { TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}}, }, Status: v1.InferencePoolStatus{ - Parents: []v1.PoolStatus{ + Parents: []v1.ParentStatus{ { - GatewayRef: v1.ParentGatewayReference{Name: "my-gateway"}, + ParentRef: v1.ParentReference{Name: "my-gateway"}, Conditions: []metav1.Condition{ { Type: string(v1.InferencePoolConditionAccepted), @@ -337,7 +411,7 @@ func TestInferencePoolConvertFrom(t *testing.T) { want: &InferencePool{ TypeMeta: metav1.TypeMeta{ Kind: "InferencePool", - APIVersion: "inference.networking.k8s.io/v1", + APIVersion: GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pool", diff --git a/client-go/applyconfiguration/api/v1/inferencepoolstatus.go b/client-go/applyconfiguration/api/v1/inferencepoolstatus.go index 5c66e3464..499b77151 100644 --- a/client-go/applyconfiguration/api/v1/inferencepoolstatus.go +++ b/client-go/applyconfiguration/api/v1/inferencepoolstatus.go @@ -21,7 +21,7 @@ package v1 // InferencePoolStatusApplyConfiguration represents a declarative configuration of the InferencePoolStatus type for use // with apply. type InferencePoolStatusApplyConfiguration struct { - Parents []PoolStatusApplyConfiguration `json:"parent,omitempty"` + Parents []ParentStatusApplyConfiguration `json:"parents,omitempty"` } // InferencePoolStatusApplyConfiguration constructs a declarative configuration of the InferencePoolStatus type for use with @@ -33,7 +33,7 @@ func InferencePoolStatus() *InferencePoolStatusApplyConfiguration { // WithParents adds the given value to the Parents field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Parents field. -func (b *InferencePoolStatusApplyConfiguration) WithParents(values ...*PoolStatusApplyConfiguration) *InferencePoolStatusApplyConfiguration { +func (b *InferencePoolStatusApplyConfiguration) WithParents(values ...*ParentStatusApplyConfiguration) *InferencePoolStatusApplyConfiguration { for i := range values { if values[i] == nil { panic("nil value passed to WithParents") diff --git a/client-go/applyconfiguration/api/v1/parentgatewayreference.go b/client-go/applyconfiguration/api/v1/parentreference.go similarity index 69% rename from client-go/applyconfiguration/api/v1/parentgatewayreference.go rename to client-go/applyconfiguration/api/v1/parentreference.go index 5e23aebe6..2798f020f 100644 --- a/client-go/applyconfiguration/api/v1/parentgatewayreference.go +++ b/client-go/applyconfiguration/api/v1/parentreference.go @@ -22,25 +22,25 @@ import ( apiv1 "sigs.k8s.io/gateway-api-inference-extension/api/v1" ) -// ParentGatewayReferenceApplyConfiguration represents a declarative configuration of the ParentGatewayReference type for use +// ParentReferenceApplyConfiguration represents a declarative configuration of the ParentReference type for use // with apply. -type ParentGatewayReferenceApplyConfiguration struct { +type ParentReferenceApplyConfiguration struct { Group *apiv1.Group `json:"group,omitempty"` Kind *apiv1.Kind `json:"kind,omitempty"` Name *apiv1.ObjectName `json:"name,omitempty"` Namespace *apiv1.Namespace `json:"namespace,omitempty"` } -// ParentGatewayReferenceApplyConfiguration constructs a declarative configuration of the ParentGatewayReference type for use with +// ParentReferenceApplyConfiguration constructs a declarative configuration of the ParentReference type for use with // apply. -func ParentGatewayReference() *ParentGatewayReferenceApplyConfiguration { - return &ParentGatewayReferenceApplyConfiguration{} +func ParentReference() *ParentReferenceApplyConfiguration { + return &ParentReferenceApplyConfiguration{} } // WithGroup sets the Group field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Group field is set to the value of the last call. -func (b *ParentGatewayReferenceApplyConfiguration) WithGroup(value apiv1.Group) *ParentGatewayReferenceApplyConfiguration { +func (b *ParentReferenceApplyConfiguration) WithGroup(value apiv1.Group) *ParentReferenceApplyConfiguration { b.Group = &value return b } @@ -48,7 +48,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithGroup(value apiv1.Group) // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Kind field is set to the value of the last call. -func (b *ParentGatewayReferenceApplyConfiguration) WithKind(value apiv1.Kind) *ParentGatewayReferenceApplyConfiguration { +func (b *ParentReferenceApplyConfiguration) WithKind(value apiv1.Kind) *ParentReferenceApplyConfiguration { b.Kind = &value return b } @@ -56,7 +56,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithKind(value apiv1.Kind) *P // WithName sets the Name field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Name field is set to the value of the last call. -func (b *ParentGatewayReferenceApplyConfiguration) WithName(value apiv1.ObjectName) *ParentGatewayReferenceApplyConfiguration { +func (b *ParentReferenceApplyConfiguration) WithName(value apiv1.ObjectName) *ParentReferenceApplyConfiguration { b.Name = &value return b } @@ -64,7 +64,7 @@ func (b *ParentGatewayReferenceApplyConfiguration) WithName(value apiv1.ObjectNa // WithNamespace sets the Namespace field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Namespace field is set to the value of the last call. -func (b *ParentGatewayReferenceApplyConfiguration) WithNamespace(value apiv1.Namespace) *ParentGatewayReferenceApplyConfiguration { +func (b *ParentReferenceApplyConfiguration) WithNamespace(value apiv1.Namespace) *ParentReferenceApplyConfiguration { b.Namespace = &value return b } diff --git a/client-go/applyconfiguration/api/v1/poolstatus.go b/client-go/applyconfiguration/api/v1/parentstatus.go similarity index 57% rename from client-go/applyconfiguration/api/v1/poolstatus.go rename to client-go/applyconfiguration/api/v1/parentstatus.go index 6c582d8c8..5accb0f45 100644 --- a/client-go/applyconfiguration/api/v1/poolstatus.go +++ b/client-go/applyconfiguration/api/v1/parentstatus.go @@ -22,23 +22,23 @@ import ( metav1 "k8s.io/client-go/applyconfigurations/meta/v1" ) -// PoolStatusApplyConfiguration represents a declarative configuration of the PoolStatus type for use +// ParentStatusApplyConfiguration represents a declarative configuration of the ParentStatus type for use // with apply. -type PoolStatusApplyConfiguration struct { - Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` - GatewayRef *ParentGatewayReferenceApplyConfiguration `json:"parentRef,omitempty"` +type ParentStatusApplyConfiguration struct { + Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` + ParentRef *ParentReferenceApplyConfiguration `json:"parentRef,omitempty"` } -// PoolStatusApplyConfiguration constructs a declarative configuration of the PoolStatus type for use with +// ParentStatusApplyConfiguration constructs a declarative configuration of the ParentStatus type for use with // apply. -func PoolStatus() *PoolStatusApplyConfiguration { - return &PoolStatusApplyConfiguration{} +func ParentStatus() *ParentStatusApplyConfiguration { + return &ParentStatusApplyConfiguration{} } // WithConditions adds the given value to the Conditions field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Conditions field. -func (b *PoolStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *PoolStatusApplyConfiguration { +func (b *ParentStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *ParentStatusApplyConfiguration { for i := range values { if values[i] == nil { panic("nil value passed to WithConditions") @@ -48,10 +48,10 @@ func (b *PoolStatusApplyConfiguration) WithConditions(values ...*metav1.Conditio return b } -// WithGatewayRef sets the GatewayRef field in the declarative configuration to the given value +// WithParentRef sets the ParentRef field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the GatewayRef field is set to the value of the last call. -func (b *PoolStatusApplyConfiguration) WithGatewayRef(value *ParentGatewayReferenceApplyConfiguration) *PoolStatusApplyConfiguration { - b.GatewayRef = value +// If called multiple times, the ParentRef field is set to the value of the last call. +func (b *ParentStatusApplyConfiguration) WithParentRef(value *ParentReferenceApplyConfiguration) *ParentStatusApplyConfiguration { + b.ParentRef = value return b } diff --git a/client-go/applyconfiguration/utils.go b/client-go/applyconfiguration/utils.go index 8a3b6b384..06626998d 100644 --- a/client-go/applyconfiguration/utils.go +++ b/client-go/applyconfiguration/utils.go @@ -44,10 +44,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apiv1.InferencePoolStatusApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("LabelSelector"): return &apiv1.LabelSelectorApplyConfiguration{} - case v1.SchemeGroupVersion.WithKind("ParentGatewayReference"): - return &apiv1.ParentGatewayReferenceApplyConfiguration{} - case v1.SchemeGroupVersion.WithKind("PoolStatus"): - return &apiv1.PoolStatusApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ParentReference"): + return &apiv1.ParentReferenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ParentStatus"): + return &apiv1.ParentStatusApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("Port"): return &apiv1.PortApplyConfiguration{} diff --git a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml index 9a2891478..15c902c9e 100644 --- a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml +++ b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml @@ -50,7 +50,7 @@ spec: failureMode: default: FailClose description: |- - Configures how the gateway handles the case when the extension is not responsive. + Configures how the parent handles the case when the extension is not responsive. Defaults to failClose. enum: - FailOpen @@ -165,46 +165,28 @@ spec: - targetPorts type: object status: - default: - parent: - - conditions: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Pending - status: Unknown - type: Accepted - parentRef: - kind: Status - name: default - description: Status defines the observed state of InferencePool. - minProperties: 1 + description: Status defines the observed state of the InferencePool. properties: - parent: + parents: description: |- - Parents is a list of parent resources (usually Gateways) that are - associated with the InferencePool, and the status of the InferencePool with respect to - each parent. + Parents is a list of parent resources, typically Gateways, that are associated with + the InferencePool, and the status of the InferencePool with respect to each parent. - A maximum of 32 Gateways will be represented in this list. When the list contains - `kind: Status, name: default`, it indicates that the InferencePool is not - associated with any Gateway and a controller must perform the following: + A controller that manages the InferencePool, must add an entry for each parent it manages + and remove the parent entry when the controller no longer considers the InferencePool to + be associated with that parent. - - Remove the parent when setting the "Accepted" condition. - - Add the parent when the controller will no longer manage the InferencePool - and no other parents exist. + A maximum of 32 parents will be represented in this list. When the list is empty, + it indicates that the InferencePool is not associated with any parents. items: - description: PoolStatus defines the observed state of InferencePool - from a Gateway. + description: ParentStatus defines the observed state of InferencePool + from a Parent, i.e. Gateway. properties: conditions: - default: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Pending - status: Unknown - type: Accepted description: |- - Conditions track the state of the InferencePool. + Conditions is a list of status conditions that provide information about the observed + state of the InferencePool. This field is required to be set by the controller that + manages the InferencePool. Known condition types are: @@ -266,38 +248,45 @@ spec: - type type: object maxItems: 8 + minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map parentRef: - description: GatewayRef indicates the gateway that observed - state of InferencePool. + description: |- + ParentRef is used to identify the parent resource that this status + is associated with. It is used to match the InferencePool with the parent + resource, such as a Gateway. properties: group: default: gateway.networking.k8s.io - description: Group is the group of the referent. + description: |- + Group is the group of the referent API object. When unspecified, the referent is assumed + to be in the "gateway.networking.k8s.io" API group. maxLength: 253 minLength: 0 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: Kind is kind of the referent. For example "Gateway". + description: |- + Kind is the kind of the referent API object. When unspecified, the referent is assumed + to be a "Gateway" kind. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. + description: Name is the name of the referent API object. maxLength: 253 minLength: 1 type: string namespace: description: |- - Namespace is the namespace of the referent. If not present, - the namespace of the referent is assumed to be the same as - the namespace of the referring object. + Namespace is the namespace of the referent API object. When unspecified, + the namespace of the referent is assumed to be the same as the namespace + of the referring object. maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -306,6 +295,7 @@ spec: - name type: object required: + - conditions - parentRef type: object maxItems: 32 diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 39301e342..fe0168ad4 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -32,6 +32,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiconfig "sigs.k8s.io/gateway-api/conformance/utils/config" @@ -105,7 +106,9 @@ func InferencePoolMustHaveCondition(t *testing.T, c client.Reader, poolNN types. } for _, parentStatus := range pool.Status.Parents { - if string(parentStatus.GatewayRef.Namespace) == gateway.Namespace && string(parentStatus.GatewayRef.Name) == gateway.Name { + if parentStatus.ParentRef.Namespace != nil && + string(*parentStatus.ParentRef.Namespace) == gateway.Namespace && + string(parentStatus.ParentRef.Name) == gateway.Name { if checkCondition(t, parentStatus.Conditions, expectedCondition) { conditionFound = true return true, nil @@ -130,8 +133,11 @@ func InferencePoolMustHaveCondition(t *testing.T, c client.Reader, poolNN types. debugMsg += " (No parent statuses reported)" } for i, parentStatus := range lastObservedPool.Status.Parents { - namespace := parentStatus.GatewayRef.Namespace - debugMsg += fmt.Sprintf("\n Parent %d (Gateway: %s/%s):", i, namespace, parentStatus.GatewayRef.Name) + namespace := parentStatus.ParentRef.Namespace + if namespace == nil { + namespace = ptr.To(inferenceapi.Namespace(poolNN.Namespace)) // Fallback to the pool's namespace + } + debugMsg += fmt.Sprintf("\n Parent %d (Gateway: %s/%s):", i, *namespace, parentStatus.ParentRef.Name) if len(parentStatus.Conditions) == 0 { debugMsg += " (No conditions reported for this parent)" } From c377456346c781b8bee562f4bde7051da9183f1c Mon Sep 17 00:00:00 2001 From: Daneyon Hansen Date: Thu, 21 Aug 2025 14:32:45 -0700 Subject: [PATCH 2/5] Renames Pool v1 FailMode Types Signed-off-by: Daneyon Hansen --- api/v1/inferencepool_types.go | 75 +++++++++++-------- api/v1/shared_types.go | 5 +- api/v1/zz_generated.deepcopy.go | 10 +++ apix/v1alpha2/inferencepool_conversion.go | 53 ++++++++----- .../v1alpha2/inferencepool_conversion_test.go | 10 +-- .../api/v1/endpointpickerref.go | 12 +-- ...ence.networking.k8s.io_inferencepools.yaml | 27 +++---- 7 files changed, 115 insertions(+), 77 deletions(-) diff --git a/api/v1/inferencepool_types.go b/api/v1/inferencepool_types.go index 234b888a2..d0e744c88 100644 --- a/api/v1/inferencepool_types.go +++ b/api/v1/inferencepool_types.go @@ -35,8 +35,10 @@ type InferencePool struct { // +optional metav1.ObjectMeta `json:"metadata,omitempty"` + // Spec defines the desired state of the InferencePool. + // // +required - Spec InferencePoolSpec `json:"spec,omitzero"` + Spec InferencePoolSpec `json:"spec"` // Status defines the observed state of the InferencePool. // @@ -45,7 +47,7 @@ type InferencePool struct { Status InferencePoolStatus `json:"status,omitempty"` } -// InferencePoolList contains a list of InferencePool. +// InferencePoolList contains a list InferencePools. // // +kubebuilder:object:root=true type InferencePoolList struct { @@ -54,7 +56,7 @@ type InferencePoolList struct { Items []InferencePool `json:"items"` } -// InferencePoolSpec defines the desired state of InferencePool +// InferencePoolSpec defines the desired state of the InferencePool. type InferencePoolSpec struct { // Selector determines which Pods are members of this inference pool. // It matches Pods by their labels only within the same namespace; cross-namespace @@ -65,19 +67,22 @@ type InferencePoolSpec struct { // this configuration into a Service resource. // // +required - Selector LabelSelector `json:"selector,omitempty,omitzero"` + Selector LabelSelector `json:"selector"` // TargetPorts defines a list of ports that are exposed by this InferencePool. // Currently, the list may only include a single port definition. + // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=1 // +listType=atomic // +required - TargetPorts []Port `json:"targetPorts,omitempty"` + TargetPorts []Port `json:"targetPorts"` - // EndpointPickerRef configures an endpoint picker as an extension service. + // EndpointPickerRef is a reference to the Endpoint Picker extension and its + // associated configuration. + // // +required - EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef,omitempty,omitzero"` + EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef"` } // Port defines the network port that will be exposed by this InferencePool. @@ -86,13 +91,14 @@ type Port struct { // The number must be in the range 1 to 65535. // // +required - Number PortNumber `json:"number,omitempty"` + Number PortNumber `json:"number"` } -// Extension specifies how to configure an extension that runs the endpoint picker. +// EndpointPickerRef specifies a reference to an Endpoint Picker extension and its +// associated configuration. type EndpointPickerRef struct { - // Group is the group of the referent. - // The default value is "", representing the Core API group. + // Group is the group of the referent API object. When unspecified, the default value + // is "", representing the Core API group. // // +optional // +kubebuilder:default="" @@ -100,7 +106,7 @@ type EndpointPickerRef struct { // Kind is the Kubernetes resource kind of the referent. // - // Required if the referent is ambiguous(e.g. service with one port is unambiguous). + // Required if the referent is ambiguous, e.g. service with multiple ports. // // Defaults to "Service" when not specified. // @@ -112,40 +118,42 @@ type EndpointPickerRef struct { // // +optional // +kubebuilder:default=Service - Kind Kind `json:"kind,omitempty"` + Kind *Kind `json:"kind,omitempty"` - // Name is the name of the referent. + // Name is the name of the referent API object. // // +required - Name ObjectName `json:"name,omitempty"` + Name ObjectName `json:"name"` - // The port number on the service running the extension. When unspecified, - // implementations SHOULD infer a default value of 9002 when the Kind is - // Service. + // PortNumber is the port number of the Endpoint Picker extension service. When unspecified, + // implementations SHOULD infer a default value of 9002 when the kind field is "Service" or + // unspecified (defaults to "Service"). // // +optional //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as 0 usually means all ports. PortNumber *PortNumber `json:"portNumber,omitempty"` - // Configures how the parent handles the case when the extension is not responsive. - // Defaults to failClose. + // FailureMode configures how the parent handles the case when the Endpoint Picker extension + // is non-responsive. When unspecified, defaults to "FailClose". // // +optional // +kubebuilder:default="FailClose" - FailureMode ExtensionFailureMode `json:"failureMode,omitempty"` + FailureMode *EndpointPickerFailureMode `json:"failureMode,omitempty"` } -// ExtensionFailureMode defines the options for how the parent handles the case when the extension is not -// responsive. +// EndpointPickerFailureMode defines the options for how the parent handles the case when the +// Endpoint Picker extension is non-responsive. +// // +kubebuilder:validation:Enum=FailOpen;FailClose -type ExtensionFailureMode string +type EndpointPickerFailureMode string const ( - // FailOpen specifies that the proxy should forward the request to an endpoint of its picking when - // the Endpoint Picker fails. - FailOpen ExtensionFailureMode = "FailOpen" - // FailClose specifies that the proxy should drop the request when the Endpoint Picker fails. - FailClose ExtensionFailureMode = "FailClose" + // EndpointPickerFailOpen specifies that the parent should forward the request to an endpoint + // of its picking when the Endpoint Picker extension fails. + EndpointPickerFailOpen EndpointPickerFailureMode = "FailOpen" + // EndpointPickerFailClose specifies that the parent should drop the request when the Endpoint + // Picker extension fails. + EndpointPickerFailClose EndpointPickerFailureMode = "FailClose" ) // InferencePoolStatus defines the observed state of the InferencePool. @@ -190,7 +198,7 @@ type ParentStatus struct { // resource, such as a Gateway. // // +required - ParentRef ParentReference `json:"parentRef,omitzero"` + ParentRef ParentReference `json:"parentRef"` } // InferencePoolConditionType is a type of status condition for the InferencePool. @@ -205,7 +213,7 @@ const ( // // Possible reasons for this condition to be True are: // - // * "Accepted" + // * "SupportedByParent" // // Possible reasons for this condition to be False are: // @@ -221,8 +229,9 @@ const ( InferencePoolConditionAccepted InferencePoolConditionType = "Accepted" // InferencePoolReasonAccepted is a reason used with the "Accepted" condition - // when the InferencePool has been accepted by the Parent. - InferencePoolReasonAccepted InferencePoolReason = "Accepted" + // when the InferencePool is accepted by a Parent because the Parent supports + // InferencePool as a backend. + InferencePoolReasonAccepted InferencePoolReason = "SupportedByParent" // InferencePoolReasonNotSupportedByParent is a reason used with the "Accepted" // condition when the InferencePool has not been accepted by a Parent because diff --git a/api/v1/shared_types.go b/api/v1/shared_types.go index 64425e735..c473cd22b 100644 --- a/api/v1/shared_types.go +++ b/api/v1/shared_types.go @@ -132,11 +132,12 @@ type LabelValue string // LabelSelector defines a query for resources based on their labels. // This simplified version uses only the matchLabels field. type LabelSelector struct { - // matchLabels contains a set of required {key,value} pairs. + // MatchLabels contains a set of required {key,value} pairs. // An object must match every label in this map to be selected. // The matching logic is an AND operation on all entries. // // +required + // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=64 - MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitempty" protobuf:"bytes,1,rep,name=matchLabels"` + MatchLabels map[LabelKey]LabelValue `json:"matchLabels"` } diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 2324328d2..791bc96e4 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -33,11 +33,21 @@ func (in *EndpointPickerRef) DeepCopyInto(out *EndpointPickerRef) { *out = new(Group) **out = **in } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } if in.PortNumber != nil { in, out := &in.PortNumber, &out.PortNumber *out = new(PortNumber) **out = **in } + if in.FailureMode != nil { + in, out := &in.FailureMode, &out.FailureMode + *out = new(EndpointPickerFailureMode) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointPickerRef. diff --git a/apix/v1alpha2/inferencepool_conversion.go b/apix/v1alpha2/inferencepool_conversion.go index 562568b90..76899ce6f 100644 --- a/apix/v1alpha2/inferencepool_conversion.go +++ b/apix/v1alpha2/inferencepool_conversion.go @@ -24,6 +24,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1" ) @@ -106,7 +107,7 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error return nil, err } - // v1alpha2 uses json:"parent" (singular), v1 uses json:"parents" + // v1alpha2 used json:"parent" (singular) v1 uses json:"parents" if v, ok := u.Object["parent"]; ok { u.Object["parents"] = v delete(u.Object, "parent") @@ -116,6 +117,17 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error if err != nil { return nil, err } + + // Map condition reason string: "Accepted" (v1alpha2) -> "SupportedByParent" (v1) + for i := range out.Parents { + for j := range out.Parents[i].Conditions { + c := &out.Parents[i].Conditions[j] + if c.Type == string(v1.InferencePoolConditionAccepted) && + c.Reason == string(InferencePoolReasonAccepted) { + c.Reason = string(v1.InferencePoolReasonAccepted) + } + } + } return out, nil } @@ -128,7 +140,7 @@ func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, err return nil, err } - // v1 uses json:"parents", v1alpha2 uses json:"parent" (singular) + // v1 uses json:"parents"; v1alpha2 used json:"parent" (singular) if v, ok := u.Object["parents"]; ok { u.Object["parent"] = v delete(u.Object, "parents") @@ -138,6 +150,17 @@ func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, err if err != nil { return nil, err } + + // Map condition reason string: "SupportedByParent" (v1) -> "Accepted" (v1alpha2) + for i := range out.Parents { + for j := range out.Parents[i].Conditions { + c := &out.Parents[i].Conditions[j] + if c.Type == string(v1.InferencePoolConditionAccepted) && + c.Reason == string(v1.InferencePoolReasonAccepted) { + c.Reason = string(InferencePoolReasonAccepted) + } + } + } return out, nil } @@ -147,19 +170,17 @@ func convertExtensionRefToV1(src *Extension) (v1.EndpointPickerRef, error) { return endpointPickerRef, errors.New("src cannot be nil") } if src.Group != nil { - v1Group := v1.Group(*src.Group) - endpointPickerRef.Group = &v1Group + endpointPickerRef.Group = ptr.To(v1.Group(*src.Group)) } if src.Kind != nil { - endpointPickerRef.Kind = v1.Kind(*src.Kind) + endpointPickerRef.Kind = ptr.To(v1.Kind(*src.Kind)) } endpointPickerRef.Name = v1.ObjectName(src.Name) if src.PortNumber != nil { - v1PortNumber := v1.PortNumber(*src.PortNumber) - endpointPickerRef.PortNumber = &v1PortNumber + endpointPickerRef.PortNumber = ptr.To(v1.PortNumber(*src.PortNumber)) } if src.FailureMode != nil { - endpointPickerRef.FailureMode = v1.ExtensionFailureMode(*src.FailureMode) + endpointPickerRef.FailureMode = ptr.To(v1.EndpointPickerFailureMode(*src.FailureMode)) } return endpointPickerRef, nil @@ -171,21 +192,17 @@ func convertEndpointPickerRefFromV1(src *v1.EndpointPickerRef) (Extension, error return extension, errors.New("src cannot be nil") } if src.Group != nil { - group := Group(*src.Group) - extension.Group = &group + extension.Group = ptr.To(Group(*src.Group)) } - if src.Kind != "" { - kind := Kind(src.Kind) - extension.Kind = &kind + if src.Kind != nil { + extension.Kind = ptr.To(Kind(*src.Kind)) } extension.Name = ObjectName(src.Name) if src.PortNumber != nil { - portNumber := PortNumber(*src.PortNumber) - extension.PortNumber = &portNumber + extension.PortNumber = ptr.To(PortNumber(*src.PortNumber)) } - if src.FailureMode != "" { - extensionFailureMode := ExtensionFailureMode(src.FailureMode) - extension.FailureMode = &extensionFailureMode + if src.FailureMode != nil { + extension.FailureMode = ptr.To(ExtensionFailureMode(*src.FailureMode)) } return extension, nil } diff --git a/apix/v1alpha2/inferencepool_conversion_test.go b/apix/v1alpha2/inferencepool_conversion_test.go index 8f678e9da..4e159746c 100644 --- a/apix/v1alpha2/inferencepool_conversion_test.go +++ b/apix/v1alpha2/inferencepool_conversion_test.go @@ -33,7 +33,7 @@ var ( v1Group = v1.Group("my-group") v1Kind = v1.Kind("MyKind") - v1FailureMode = v1.ExtensionFailureMode("Deny") + v1FailureMode = v1.EndpointPickerFailureMode("Deny") v1PortNumber = v1.PortNumber(9000) ) @@ -102,10 +102,10 @@ func TestInferencePoolConvertTo(t *testing.T) { TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}}, EndpointPickerRef: v1.EndpointPickerRef{ Group: &v1Group, - Kind: v1Kind, + Kind: &v1Kind, Name: "my-epp-service", PortNumber: &v1PortNumber, - FailureMode: v1FailureMode, + FailureMode: &v1FailureMode, }, }, Status: v1.InferencePoolStatus{ @@ -311,10 +311,10 @@ func TestInferencePoolConvertFrom(t *testing.T) { TargetPorts: []v1.Port{{Number: v1.PortNumber(int32(8080))}}, EndpointPickerRef: v1.EndpointPickerRef{ Group: &v1Group, - Kind: v1Kind, + Kind: &v1Kind, Name: "my-epp-service", PortNumber: &v1PortNumber, - FailureMode: v1FailureMode, + FailureMode: &v1FailureMode, }, }, Status: v1.InferencePoolStatus{ diff --git a/client-go/applyconfiguration/api/v1/endpointpickerref.go b/client-go/applyconfiguration/api/v1/endpointpickerref.go index 8e82230bd..8a9991bc5 100644 --- a/client-go/applyconfiguration/api/v1/endpointpickerref.go +++ b/client-go/applyconfiguration/api/v1/endpointpickerref.go @@ -25,11 +25,11 @@ import ( // EndpointPickerRefApplyConfiguration represents a declarative configuration of the EndpointPickerRef type for use // with apply. type EndpointPickerRefApplyConfiguration struct { - Group *apiv1.Group `json:"group,omitempty"` - Kind *apiv1.Kind `json:"kind,omitempty"` - Name *apiv1.ObjectName `json:"name,omitempty"` - PortNumber *apiv1.PortNumber `json:"portNumber,omitempty"` - FailureMode *apiv1.ExtensionFailureMode `json:"failureMode,omitempty"` + Group *apiv1.Group `json:"group,omitempty"` + Kind *apiv1.Kind `json:"kind,omitempty"` + Name *apiv1.ObjectName `json:"name,omitempty"` + PortNumber *apiv1.PortNumber `json:"portNumber,omitempty"` + FailureMode *apiv1.EndpointPickerFailureMode `json:"failureMode,omitempty"` } // EndpointPickerRefApplyConfiguration constructs a declarative configuration of the EndpointPickerRef type for use with @@ -73,7 +73,7 @@ func (b *EndpointPickerRefApplyConfiguration) WithPortNumber(value apiv1.PortNum // WithFailureMode sets the FailureMode field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the FailureMode field is set to the value of the last call. -func (b *EndpointPickerRefApplyConfiguration) WithFailureMode(value apiv1.ExtensionFailureMode) *EndpointPickerRefApplyConfiguration { +func (b *EndpointPickerRefApplyConfiguration) WithFailureMode(value apiv1.EndpointPickerFailureMode) *EndpointPickerRefApplyConfiguration { b.FailureMode = &value return b } diff --git a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml index 15c902c9e..e37054921 100644 --- a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml +++ b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml @@ -41,17 +41,18 @@ spec: metadata: type: object spec: - description: InferencePoolSpec defines the desired state of InferencePool + description: Spec defines the desired state of the InferencePool. properties: endpointPickerRef: - description: EndpointPickerRef configures an endpoint picker as an - extension service. + description: |- + EndpointPickerRef is a reference to the Endpoint Picker extension and its + associated configuration. properties: failureMode: default: FailClose description: |- - Configures how the parent handles the case when the extension is not responsive. - Defaults to failClose. + FailureMode configures how the parent handles the case when the Endpoint Picker extension + is non-responsive. When unspecified, defaults to "FailClose". enum: - FailOpen - FailClose @@ -59,8 +60,8 @@ spec: group: default: "" description: |- - Group is the group of the referent. - The default value is "", representing the Core API group. + Group is the group of the referent API object. When unspecified, the default value + is "", representing the Core API group. maxLength: 253 minLength: 0 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -70,7 +71,7 @@ spec: description: |- Kind is the Kubernetes resource kind of the referent. - Required if the referent is ambiguous(e.g. service with one port is unambiguous). + Required if the referent is ambiguous, e.g. service with multiple ports. Defaults to "Service" when not specified. @@ -84,15 +85,15 @@ spec: pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. + description: Name is the name of the referent API object. maxLength: 253 minLength: 1 type: string portNumber: description: |- - The port number on the service running the extension. When unspecified, - implementations SHOULD infer a default value of 9002 when the Kind is - Service. + PortNumber is the port number of the Endpoint Picker extension service. When unspecified, + implementations SHOULD infer a default value of 9002 when the kind field is "Service" or + unspecified (defaults to "Service"). format: int32 maximum: 65535 minimum: 1 @@ -129,7 +130,7 @@ spec: pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ type: string description: |- - matchLabels contains a set of required {key,value} pairs. + MatchLabels contains a set of required {key,value} pairs. An object must match every label in this map to be selected. The matching logic is an AND operation on all entries. type: object From 7357a5c6bb519f719fcacd93895372577d8a23ca Mon Sep 17 00:00:00 2001 From: Daneyon Hansen Date: Thu, 21 Aug 2025 16:13:17 -0700 Subject: [PATCH 3/5] Runs API docs generators Signed-off-by: Daneyon Hansen --- site-src/reference/spec.md | 102 ++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/site-src/reference/spec.md b/site-src/reference/spec.md index 9b31f4470..97314dc98 100644 --- a/site-src/reference/spec.md +++ b/site-src/reference/spec.md @@ -15,43 +15,44 @@ inference.networking.k8s.io API group. -#### Extension +#### EndpointPickerFailureMode +_Underlying type:_ _string_ +EndpointPickerFailureMode defines the options for how the parent handles the case when the +Endpoint Picker extension is non-responsive. -Extension specifies how to configure an extension that runs the endpoint picker. +_Validation:_ +- Enum: [FailOpen FailClose] +_Appears in:_ +- [EndpointPickerRef](#endpointpickerref) +| Field | Description | +| --- | --- | +| `FailOpen` | EndpointPickerFailOpen specifies that the parent should forward the request to an endpoint
of its picking when the Endpoint Picker extension fails.
| +| `FailClose` | EndpointPickerFailClose specifies that the parent should drop the request when the Endpoint
Picker extension fails.
| -_Appears in:_ -- [InferencePoolSpec](#inferencepoolspec) -| Field | Description | Default | Validation | -| --- | --- | --- | --- | -| `group` _[Group](#group)_ | Group is the group of the referent.
The default value is "", representing the Core API group. | | MaxLength: 253
MinLength: 0
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| -| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent.
Defaults to "Service" when not specified.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations MUST NOT
support ExternalName Services. | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| -| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| -| `portNumber` _[PortNumber](#portnumber)_ | The port number on the service running the extension. When unspecified,
implementations SHOULD infer a default value of 9002 when the Kind is
Service. | | Maximum: 65535
Minimum: 1
| -| `failureMode` _[ExtensionFailureMode](#extensionfailuremode)_ | Configures how the gateway handles the case when the extension is not responsive.
Defaults to failClose. | FailClose | Enum: [FailOpen FailClose]
| +#### EndpointPickerRef -#### ExtensionFailureMode -_Underlying type:_ _string_ +EndpointPickerRef specifies a reference to an Endpoint Picker extension and its +associated configuration. -ExtensionFailureMode defines the options for how the gateway handles the case when the extension is not -responsive. -_Validation:_ -- Enum: [FailOpen FailClose] _Appears in:_ -- [Extension](#extension) +- [InferencePoolSpec](#inferencepoolspec) -| Field | Description | -| --- | --- | -| `FailOpen` | FailOpen specifies that the proxy should forward the request to an endpoint of its picking when the Endpoint Picker fails.
| -| `FailClose` | FailClose specifies that the proxy should drop the request when the Endpoint Picker fails.
| +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent API object. When unspecified, the default value
is "", representing the Core API group. | | MaxLength: 253
MinLength: 0
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent API object. When unspecified,
the referent is assumed to be a "Service" kind.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations MUST NOT
support ExternalName Services. | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent API object. | | MaxLength: 253
MinLength: 1
| +| `portNumber` _[PortNumber](#portnumber)_ | PortNumber is the port number of the Endpoint Picker extension service. When unspecified,
implementations SHOULD infer a default value of 9002 when the kind field is "Service" or
unspecified (defaults to "Service"). | | Maximum: 65535
Minimum: 1
| +| `failureMode` _[EndpointPickerFailureMode](#endpointpickerfailuremode)_ | FailureMode configures how the parent handles the case when the Endpoint Picker extension
is non-responsive. When unspecified, defaults to "FailClose". | FailClose | Enum: [FailOpen FailClose]
| #### Group @@ -80,8 +81,8 @@ _Validation:_ - Pattern: `^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` _Appears in:_ -- [Extension](#extension) -- [ParentGatewayReference](#parentgatewayreference) +- [EndpointPickerRef](#endpointpickerref) +- [ParentReference](#parentreference) @@ -101,8 +102,8 @@ InferencePool is the Schema for the InferencePools API. | `apiVersion` _string_ | `inference.networking.k8s.io/v1` | | | | `kind` _string_ | `InferencePool` | | | | `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | -| `spec` _[InferencePoolSpec](#inferencepoolspec)_ | | | | -| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of InferencePool. | \{ parent:[map[conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] parentRef:map[kind:Status name:default]]] \} | MinProperties: 1
| +| `spec` _[InferencePoolSpec](#inferencepoolspec)_ | Spec defines the desired state of the InferencePool. | | | +| `status` _[InferencePoolStatus](#inferencepoolstatus)_ | Status defines the observed state of the InferencePool. | | | @@ -113,7 +114,7 @@ InferencePool is the Schema for the InferencePools API. -InferencePoolSpec defines the desired state of InferencePool +InferencePoolSpec defines the desired state of the InferencePool. @@ -124,24 +125,23 @@ _Appears in:_ | --- | --- | --- | --- | | `selector` _[LabelSelector](#labelselector)_ | Selector determines which Pods are members of this inference pool.
It matches Pods by their labels only within the same namespace; cross-namespace
selection is not supported.
The structure of this LabelSelector is intentionally simple to be compatible
with Kubernetes Service selectors, as some implementations may translate
this configuration into a Service resource. | | | | `targetPorts` _[Port](#port) array_ | TargetPorts defines a list of ports that are exposed by this InferencePool.
Currently, the list may only include a single port definition. | | MaxItems: 1
MinItems: 1
| -| `extensionRef` _[Extension](#extension)_ | Extension configures an endpoint picker as an extension service. | | | +| `endpointPickerRef` _[EndpointPickerRef](#endpointpickerref)_ | EndpointPickerRef is a reference to the Endpoint Picker extension and its
associated configuration. | | | #### InferencePoolStatus -InferencePoolStatus defines the observed state of InferencePool. +InferencePoolStatus defines the observed state of the InferencePool. + -_Validation:_ -- MinProperties: 1 _Appears in:_ - [InferencePool](#inferencepool) | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `parent` _[PoolStatus](#poolstatus) array_ | Parents is a list of parent resources (usually Gateways) that are
associated with the InferencePool, and the status of the InferencePool with respect to
each parent.
A maximum of 32 Gateways will be represented in this list. When the list contains
`kind: Status, name: default`, it indicates that the InferencePool is not
associated with any Gateway and a controller must perform the following:
- Remove the parent when setting the "Accepted" condition.
- Add the parent when the controller will no longer manage the InferencePool
and no other parents exist. | | MaxItems: 32
| +| `parents` _[ParentStatus](#parentstatus) array_ | Parents is a list of parent resources, typically Gateways, that are associated with
the InferencePool, and the status of the InferencePool with respect to each parent.
A controller that manages the InferencePool, must add an entry for each parent it manages
and remove the parent entry when the controller no longer considers the InferencePool to
be associated with that parent.
A maximum of 32 parents will be represented in this list. When the list is empty,
it indicates that the InferencePool is not associated with any parents. | | MaxItems: 32
| #### Kind @@ -165,8 +165,8 @@ _Validation:_ - Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` _Appears in:_ -- [Extension](#extension) -- [ParentGatewayReference](#parentgatewayreference) +- [EndpointPickerRef](#endpointpickerref) +- [ParentReference](#parentreference) @@ -217,7 +217,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `matchLabels` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | matchLabels contains a set of required \{key,value\} pairs.
An object must match every label in this map to be selected.
The matching logic is an AND operation on all entries. | | MaxItems: 64
| +| `matchLabels` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | MatchLabels contains a set of required \{key,value\} pairs.
An object must match every label in this map to be selected.
The matching logic is an AND operation on all entries. | | MaxItems: 64
MinItems: 1
| #### LabelValue @@ -272,7 +272,7 @@ _Validation:_ - Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` _Appears in:_ -- [ParentGatewayReference](#parentgatewayreference) +- [ParentReference](#parentreference) @@ -289,36 +289,36 @@ _Validation:_ - MinLength: 1 _Appears in:_ -- [Extension](#extension) -- [ParentGatewayReference](#parentgatewayreference) +- [EndpointPickerRef](#endpointpickerref) +- [ParentReference](#parentreference) -#### ParentGatewayReference +#### ParentReference -ParentGatewayReference identifies an API object including its namespace, -defaulting to Gateway. +ParentReference identifies an API object. It is used to associate the InferencePool with a +parent resource, such as a Gateway. _Appears in:_ -- [PoolStatus](#poolstatus) +- [ParentStatus](#parentstatus) | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `group` _[Group](#group)_ | Group is the group of the referent. | gateway.networking.k8s.io | MaxLength: 253
MinLength: 0
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| -| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Gateway". | Gateway | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| -| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| -| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent. If not present,
the namespace of the referent is assumed to be the same as
the namespace of the referring object. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `group` _[Group](#group)_ | Group is the group of the referent API object. When unspecified, the referent is assumed
to be in the "gateway.networking.k8s.io" API group. | gateway.networking.k8s.io | MaxLength: 253
MinLength: 0
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the kind of the referent API object. When unspecified, the referent is assumed
to be a "Gateway" kind. | Gateway | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent API object. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent API object. When unspecified,
the namespace of the referent is assumed to be the same as the namespace
of the referring object. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| -#### PoolStatus +#### ParentStatus -PoolStatus defines the observed state of InferencePool from a Gateway. +ParentStatus defines the observed state of InferencePool from a Parent, i.e. Gateway. @@ -327,8 +327,8 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions track the state of the InferencePool.
Known condition types are:
* "Accepted"
* "ResolvedRefs" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] | MaxItems: 8
| -| `parentRef` _[ParentGatewayReference](#parentgatewayreference)_ | GatewayRef indicates the gateway that observed state of InferencePool. | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions is a list of status conditions that provide information about the observed
state of the InferencePool. This field is required to be set by the controller that
manages the InferencePool.
Known condition types are:
* "Accepted"
* "ResolvedRefs" | | MaxItems: 8
MinItems: 1
| +| `parentRef` _[ParentReference](#parentreference)_ | ParentRef is used to identify the parent resource that this status
is associated with. It is used to match the InferencePool with the parent
resource, such as a Gateway. | | | #### Port @@ -358,7 +358,7 @@ _Validation:_ - Minimum: 1 _Appears in:_ -- [Extension](#extension) +- [EndpointPickerRef](#endpointpickerref) - [Port](#port) From 69c946dfce109b300169bbb124722a2b890a4c60 Mon Sep 17 00:00:00 2001 From: Daneyon Hansen Date: Thu, 21 Aug 2025 16:26:52 -0700 Subject: [PATCH 4/5] Resolves latest kubeapilinter failures Signed-off-by: Daneyon Hansen --- api/v1/inferencepool_types.go | 11 ++++++++--- api/v1/shared_types.go | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/api/v1/inferencepool_types.go b/api/v1/inferencepool_types.go index d0e744c88..7a8c1cc52 100644 --- a/api/v1/inferencepool_types.go +++ b/api/v1/inferencepool_types.go @@ -38,7 +38,7 @@ type InferencePool struct { // Spec defines the desired state of the InferencePool. // // +required - Spec InferencePoolSpec `json:"spec"` + Spec InferencePoolSpec `json:"spec,omitzero"` // Status defines the observed state of the InferencePool. // @@ -67,6 +67,7 @@ type InferencePoolSpec struct { // this configuration into a Service resource. // // +required + //nolint:kubeapilinter // ignore kubeapilinter here as we don't want to use pointer here. Selector LabelSelector `json:"selector"` // TargetPorts defines a list of ports that are exposed by this InferencePool. @@ -76,13 +77,14 @@ type InferencePoolSpec struct { // +kubebuilder:validation:MaxItems=1 // +listType=atomic // +required + //nolint:kubeapilinter // ignore kubeapilinter here since the field is required and we don't want omitempty tag. TargetPorts []Port `json:"targetPorts"` // EndpointPickerRef is a reference to the Endpoint Picker extension and its // associated configuration. // // +required - EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef"` + EndpointPickerRef EndpointPickerRef `json:"endpointPickerRef,omitzero"` } // Port defines the network port that will be exposed by this InferencePool. @@ -91,6 +93,7 @@ type Port struct { // The number must be in the range 1 to 65535. // // +required + //nolint:kubeapilinter // ignore kubeapilinter here since the field is required and we don't want omitempty tag. Number PortNumber `json:"number"` } @@ -123,6 +126,7 @@ type EndpointPickerRef struct { // Name is the name of the referent API object. // // +required + //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer since empty means default value. Name ObjectName `json:"name"` // PortNumber is the port number of the Endpoint Picker extension service. When unspecified, @@ -138,6 +142,7 @@ type EndpointPickerRef struct { // // +optional // +kubebuilder:default="FailClose" + //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer since empty means default value. FailureMode *EndpointPickerFailureMode `json:"failureMode,omitempty"` } @@ -198,7 +203,7 @@ type ParentStatus struct { // resource, such as a Gateway. // // +required - ParentRef ParentReference `json:"parentRef"` + ParentRef ParentReference `json:"parentRef,omitzero"` } // InferencePoolConditionType is a type of status condition for the InferencePool. diff --git a/api/v1/shared_types.go b/api/v1/shared_types.go index c473cd22b..bc315fd4f 100644 --- a/api/v1/shared_types.go +++ b/api/v1/shared_types.go @@ -139,5 +139,5 @@ type LabelSelector struct { // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=64 - MatchLabels map[LabelKey]LabelValue `json:"matchLabels"` + MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitempty"` } From 6f89efd1d22098b65600686976898ff6ff575420 Mon Sep 17 00:00:00 2001 From: Daneyon Hansen Date: Fri, 22 Aug 2025 12:09:41 -0700 Subject: [PATCH 5/5] Resolve robscott feedback Signed-off-by: Daneyon Hansen --- .golangci-kal.yml | 2 + api/v1/inferencepool_types.go | 57 +++---- api/v1/shared_types.go | 2 +- apix/v1alpha2/inferencepool_conversion.go | 153 ++++++++---------- .../v1alpha2/inferencepool_conversion_test.go | 74 --------- apix/v1alpha2/zz_generated.deepcopy.go | 2 +- ...ence.networking.k8s.io_inferencepools.yaml | 14 +- site-src/reference/spec.md | 4 +- 8 files changed, 105 insertions(+), 203 deletions(-) diff --git a/.golangci-kal.yml b/.golangci-kal.yml index a5d853bfe..099d81da6 100644 --- a/.golangci-kal.yml +++ b/.golangci-kal.yml @@ -32,6 +32,8 @@ linters: policy: SuggestFix # SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`. omitempty: policy: SuggestFix # SuggestFix | Warn | Ignore # The policy for omitempty in optional fields. Defaults to `SuggestFix`. + omitzero: + policy: Forbid # Enforce the `omitempty` route with a pointer for all optional structs. exclusions: generated: strict paths: diff --git a/api/v1/inferencepool_types.go b/api/v1/inferencepool_types.go index 7a8c1cc52..05c7c9f88 100644 --- a/api/v1/inferencepool_types.go +++ b/api/v1/inferencepool_types.go @@ -43,11 +43,10 @@ type InferencePool struct { // Status defines the observed state of the InferencePool. // // +optional - //nolint:kubeapilinter // ignore kubeapilinter to follow K8s conventions of optional but non-pointer. Status InferencePoolStatus `json:"status,omitempty"` } -// InferencePoolList contains a list InferencePools. +// InferencePoolList contains a list of InferencePools. // // +kubebuilder:object:root=true type InferencePoolList struct { @@ -67,8 +66,7 @@ type InferencePoolSpec struct { // this configuration into a Service resource. // // +required - //nolint:kubeapilinter // ignore kubeapilinter here as we don't want to use pointer here. - Selector LabelSelector `json:"selector"` + Selector LabelSelector `json:"selector,omitzero"` // TargetPorts defines a list of ports that are exposed by this InferencePool. // Currently, the list may only include a single port definition. @@ -77,8 +75,7 @@ type InferencePoolSpec struct { // +kubebuilder:validation:MaxItems=1 // +listType=atomic // +required - //nolint:kubeapilinter // ignore kubeapilinter here since the field is required and we don't want omitempty tag. - TargetPorts []Port `json:"targetPorts"` + TargetPorts []Port `json:"targetPorts,omitzero"` // EndpointPickerRef is a reference to the Endpoint Picker extension and its // associated configuration. @@ -93,8 +90,7 @@ type Port struct { // The number must be in the range 1 to 65535. // // +required - //nolint:kubeapilinter // ignore kubeapilinter here since the field is required and we don't want omitempty tag. - Number PortNumber `json:"number"` + Number PortNumber `json:"number,omitzero"` } // EndpointPickerRef specifies a reference to an Endpoint Picker extension and its @@ -126,15 +122,13 @@ type EndpointPickerRef struct { // Name is the name of the referent API object. // // +required - //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer since empty means default value. - Name ObjectName `json:"name"` + Name ObjectName `json:"name,omitzero"` // PortNumber is the port number of the Endpoint Picker extension service. When unspecified, // implementations SHOULD infer a default value of 9002 when the kind field is "Service" or // unspecified (defaults to "Service"). // // +optional - //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as 0 usually means all ports. PortNumber *PortNumber `json:"portNumber,omitempty"` // FailureMode configures how the parent handles the case when the Endpoint Picker extension @@ -142,7 +136,6 @@ type EndpointPickerRef struct { // // +optional // +kubebuilder:default="FailClose" - //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer since empty means default value. FailureMode *EndpointPickerFailureMode `json:"failureMode,omitempty"` } @@ -185,18 +178,18 @@ type ParentStatus struct { // state of the InferencePool. This field is required to be set by the controller that // manages the InferencePool. // - // Known condition types are: + // Supported condition types are: // // * "Accepted" // * "ResolvedRefs" // - // +required + // +optional // +listType=map // +listMapKey=type - // +kubebuilder:validation:MinItems=1 + // +patchStrategy=merge + // +patchMergeKey=type // +kubebuilder:validation:MaxItems=8 - //nolint:kubeapilinter // ignore kubeapilinter here as we want conditions to be required. - Conditions []metav1.Condition `json:"conditions"` + Conditions []metav1.Condition `json:"conditions,omitempty"` // ParentRef is used to identify the parent resource that this status // is associated with. It is used to match the InferencePool with the parent @@ -222,7 +215,7 @@ const ( // // Possible reasons for this condition to be False are: // - // * "NotSupportedByParent" + // * "Accepted" // * "HTTPRouteNotAccepted" // // Possible reasons for this condition to be Unknown are: @@ -236,22 +229,18 @@ const ( // InferencePoolReasonAccepted is a reason used with the "Accepted" condition // when the InferencePool is accepted by a Parent because the Parent supports // InferencePool as a backend. - InferencePoolReasonAccepted InferencePoolReason = "SupportedByParent" + InferencePoolReasonAccepted InferencePoolReason = "Accepted" // InferencePoolReasonNotSupportedByParent is a reason used with the "Accepted" // condition when the InferencePool has not been accepted by a Parent because // the Parent does not support InferencePool as a backend. InferencePoolReasonNotSupportedByParent InferencePoolReason = "NotSupportedByParent" - // InferencePoolReasonHTTPRouteNotAccepted is a reason used with the "Accepted" - // condition when the InferencePool is referenced by an HTTPRoute that has been - // rejected by the Parent. The user should inspect the status of the referring - // HTTPRoute for the specific reason. + // InferencePoolReasonHTTPRouteNotAccepted is an optional reason used with the + // "Accepted" condition when the InferencePool is referenced by an HTTPRoute that + // has been rejected by the Parent. The user should inspect the status of the + // referring HTTPRoute for the specific reason. InferencePoolReasonHTTPRouteNotAccepted InferencePoolReason = "HTTPRouteNotAccepted" - - // This reason is used with the "Accepted" when a controller has not yet - // reconciled the InferencePool. - InferencePoolReasonPending InferencePoolReason = "Pending" ) const ( @@ -295,19 +284,21 @@ type ParentReference struct { // // +optional // +kubebuilder:default=Gateway - //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means default value. Kind *Kind `json:"kind,omitempty"` // Name is the name of the referent API object. // // +required - Name ObjectName `json:"name,omitempty"` + Name ObjectName `json:"name,omitzero"` - // Namespace is the namespace of the referent API object. When unspecified, - // the namespace of the referent is assumed to be the same as the namespace - // of the referring object. + // Namespace is the namespace of the referenced object. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace different than the local namespace is specified, + // a ReferenceGrant object is required in the referent namespace to allow that + // namespace's owner to accept the reference. See the ReferenceGrant + // documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/ // // +optional - //nolint:kubeapilinter // ignore kubeapilinter here as we want to use pointer here as empty means same namespace. Namespace *Namespace `json:"namespace,omitempty"` } diff --git a/api/v1/shared_types.go b/api/v1/shared_types.go index bc315fd4f..992838c71 100644 --- a/api/v1/shared_types.go +++ b/api/v1/shared_types.go @@ -139,5 +139,5 @@ type LabelSelector struct { // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=64 - MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitempty"` + MatchLabels map[LabelKey]LabelValue `json:"matchLabels,omitzero"` } diff --git a/apix/v1alpha2/inferencepool_conversion.go b/apix/v1alpha2/inferencepool_conversion.go index 76899ce6f..7ec7302c2 100644 --- a/apix/v1alpha2/inferencepool_conversion.go +++ b/apix/v1alpha2/inferencepool_conversion.go @@ -18,12 +18,8 @@ package v1alpha2 import ( "errors" - "fmt" - "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1" @@ -43,9 +39,6 @@ func (src *InferencePool) ConvertTo(dst *v1.InferencePool) error { return err } - // v1 requires at least one condition per parent. - ensureV1StatusConditionsMinimum(v1Status) - meta := metav1.TypeMeta{ Kind: src.Kind, APIVersion: v1.GroupVersion.String(), // Ensure the API version is set correctly. @@ -102,31 +95,24 @@ func convertStatusToV1(src *InferencePoolStatus) (*v1.InferencePoolStatus, error if src == nil { return nil, errors.New("src cannot be nil") } - u, err := toUnstructured(src) - if err != nil { - return nil, err - } - - // v1alpha2 used json:"parent" (singular) v1 uses json:"parents" - if v, ok := u.Object["parent"]; ok { - u.Object["parents"] = v - delete(u.Object, "parent") - } - - out, err := convert[v1.InferencePoolStatus](u) - if err != nil { - return nil, err + out := &v1.InferencePoolStatus{ + Parents: make([]v1.ParentStatus, 0, len(src.Parents)), } - - // Map condition reason string: "Accepted" (v1alpha2) -> "SupportedByParent" (v1) - for i := range out.Parents { - for j := range out.Parents[i].Conditions { - c := &out.Parents[i].Conditions[j] - if c.Type == string(v1.InferencePoolConditionAccepted) && - c.Reason == string(InferencePoolReasonAccepted) { - c.Reason = string(v1.InferencePoolReasonAccepted) + for _, p := range src.Parents { + ps := v1.ParentStatus{ + ParentRef: toV1ParentRef(p.GatewayRef), + Conditions: make([]metav1.Condition, 0, len(p.Conditions)), + } + for _, c := range p.Conditions { + cc := c + // v1alpha2: "Accepted" -> v1: "SupportedByParent" + if cc.Type == string(v1.InferencePoolConditionAccepted) && + cc.Reason == string(InferencePoolReasonAccepted) { + cc.Reason = string(v1.InferencePoolReasonAccepted) } + ps.Conditions = append(ps.Conditions, cc) } + out.Parents = append(out.Parents, ps) } return out, nil } @@ -135,33 +121,64 @@ func convertStatusFromV1(src *v1.InferencePoolStatus) (*InferencePoolStatus, err if src == nil { return nil, errors.New("src cannot be nil") } - u, err := toUnstructured(src) - if err != nil { - return nil, err + out := &InferencePoolStatus{ + Parents: make([]PoolStatus, 0, len(src.Parents)), } - - // v1 uses json:"parents"; v1alpha2 used json:"parent" (singular) - if v, ok := u.Object["parents"]; ok { - u.Object["parent"] = v - delete(u.Object, "parents") + for _, p := range src.Parents { + ps := PoolStatus{ + GatewayRef: fromV1ParentRef(p.ParentRef), + Conditions: make([]metav1.Condition, 0, len(p.Conditions)), + } + for _, c := range p.Conditions { + cc := c + // v1: "SupportedByParent" -> v1alpha2: "Accepted" + if cc.Type == string(v1.InferencePoolConditionAccepted) && + cc.Reason == string(v1.InferencePoolReasonAccepted) { + cc.Reason = string(InferencePoolReasonAccepted) + } + ps.Conditions = append(ps.Conditions, cc) + } + out.Parents = append(out.Parents, ps) } + return out, nil +} - out, err := convert[InferencePoolStatus](u) - if err != nil { - return nil, err +func toV1ParentRef(in ParentGatewayReference) v1.ParentReference { + out := v1.ParentReference{ + Name: v1.ObjectName(in.Name), + } + if in.Group != nil { + g := v1.Group(*in.Group) + out.Group = &g + } + if in.Kind != nil { + k := v1.Kind(*in.Kind) + out.Kind = &k } + if in.Namespace != nil { + ns := v1.Namespace(*in.Namespace) + out.Namespace = &ns + } + return out +} - // Map condition reason string: "SupportedByParent" (v1) -> "Accepted" (v1alpha2) - for i := range out.Parents { - for j := range out.Parents[i].Conditions { - c := &out.Parents[i].Conditions[j] - if c.Type == string(v1.InferencePoolConditionAccepted) && - c.Reason == string(v1.InferencePoolReasonAccepted) { - c.Reason = string(InferencePoolReasonAccepted) - } - } +func fromV1ParentRef(in v1.ParentReference) ParentGatewayReference { + out := ParentGatewayReference{ + Name: ObjectName(in.Name), } - return out, nil + if in.Group != nil { + g := Group(*in.Group) + out.Group = &g + } + if in.Kind != nil { + k := Kind(*in.Kind) + out.Kind = &k + } + if in.Namespace != nil { + ns := Namespace(*in.Namespace) + out.Namespace = &ns + } + return out } func convertExtensionRefToV1(src *Extension) (v1.EndpointPickerRef, error) { @@ -206,39 +223,3 @@ func convertEndpointPickerRefFromV1(src *v1.EndpointPickerRef) (Extension, error } return extension, nil } - -func toUnstructured(obj any) (*unstructured.Unstructured, error) { - u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) - if err != nil { - return nil, err - } - return &unstructured.Unstructured{Object: u}, nil -} - -func convert[T any](u *unstructured.Unstructured) (*T, error) { - var res T - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &res); err != nil { - return nil, fmt.Errorf("error converting unstructured to T: %v", err) - } - return &res, nil -} - -// Ensure v1's PoolStatus.Conditions has at least one entry. -func ensureV1StatusConditionsMinimum(s *v1.InferencePoolStatus) { - if s == nil { - return - } - epoch := metav1.NewTime(time.Unix(0, 0)) - for i := range s.Parents { - ps := &s.Parents[i] - if len(ps.Conditions) == 0 { - ps.Conditions = []metav1.Condition{{ - Type: string(v1.InferencePoolConditionAccepted), - Status: metav1.ConditionUnknown, - Reason: string(v1.InferencePoolReasonPending), - Message: "Waiting for controller", - LastTransitionTime: epoch, - }} - } - } -} diff --git a/apix/v1alpha2/inferencepool_conversion_test.go b/apix/v1alpha2/inferencepool_conversion_test.go index 4e159746c..5a828dc37 100644 --- a/apix/v1alpha2/inferencepool_conversion_test.go +++ b/apix/v1alpha2/inferencepool_conversion_test.go @@ -194,80 +194,6 @@ func TestInferencePoolConvertTo(t *testing.T) { }, wantErr: false, }, - { - name: "synthesize status conditions only where empty", - src: &InferencePool{ - TypeMeta: metav1.TypeMeta{ - Kind: "InferencePool", - APIVersion: GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pool", - Namespace: "test-ns", - }, - Spec: InferencePoolSpec{ - Selector: map[LabelKey]LabelValue{"app": "my-model-server"}, - TargetPortNumber: 8080, - }, - Status: InferencePoolStatus{ - Parents: []PoolStatus{ - { - GatewayRef: ParentGatewayReference{Name: "gw-a"}, - Conditions: []metav1.Condition{{ - Type: string(InferencePoolConditionAccepted), - Status: metav1.ConditionTrue, - Reason: string(InferencePoolReasonAccepted), - LastTransitionTime: timestamp, - }}, - }, - { - GatewayRef: ParentGatewayReference{Name: "gw-b"}, - // Conditions empty -> should be synthesized - }, - }, - }, - }, - want: &v1.InferencePool{ - TypeMeta: metav1.TypeMeta{ - Kind: "InferencePool", - APIVersion: v1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pool", - Namespace: "test-ns", - }, - Spec: v1.InferencePoolSpec{ - Selector: v1.LabelSelector{ - MatchLabels: map[v1.LabelKey]v1.LabelValue{"app": "my-model-server"}, - }, - TargetPorts: []v1.Port{{Number: v1.PortNumber(8080)}}, - }, - Status: v1.InferencePoolStatus{ - Parents: []v1.ParentStatus{ - { - ParentRef: v1.ParentReference{Name: "gw-a"}, - Conditions: []metav1.Condition{{ - Type: string(v1.InferencePoolConditionAccepted), - Status: metav1.ConditionTrue, - Reason: string(v1.InferencePoolReasonAccepted), - LastTransitionTime: timestamp, - }}, - }, - { - ParentRef: v1.ParentReference{Name: "gw-b"}, - Conditions: []metav1.Condition{{ - Type: string(v1.InferencePoolConditionAccepted), - Status: metav1.ConditionUnknown, - Reason: string(v1.InferencePoolReasonPending), - Message: "Waiting for controller", - LastTransitionTime: timestamp, - }}, - }, - }, - }, - }, - wantErr: false, - }, } for _, tt := range tests { diff --git a/apix/v1alpha2/zz_generated.deepcopy.go b/apix/v1alpha2/zz_generated.deepcopy.go index 5a71e7530..0249d442d 100644 --- a/apix/v1alpha2/zz_generated.deepcopy.go +++ b/apix/v1alpha2/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ package v1alpha2 import ( "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml index e37054921..2dec05cdb 100644 --- a/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml +++ b/config/crd/bases/inference.networking.k8s.io_inferencepools.yaml @@ -189,7 +189,7 @@ spec: state of the InferencePool. This field is required to be set by the controller that manages the InferencePool. - Known condition types are: + Supported condition types are: * "Accepted" * "ResolvedRefs" @@ -249,7 +249,6 @@ spec: - type type: object maxItems: 8 - minItems: 1 type: array x-kubernetes-list-map-keys: - type @@ -285,9 +284,13 @@ spec: type: string namespace: description: |- - Namespace is the namespace of the referent API object. When unspecified, - the namespace of the referent is assumed to be the same as the namespace - of the referring object. + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/ maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -296,7 +299,6 @@ spec: - name type: object required: - - conditions - parentRef type: object maxItems: 32 diff --git a/site-src/reference/spec.md b/site-src/reference/spec.md index 97314dc98..a06968b29 100644 --- a/site-src/reference/spec.md +++ b/site-src/reference/spec.md @@ -311,7 +311,7 @@ _Appears in:_ | `group` _[Group](#group)_ | Group is the group of the referent API object. When unspecified, the referent is assumed
to be in the "gateway.networking.k8s.io" API group. | gateway.networking.k8s.io | MaxLength: 253
MinLength: 0
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| | `kind` _[Kind](#kind)_ | Kind is the kind of the referent API object. When unspecified, the referent is assumed
to be a "Gateway" kind. | Gateway | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| | `name` _[ObjectName](#objectname)_ | Name is the name of the referent API object. | | MaxLength: 253
MinLength: 1
| -| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent API object. When unspecified,
the namespace of the referent is assumed to be the same as the namespace
of the referring object. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referenced object. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details: https://gateway-api.sigs.k8s.io/api-types/referencegrant/ | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| #### ParentStatus @@ -327,7 +327,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions is a list of status conditions that provide information about the observed
state of the InferencePool. This field is required to be set by the controller that
manages the InferencePool.
Known condition types are:
* "Accepted"
* "ResolvedRefs" | | MaxItems: 8
MinItems: 1
| +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions is a list of status conditions that provide information about the observed
state of the InferencePool. This field is required to be set by the controller that
manages the InferencePool.
Supported condition types are:
* "Accepted"
* "ResolvedRefs" | | MaxItems: 8
| | `parentRef` _[ParentReference](#parentreference)_ | ParentRef is used to identify the parent resource that this status
is associated with. It is used to match the InferencePool with the parent
resource, such as a Gateway. | | |