diff --git a/pkg/kthena-router/webhook/validator.go b/pkg/kthena-router/webhook/validator.go index 04b803c31..81e7e92ff 100644 --- a/pkg/kthena-router/webhook/validator.go +++ b/pkg/kthena-router/webhook/validator.go @@ -180,6 +180,16 @@ func (v *KthenaRouterValidator) validateModelRoute(modelRoute *networkingv1alpha if len(rule.TargetModels) == 0 { allErrs = append(allErrs, field.Required(ruleField.Child("targetModels"), "each rule must have at least one target model")) } + for j, target := range rule.TargetModels { + targetField := ruleField.Child("targetModels").Index(j) + if target == nil { + allErrs = append(allErrs, field.Invalid(targetField, target, "target model must not be nil")) + continue + } + if target.ModelServerName == "" { + allErrs = append(allErrs, field.Required(targetField.Child("modelServerName"), "modelServerName must not be empty")) + } + } } if len(allErrs) > 0 { diff --git a/pkg/kthena-router/webhook/validator_test.go b/pkg/kthena-router/webhook/validator_test.go index 855beb303..9747c953e 100644 --- a/pkg/kthena-router/webhook/validator_test.go +++ b/pkg/kthena-router/webhook/validator_test.go @@ -330,6 +330,88 @@ func TestValidateModelRoute(t *testing.T) { expectValid: false, expectedReason: "validation failed: - spec.rules[0]: Invalid value: null: rule must not be nil", }, + { + name: "invalid model route - targetModel with empty modelServerName", + modelRoute: &networkingv1alpha1.ModelRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "networking.serving.volcano.sh/v1alpha1", + Kind: "ModelRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-route", + Namespace: "default", + }, + Spec: networkingv1alpha1.ModelRouteSpec{ + ModelName: "test-model", + Rules: []*networkingv1alpha1.Rule{ + { + Name: "test-rule", + TargetModels: []*networkingv1alpha1.TargetModel{ + { + ModelServerName: "", + }, + }, + }, + }, + }, + }, + expectValid: false, + expectedReason: "validation failed: - spec.rules[0].targetModels[0].modelServerName: Required value: modelServerName must not be empty", + }, + { + name: "invalid model route - nil target model entry", + modelRoute: &networkingv1alpha1.ModelRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "networking.serving.volcano.sh/v1alpha1", + Kind: "ModelRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-route", + Namespace: "default", + }, + Spec: networkingv1alpha1.ModelRouteSpec{ + ModelName: "test-model", + Rules: []*networkingv1alpha1.Rule{ + { + Name: "test-rule", + TargetModels: []*networkingv1alpha1.TargetModel{ + nil, + }, + }, + }, + }, + }, + expectValid: false, + expectedReason: "validation failed: - spec.rules[0].targetModels[0]: Invalid value: null: target model must not be nil", + }, + { + name: "invalid model route - mixed valid and invalid targetModels", + modelRoute: &networkingv1alpha1.ModelRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "networking.serving.volcano.sh/v1alpha1", + Kind: "ModelRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-route", + Namespace: "default", + }, + Spec: networkingv1alpha1.ModelRouteSpec{ + ModelName: "test-model", + Rules: []*networkingv1alpha1.Rule{ + { + Name: "test-rule", + TargetModels: []*networkingv1alpha1.TargetModel{ + {ModelServerName: "valid-server"}, + {ModelServerName: ""}, + nil, + }, + }, + }, + }, + }, + expectValid: false, + expectedReason: "validation failed: - spec.rules[0].targetModels[1].modelServerName: Required value: modelServerName must not be empty - spec.rules[0].targetModels[2]: Invalid value: null: target model must not be nil", + }, { name: "invalid model route - combined errors: missing model name and empty targetModels", modelRoute: &networkingv1alpha1.ModelRoute{