sigs.k8s.io/kueue@v0.6.2/pkg/controller/jobframework/validation.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 http://www.apache.org/licenses/LICENSE-2.0 7 Unless required by applicable law or agreed to in writing, software 8 distributed under the License is distributed on an "AS IS" BASIS, 9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 See the License for the specific language governing permissions and 11 limitations under the License. 12 */ 13 14 package jobframework 15 16 import ( 17 "fmt" 18 "strings" 19 20 batchv1 "k8s.io/api/batch/v1" 21 apivalidation "k8s.io/apimachinery/pkg/api/validation" 22 "k8s.io/apimachinery/pkg/util/sets" 23 "k8s.io/apimachinery/pkg/util/validation" 24 "k8s.io/apimachinery/pkg/util/validation/field" 25 jobset "sigs.k8s.io/jobset/api/jobset/v1alpha2" 26 27 "sigs.k8s.io/kueue/pkg/controller/constants" 28 ) 29 30 var ( 31 annotationsPath = field.NewPath("metadata", "annotations") 32 labelsPath = field.NewPath("metadata", "labels") 33 parentWorkloadKeyPath = annotationsPath.Key(constants.ParentWorkloadAnnotation) 34 queueNameLabelPath = labelsPath.Key(constants.QueueLabel) 35 workloadPriorityClassNamePath = labelsPath.Key(constants.WorkloadPriorityClassLabel) 36 supportedPrebuiltWlJobGVKs = sets.New(batchv1.SchemeGroupVersion.WithKind("Job").String(), 37 jobset.SchemeGroupVersion.WithKind("JobSet").String()) 38 ) 39 40 func ValidateCreateForQueueName(job GenericJob) field.ErrorList { 41 var allErrs field.ErrorList 42 allErrs = append(allErrs, ValidateLabelAsCRDName(job, constants.QueueLabel)...) 43 allErrs = append(allErrs, ValidateLabelAsCRDName(job, constants.PrebuiltWorkloadLabel)...) 44 allErrs = append(allErrs, ValidateAnnotationAsCRDName(job, constants.QueueAnnotation)...) 45 46 // this rule should be relaxed when its confirmed that running wit a prebuilt wl is fully supported by each integration 47 if _, hasPrebuilt := job.Object().GetLabels()[constants.PrebuiltWorkloadLabel]; hasPrebuilt { 48 gvk := job.GVK().String() 49 if !supportedPrebuiltWlJobGVKs.Has(gvk) { 50 allErrs = append(allErrs, field.Forbidden(labelsPath.Key(constants.PrebuiltWorkloadLabel), fmt.Sprintf("Is not supported for %q", gvk))) 51 } 52 } 53 return allErrs 54 } 55 56 func ValidateAnnotationAsCRDName(job GenericJob, crdNameAnnotation string) field.ErrorList { 57 var allErrs field.ErrorList 58 if value, exists := job.Object().GetAnnotations()[crdNameAnnotation]; exists { 59 if errs := validation.IsDNS1123Subdomain(value); len(errs) > 0 { 60 allErrs = append(allErrs, field.Invalid(annotationsPath.Key(crdNameAnnotation), value, strings.Join(errs, ","))) 61 } 62 } 63 return allErrs 64 } 65 66 func ValidateLabelAsCRDName(job GenericJob, crdNameLabel string) field.ErrorList { 67 var allErrs field.ErrorList 68 if value, exists := job.Object().GetLabels()[crdNameLabel]; exists { 69 if errs := validation.IsDNS1123Subdomain(value); len(errs) > 0 { 70 allErrs = append(allErrs, field.Invalid(labelsPath.Key(crdNameLabel), value, strings.Join(errs, ","))) 71 } 72 } 73 return allErrs 74 } 75 76 func ValidateCreateForParentWorkload(job GenericJob) field.ErrorList { 77 var allErrs field.ErrorList 78 if _, exists := job.Object().GetAnnotations()[constants.ParentWorkloadAnnotation]; exists { 79 if job.Object().GetOwnerReferences() == nil { 80 allErrs = append(allErrs, field.Forbidden(parentWorkloadKeyPath, "must not add a parent workload annotation to job without OwnerReference")) 81 } 82 } 83 return allErrs 84 } 85 86 func ValidateUpdateForQueueName(oldJob, newJob GenericJob) field.ErrorList { 87 var allErrs field.ErrorList 88 if !newJob.IsSuspended() { 89 allErrs = append(allErrs, apivalidation.ValidateImmutableField(QueueName(oldJob), QueueName(newJob), queueNameLabelPath)...) 90 } 91 92 oldWlName, _ := PrebuiltWorkloadFor(oldJob) 93 newWlName, _ := PrebuiltWorkloadFor(newJob) 94 allErrs = append(allErrs, apivalidation.ValidateImmutableField(oldWlName, newWlName, labelsPath.Key(constants.PrebuiltWorkloadLabel))...) 95 return allErrs 96 } 97 98 func ValidateUpdateForParentWorkload(oldJob, newJob GenericJob) field.ErrorList { 99 allErrs := apivalidation.ValidateImmutableField(ParentWorkloadName(newJob), ParentWorkloadName(oldJob), parentWorkloadKeyPath) 100 return allErrs 101 } 102 103 func ValidateUpdateForWorkloadPriorityClassName(oldJob, newJob GenericJob) field.ErrorList { 104 allErrs := apivalidation.ValidateImmutableField(workloadPriorityClassName(oldJob), workloadPriorityClassName(newJob), workloadPriorityClassNamePath) 105 return allErrs 106 }