Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/v1/inferencepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type Port struct {

// EndpointPickerRef specifies a reference to an Endpoint Picker extension and its
// associated configuration.
// +kubebuilder:validation:XValidation:rule="self.kind != 'Service' || has(self.port)",message="port is required when kind is 'Service'"
// +kubebuilder:validation:XValidation:rule="self.kind != 'Service' || has(self.port)",message="port is required when kind is 'Service' and unset(default to 'Service')"
type EndpointPickerRef struct {
// Group is the group of the referent API object. When unspecified, the default value
// is "", representing the Core API group.
Expand Down
1 change: 1 addition & 0 deletions apix/v1alpha2/inferencepool_conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ spec:
- name
type: object
x-kubernetes-validations:
- message: port is required when kind is 'Service'
- message: port is required when kind is 'Service' and unset(default
to 'Service')
rule: self.kind != 'Service' || has(self.port)
selector:
description: |-
Expand Down
41 changes: 13 additions & 28 deletions test/cel/inferencepool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ import (
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/gateway-api-inference-extension/api/v1"

v1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
)

func TestValidateInferencePool(t *testing.T) {
ctx := context.Background()

// baseInferencePool is a valid, minimal InferencePool resource.
// We use a non-Service kind for the picker to ensure the base object is valid
// without needing a port, making it a neutral starting point for mutations.
// baseInferencePool is a valid, InferencePool resource.
baseInferencePool := v1.InferencePool{
ObjectMeta: metav1.ObjectMeta{
Name: "base-pool",
Expand All @@ -43,13 +42,13 @@ func TestValidateInferencePool(t *testing.T) {
},
Selector: v1.LabelSelector{
MatchLabels: map[v1.LabelKey]v1.LabelValue{
"app": "my-model-server",
"app": "model-server",
},
},
EndpointPickerRef: v1.EndpointPickerRef{
Name: "epp",
Kind: "Service",
Port: ptrTo(v1.Port{Number: 9000}),
Port: ptrTo(v1.Port{Number: 9002}),
},
},
}
Expand All @@ -59,6 +58,12 @@ func TestValidateInferencePool(t *testing.T) {
mutate func(ip *v1.InferencePool)
wantErrors []string
}{
{
desc: "passes validation with a valid configuration",
mutate: func(ip *v1.InferencePool) {
},
wantErrors: nil,
},
{
desc: "fails validation when kind is unset (defaults to Service) and port is missing",
mutate: func(ip *v1.InferencePool) {
Expand All @@ -67,7 +72,7 @@ func TestValidateInferencePool(t *testing.T) {
ip.Spec.EndpointPickerRef.Name = "vllm-llama3-8b-instruct-epp"
ip.Spec.EndpointPickerRef.Port = nil
},
wantErrors: []string{"port is required when kind is 'Service'"},
wantErrors: []string{"port is required when kind is 'Service' and unset(default to 'Service')"},
},
{
desc: "fails validation when kind is explicitly 'Service' and port is missing",
Expand All @@ -76,27 +81,7 @@ func TestValidateInferencePool(t *testing.T) {
ip.Spec.EndpointPickerRef.Name = "vllm-llama3-8b-instruct-epp"
ip.Spec.EndpointPickerRef.Port = nil
},
wantErrors: []string{"port is required when kind is 'Service'"},
},
{
desc: "passes validation when kind is 'Service' and port is present",
mutate: func(ip *v1.InferencePool) {
ip.Spec.EndpointPickerRef.Kind = "Service"
ip.Spec.EndpointPickerRef.Name = "vllm-llama3-8b-instruct-epp"
ip.Spec.EndpointPickerRef.Port = &v1.Port{
Number: 9002,
}
},
// No errors expected, so wantErrors is nil or empty.
wantErrors: nil,
},
{
desc: "passes validation with a valid, minimal configuration",
mutate: func(ip *v1.InferencePool) {
// This mutation just uses the base configuration, which should be valid.
// It's a good sanity check. The base uses a non-Service Kind.
},
wantErrors: nil,
wantErrors: []string{"port is required when kind is 'Service' and unset(default to 'Service')"},
},
}

Expand Down
9 changes: 6 additions & 3 deletions test/cel/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ import (
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"

inferencev1 "sigs.k8s.io/gateway-api-inference-extension/api/v1"
inferencev1alpha2 "sigs.k8s.io/gateway-api-inference-extension/apix/v1alpha2"
)

var k8sClient client.Client
Expand All @@ -40,10 +42,11 @@ func TestMain(m *testing.M) {
var testEnv *envtest.Environment
var err error

inferencev1.AddToScheme(scheme)
_ = inferencev1.Install(scheme)
_ = inferencev1alpha2.Install(scheme)

// Add core APIs in case we refer secrets, services and configmaps
corev1.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

// If one wants to use a local cluster, a KUBECONFIG envvar should be passed,
// otherwise testenv will be used
Expand All @@ -65,7 +68,7 @@ func TestMain(m *testing.M) {
DownloadBinaryAssetsVersion: k8sVersion,
CRDInstallOptions: envtest.CRDInstallOptions{
Paths: []string{
filepath.Join("..", "..", "..", "config", "crd", "bases"),
filepath.Join("..", "..", "config", "crd", "bases"),
},
CleanUpAfterUse: true,
},
Expand Down