@@ -19,6 +19,7 @@ package v1alpha1
1919import (
2020 "fmt"
2121 "reflect"
22+ "strings"
2223
2324 corev1 "k8s.io/api/core/v1"
2425 networkingv1 "k8s.io/api/networking/v1"
@@ -36,6 +37,27 @@ var validPVCAccessModeStrs = []corev1.PersistentVolumeAccessMode{
3637 corev1 .ReadWriteOncePod ,
3738}
3839
40+ // validateNIMServiceSpec aggregates all structural validation checks for a NIMService
41+ // object. It is intended to be invoked by both ValidateCreate and ValidateUpdate to
42+ // ensure the resource is well-formed before any other validation (e.g. immutability)
43+ // is performed.
44+ func validateNIMServiceSpec (spec * appsv1alpha1.NIMServiceSpec , fldPath * field.Path , kubeVersion string ) field.ErrorList {
45+ errList := field.ErrorList {}
46+
47+ // Validate individual sections of the spec using existing helper functions.
48+ errList = append (errList , validateImageConfiguration (& spec .Image , fldPath .Child ("image" ))... )
49+ errList = append (errList , validateAuthSecret (& spec .AuthSecret , fldPath .Child ("authSecret" ))... )
50+ errList = append (errList , validateServiceStorageConfiguration (& spec .Storage , fldPath .Child ("storage" ))... )
51+ errList = append (errList , validateExposeConfiguration (& spec .Expose , fldPath .Child ("expose" ).Child ("ingress" ))... )
52+ errList = append (errList , validateMetricsConfiguration (& spec .Metrics , fldPath .Child ("metrics" ))... )
53+ errList = append (errList , validateScaleConfiguration (& spec .Scale , fldPath .Child ("scale" ))... )
54+ errList = append (errList , validateResourcesConfiguration (spec .Resources , fldPath .Child ("resources" ))... )
55+ errList = append (errList , validateDRAResourcesConfiguration (spec , fldPath , kubeVersion )... )
56+ errList = append (errList , validateKServeConfiguration (spec , fldPath )... )
57+
58+ return errList
59+ }
60+
3961func validateImageConfiguration (image * appsv1alpha1.Image , fldPath * field.Path ) field.ErrorList {
4062 errList := field.ErrorList {}
4163 if image .Repository == "" {
@@ -212,22 +234,39 @@ func validateResourcesConfiguration(resources *corev1.ResourceRequirements, fldP
212234 return errList
213235}
214236
215- // validateNIMServiceSpec aggregates all structural validation checks for a NIMService
216- // object. It is intended to be invoked by both ValidateCreate and ValidateUpdate to
217- // ensure the resource is well-formed before any other validation (e.g. immutability)
218- // is performed.
219- func validateNIMServiceSpec (spec * appsv1alpha1.NIMServiceSpec , fldPath * field.Path , kubeVersion string ) field.ErrorList {
237+ // validateKServeonfiguration implements required KServe validations.
238+ func validateKServeConfiguration (spec * appsv1alpha1.NIMServiceSpec , fldPath * field.Path ) field.ErrorList {
220239 errList := field.ErrorList {}
221240
222- // Validate individual sections of the spec using existing helper functions.
223- errList = append (errList , validateImageConfiguration (& spec .Image , fldPath .Child ("image" ))... )
224- errList = append (errList , validateAuthSecret (& spec .AuthSecret , fldPath .Child ("authSecret" ))... )
225- errList = append (errList , validateServiceStorageConfiguration (& spec .Storage , fldPath .Child ("storage" ))... )
226- errList = append (errList , validateExposeConfiguration (& spec .Expose , fldPath .Child ("expose" ).Child ("ingress" ))... )
227- errList = append (errList , validateMetricsConfiguration (& spec .Metrics , fldPath .Child ("metrics" ))... )
228- errList = append (errList , validateScaleConfiguration (& spec .Scale , fldPath .Child ("scale" ))... )
229- errList = append (errList , validateResourcesConfiguration (spec .Resources , fldPath .Child ("resources" ))... )
230- errList = append (errList , validateDRAResourcesConfiguration (spec , fldPath , kubeVersion )... )
241+ platformIsKServe := spec .InferencePlatform == appsv1alpha1 .PlatformTypeKServe
242+
243+ // mode is the value, and annotated is true if the key-value pair exist.
244+ mode , annotated := spec .Annotations ["serving.kserve.org/deploymentMode" ]
245+ // If the annotation is absent, kserve defaults to serverless.
246+ serverless := ! annotated || strings .EqualFold (mode , "serverless" )
247+
248+ // When Spec.InferencePlatform is "kserve" and used in "serverless" mode:
249+ if platformIsKServe && serverless {
250+ // Spec.Scale (autoscaling) cannot be set.
251+ if spec .Scale .Enabled != nil && * spec .Scale .Enabled {
252+ errList = append (errList , field .Forbidden (fldPath .Child ("scale" ).Child ("enabled" ), fmt .Sprintf ("%s (autoscaling) cannot be set when KServe runs in serverless mode" , fldPath .Child ("scale" ))))
253+ }
254+
255+ // Spec.Expose.Ingress cannot be set.
256+ if spec .Expose .Ingress .Enabled != nil && * spec .Expose .Ingress .Enabled {
257+ errList = append (errList , field .Forbidden (fldPath .Child ("expose" ).Child ("ingress" ).Child ("enabled" ), fmt .Sprintf ("%s cannot be set when KServe runs in serverless mode" , fldPath .Child ("expose" ).Child ("ingress" ))))
258+ }
259+
260+ // Spec.Metrics.ServiceMonitor cannot be set.
261+ if spec .Metrics .Enabled != nil && * spec .Metrics .Enabled {
262+ errList = append (errList , field .Forbidden (fldPath .Child ("metrics" ).Child ("enabled" ), fmt .Sprintf ("%s cannot be set when KServe runs in serverless mode" , fldPath .Child ("metrics" ).Child ("serviceMonitor" ))))
263+ }
264+ }
265+
266+ // Spec.MultiNode cannot be enabled when inferencePlatform is kserve.
267+ if platformIsKServe && spec .MultiNode != nil {
268+ errList = append (errList , field .Forbidden (fldPath .Child ("multiNode" ), "cannot be set when KServe runs in serverless mode" ))
269+ }
231270
232271 return errList
233272}
0 commit comments